[SCM] python-pyo/master: New upstream version 0.8.7

tiago at users.alioth.debian.org tiago at users.alioth.debian.org
Thu Aug 31 11:42:01 UTC 2017


The following commit has been merged in the master branch:
commit 878c6ff05c582f9c62787242e3e230b46bcba020
Author: Tiago Bortoletto Vaz <tiago at debian.org>
Date:   Thu Aug 31 07:10:48 2017 -0400

    New upstream version 0.8.7

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..37a3d77
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,62 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+env/
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+*.egg-info/
+.installed.cfg
+*.egg
+
+# PyInstaller
+#  Usually these files are written by a python script from a template
+#  before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*,cover
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# OSX
+.DS_Store
+
diff --git a/COPYING.LESSER.txt b/COPYING.LESSER.txt
new file mode 100644
index 0000000..853047c
--- /dev/null
+++ b/COPYING.LESSER.txt
@@ -0,0 +1,165 @@
+                GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions.
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version.
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/pyolib/COPYING.txt b/COPYING.txt
similarity index 100%
copy from pyolib/COPYING.txt
copy to COPYING.txt
diff --git a/ChangeLog b/ChangeLog
index ef1d32f..3f03cd5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,998 @@
+2017-08-28 belangeo <belangeo at gmail.com>
+
+    * Upgraded version number to 0.8.7.
+
+2017-08-28 belangeo <belangeo at gmail.com>
+
+    * Update MacOS and Windows build routine to compile for python 2.7,
+      3.5 and 3.6.
+
+2017-08-xx belangeo <belangeo at gmail.com>
+
+    * Fixed encoding of path for various objects.
+
+2017-08-25 belangeo <belangeo at gmail.com>
+
+    * Fixed clean-up of VoiceManager object.
+
+2017-08-25 belangeo <belangeo at gmail.com>
+
+    * Fixed ending point of TableRec's time stream (now keep the last 
+      value instead of switching back to 0).
+
+2017-08-23 belangeo <belangeo at gmail.com>
+
+    * Fixed windows 10 dependencies.
+
+2017-08-07 belangeo <belangeo at gmail.com>
+
+    * OscDataSend now can send more than one message per buffer size.
+
+2017-06-28 belangeo <belangeo at gmail.com>
+
+    * Fixed Expr unicode handling.
+
+2017-06-27 belangeo <belangeo at gmail.com>
+
+    * Wrap jack api detection inside a try-except statement in case
+      jack2-dbus is used instead of jackd.
+
+2017-06-05 belangeo <belangeo at gmail.com>
+
+    * Added getInterpolated method to PyoMatrixObject class.
+
+2017-06-05 belangeo <belangeo at gmail.com>
+
+    * The server now allow up to 16 channel rms outputs for GUI drawing.
+
+2017-05-18 belangeo <belangeo at gmail.com>
+
+	* Disable Microsoft Midi devices by default. Added
+	  Server.allowMicrosoftMidiDevices() method to enable them.
+
+2017-05-16 belangeo <belangeo at gmail.com>
+
+    * Converted remaining print statements to function calls.
+
+2017-04-20 belangeo <belangeo at gmail.com>
+
+    * Upgraded version number to 0.8.6.
+
+2017-04-20 belangeo <belangeo at gmail.com>
+
+    * Added a Copy menu item in PyoObject.ctrl() and DataTable.graph() windows.
+
+2017-04-20 belangeo <belangeo at gmail.com>
+
+    * Added setRandomType(dist, x) method to SfMarkerShuffler object.
+
+2017-04-20 belangeo <belangeo at gmail.com>
+
+    * Fixed TableRec, TrigTableRec and Looper time stream not started on play.
+
+2017-04-18 belangeo <belangeo at gmail.com>
+
+    * Fixed libraries dynamic links in MacOS installer scripts.
+
+2017-04-13 belangeo <belangeo at gmail.com>
+
+    * Fixed segfault in Resample_dealloc function.
+
+2017-04-10 belangeo <belangeo at gmail.com>
+
+    * Wrapped non-blocking offline processing between PyGILState_Ensure and
+    PyGILState_Release calls.
+
+2017-04-10 belangeo <belangeo at gmail.com>
+
+    * Updated liblo from 0.26 to 0.28 on Windows. This fixes a bug with socket
+    not properly closed.
+
+2017-04-09 belangeo <belangeo at gmail.com>
+
+    * Fixed segfault when updating ControlSlider value from the audio thread.
+
+2017-04-07 belangeo <belangeo at gmail.com>
+
+    * Fixed CallAfter segfault when deleted inside its own callback.
+
+2017-04-06 belangeo <belangeo at gmail.com>
+
+    * Fixed TableRead which continues to play when freq is negative and loop is off.
+
+2017-04-06 belangeo <belangeo at gmail.com>
+
+    * Added "speed" argument to Seq object. Useful to create continuous time
+      deceleration or acceleration.
+
+2017-03-31 belangeo <belangeo at gmail.com>
+
+    * Upgraded version number to 0.8.5.
+
+2017-03-31 belangeo <belangeo at gmail.com>
+
+    * Added two examples in 07-effects, 01-flanger.py and 02-schroeder-reverb.py.
+
+2017-03-31 belangeo <belangeo at gmail.com>
+
+    * Removed Server.setInOutDefaultDeviceFromHost(host) method.
+      Added a new winhost argument to the Server's initialization.
+      Added pa_get_default_devices_from_host(host) function.
+
+2017-03-27 belangeo <belangeo at gmail.com>
+
+    * Check the jack api version before compiling to ensure existing
+    functions are used (jack_port_set_name/jack_port_rename).
+
+2017-03-26 belangeo <belangeo at gmail.com>
+
+    * Added setInOutDefaultDeviceFromHost(host) to the Server object.
+
+2017-03-24 belangeo <belangeo at gmail.com>
+
+    * Upgraded version number to 0.8.4.
+
+2017-03-23 belangeo <belangeo at gmail.com>
+
+    * Added `id` and `object` attributes to wxgui's object events.
+
+2017-03-22 belangeo <belangeo at gmail.com>
+
+    * Added setJackInputPortNames and setJackOutputPortNames methods to the
+      Server object. This allow the user to rename jack input/output ports.
+
+2017-03-21 belangeo <belangeo at gmail.com>
+
+    * Updated portaudio interface to make it much more secure.
+
+2017-03-20 belangeo <belangeo at gmail.com>
+
+    * Added setIsJackTransportSlave method to Server object (it allows to
+      start/stop the Server from jack transport).
+
+2017-03-17 belangeo <belangeo at gmail.com>
+
+    * Fixed GIL conflicts with portaudio, portmidi and jack library calls.
+
+2017-03-11 belangeo <belangeo at gmail.com>
+
+    * Added a setKeepLast method to TableRead object (will hold last value).
+
+2017-03-10 belangeo <belangeo at gmail.com>
+
+    * Added a setMode method to Selector object to switch between
+      equal power mode and linear fade.
+
+2017-03-06 belangeo <belangeo at gmail.com>
+
+    * Fixed SfMarkerLooper and SfMarkerShuffler markers not accurate
+      when soundfile sampling rate is not the same as the server's
+      sampling rate.
+
+2017-03-04 belangeo <belangeo at gmail.com>
+
+    * Added a "title" argument to Server.gui() method.
+
+2017-03-03 belangeo <belangeo at gmail.com>
+
+    * MidiDispatcher can send sysex message with sendx() method.
+
+2017-03-03 belangeo <belangeo at gmail.com>
+
+    * Midi input refactoring. Events are now spreaded over the buffer size
+	  according to the event's timestamp.
+
+2017-02-19 belangeo <belangeo at gmail.com>
+
+    * Added examples about multicore audio programming with pyo.
+
+2017-02-14 belangeo <belangeo at gmail.com>
+
+    * Fixed segfault in MidiListener callback function with python3.
+    * Fixed string versus unicode in MidiDispatcher's getDeviceInfos method.
+
+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.
+
+2016-12-08 belangeo <belangeo at gmail.com>
+
+    * Iter now accepts PyoObjects in its list of values.
+
+2016-12-08 belangeo <belangeo at gmail.com>
+
+    * Iter now sends a thrigger when it reaches the last value.
+
+2016-11-25 belangeo <belangeo at gmail.com>
+
+    * SigTo ramp time now can be controlled at audio rate (issue #87).
+
+2016-11-23 belangeo <belangeo at gmail.com>
+
+    * Added __iter__(), __next__() and next() (python 2 compatibility) methods 
+      to PyoBaseObject.
+
+2016-11-22 belangeo <belangeo at gmail.com>
+
+    * Added reset method to various objects (AllpassWG, Chorus, Freeverb, 
+      Harmonizer, STRev, WGVerb, Waveguide).
+
+2016-11-16 belangeo <belangeo at gmail.com>
+
+    * TableWrite now takes into account the feedback argument of NewTable 
+      object and interpolates to fill in gaps if position moves faster than 
+      the sampling rate.
+
+2016-11-07 belangeo <belangeo at gmail.com>
+
+    * Added missing methods to Notein object and ctrl() method in midi.py. 
+
+2016-11-07 belangeo <belangeo at gmail.com>
+
+    * Added a `callback` argument to PyoObject.set() method. 
+
+2016-11-06 Aron Granberg <http://arongranberg.com>
+
+    * Python 3 migration. Still need to port pyo's GUI written with WxPython
+      to WxPython Phoenix (the port of WxPython Classic to python 3). Some
+      widgets are broken.  
+
+2016-11-02 belangeo <belangeo at gmail.com>
+
+    * Fixed jack ports auto-connection algorithm. 
+
+2016-10-28 belangeo <belangeo at gmail.com>
+
+    * Added an 'inverse' argument to PVGate object. When set to True, the 
+      damping factor is applied to bins with an amplitude above the threshold.
+
+2016-10-26 belangeo <belangeo at gmail.com>
+
+    * Added a time stream, which gives the current normalized position, to Looper object.
+    
+    * Added loopnow() method to Looper object.
+    
+    * Added appendFadeTime() and fadeInSeconds() methods to Looper object.
+
+2016-10-24 belangeo <belangeo at gmail.com>
+
+    * Added a new file, called `How to improve performance of your pyo
+      programs`, to the documentation.
+
+2016-10-21 belangeo <belangeo at gmail.com>
+
+    * Added Server.getCurrentTime() and Server.getCurrentAmp() methods.
+
+2016-10-04 belangeo <belangeo at gmail.com>
+
+    * Added new object: LogiMap, random generator based on the logistic map.
+
+    * Added Server.setCallback method to allow the user to define a custom
+      process function. This function will be called once per buffer size, 
+      just before the computation of the audio object tree. 
+      
+    * Added PyoTableObject.getBuffer() method. The PyoTableObject now support 
+      the buffer protocol (see PEP 3118), which allow a table to share its 
+      data memory with any object that support the buffer protocol 
+      (ex. numpy ndarray). 
+
+2016-09-29 belangeo <belangeo at gmail.com>
+
+    * Added sysexout() method to the Server object.
+
+2016-09-08 belangeo <belangeo at gmail.com>
+
+    * Added new examples, 05-envelopes and 06-filters.
+
+2016-08-09 belangeo <belangeo at gmail.com>
+
+    * Replaced all printf statements with PySys_WriteStdout. This allow to
+      redirect message from pyo to a string or a file, instead of the stdout.
+
+2016-06-01 belangeo <belangeo at gmail.com>
+
+    * Added WDMKS in the portaudio build routine.
+
+2016-05-13 belangeo <belangeo at gmail.com>
+
+    * Fixed wrong definition of withOsc() and withCoreaudio().
+    * Real final revision for version 0.8.0.
+    - SHA: 
+
+2016-05-12 belangeo <belangeo at gmail.com>
+
+    * Final revision for version 0.8.0.
+    - SHA: e833e404e20e9531b901ee8924b66f711f3c5e8f
+
+2016-05-10 belangeo <belangeo at gmail.com>
+
+    * Added new functions: withPortaudio, withPortmidi, withCoreaudio, withJack, withOSC.
+
+2016-05-10 belangeo <belangeo at gmail.com>
+
+    * Added a bela framework (BeagleBone Black) with instructions in the embedded folder.
+
+2016-05-10 belangeo <belangeo at gmail.com>
+
+    * Added a new compilation flag, --minimal, to build without portaudio, portmidi and liblo.
+
+2016-05-10 belangeo <belangeo at gmail.com>
+
+    * Added new examples on the online documentation.
+
+2016-05-06 belangeo <belangeo at gmail.com>
+
+    * Made portaudio, portmidi and liblo optional dependencies.
+
+2016-04-29 belangeo <belangeo at gmail.com>
+
+    * Added a quality factor everywhere a FLAC or OGG sound file can be saved on disk.
+
+2016-04-03 belangeo <belangeo at gmail.com>
+
+    * Disto uses now a simple but more efficient waveshaper formula. This algorithm 
+	  is faster and does not produce large amplitude variation like the atan2 function.
+
+2016-04-03 belangeo <belangeo at gmail.com>
+
+    * Added new object: Exp, calculates the value of e to the power of x.
+
+2016-04-02 belangeo <belangeo at gmail.com>
+
+    * Revision, clean-up and optimization of various filters in the library.
+    (Biquad, Biquadx, Port, Tone, Atone, Allpass, Allpass2, Phaser, BandSplit MoogLP).
+
+2016-03-31 belangeo <belangeo at gmail.com>
+
+    * Fixed bug when a LFO object receives a negative frequency.
+
+2016-03-28 belangeo <belangeo at gmail.com>
+
+    *  Added new object: FastSine, two fast sin approximations (faster than linear table lookup).
+
+2016-03-27 belangeo <belangeo at gmail.com>
+
+    *  Added new function : getPyoKeywords, returns the list of pyo keywords (classes and functions).
+
+2016-03-26 belangeo <belangeo at gmail.com>
+
+    *  Added an argument arg to the Pattern object.
+
+2016-03-25 belangeo <belangeo at gmail.com>
+
+    *  Fixed unwanted offset in type 7 (sinmod) of LFO object.
+
+2016-03-23 belangeo <belangeo at gmail.com>
+
+    *  Added setExp() method to Fader, Adsr, MidiAdsr and MidiDelAdsr, allowing
+
+2016-03-18 belangeo <belangeo at gmail.com>
+
+    *  Fixed Counter.reset() method.
+
+2016-03-18 belangeo <belangeo at gmail.com>
+
+    *  A CallAfter object can now be triggered many times.
+
+2016-03-18 belangeo <belangeo at gmail.com>
+
+    *  Added new object: MoogLP, 24dB/oct resonant lowpass filter.
+
+2016-03-16 belangeo <belangeo at gmail.com>
+
+    *  Added new object: ChenLee, another chaotic attractor based on the Chen-Lee system.
+
+2016-03-16 belangeo <belangeo at gmail.com>
+
+    *  Added new object: PadSynthTable, a beautiful algorithm from Nasca Octavian Paul.
+
+2016-03-13 belangeo <belangeo at gmail.com>
+
+    *  Added rotate and copyData methods to the PyoTableObject.
+
+2016-03-12 belangeo <belangeo at gmail.com>
+
+    *  Fixed TableWrite writing pointer in the table. Added a mode attribute
+    to select between normalized (0->1) or raw (samples) position.
+
+2016-03-01 belangeo <belangeo at gmail.com>
+
+    * Final revision for version 0.7.9.
+    - SHA: 7ddbeacd14cd78ce4930c845a82745bb58f4a26c
+
+2016-03-01 belangeo <belangeo at gmail.com>
+
+    *  Upgraded version number to 0.7.9.
+
+2016-03-01 belangeo <belangeo at gmail.com>
+
+    *  Pyo now uses its own PRNG to avoid conflicts with other libs or 
+    modules that use rand()/srand() in the same process. This fixed the 
+    Server's global seed behaviour.
+
+2016-02-29 belangeo <belangeo at gmail.com>
+
+    * Fixed a bug, introduced by unicode addresses handler, in Open Sound 
+    Control objects.
+
+2016-02-29 belangeo <belangeo at gmail.com>
+
+    * Exposed internal GUI widgets in the official API. New objects are
+    PyoGuiControlSlider, PyoGuiVuMeter, PyoGuiGrapher, PyoGuiMultiSlider,
+    PyoGuiSpectrum, PyoGuiScope and PyoGuiSndView.
+
+2016-02-17 belangeo <belangeo at gmail.com>
+
+    * E-Pyo: Added a warning before quitting the application.
+
+2016-02-12 belangeo <belangeo at gmail.com>
+
+    * Fixed a bug in Notein voice assignation.
+
+2016-02-12 belangeo <belangeo at gmail.com>
+
+    * Added readyToDetect() method to AttackDetector object.
+
+2016-01-29 belangeo <belangeo at gmail.com>
+
+    * Fixed segfault in Server dealloc function.
+
+2016-01-08 belangeo <belangeo at gmail.com>
+
+    * Final revision for version 0.7.8.
+    - SHA: e71cb0b5254da456bea129113da3d258a5b75dea
+
+2016-01-07 belangeo <belangeo at gmail.com>
+
+    * Added new object: Expr, sample-based prefix expression evaluator.
+
+2015-12-04 belangeo <belangeo at gmail.com>
+
+    * Added new object: Resample, allow multi-rate DSP chains.
+
+2015-12-04 belangeo <belangeo at gmail.com>
+
+    * Added Juce PyoPlugin framework in the embedded folder.
+
+2015-10-26 belangeo <belangeo at gmail.com>
+
+    * Fixed memory leak when using PyFloat_AS_DOUBLE(PyNumber_Float(x)) 
+      to fill table data.
+
+2015-10-25 belangeo <belangeo at gmail.com>
+
+    * Added a closeGui() method to the Server object. This allow to 
+      programatically close the Server window.
+
+2015-10-24 belangeo <belangeo at gmail.com>
+
+    * Added a method addMidiEvent to the Server object. This allow to 
+      programatically simulate MIDI events. Added the functionnaility 
+      to the embedded framework and modify the puredata pyo~ object help 
+      patch to illustrate how to generate MIDI events from the host program.
+
+2015-10-18 belangeo <belangeo at gmail.com>
+
+    *  Fixed triangle waveform amplitude in LFO object. Fixed calculation 
+       of Follower/Follower2 lowpass cutoff frequencies.
+
+2015-10-12 belangeo <belangeo at gmail.com>
+
+    * Final revision for version 0.7.7.
+    - SHA : 217b0cb40c8b82dad8c66718910fcd6e8f983034
+
+2015-10-11 belangeo <belangeo at gmail.com>
+
+    * Fixed clicks at the end of the Adsr envelope.
+
+2015-09-25 belangeo <belangeo at gmail.com>
+
+    * Added a trigger stream to Looper to signal the beginning of a new loop.
+
+2015-09-15 belangeo <belangeo at gmail.com>
+
+    * Automatically add the current working directory in sys.path when the
+      background server is started.
+
+2015-09-03 belangeo <belangeo at gmail.com>
+
+    * Added a pause() method to Linseg and Expseg objects (keep the internal phase).
+
+2015-09-03 belangeo <belangeo at gmail.com>
+
+    * All OSC objects now accept string or unicode types as address parameter.
+
+2015-09-03 belangeo <belangeo at gmail.com>
+
+    * Fixed crash (OSX) when the server GUI is closed with the red button.
+
+2015-09-02 belangeo <belangeo at gmail.com>
+
+    * Fixed crash on server shutdown.
+
+2015-08-25 belangeo <belangeo at gmail.com>
+
+    * Added new objects: MidiListener and OscListener (self-contained MIDI and OSC servers).
+
+-------------------------------------------------------------------------------------
+
+2015-07-27 belangeo <belangeo at gmail.com>
+
+    * Final revision for version 0.7.6.
+    - rev 1335
+
+2015-07-24 belangeo <belangeo at gmail.com>
+
+    * Release tag: 0.7.6.
+    - rev 1333
+
+2015-07-24 belangeo <belangeo at gmail.com>
+
+    * Added missing types to OscDataSend and OscDataReceive (char, blob, True, 
+    False, None and MIDI packet).
+    - rev 1332
+
+2015-07-21 belangeo <belangeo at gmail.com>
+
+    * Fixed Centroid output with silence as input.
+    - rev 1330
+
+2015-07-21 belangeo <belangeo at gmail.com>
+
+    * Added new objet: RawMidi, a raw Midi handler.
+    - rev 1329
+
+2015-07-21 belangeo <belangeo at gmail.com>
+
+    * Added pyoArgsAssert call in each object's methods.
+    - rev 1320, 1325, 1327, 1328
+
+2015-07-20 belangeo <belangeo at gmail.com>
+
+    * Fixed the "segmentation fault" that occur sometimes when deleting an object.
+    - rev 1326
+    
+2015-05-31 belangeo <belangeo at gmail.com>
+
+    * E-Pyo: Fixed project tree.
+    - rev 1315
+
+2015-05-29 belangeo <belangeo at gmail.com>
+
+    * E-Pyo: stderr now prints to the output panel.
+    - rev 1314
+ 
+2015-05-25 belangeo <belangeo at gmail.com>
+
+    * E-Pyo: Added code block selection (#--> and #<-- are delimiters). 
+    The background server now prints to the output panel.
+    - rev 1313
+
+2015-04-29 belangeo <belangeo at gmail.com>
+
+    * Fixed CPU usage of PeakAmp.
+    - rev 1312
+
+-------------------------------------------------------------------------------------
+2015-03-05 belangeo <belangeo at gmail.com>
+
+    * Fixed crash when portaudio stream is stopped on OSX (created when fixed
+	for Windows). Rev 1310 is the sources for 0.7.5 release.
+    - rev 1310
+
+2015-03-05 belangeo <belangeo at gmail.com>
+
+    * Release tag: 0.7.5.
+    - rev 1308
+
+2015-03-05 belangeo <belangeo at gmail.com>
+
+    * Added documentation for server methods setTimeCallable and setMeterCallable.
+    - rev 1304
+
+2015-03-05 belangeo <belangeo at gmail.com>
+
+    * Changed license to the more permissive LGPL version 3.
+    - rev 1303
+
+2015-03-03 belangeo <belangeo at gmail.com>
+
+    * The Server can be booted with a different number of input and output channels.
+    - rev 1301
+
+2015-03-03 belangeo <belangeo at gmail.com>
+
+    * Wraped input of Record in an InputFader object.
+    - rev 1300
+
+2015-03-03 belangeo <belangeo at gmail.com>
+
+    * Fixed bug in Hilbert object.
+    - rev 1299
+
+2015-02-18 belangeo <belangeo at gmail.com>
+
+    * Added mul, add and sub methods to PyoTableObject. These methods can 
+    take float, list or another PyoTableObject as argument.
+    - rev 1298
+
+2015-02-13 belangeo <belangeo at gmail.com>
+
+    * Added new objet: AtanTable, generates arctangent transfert functions.
+    - rev 1296
+
+2015-02-11 belangeo <belangeo at gmail.com>
+
+    * Fixed a bug when changing the looping mode of the Looper object.
+    - rev 1295
+
+2015-02-09 belangeo <belangeo at gmail.com>
+
+    * Added a reset method to the Looper objet.
+    - rev 1294
+
+2015-02-08 belangeo <belangeo at gmail.com>
+
+    * E-Pyo: Added a refresh button to actualize the content of the folder panel.
+    - rev 1292
+
+2015-02-07 belangeo <belangeo at gmail.com>
+
+    * E-Pyo: Added a menu item to set a master document (the one that will be executed whatever 
+    which one has the focus).
+    - rev 1291
+
+2015-02-03 belangeo <belangeo at gmail.com>
+
+    * Added getServer, getSamplingRate and getBufferSize to PyoObjectBase. These methods can be 
+    accessed from any pyo objects.
+    - rev 1290
+
+2015-02-03 belangeo <belangeo at gmail.com>
+
+    * Fixed a bug with class method referenced inside pyo object. Save them as weak reference, 
+    allowing the garbage collector to properly delete the objects when reference count falls to 0.
+    - rev 1289
+
+2015-02-02 belangeo <belangeo at gmail.com>
+
+    * Added new objet: TableWrite, records values in a table at arbitrary location.
+    - rev 1288
+
+-------------------------------------------------------------------------------------
+
+2015-01-29 belangeo <belangeo at gmail.com>
+
+    * Release tag: 0.7.4
+    - rev 1284
+
+2015-01-29 belangeo <belangeo at gmail.com>
+
+    * Added new function: floatmap, 0-1 range mapper. Fixed bug in DataTable initialization 
+    and added an automatic refresh of the DataTable grapher window.
+    - rev 1282
+
+2015-01-26 belangeo <belangeo at gmail.com>
+
+    * Added new objet: Particle, a full control granular synthesis generator.
+    - rev 1281
+
+2015-01-24 belangeo <belangeo at gmail.com>
+
+    * Added setSync method to Granule object. Allow to toggle between synchronous 
+    and asynchronous granulation. Added noteon and noteoff trigger streams to Notein 
+    object.
+
+    - rev 1280
+
+2014-12-15 belangeo <belangeo at gmail.com>
+
+    * Added reset method to CtlScan and CtlScan2 objects.
+    - rev 1279
+
+2014-12-03 belangeo <belangeo at gmail.com>
+
+    * Added new objet: PeakAmp, a peak amplitude follower.
+    - rev 1277
+
+2014-11-27 belangeo <belangeo at gmail.com>
+
+    * Added reset method to Beat and Euclide objects.
+    - rev 1275
+
+-------------------------------------------------------------------------------------
+
+2014-10-17 belangeo <belangeo at gmail.com>
+
+    * Release tag: 0.7.3.
+    - rev 1273
+
+2014-11-15 belangeo <belangeo at gmail.com>
+
+    * Added new objet: Scope, an audio waveform display.
+    - rev 1270
+
+2014-11-12 belangeo <belangeo at gmail.com>
+
+    * E-Pyo: Fix marker's line numbering.
+    - rev 1267
+
+2014-11-08 belangeo <belangeo at gmail.com>
+
+    * E-Pyo: Added Save As Template... menu item.
+    - rev 1263
+
+2014-11-02 belangeo <belangeo at gmail.com>
+
+    * Fixed bug in Fader decreasing ramp.
+    - rev 1262
+
+2014-10-28 belangeo <belangeo at gmail.com>
+
+    * Added midi output methods to the Server object. noteout, afterout, ctlout, programout, pressout and bendout.
+    - rev 1261
+
+2014-10-28 belangeo <belangeo at gmail.com>
+
+    * Server.setMidiOutputDevice(idx) with `idx` greater than the higher portmidi devices index opens all available output devices.
+    - rev 1260
+
+2014-10-24 belangeo <belangeo at gmail.com>
+
+    * Added new object: FToM, converts an audio stream containning frequencies in hertz to a midi note audio stream.
+    - rev 1259
+
+2014-10-23 belangeo <belangeo at gmail.com>
+
+    * Added new function: hzToMidi, converts a frequency in hertz to a midi note value.
+    - rev 1258
+
+-------------------------------------------------------------------------------------
+
+2014-10-17 belangeo <belangeo at gmail.com>
+
+    * Release tag: 0.7.2.
+    - rev 1256
+
+2014-10-16 belangeo <belangeo at gmail.com>
+
+    * Server.setMidiInputDevice(idx) with `idx` greater than the higher portmidi input index opens all available devices.
+    - rev 1254
+
+2014-10-16 belangeo <belangeo at gmail.com>
+
+    * OSX installer: Also install pyo in anaconda site-packages directory if exist.
+    - rev 1253
+
+2014-10-16 belangeo <belangeo at gmail.com>
+
+    * Added new object : TrigBurst, generates a time/amplitude expandable trigger pattern.
+    - rev 1252
+
+2014-10-14 belangeo <belangeo at gmail.com>
+
+    * Added new object : Euclide, Euclidean rhythm generator.
+    - rev 1251
+
+2014-10-13 belangeo <belangeo at gmail.com>
+
+    * Windows installers now check for the current python installation directory before installing files.
+    - rev 1244 - 1250
+
+2014-10-10 belangeo <belangeo at gmail.com>
+
+    * E-Pyo: Fixed inconsistencies in Find/Replace behaviours.
+    - rev 1241
+
+2014-10-10 belangeo <belangeo at gmail.com>
+
+    * Added new object : SmoothDelay, a delay line that does not produce clicks or pitch shifting when the delay time is changing.
+    - rev 1239
+
+2014-10-08 belangeo <belangeo at gmail.com>
+
+    * Added new object : AttackDetector, audio signal onset detection.
+    - rev 1238
+
+2014-10-07 belangeo <belangeo at gmail.com>
+
+    * Added new object : Centroid, Computes the spectral centroid of an input signal.
+    - rev 1237
+
+-------------------------------------------------------------------------------------
+
+2014-08-29 belangeo <belangeo at gmail.com>
+
+    * Release tag: 0.7.1.
+    - rev 1236
+
+2014-09-12 belangeo <belangeo at gmail.com>
+
+    * E-Pyo: Added RadioPyo to the template choices.  
+    - rev 1234
+
+2014-09-09 belangeo <belangeo at gmail.com>
+
+    * Fixed Compare when used with None or a string. Print a warning and set 'comp' attribute to 0. 
+    - rev 1229
+
+2014-09-05 belangeo <belangeo at gmail.com>
+
+    * Fixed live interpreter of the server window when using arrow keys navigation.
+    - rev 1228
+
+2014-09-04 belangeo <belangeo at gmail.com>
+
+    * E-Pyo: Check if WxPython 3.0 is installed, otherwise uses 2.8.
+    - rev 1227
+
+2014-09-02 belangeo <belangeo at gmail.com>
+
+    * Added anti-aliasing to PyoTableObject's grapher widget. Fixed Ctrl+W on the grapher.
+    - rev 1225, 1226
+
+-------------------------------------------------------------------------------------
+
+2014-08-29 belangeo <belangeo at gmail.com>
+
+    * Release tag: 0.7.0.
+    - rev 1224
+
+2014-08-26 belangeo <belangeo at gmail.com>
+
+    * pyo can now be used without any GUI toolkit (WxPython or TKinter). Widgets are simply disabled.
+    - rev 1208
+
+2014-06-22 belangeo <belangeo at gmail.com>
+
+    * Added Server methods to auto-connect Jack ports to already opened ports.
+    - rev 1201
+
+2014-05-23 belangeo <belangeo at gmail.com>
+
+    * E-Pyo: output log now in realtime.
+    - rev 1197
+
+2014-04-24 belangeo <belangeo at gmail.com>
+
+    * Added new object: Tanh, hyperbolic tangent function on audio signal.
+    - rev 1188
+
+-------------------------------------------------------------------------------------
+
+2014-04-11 belangeo <belangeo at gmail.com>
+
+    * Release tag: 0.6.9.
+    - rev 1185
+
+2014-04-11 belangeo <belangeo at gmail.com>
+
+    * Added lot of methods to PyoTableObject (retify, bipolarGain, invert, lowpass, fadein, fadeout, pow).
+    - rev 1182
+
+2014-04-04 belangeo <belangeo at gmail.com>
+
+    * Added new object: PartialTable, generates waveforms made of inharmonic components.
+    - rev 1177
+
+2014-03-12 belangeo <belangeo at gmail.com>
+
+    * Added a Scope example in examples/utilities.
+    - rev 1168
+
+2013-12-24 belangeo <belangeo at gmail.com>
+
+    * Added new object: STRev, Stereo reverb.
+    - rev 1154
+
+2013-12-24 belangeo <belangeo at gmail.com>
+
+    * Added dataOnly argument to SLMap. User can now control parameters, in ctrl window, that do not accept audio signal but discreet values.
+    - rev 1153
+
+2013-12-10 belangeo <belangeo at gmail.com>
+
+    * Added new object: ComplexRes, Complex one-pole resonator filter.
+    - rev 1148
+
+2013-10-18 belangeo <belangeo at gmail.com>
+
+    * Added new object: TrackHold, Performs a 'thru' and hold on its input signal.
+    - rev 1143
+
 -------------------------------------------------------------------------------------
 
 2013-10-16 belangeo <belangeo at gmail.com>
@@ -584,7 +1579,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/README.md b/README.md
new file mode 100644
index 0000000..0df0be4
--- /dev/null
+++ b/README.md
@@ -0,0 +1,107 @@
+# Pyo - Python DSP module #
+
+pyo is a Python module written in C to help digital signal processing script 
+creation.
+
+pyo is a Python module containing classes for a wide variety of audio signal 
+processing types. With pyo, user will be able to include signal processing 
+chains directly in Python scripts or projects, and to manipulate them in real 
+time through the interpreter. Tools in pyo module offer primitives, like 
+mathematical operations on audio signal, basic signal processing (filters, 
+delays, synthesis generators, etc.), but also complex algorithms to create 
+sound granulation and others creative audio manipulations. pyo supports OSC 
+protocol (Open Sound Control), to ease communications between softwares, and 
+MIDI protocol, for generating sound events and controlling process parameters. 
+pyo allows creation of sophisticated signal processing chains with all the 
+benefits of a mature, and widely used, general programming language.
+
+Systems : macOS (10.6 -> 10.12), linux, Windows (XP, Vista, 7, 8, 10)
+
+Python versions : 2.7.x (stable), 3.x.x (still experimental but fully functional)
+
+[PYO OFFICAL WEB SITE](http://ajaxsoundstudio.com/pyo/)
+
+**Download latest binaries, source release and documentation** 
+[HERE](http://ajaxsoundstudio.com/pyo/)!
+
+
+How to get pyo running from sources on OS X and linux:
+[INSTALL Instructions](http://ajaxsoundstudio.com/pyodoc/compiling.html)
+
+pyo was awarded **second prize** in the 
+[Lomus 2012](http://concours.afim-asso.org/2012/) Free Software Competition.
+
+## Radio Pyo ##
+
+If you want to listen to scripts rendered in real-time, just connect to 
+[Radio Pyo](http://radiopyo.acaia.ca/) !
+
+You want to have your script played on the radio ? Follow the instructions on this
+[post](http://acaia.ca/~tiago/posts/introducing-radio-pyo-live-music-in-python/) !
+
+## Softwares using pyo as audio engine ##
+
+[Zyne](https://github.com/belangeo/zyne) : A modular soft synthesizer.
+
+[Soundgrain](http://ajaxsoundstudio.com/software/soundgrain/) : 
+A graphical interface where users can draw and edit trajectories to control 
+granular sound synthesis.
+
+[Cecilia 5](http://ajaxsoundstudio.com/software/cecilia/) : An audio signal 
+processing environment.
+
+[PsychoPy](http://www.psychopy.org/) : An open-source application to allow the 
+presentation of stimuli and collection of data for a wide range of neuroscience, 
+psychology and psychophysics experiments.
+
+[Pyo Synth](https://github.com/alexandrepoirier/PyoSynth) : Pyo Synth is an open
+source application that makes the manipulation of pyo scripts easier by letting
+you control it with a midi keyboard. 
+
+## Examples ##
+
+pyo is fully integrated to Python and very simple to use.
+
+Play a sound:
+
+```
+>>> from pyo import *
+>>> s = Server().boot()
+>>> s.start()
+>>> sf = SfPlayer("path/to/your/sound.aif", speed=1, loop=True).out()
+```
+
+Granulate an audio buffer:
+
+```
+>>> s = Server().boot()
+>>> s.start()
+>>> snd = SndTable("path/to/your/sound.aif")
+>>> env = HannTable()
+>>> pos = Phasor(freq=snd.getRate()*.25, mul=snd.getSize())
+>>> dur = Noise(mul=.001, add=.1)
+>>> g = Granulator(snd, env, [1, 1.001], pos, dur, 24, mul=.1).out()
+```
+
+Generate melodies:
+
+```
+>>> s = Server().boot()
+>>> s.start()
+>>> wav = SquareTable()
+>>> env = CosTable([(0,0), (100,1), (500,.3), (8191,0)])
+>>> met = Metro(.125, 12).play()
+>>> amp = TrigEnv(met, table=env, mul=.1)
+>>> pit = TrigXnoiseMidi(met, dist='loopseg', x1=20, scale=1, mrange=(48,84))
+>>> out = Osc(table=wav, freq=pit, mul=amp).out()
+```
+
+## Donation ##
+
+This project is developed by Olivier Bélanger on his free time to provide a 
+fully integrated Python dsp module for sound exploration and music composition. 
+If you feel this project is useful to you and want to support it and it's 
+future development please consider donating money. I only ask for a small 
+donation, but of course I appreciate any amount.
+
+[![](https://www.paypal.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9CA99DH6ES3HA)
diff --git a/TODO.md b/TODO.md
new file mode 100644
index 0000000..4abe454
--- /dev/null
+++ b/TODO.md
@@ -0,0 +1,86 @@
+This is a list of features/fixes to implement for future releases
+=================================================================
+
+Internal
+--------
+
+- Replace malloc/realloc with a custom memory pool allocator.
+
+- Use inheritance (instead of a bunch of macros) at the C level. 
+  PyoObject_base or Stream) should handle `mul`, `add` and 
+  stream-related functions for every PyoObject. It should make the 
+  code much simple and easier to maintain/extend, and also reduce 
+  compiling time and binary size.
+
+
+Server
+------
+
+- A method to retrieve a graph of the internal state of the server 
+  (active objects, connections, attribute values, ...).
+
+- Remove, if possible, PyGILState_Ensure/PyGILState_Release from 
+  the process_buffers function.
+
+Examples
+--------
+
+- A section about building fx and synth classes.
+
+
+Objects
+-------
+
+- TrigMap(inputs, values, init=0, mul=1, add=0)
+
+  Where `inputs` are a list of trigger objects and `values` (list of floats) 
+  the corresponding values to output depending which trigger has been detected.
+  A trigger from the second object will make the object output the second value
+  from the list.
+
+MIDI
+----
+
+- Jack on windows.
+
+- Create a MidiLinseg object that act like MidiAdsr but with a breakpoints
+  function as the envelope. The sustain point should be settable by the user.
+
+- sysex support in MidiListener.
+
+
+GUI
+---
+
+- Implement all GUI components with Tkinter and make it the default GUI
+  toolkit (instead of wxpython). WxPython classes could be removed from
+  pyo sources and built as an optional extra package (pyo-wxgui). The idea
+  is to remove an extra dependency, as tk is generally builtin with python.
+
+- MixerGUI, an interface to control the routing of a Mixer object.
+
+- Keyboard, a virtual MIDI keyboard (adapted from Zyne's one).
+
+- Ability to set channel "name" in the view of PyoGuiScope and PyoGuiSpectrum.
+
+Tables
+------
+
+- Objects that can write to tables should accept any PyoTableObject,
+  not just a NewTable or a DataTable.
+
+Matrices
+--------
+
+- Implement the buffer protocol as in the PyoTableObject.
+
+E-Pyo
+-----
+
+- Complete review of E-Pyo on Windows. Lot of features don't seem to work.
+
+- Window splitter to show more than one file at the time (multiple 
+  views) ?
+
+- We need A way to let the user interact with the script via input() 
+  and raw_input() functions.
diff --git a/doc-sphinx/build.py b/doc-sphinx/build.py
index fdcb309..30fa130 100644
--- a/doc-sphinx/build.py
+++ b/doc-sphinx/build.py
@@ -1,5 +1,4 @@
 import os, sys
-from types import ListType
 from pyo import *
 
 build_format = "html"
@@ -7,6 +6,9 @@ build_folder = "./build_html"
 if "--latex" in sys.argv:
     build_format = "latex"
     build_folder = "./build_latex"
+elif "--man" in sys.argv:
+    build_format = "man"
+    build_folder = "./build_man"
 
 f = open(os.getcwd() + '/source/api/alphabetical.rst', 'w')
 
@@ -36,15 +38,19 @@ def getDocFirstLine(obj):
 format = "- :py:class:`%s` : %s\n"
 
 lines = []
-for key in ['Server', 'Stream', 'TableStream', 'PyoObjectBase', 'Map']:
-    if type(OBJECTS_TREE[key]) == ListType:
-        for obj in OBJECTS_TREE[key]:
-            lines.append(format % (obj, getDocFirstLine(obj)))
+for key in ['Server', 'Stream', 'TableStream', 'PyoObjectBase', 'Map', 
+            'MidiListener', 'OscListener', 'PyoGui']:
+    if type(OBJECTS_TREE[key]) == list:
+        if key in ['MidiListener', 'OscListener']:
+            lines.append(format % (key, getDocFirstLine(key)))
+        else:
+            for obj in OBJECTS_TREE[key]:
+                lines.append(format % (obj, getDocFirstLine(obj)))
     else:
         if key == 'Map': key2list = ['SLMap']
         else: key2list = ['PyoMatrixObject', 'PyoTableObject', 'PyoObject', 'PyoPVObject']
         for key2 in key2list:
-            if type(OBJECTS_TREE[key][key2]) == ListType:
+            if type(OBJECTS_TREE[key][key2]) == list:
                 for obj in OBJECTS_TREE[key][key2]:
                     lines.append(format % (obj, getDocFirstLine(obj)))
             else:
@@ -58,14 +64,48 @@ for line in lines:
 
 f.close()
 
-os.system("sphinx-build -a -b %s ./source %s" % (build_format, build_folder))
+# New examples listing
+os.mkdir("source/examples")
+folders = sorted([d for d in os.listdir("../examples") if d[0] in ['0', '1']])
+for dir in folders:
+    os.mkdir("source/examples/%s" % dir)
+    index = open("source/examples/%s/index.rst" % dir, "w")
+    index.write(dir + "\n")
+    index.write("="*40)
+    index.write("\n\n.. toctree::\n   :maxdepth: 1\n\n")
+    for name in sorted(os.listdir("../examples/%s" % dir)):
+        index.write("   " + name[:-3] + "\n")
+        with open("../examples/%s/%s" % (dir, name), "r") as f:
+            text = f.read()
+        with open("source/examples/%s/%s.rst" % (dir, name[:-3]), "w") as f:
+            pos = text.find('"""')
+            pos = text.find('"""', pos+3)
+            code = text[pos+3:].strip()
+            intro = text[:pos+3].replace('"""', '').strip()
+            tpos = intro.find("\n")
+            title = intro[:tpos]
+            f.write(title + "\n")
+            f.write("="*140)
+            f.write("\n")
+            f.write(intro[tpos:])
+            f.write("\n\n")
+            f.write(".. code-block:: python\n\n")
+            for line in code.splitlines():
+                f.write("    " + line + "\n")
+            f.write("\n")
+    index.close()
+
+os.system("cp ../utils/E-PyoIcon.png source/")
+
+os.system("sphinx-build -a -E -j 4 -b %s ./source %s" % (build_format, build_folder))
 
 if build_format == "latex":
     os.system("cd build_latex; pdflatex -interaction nonstopmode Pyo;  pdflatex -interaction nonstopmode Pyo")
-else:
-    # Upload on iACT server
-    print "Upload documentation (y/n)?"
-    ans = raw_input()
-    if (ans == 'y'):
-        os.system('scp -r %s/* sysop at 132.204.178.49:/Library/WebServer/Documents/pyo/manual-dev/' % build_folder)
 
+rep = raw_input("Do you want to upload to ajax server (y/n) ? ")
+if rep == "y":
+        os.system("scp -r build_html/* jeadum1 at ajaxsoundstudio.com:/home/jeadum1/ajaxsoundstudio.com/pyodoc")
+
+os.system("rm -r source/examples")
+
+os.system("rm  source/E-PyoIcon.png")
diff --git a/doc-sphinx/source/_static/nature.css b/doc-sphinx/source/_static/nature.css
index 5d73f48..7fc7c54 100644
--- a/doc-sphinx/source/_static/nature.css
+++ b/doc-sphinx/source/_static/nature.css
@@ -132,12 +132,12 @@ div.sphinxsidebar input[type=text]{
 /* -- body styles ----------------------------------------------------------- */
  
 a {
-    color: #005B81;
+    color: #333388;
     text-decoration: none;
 }
  
 a:hover {
-    color: #E32EFF;
+    color: #111166;
     text-decoration: underline;
 }
  
diff --git a/doc-sphinx/source/_static/structure.png b/doc-sphinx/source/_static/structure.png
new file mode 100644
index 0000000..7f44901
Binary files /dev/null and b/doc-sphinx/source/_static/structure.png differ
diff --git a/doc-sphinx/source/about.rst b/doc-sphinx/source/about.rst
index 4add116..e90824b 100644
--- a/doc-sphinx/source/about.rst
+++ b/doc-sphinx/source/about.rst
@@ -1,15 +1,31 @@
-About Pyo
+About pyo
 =================
 
-Pyo is a Python module written in C to help digital signal processing script creation.
+Pyo is a Python module written in C to help digital signal processing script 
+creation. It provides a complete set of classes to build audio softwares, 
+compose algorithmic musics or simply explore audio processing with a simple, 
+mature and powerful programming language.
 
-Pyo is a Python module containing classes for a wide variety of audio signal processing types. With pyo, user will be able to include signal processing chains directly in Python scripts or projects, and to manipulate them in real time through the interpreter. Tools in pyo module offer primitives, like mathematical operations on audio signal, basic signal processing (filters, delays, synthesis generators, etc.), but also complex algorithms to create sound granulation and others creative sound manipulations. Pyo supports OSC protocol (Open Sound Control), to ease communications between softwares, and MIDI protocol, for generating sound events and controlling process parameters. Pyo allows creation of sophisticated signal processing chains with all the benefits of a mature, and wild used, general programming language. 
+Pyo contains 
+classes for a wide variety of audio signal processing. With pyo, the user will 
+be able to include signal processing chains directly in Python scripts or 
+projects, and to manipulate them in real time through the interpreter. Tools 
+in the pyo module offer primitives, like mathematical operations on audio 
+signals, basic signal processing (filters, delays, synthesis generators, etc.), 
+but also complex algorithms to create sound granulation and other creative 
+audio manipulations. pyo supports the OSC protocol (Open Sound Control) to ease 
+communications between softwares, and the MIDI protocol for generating sound 
+events and controlling process parameters. pyo allows the creation of 
+sophisticated signal processing chains with all the benefits of a mature and 
+widely used general programming language. 
 
 Pyo is developed by Olivier Bélanger < belangeo at gmail.com >
 
-For questions and comments, please subscribe to the `pyo-discuss <http://groups.google.com/group/pyo-discuss>`_ mailing list.
+For questions and comments, please subscribe to the 
+`pyo-discuss <http://groups.google.com/group/pyo-discuss>`_ mailing list.
 
-To report a bug or to request a feature, use the `issues tracker <http://code.google.com/p/pyo/issues/list>`_ on googlecode.
+To report a bug or to request a feature, use the 
+`issues tracker <https://github.com/belangeo/pyo/issues>`_ on github.
 
 Sources and binaries can be downloaded at:
-http://code.google.com/p/pyo/
+http://ajaxsoundstudio.com/software/pyo/
diff --git a/doc-sphinx/source/api/alphabetical.rst b/doc-sphinx/source/api/alphabetical.rst
index 3b2862b..3863799 100644
--- a/doc-sphinx/source/api/alphabetical.rst
+++ b/doc-sphinx/source/api/alphabetical.rst
@@ -7,20 +7,22 @@ Alphabetical class reference
 - :py:class:`AToDB` :     Returns the decibel equivalent of an amplitude value.
 - :py:class:`Abs` :     Performs an absolute function on audio signal.
 - :py:class:`Adsr` :     Attack - Decay - Sustain - Release envelope generator.
-- :py:class:`Allpass2` :     Second-order phase shifter allpass. 
+- :py:class:`Allpass2` :     Second-order phase shifter allpass.
 - :py:class:`AllpassWG` :     Out of tune waveguide model with a recursive allpass network.
 - :py:class:`Allpass` :     Delay line based allpass filter.
 - :py:class:`Atan2` :     Computes the principal value of the arc tangent of b/a.
+- :py:class:`AtanTable` :     Generates an arctangent transfert function.
 - :py:class:`Atone` :     A first-order recursive high-pass filter with variable frequency response.
+- :py:class:`AttackDetector` :     Audio signal onset detection.
 - :py:class:`Average` :     Moving average filter.
 - :py:class:`Balance` :     Adjust rms power of an audio signal according to the rms power of another.
 - :py:class:`BandSplit` :     Splits an input signal into multiple frequency bands.
 - :py:class:`Beat` :     Generates algorithmic trigger patterns.
 - :py:class:`Bendin` :     Get the current value of the pitch bend controller.
 - :py:class:`Between` :     Informs when an input signal is contained in a specified range.
-- :py:class:`Biquad` :     A sweepable general purpose biquadratic digital filter. 
+- :py:class:`Biquad` :     A sweepable general purpose biquadratic digital filter.
 - :py:class:`Biquada` :     A general purpose biquadratic digital filter (floating-point arguments).
-- :py:class:`Biquadx` :     A multi-stages sweepable general purpose biquadratic digital filter. 
+- :py:class:`Biquadx` :     A multi-stages sweepable general purpose biquadratic digital filter.
 - :py:class:`Blit` :     Band limited impulse train synthesis.
 - :py:class:`BrownNoise` :     A brown noise generator.
 - :py:class:`ButBP` :     A second-order Butterworth bandpass filter.
@@ -30,15 +32,18 @@ Alphabetical class reference
 - :py:class:`CallAfter` :     Calls a Python function after a given time.
 - :py:class:`CarToPol` :     Performs the cartesian to polar conversion.
 - :py:class:`Ceil` :     Rounds to smallest integral value greater than or equal to the input signal.
+- :py:class:`Centroid` :     Computes the spectral centroid of an input signal.
 - :py:class:`CentsToTranspo` :     Returns the transposition factor equivalent of a given cents value.
 - :py:class:`Change` :     Sends trigger that informs when input value has changed.
 - :py:class:`ChebyTable` :     Chebyshev polynomials of the first kind.
+- :py:class:`ChenLee` :     Chaotic attractor for the Chen-Lee system.
 - :py:class:`Choice` :     Periodically choose a new value from a user list.
 - :py:class:`Chorus` :     8 modulated delay lines chorus processor.
 - :py:class:`Clean_objects` :     Stops and deletes PyoObjects after a given time.
 - :py:class:`Clip` :     Clips a signal to a predefined limit.
 - :py:class:`Cloud` :     Generates random triggers.
 - :py:class:`Compare` :     Comparison object.
+- :py:class:`ComplexRes` :     Complex one-pole resonator filter.
 - :py:class:`Compress` :     Reduces the dynamic range of an audio signal.
 - :py:class:`ControlRead` :     Reads control values previously stored in text files.
 - :py:class:`ControlRec` :     Records control values and writes them in a text file.
@@ -60,14 +65,20 @@ Alphabetical class reference
 - :py:class:`Delay1` :     Delays a signal by one sample.
 - :py:class:`Delay` :     Sweepable recursive delay.
 - :py:class:`Denorm` :     Mixes low level noise to an input signal.
-- :py:class:`Disto` :     Arc tangent distortion.
+- :py:class:`Disto` :     Kind of Arc tangent distortion.
 - :py:class:`Dummy` :     Dummy object used to perform arithmetics on PyoObject.
-- :py:class:`EQ` :     Equalizer filter. 
+- :py:class:`EQ` :     Equalizer filter.
+- :py:class:`Euclide` :     Euclidean rhythm generator.
 - :py:class:`ExpTable` :     Construct a table from exponential interpolated segments.
-- :py:class:`Expseg` :     Trace a series of exponential segments between specified break-points. 
+- :py:class:`Exp` :     Calculates the value of e to the power of x.
+- :py:class:`Expr` :     Prefix audio expression evaluator.
+- :py:class:`Expr` :     Prefix audio expression evaluator.
+- :py:class:`Expseg` :     Draw a series of exponential segments between specified break-points.
 - :py:class:`FFT` :     Fast Fourier Transform.
 - :py:class:`FM` :     A simple frequency modulation generator.
+- :py:class:`FToM` :     Returns the midi note equivalent to a frequency in Hz.
 - :py:class:`Fader` :     Fadein - fadeout envelope generator.
+- :py:class:`FastSine` :     A fast sine wave approximation using the formula of a parabola.
 - :py:class:`Floor` :     Rounds to largest integral value not greater than audio signal.
 - :py:class:`Follower2` :     Envelope follower with different attack and release times.
 - :py:class:`Follower` :     Envelope follower.
@@ -79,7 +90,7 @@ Alphabetical class reference
 - :py:class:`Gate` :     Allows a signal to pass only when its amplitude is above a set threshold.
 - :py:class:`Granulator` :     Granular synthesis generator.
 - :py:class:`Granule` :     Another granular synthesis generator.
-- :py:class:`HannTable` :     Generates Hanning window function. 
+- :py:class:`HannTable` :     Generates Hanning window function.
 - :py:class:`HarmTable` :     Harmonic waveform generator.
 - :py:class:`Harmonizer` :     Generates harmonizing voices in synchrony with its audio input.
 - :py:class:`Hilbert` :     Hilbert transform.
@@ -94,11 +105,12 @@ Alphabetical class reference
 - :py:class:`Iter` :     Triggers iterate over a list of values.
 - :py:class:`LFO` :     Band-limited Low Frequency Oscillator with different wave shapes.
 - :py:class:`LinTable` :     Construct a table from segments of straight lines in breakpoint fashion.
-- :py:class:`Linseg` :     Trace a series of line segments between specified break-points. 
+- :py:class:`Linseg` :     Draw a series of line segments between specified break-points.
 - :py:class:`Log10` :     Performs a base 10 log function on audio signal.
 - :py:class:`Log2` :     Performs a base 2 log function on audio signal.
 - :py:class:`LogTable` :     Construct a table from logarithmic segments in breakpoint fashion.
 - :py:class:`Log` :     Performs a natural log function on audio signal.
+- :py:class:`LogiMap` :     Random generator based on the logistic map.
 - :py:class:`Lookup` :     Uses table to do waveshaping on an audio signal.
 - :py:class:`Looper` :     Crossfading looper.
 - :py:class:`Lorenz` :     Chaotic attractor for the Lorenz system.
@@ -112,13 +124,15 @@ Alphabetical class reference
 - :py:class:`Metro` :     Generates isochronous trigger signals.
 - :py:class:`MidiAdsr` :     Midi triggered ADSR envelope generator.
 - :py:class:`MidiDelAdsr` :     Midi triggered ADSR envelope generator with pre-delay.
+- :py:class:`MidiListener` :     Self-contained midi listener thread.
 - :py:class:`Midictl` :     Get the current value of a Midi controller.
 - :py:class:`Min` :     Outputs the minimum of two values.
 - :py:class:`Mirror` :     Reflects the signal that exceeds the `min` and `max` thresholds.
 - :py:class:`Mix` :     Mix audio streams to arbitrary number of streams.
 - :py:class:`Mixer` :     Audio mixer.
+- :py:class:`MoogLP` :     A fourth-order resonant lowpass filter.
 - :py:class:`NewMatrix` :     Create a new matrix ready for recording.
-- :py:class:`NewTable` :     Create an empty table ready for recording. 
+- :py:class:`NewTable` :     Create an empty table ready for recording.
 - :py:class:`NextTrig` :     A trigger in the second stream opens a gate only for the next one in the first stream.
 - :py:class:`Noise` :     A white noise generator.
 - :py:class:`NoteinRead` :     Reads Notein values previously stored in text files.
@@ -128,6 +142,7 @@ Alphabetical class reference
 - :py:class:`OscDataReceive` :     Receives data values over a network via the Open Sound Control protocol.
 - :py:class:`OscDataSend` :     Sends data values over a network via the Open Sound Control protocol.
 - :py:class:`OscListReceive` :     Receives list of values over a network via the Open Sound Control protocol.
+- :py:class:`OscListener` :     Self-contained OSC listener thread.
 - :py:class:`OscLoop` :     A simple oscillator with feedback reading a waveform table.
 - :py:class:`OscReceive` :     Receives values over a network via the Open Sound Control protocol.
 - :py:class:`OscSend` :     Sends values over a network via the Open Sound Control protocol.
@@ -151,13 +166,19 @@ Alphabetical class reference
 - :py:class:`PVSynth` :     Phase Vocoder synthesis object.
 - :py:class:`PVTranspose` :     Transpose the frequency components of a pv stream.
 - :py:class:`PVVerb` :     Spectral domain reverberation.
+- :py:class:`PadSynthTable` :     Generates wavetable with the PadSynth algorithm from Nasca Octavian Paul.
 - :py:class:`Pan` :     Cosinus panner with control on the spread factor.
-- :py:class:`ParaTable` :     Generates parabola window function. 
+- :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.
 - :py:class:`Percent` :     Lets pass a certain percentage of the input triggers.
-- :py:class:`Phaser` :     Multi-stages second-order phase shifter allpass filters. 
+- :py:class:`Phaser` :     Multi-stages second-order phase shifter allpass filters.
 - :py:class:`Phasor` :     A simple phase incrementor.
 - :py:class:`PinkNoise` :     A pink noise generator.
+- :py:class:`Pointer2` :     High quality table reader with control on the pointer position.
 - :py:class:`Pointer` :     Table reader with control on the pointer position.
 - :py:class:`PolToCar` :     Performs the polar to cartesian conversion.
 - :py:class:`Port` :     Exponential portamento.
@@ -165,14 +186,23 @@ Alphabetical class reference
 - :py:class:`Print` :     Print PyoObject's current value.
 - :py:class:`Programin` :     Get the current value of a program change Midi controller.
 - :py:class:`Pulsar` :     Pulsar synthesis oscillator.
+- :py:class:`PyoGuiControlSlider` :         Floating-point control slider.
+- :py:class:`PyoGuiGrapher` :         Multi-modes break-points function editor.
+- :py:class:`PyoGuiMultiSlider` :         Data multi-sliders editor.
+- :py:class:`PyoGuiScope` :         Oscilloscope display.
+- :py:class:`PyoGuiSndView` :         Soundfile display.
+- :py:class:`PyoGuiSpectrum` :         Frequency spectrum display.
+- :py:class:`PyoGuiVuMeter` :         Multi-channels Vu Meter.
 - :py:class:`RCOsc` :     Waveform aproximation of a RC circuit.
 - :py:class:`RandDur` :     Recursive time varying pseudo-random generator.
 - :py:class:`RandInt` :     Periodic pseudo-random integer generator.
 - :py:class:`Randh` :     Periodic pseudo-random generator.
 - :py:class:`Randi` :     Periodic pseudo-random generator with interpolation.
+- :py:class:`RawMidi` :     Raw Midi handler.
 - :py:class:`Record` :     Writes input sound in an audio file on the disk.
-- :py:class:`Reson` :     A second-order resonant bandpass filter. 
-- :py:class:`Resonx` :     A multi-stages second-order resonant bandpass filter. 
+- :py:class:`Resample` :     Realtime upsampling or downsampling of an audio signal.
+- :py:class:`Reson` :     A second-order resonant bandpass filter.
+- :py:class:`Resonx` :     A multi-stages second-order resonant bandpass filter.
 - :py:class:`Rossler` :     Chaotic attractor for the Rossler system.
 - :py:class:`Round` :     Rounds to the nearest integer value in a floating-point format.
 - :py:class:`SDelay` :     Simple delay without interpolation.
@@ -183,10 +213,12 @@ Alphabetical class reference
 - :py:class:`SLMapPhase` :     SLMap with normalized values for a 'phase' slider.
 - :py:class:`SLMapQ` :     SLMap with normalized values for a 'q' slider.
 - :py:class:`SPan` :     Simple equal power panner.
-- :py:class:`SVF` :     Fourth-order state variable filter allowing continuous change of the filter type. 
-- :py:class:`SampHold` :     Performs a sample-and-hold operation on its input. 
+- :py:class:`STRev` :     Stereo reverb.
+- :py:class:`SVF` :     Fourth-order state variable filter allowing continuous change of the filter type.
+- :py:class:`SampHold` :     Performs a sample-and-hold operation on its input.
 - :py:class:`SawTable` :     Sawtooth waveform generator.
 - :py:class:`Scale` :     Maps an input range of audio values to an output range.
+- :py:class:`Scope` :     Oscilloscope - audio waveform display.
 - :py:class:`Score` :     Calls functions by incrementation of a preformatted name.
 - :py:class:`Select` :     Sends trigger on matching integer values.
 - :py:class:`Selector` :     Audio selector.
@@ -194,12 +226,14 @@ 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.
-- :py:class:`SincTable` :     Generates sinc window function. 
+- :py:class:`SincTable` :     Generates sinc window function.
 - :py:class:`SineLoop` :     A simple sine wave oscillator with feedback.
 - :py:class:`Sine` :     A simple sine wave oscillator.
+- :py:class:`SmoothDelay` :     Artifact free sweepable recursive delay.
 - :py:class:`Snap` :     Snap input values on a user's defined midi scale.
 - :py:class:`SndTable` :     Transfers data from a soundfile into a function table.
 - :py:class:`Spectrum` :     Spectrum analyzer and display.
@@ -208,18 +242,24 @@ 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.
 - :py:class:`Thresh` :     Informs when a signal crosses a threshold.
 - :py:class:`Timer` :     Reports elapsed time between two trigs.
 - :py:class:`Tone` :     A first-order recursive low-pass filter with variable frequency response.
 - :py:class:`Touchin` :     Get the current value of an after-touch Midi controller.
+- :py:class:`TrackHold` :     Performs a track-and-hold operation on its input.
 - :py:class:`TranspoToCents` :     Returns the cents value equivalent of a transposition factor.
+- :py:class:`TrigBurst` :     Generates a time/amplitude expandable trigger pattern.
 - :py:class:`TrigChoice` :     Random generator from user's defined values.
 - :py:class:`TrigEnv` :     Envelope reader generator.
 - :py:class:`TrigExpseg` :     Exponential segments trigger.
@@ -235,11 +275,11 @@ Alphabetical class reference
 - :py:class:`Urn` :     Periodic pseudo-random integer generator without duplicates.
 - :py:class:`VarPort` :     Convert numeric value to PyoObject signal with portamento.
 - :py:class:`Vectral` :     Performs magnitude smoothing between successive frames.
-- :py:class:`Vocoder` :     Applies the spectral envelope of a first sound to the spectrum of a second sound. 
+- :py:class:`Vocoder` :     Applies the spectral envelope of a first sound to the spectrum of a second sound.
 - :py:class:`VoiceManager` :     Polyphony voice manager.
-- :py:class:`WGVerb` :     8 delay line mono FDN reverb.
+- :py:class:`WGVerb` :     8 delay lines mono FDN reverb.
 - :py:class:`Waveguide` :     Basic waveguide model.
-- :py:class:`WinTable` :     Generates different kind of windowing functions. 
+- :py:class:`WinTable` :     Generates different kind of windowing functions.
 - :py:class:`Wrap` :     Wraps-around the signal that exceeds the `min` and `max` thresholds.
 - :py:class:`XnoiseDur` :     Recursive time varying X-class pseudo-random generator.
 - :py:class:`XnoiseMidi` :     X-class midi notes pseudo-random generator.
diff --git a/doc-sphinx/source/api/classes/analysis.rst b/doc-sphinx/source/api/classes/analysis.rst
index 233842a..6a94baa 100644
--- a/doc-sphinx/source/api/classes/analysis.rst
+++ b/doc-sphinx/source/api/classes/analysis.rst
@@ -33,3 +33,32 @@ can use them for controlling parameters of others objects.
 .. autoclass:: Yin
    :members:
 
+*Centroid*
+------------
+
+.. autoclass:: Centroid
+   :members:
+
+*AttackDetector*
+-----------------
+
+.. autoclass:: AttackDetector
+   :members:
+
+*Spectrum*
+-----------------------------------
+
+.. autoclass:: Spectrum
+   :members:
+
+*Scope*
+-----------------------------------
+
+.. autoclass:: Scope
+   :members:
+
+*PeakAmp*
+-----------------------------------
+
+.. autoclass:: PeakAmp
+   :members:
diff --git a/doc-sphinx/source/api/classes/arithmetic.rst b/doc-sphinx/source/api/classes/arithmetic.rst
index af5fc7f..f7278cd 100644
--- a/doc-sphinx/source/api/classes/arithmetic.rst
+++ b/doc-sphinx/source/api/classes/arithmetic.rst
@@ -23,6 +23,12 @@ Tools to perform arithmetic operations on audio signals.
 .. autoclass:: Tan
    :members:
 
+*Tanh*
+------------
+
+.. autoclass:: Tanh
+   :members:
+
 *Abs*
 ------------
 
@@ -83,4 +89,9 @@ Tools to perform arithmetic operations on audio signals.
 .. autoclass:: Pow
    :members:
 
+*Exp*
+------------
+
+.. autoclass:: Exp
+   :members:
 
diff --git a/doc-sphinx/source/api/classes/dynamics.rst b/doc-sphinx/source/api/classes/dynamics.rst
index 0ac8200..cb68212 100644
--- a/doc-sphinx/source/api/classes/dynamics.rst
+++ b/doc-sphinx/source/api/classes/dynamics.rst
@@ -11,6 +11,12 @@ Objects to modify the dynamic range and sample quality of audio signals.
 .. autoclass:: Clip
    :members:
 
+*Degrade*
+----------
+
+.. autoclass:: Degrade
+   :members:
+
 *Mirror*
 ------------
 
diff --git a/doc-sphinx/source/api/classes/effects.rst b/doc-sphinx/source/api/classes/effects.rst
index be32c61..25a3201 100644
--- a/doc-sphinx/source/api/classes/effects.rst
+++ b/doc-sphinx/source/api/classes/effects.rst
@@ -78,3 +78,15 @@ as distortions, delays, chorus and reverbs.
 .. autoclass:: FreqShift
    :members:
 
+*STRev*
+------------
+
+.. autoclass:: STRev
+   :members:
+
+*SmoothDelay*
+---------------
+
+.. autoclass:: SmoothDelay
+   :members:
+
diff --git a/doc-sphinx/source/api/classes/expression.rst b/doc-sphinx/source/api/classes/expression.rst
new file mode 100644
index 0000000..9953f4e
--- /dev/null
+++ b/doc-sphinx/source/api/classes/expression.rst
@@ -0,0 +1,251 @@
+Prefix expression evaluators
+=============================
+
+.. module:: pyo
+
+.. highlight:: none
+
+Prefix audio expression evaluator. 
+
+This family implements a tiny functional programming language that 
+can be used to write synthesis or signal processing algorithms.
+
+**API documentation**
+---------------------
+
+This API is in alpha stage and subject to future changes!
+
+Builtin functions
+-----------------
+
+**Arithmetic operators**
+
+- (+ x y) : returns the sum of two values.
+- (- x y) : substracts the second value to the first and returns the result.
+- (* x y) : returns the multiplication of two values.
+- (/ x y) : returns the quotient of x/y.
+- (^ x y) : returns x to the power y.
+- (% x y) : returns the floating-point remainder of x/y.
+- (neg x) : returns the negative of x.
+
+**Moving phase operators**
+
+- (++ x y) : increments its internal state by x and wrap around 0.0 and y.
+- (-- x y) : decrements its internal state by x and wrap around 0.0 and y.
+- (~ x y) : generates a periodic ramp from 0 to 1 with frequency x and phase y.
+
+**Conditional operators**
+
+- (< x y) : returns 1 if x is less than y, otherwise returns 0.
+- (<= x y) : returns 1 if x is less than or equal to y, otherwise returns 0.
+- (> x y) : returns 1 if x is greater than y, otherwise returns 0.
+- (>= x y) : returns 1 if x is greater than or equal to y, otherwise returns 0.
+- (== x y) : returns 1 if x is equal to y, otherwise returns 0.
+- (!= x y) : returns 1 if x is not equal to y, otherwise returns 0.
+- (if (cond) (then) (else)) : returns then for any non-zero value of cond, otherwise returns else.
+- (and x y) : returns 1 if both x and y are not 0, otherwise returns 0.
+- (or x y) : returns 1 if one of x or y are not 0, otherwise returns 0.
+
+**Trigonometric functions**
+
+- (sin x) : returns the sine of an angle of x radians.
+- (cos x) : returns the cosine of an angle of x radians.
+- (tan x) : returns the tangent of x radians.
+- (tanh x) : returns the hyperbolic tangent of x radians.
+- (atan x) : returns the principal value of the arc tangent of x, expressed in radians.
+- (atan2 x y) : returns the principal value of the arc tangent of y/x, expressed in radians.
+
+**Power and logarithmic functions**
+
+- (sqrt x) : returns the square root of x.
+- (log x) : returns the natural logarithm of x.
+- (log2 x) : returns the binary (base-2) logarithm of x.
+- (log10 x) : returns the common (base-10) logarithm of x.
+- (pow x y) : returns x to the power y.
+
+**Clipping functions**
+
+- (abs x) : returns the absolute value of x.
+- (floor x) : rounds x downward, returning the largest integral value that is not greater than x.
+- (ceil x) : rounds x upward, returning the smallest integral value that is not less than x.
+- (exp  x) : returns the constant e to the power x.
+- (round x) : returns the integral value that is nearest to x.
+- (min x y) : returns the smaller of its arguments: either x or y.
+- (max x y) : returns the larger of its arguments: either x or y.
+- (wrap x) : wraps x between 0 and 1.
+
+**Random fuctions**
+
+- (randf x y) : returns a pseudo-random floating-point number in the range between x and y.
+- (randi x y) : returns a pseudo-random integral number in the range between x and y.
+
+**Filter functions**
+
+- (sah x y) : samples and holds x value whenever y is smaller than its previous state.
+- (rpole x y) : real one-pole recursive filter. returns x + last_out * y.
+- (rzero x y) : real one-zero non-recursive filter. returns x - last_x * y.
+
+**Constants**
+
+- (const x) : returns x.
+- (pi) : returns an approximated value of pi.
+- (twopi) : returns a constant with value pi*2.
+- \(e\) : returns an approximated value of e.
+
+
+Comments
+--------
+
+A comment starts with two slashs ( // ) and ends at the end of the line::
+    
+    // This is a comment!
+
+Input and Output signals
+------------------------
+
+User has access to the last buffer size of input and output samples. 
+
+To use samples from past input, use $x[n] notation, where n is the position
+from the current time. $x[0] is the current input, $x[-1] is the previous
+one and $x[-buffersize] is the last available input sample.
+
+To use samples from past output, use $y[n] notation, where n is the position
+from the current time. $y[-1] is the previous output and $y[-buffersize] is 
+the last available output sample.
+
+Here an example of a first-order IIR lowpass filter expression::
+
+    // A first-order IIR lowpass filter
+    + $x[0] (* (- $y[-1] $x[0]) 0.99)
+
+
+Defining custom functions
+-------------------------
+
+The define keyword starts the definition of a custom function::
+
+    (define funcname (body))
+
+funcname is the name used to call the function in the expression and body 
+is the sequence of functions to execute. Arguments of the function are 
+extracted directly from the body. They must be named $1, $2, $3, ..., $9.
+
+Example of a sine wave function::
+
+    (define osc (
+        sin (* (twopi) (~ $1))
+        )
+    )
+    // play a sine wave
+    * (osc 440) 0.3
+
+
+State variables
+---------------
+
+User can create state variable with the keyword "let". This is useful
+to set an intermediate state to be used in multiple places in the 
+processing chain. The syntax is::
+
+    (let #var (body))
+
+The variable name must begin with a "#"::
+
+    (let #sr 44100)
+    (let #freq 1000)
+    (let #coeff (
+        ^ (e) (/ (* (* -2 (pi)) #freq) #sr)
+        )
+    )
+    + $x[0] (* (- $y[-1] $x[0]) #coeff)
+
+The variable is private to a function if created inside a custom function::
+
+    (let #freq 250) // global #freq variable
+    (define osc (
+        (let #freq (* $1 $2)) // local #freq variable
+        sin (* (twopi) (~ #freq))
+        )
+    )
+    * (+ (osc 1 #freq) (osc 2 #freq)) 0.2
+
+State variables can be used to do 1 sample feedback if used before created. 
+Undefined variables are initialized to 0::
+
+    (define oscloop (
+            (let #xsin 
+                (sin (+ (* (~ $1) (twopi)) (* #xsin $2))) // #xsin used before...
+            ) // ... "let" statement finished!
+            #xsin // oscloop function outputs #xsin variable
+        )
+    )
+    * (oscloop 200 0.7) 0.3
+    
+User variables
+--------------
+
+User variables are created with the keyword "var"::
+
+    (var #var (init)) 
+
+The variable name must begin with a "#".
+
+They are computed only at initialization, but can be changed from the python
+script with method calls (varname is a string and value is a float)::
+
+    obj.setVar(varname, value) 
+
+Library importation
+-------------------
+
+Custom functions can be defined in an external file and imported with the 
+"load" function::
+    
+    (load path/to/the/file)
+
+The content of the file will be inserted where the load function is called
+and all functions defined inside the file will then be accessible. The path
+can be absolute or relative to the current working directory.
+
+Examples
+--------
+
+Here is some expression examples.
+
+A first-order IIR lowpass filter::
+    
+    (var #sr 44100)
+    (var #cutoff 1000)
+    (let #coeff (exp (/ (* (* -2 (pi)) #cutoff) #sr)))
+    + $x[0] (* (- $y[-1] $x[0]) #coeff)
+
+A LFO'ed hyperbolic tangent distortion::
+    
+    // $1 = lfo frequency, $2 = lfo depth
+    (define lfo (
+            (+ (* (sin (* (twopi) (~ $1))) (- $2 1)) $2)
+        )
+    )
+    tanh (* $x[0] (lfo .25 10))
+
+A triangle waveform generator (use Sig(0) as input argument to bypass input)::
+    
+    (var #freq 440)
+    // $1 = oscillator frequency
+    (define triangle (
+            (let #ph (~ $1))
+            (- (* (min #ph (- 1 #ph)) 4) 1)
+        )
+    )
+    triangle #freq
+
+.. highlight:: python
+
+**Objects**
+-----------
+
+*Expr*
+----------
+
+.. autoclass:: Expr
+   :members:
diff --git a/doc-sphinx/source/api/classes/filters.rst b/doc-sphinx/source/api/classes/filters.rst
index 865fb9a..ba96b4e 100644
--- a/doc-sphinx/source/api/classes/filters.rst
+++ b/doc-sphinx/source/api/classes/filters.rst
@@ -180,4 +180,14 @@ sinusoidal component according to its frequency.
 .. autoclass:: ButBR
    :members:
 
+*ComplexRes*
+------------
+
+.. autoclass:: ComplexRes
+   :members:
 
+*MoogLP*
+------------
+
+.. autoclass:: MoogLP
+   :members:
diff --git a/doc-sphinx/source/api/classes/fourier.rst b/doc-sphinx/source/api/classes/fourier.rst
index 148ea3d..1955415 100644
--- a/doc-sphinx/source/api/classes/fourier.rst
+++ b/doc-sphinx/source/api/classes/fourier.rst
@@ -51,12 +51,6 @@ spectral domain.
 .. autoclass:: CvlVerb
    :members:
 
-*Spectrum*
------------------------------------
-
-.. autoclass:: Spectrum
-   :members:
-
 *Vectral*
 -----------------------------------
 
diff --git a/doc-sphinx/source/api/classes/generators.rst b/doc-sphinx/source/api/classes/generators.rst
index 17632ce..0316e5d 100644
--- a/doc-sphinx/source/api/classes/generators.rst
+++ b/doc-sphinx/source/api/classes/generators.rst
@@ -18,12 +18,24 @@ processing chain or as parameter's modifiers.
 .. autoclass:: BrownNoise
    :members:
 
+*ChenLee*
+-----------------------------------
+
+.. autoclass:: ChenLee
+   :members:
+
 *CrossFM*
 -----------------------------------
 
 .. autoclass:: CrossFM
    :members:
 
+*FastSine*
+-----------------------------------
+
+.. autoclass:: FastSine
+   :members:
+
 *FM*
 -----------------------------------
 
diff --git a/doc-sphinx/source/api/classes/index.rst b/doc-sphinx/source/api/classes/index.rst
index cf8a2f2..95836a9 100644
--- a/doc-sphinx/source/api/classes/index.rst
+++ b/doc-sphinx/source/api/classes/index.rst
@@ -5,12 +5,14 @@ Classes by category
    :maxdepth: 2
 
    server
+   listener
    _core
    analysis
    arithmetic
    controls
    dynamics
    effects
+   expression
    filters
    fourier
    pvoc
@@ -29,4 +31,5 @@ Classes by category
    tables
    matrices
    map
+   wxgui
 
diff --git a/doc-sphinx/source/api/classes/listener.rst b/doc-sphinx/source/api/classes/listener.rst
new file mode 100644
index 0000000..d61ce3b
--- /dev/null
+++ b/doc-sphinx/source/api/classes/listener.rst
@@ -0,0 +1,25 @@
+Controller listeners
+===================================
+
+.. module:: pyo
+
+These objects can be used to create MIDI and/or OSC listeners without the
+need to boot ands start an audio server before receiving messages.
+
+*MidiListener*
+-----------------------------------
+
+.. autoclass:: MidiListener
+   :members:
+
+*MidiDispatcher*
+-----------------------------------
+
+.. autoclass:: MidiDispatcher
+   :members:
+
+*OscListener*
+-----------------------------------
+
+.. autoclass:: OscListener
+   :members:
diff --git a/doc-sphinx/source/api/classes/midi.rst b/doc-sphinx/source/api/classes/midi.rst
index bb7dc1d..094c588 100644
--- a/doc-sphinx/source/api/classes/midi.rst
+++ b/doc-sphinx/source/api/classes/midi.rst
@@ -64,3 +64,8 @@ used as controls and can't be sent to the output soundcard.
 .. autoclass:: Touchin
    :members:
 
+*RawMidi*
+-----------------------------------
+
+.. autoclass:: RawMidi
+   :members:
diff --git a/doc-sphinx/source/api/classes/opensndctrl.rst b/doc-sphinx/source/api/classes/opensndctrl.rst
index fbffedc..7cab1d7 100644
--- a/doc-sphinx/source/api/classes/opensndctrl.rst
+++ b/doc-sphinx/source/api/classes/opensndctrl.rst
@@ -14,6 +14,11 @@ input port.
 The audio streams of these objects are essentially intended to be
 controls and can't be sent to the output soundcard.
 
+.. note::
+    
+    These objects are available only if pyo is built with OSC (Open Sound 
+    Control) support.
+
 *OscDataReceive*
 -----------------------------------
 
diff --git a/doc-sphinx/source/api/classes/randoms.rst b/doc-sphinx/source/api/classes/randoms.rst
index b7f79e8..c49c505 100644
--- a/doc-sphinx/source/api/classes/randoms.rst
+++ b/doc-sphinx/source/api/classes/randoms.rst
@@ -11,6 +11,12 @@ Set of objects that implement different kinds of random noise generators.
 .. autoclass:: Choice
    :members:
 
+*LogiMap*
+-----------------------------------
+
+.. autoclass:: LogiMap
+   :members:
+
 *RandDur*
 -----------------------------------
 
diff --git a/doc-sphinx/source/api/classes/tableprocess.rst b/doc-sphinx/source/api/classes/tableprocess.rst
index 3ad98e6..25f7764 100644
--- a/doc-sphinx/source/api/classes/tableprocess.rst
+++ b/doc-sphinx/source/api/classes/tableprocess.rst
@@ -56,12 +56,30 @@ store audio samples or algorithmic sequences for future uses.
 .. autoclass:: OscTrig
    :members:
 
+*Particle*
+-----------------------------------
+
+.. autoclass:: Particle
+   :members:
+
+*Particle2*
+-----------------------------------
+
+.. autoclass:: Particle2
+   :members:
+
 *Pointer*
 -----------------------------------
 
 .. autoclass:: Pointer
    :members:
 
+*Pointer2*
+-----------------------------------
+
+.. autoclass:: Pointer2
+   :members:
+
 *Pulsar*
 -----------------------------------
 
@@ -98,9 +116,26 @@ store audio samples or algorithmic sequences for future uses.
 .. autoclass:: TableRec
    :members:
 
+*TableWrite*
+-----------------------------------
+
+.. autoclass:: TableWrite
+   :members:
+
 *TableScale*
 -----------------------------------
 
 .. 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 569743b..fdc9b79 100644
--- a/doc-sphinx/source/api/classes/tables.rst
+++ b/doc-sphinx/source/api/classes/tables.rst
@@ -78,6 +78,12 @@ in memory and access them quickly.
 .. autoclass:: ParaTable
    :members:
 
+*PartialTable*
+-----------------------------------
+
+.. autoclass:: PartialTable
+   :members:
+
 *SawTable*
 -----------------------------------
 
@@ -108,3 +114,20 @@ in memory and access them quickly.
 .. autoclass:: WinTable
    :members:
 
+*AtanTable*
+-----------------------------------
+
+.. autoclass:: AtanTable
+   :members:
+
+*PadSynthTable*
+-----------------------------------
+
+.. autoclass:: PadSynthTable
+   :members:
+
+*SharedTable*
+-----------------------------------
+
+.. autoclass:: SharedTable
+   :members:
diff --git a/doc-sphinx/source/api/classes/triggers.rst b/doc-sphinx/source/api/classes/triggers.rst
index 778d1d9..917c802 100644
--- a/doc-sphinx/source/api/classes/triggers.rst
+++ b/doc-sphinx/source/api/classes/triggers.rst
@@ -40,6 +40,12 @@ processes with sample rate timing accuracy.
 .. autoclass:: Counter
    :members:
 
+*Euclide*
+-----------------------------------
+
+.. autoclass:: Euclide
+   :members:
+
 *Iter*
 -----------------------------------
 
@@ -94,6 +100,12 @@ processes with sample rate timing accuracy.
 .. autoclass:: Trig
    :members:
 
+*TrigBurst*
+-----------------------------------
+
+.. autoclass:: TrigBurst
+   :members:
+
 *TrigChoice*
 -----------------------------------
 
diff --git a/doc-sphinx/source/api/classes/utils.rst b/doc-sphinx/source/api/classes/utils.rst
index 58ebb12..782529f 100644
--- a/doc-sphinx/source/api/classes/utils.rst
+++ b/doc-sphinx/source/api/classes/utils.rst
@@ -59,6 +59,12 @@ Miscellaneous objects.
 .. autoclass:: Denorm
    :members:
 
+*FToM*
+-----------------------------------
+
+.. autoclass:: FToM
+   :members:
+
 *Interp*
 -----------------------------------
 
@@ -125,3 +131,14 @@ Miscellaneous objects.
 .. autoclass:: TranspoToCents
    :members:
 
+*TrackHold*
+-----------------------------------
+
+.. autoclass:: TrackHold
+   :members:
+
+*Resample*
+-----------------------------------
+
+.. autoclass:: Resample
+   :members:
diff --git a/doc-sphinx/source/api/classes/wxgui.rst b/doc-sphinx/source/api/classes/wxgui.rst
new file mode 100644
index 0000000..2214a23
--- /dev/null
+++ b/doc-sphinx/source/api/classes/wxgui.rst
@@ -0,0 +1,52 @@
+Additional WxPython widgets 
+===============================
+
+.. module:: pyo
+
+The classes in this module are based on internal classes that where 
+originally designed to help the creation of graphical tools for the
+control and the visualization of audio signals. WxPython must be installed
+under the current Python distribution to access these classes.
+
+
+*PyoGuiControlSlider*
+-----------------------------------
+
+.. autoclass:: PyoGuiControlSlider
+   :members:
+
+*PyoGuiVuMeter*
+-----------------------------------
+
+.. autoclass:: PyoGuiVuMeter
+   :members:
+
+*PyoGuiGrapher*
+-----------------------------------
+
+.. autoclass:: PyoGuiGrapher
+   :members:
+
+*PyoGuiMultiSlider*
+-----------------------------------
+
+.. autoclass:: PyoGuiMultiSlider
+   :members:
+
+*PyoGuiSpectrum*
+-----------------------------------
+
+.. autoclass:: PyoGuiSpectrum
+   :members:
+
+*PyoGuiScope*
+-----------------------------------
+
+.. autoclass:: PyoGuiScope
+   :members:
+
+*PyoGuiSndView*
+-----------------------------------
+
+.. autoclass:: PyoGuiSndView
+   :members:
diff --git a/doc-sphinx/source/api/functions/audio.rst b/doc-sphinx/source/api/functions/audio.rst
index d9b36ec..0f9edc6 100644
--- a/doc-sphinx/source/api/functions/audio.rst
+++ b/doc-sphinx/source/api/functions/audio.rst
@@ -1,8 +1,24 @@
 Audio Setup
 ======================================
 
+Set of functions to inspect the system's audio configuration.
+
+.. note::
+
+    These functions are available only if pyo is built with portaudio support.
+ 
 .. module:: pyo
 
+*pa_get_version*
+---------------------------------
+
+.. autofunction:: pa_get_version
+
+*pa_get_version_text*
+---------------------------------
+
+.. autofunction:: pa_get_version_text
+
 *pa_count_host_apis*
 ---------------------------------
 
@@ -18,6 +34,11 @@ Audio Setup
 
 .. autofunction:: pa_get_default_host_api
 
+*pa_get_default_devices_from_host*
+-------------------------------------
+
+.. autofunction:: pa_get_default_devices_from_host
+
 *pa_count_devices*
 ---------------------------------
 
diff --git a/doc-sphinx/source/api/functions/conv.rst b/doc-sphinx/source/api/functions/conv.rst
index ec0273c..9261abd 100644
--- a/doc-sphinx/source/api/functions/conv.rst
+++ b/doc-sphinx/source/api/functions/conv.rst
@@ -33,6 +33,11 @@ Conversions
 
 .. autofunction:: rescale(data, xmin=0.0, xmax=1.0, ymin=0.0, ymax=1.0, xlog=False, ylog=False)
 
+*floatmap*
+---------------------------------
+
+.. autofunction:: floatmap(x, min=0.0, max=1.0, exp=1.0)
+
 *distanceToSegment*
 ---------------------------------
 
diff --git a/doc-sphinx/source/api/functions/midi.rst b/doc-sphinx/source/api/functions/midi.rst
index 7adfd0d..7356e77 100644
--- a/doc-sphinx/source/api/functions/midi.rst
+++ b/doc-sphinx/source/api/functions/midi.rst
@@ -1,6 +1,12 @@
 Midi Setup
 ======================================
 
+Set of functions to inspect the system's midi configuration.
+
+.. note::
+
+    These functions are available only if pyo is built with portmidi support.
+
 .. module:: pyo
 
 *pm_get_default_output*
diff --git a/doc-sphinx/source/api/functions/server.rst b/doc-sphinx/source/api/functions/server.rst
index 07b8b15..1fb29d5 100644
--- a/doc-sphinx/source/api/functions/server.rst
+++ b/doc-sphinx/source/api/functions/server.rst
@@ -1,4 +1,4 @@
-Server Quieries
+Server Queries
 ======================================
 
 .. module:: pyo
diff --git a/doc-sphinx/source/api/functions/sndfile.rst b/doc-sphinx/source/api/functions/sndfile.rst
index 05fd50a..a177fc8 100644
--- a/doc-sphinx/source/api/functions/sndfile.rst
+++ b/doc-sphinx/source/api/functions/sndfile.rst
@@ -11,10 +11,10 @@ Soundfile
 *savefile*
 ---------------------------------
 
-.. autofunction:: savefile(samples, path, sr=44100, channels=1, fileformat=0, sampletype=0)
+.. autofunction:: savefile(samples, path, sr=44100, channels=1, fileformat=0, sampletype=0, quality=0.4)
 
 *savefileFromTable*
 ---------------------------------
 
-.. autofunction:: savefileFromTable(table, path, fileformat=0, sampletype=0)
+.. autofunction:: savefileFromTable(table, path, fileformat=0, sampletype=0, quality=0.4)
 
diff --git a/doc-sphinx/source/api/functions/util.rst b/doc-sphinx/source/api/functions/util.rst
index f89c566..6193cf5 100644
--- a/doc-sphinx/source/api/functions/util.rst
+++ b/doc-sphinx/source/api/functions/util.rst
@@ -18,6 +18,36 @@ Utilities
 
 .. autofunction:: getVersion
 
+*getPyoKeywords*
+---------------------------------
+
+.. autofunction:: getPyoKeywords
+
+*withPortaudio*
+---------------------------------
+
+.. autofunction:: withPortaudio
+
+*withPortmidi*
+---------------------------------
+
+.. autofunction:: withPortmidi
+
+*withJack*
+---------------------------------
+
+.. autofunction:: withJack
+
+*withCoreaudio*
+---------------------------------
+
+.. autofunction:: withCoreaudio
+
+*withOSC*
+---------------------------------
+
+.. autofunction:: withOSC
+
 *convertStringToSysEncoding*
 ---------------------------------
 
diff --git a/doc-sphinx/source/api/index.rst b/doc-sphinx/source/api/index.rst
index 30d459a..fcecb5c 100644
--- a/doc-sphinx/source/api/index.rst
+++ b/doc-sphinx/source/api/index.rst
@@ -1,4 +1,4 @@
-API Documentation
+API documentation
 ===============================
 
 .. toctree::
diff --git a/doc-sphinx/source/compiling.rst b/doc-sphinx/source/compiling.rst
index 78adfb0..cc40692 100644
--- a/doc-sphinx/source/compiling.rst
+++ b/doc-sphinx/source/compiling.rst
@@ -1,81 +1,82 @@
-Compiling
-=====================
+Compiling pyo from sources
+==========================
 
-Here is how you can compile pyo from sources.
+Here is how you can compile pyo from sources on Linux and MacOS (if you are
+interested in the adventure of compiling pyo from sources on Windows, you can 
+take a look at my personal notes in `windows-7-build-routine.txt 
+<https://github.com/belangeo/pyo/blob/master/scripts/win/windows-7-build-routine.txt>`_).
 
 Dependencies
---------------
+------------
 
-To compile pyo, you will need the following dependencies: 
+To compile pyo with all its features, you will need the following dependencies: 
 
-- `Python 2.6 or 2.7 <http://www.python.org/download/releases/>`_
+- `Python 2.7.x or 3.5.x <https://www.python.org/downloads/>`_
+- `WxPython 3.0 <http://www.wxpython.org/download.php/>`_
 - `Portaudio <http://www.portaudio.com/>`_
 - `Portmidi <http://portmedia.sourceforge.net/portmidi/>`_
 - `libsndfile <http://www.mega-nerd.com/libsndfile/>`_
 - `liblo <http://liblo.sourceforge.net/>`_
-
-
-Under Mac OS X, to retrieve necessary dependency librairies and headers to compile pyo, you can run the "get_dependencies.sh" script from the scripts folder in pyo sources, it will download them to /usr/local/lib and /usr/local/include directory. 
-
-For i386 architecture (32-bit python): 
-
-.. code-block:: bash
-
-    sh scripts/get_dependencies.sh
-
-For i386/x86_64 architectures (64-bit python): 
-
-.. code-block:: bash
-
-    sh scripts/get_dependencies_x86_64.sh
-
+- `git <https://git-scm.com/>`_ (if you want the latest sources)
 
 Getting sources
--------------------
+---------------
 
-You can download pyo's source checking out the source code here: 
+You can download pyo's sources by checking out the source code 
+`here <https://github.com/belangeo/pyo>`_: 
 
 .. code-block:: bash
 
-    svn checkout http://pyo.googlecode.com/svn/trunk/ pyo-read-only
+    git clone https://github.com/belangeo/pyo.git
 
 Compilation
 ---------------
 
-Please note that under Mac OS X you will need to install the **Apple's developer tools** to compile pyo.
+Please note that under MacOS you will need to install the 
+**Apple's developer tools** to compile pyo.
 
 Once you have all the required dependencies, go in pyo's directory: 
 
 .. code-block:: bash
 
-    cd pyo-read-only
+    cd path/to/pyo
 
-You then need to build the extension: 
+And build the library: 
 
+MacOS:
+    
 .. code-block:: bash
 
     sudo python setup.py install
 
-You can customize you compilation by giving some flags to the command line.
+Debian & Ubuntu:
+    
+.. code-block:: bash
+
+    sudo python setup.py install --install-layout=deb
+
+You can customize your compilation by giving some flags to the command line.
 
 .. _compilation-flags-label:
 
 Compilation flags
-*********************
+*****************
 
-If you want to be able to use coreaudio (Mac OS X): 
+If you want to be able to use coreaudio (MacOS): 
 
 .. code-block:: bash
 
     --use-coreaudio
 
-If you want JACK support (Linux, Mac OS X): 
+If you want JACK support (Linux, MacOS): 
 
 .. code-block:: bash
 
     --use-jack
 
-If you want to be able to use a 64-bit pyo (All platforms), this will build both single and double precision: 
+If you want to be able to use a 64-bit pyo (All platforms, this is the sample
+resolution, not the architecture), this will build both single and double 
+precisions: 
 
 .. code-block:: bash
 
@@ -87,14 +88,39 @@ If you want to disable most of messages printed to the console:
     
     --no-messages
 
-If you want to compile external classes defined in externals folder:
+If you want to compile external classes defined in pyo/externals folder:
 
 .. code-block:: bash
 
     --compile-externals
 
+By default, debug symbols are off. If you want to compile pyo with debug symbols:
+
+.. code-block:: bash
+
+    --debug
+
+By default, optimizations are activated. If you want to compile pyo without 
+optimizations:
+
+.. code-block:: bash
+
+    --fast-compile
+
+If you want to compile pyo with minimal dependencies (mostly for integrated use
+in a host environment):
+
+.. code-block:: bash
+
+    --minimal
+
+This will compile pyo without portaudio, portmidi and liblo support.
+
 Compilation scripts
-**********************
+*******************
+
+In the ./scripts folder, there is some alternate scripts to simplify the 
+compilation process a little bit.
 
 To compile both 32-bit and 64-bit resolutions on linux (with jack support):
 
@@ -102,42 +128,49 @@ To compile both 32-bit and 64-bit resolutions on linux (with jack support):
 
     sudo sh scripts/compile_linux_withJack.sh
 
-To compile both 32-bit and 64-bit resolutions on OS X (without Jack):
+To compile both 32-bit and 64-bit resolutions on macOS (without Jack):
 
 .. code-block:: bash
 
     sudo sh scripts/compile_OSX.sh
 
-To compile both 32-bit and 64-bit resolutions on OS X (with Jack):
+To compile both 32-bit and 64-bit resolutions on macOS (with Jack):
 
 .. code-block:: bash
 
     sudo sh scripts/compile_OSX_withJack.sh
 
-Ubuntu (Debian)
--------------------
+Debian & Ubuntu (apt-get)
+-------------------------
 
-Under Ubuntu you can type the following commands to get pyo up and running: 
+Under Debian & Ubuntu you can type the following commands to get pyo up 
+and running: 
 
 .. code-block:: bash
 
-    sudo apt-get install libjack-jack2-dev libportmidi-dev portaudio19-dev liblo-dev 
-    sudo apt-get install libsndfile-dev python-dev python-tk subversion 
-    sudo apt-get install python-imaging-tk python-wxgtk2.8
-    svn checkout http://pyo.googlecode.com/svn/trunk/ pyo-read-only
-    cd pyo-read-only
+    sudo apt-get install libjack-jackd2-dev libportmidi-dev portaudio19-dev liblo-dev 
+    sudo apt-get install libsndfile-dev python-dev python-tk 
+    sudo apt-get install python-imaging-tk python-wxgtk3.0
+    git clone https://github.com/belangeo/pyo.git
+    cd pyo
     sudo python setup.py install --install-layout=deb --use-jack --use-double
 
-OSX (Homebrew)
---------------------
+* On Ubuntu system prior to vivid, wxpython 3.0 must be compiled from sources.
+ 
+MacOS (Homebrew)
+----------------
 
-Under OS X, it is very simple to build pyo from sources with the Homebrew package mananger:
+Under macOS, it is very simple to build pyo from sources with the Homebrew 
+package manager.
+
+First, install Python and WxPython from the binary installers.
+
+Second, you need to install `Homebrew <http://brew.sh/>`_. Then, in a terminal 
+window:
 
 .. code-block:: bash
 
-    brew install python liblo libsndfile portaudio portmidi
-    svn checkout http://pyo.googlecode.com/svn/trunk/ pyo
+    brew install liblo libsndfile portaudio portmidi --universal
+    git clone https://github.com/belangeo/pyo.git
     cd pyo
     python setup.py install --use-coreaudio --use-double 
-
-
diff --git a/doc-sphinx/source/conf.py b/doc-sphinx/source/conf.py
index 55ad51d..b551713 100644
--- a/doc-sphinx/source/conf.py
+++ b/doc-sphinx/source/conf.py
@@ -12,6 +12,7 @@
 # serve to show the default.
 
 import sys, os
+from pyo import PYO_VERSION
 
 # If extensions (or modules to document with autodoc) are in another directory,
 # add these directories to sys.path here. If the directory is relative to the
@@ -42,16 +43,16 @@ master_doc = 'index'
 
 # General information about the project.
 project = u'Pyo'
-copyright = u'2013, Olivier Bélanger'
+copyright = u'2016, Olivier Bélanger'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
 # built documents.
 #
 # The short X.Y version.
-version = '0.6.8'
+version = PYO_VERSION
 # The full version, including alpha/beta/rc tags.
-release = '0.6.8'
+release = PYO_VERSION
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/doc-sphinx/source/download.rst b/doc-sphinx/source/download.rst
index fdf63a4..56eac40 100644
--- a/doc-sphinx/source/download.rst
+++ b/doc-sphinx/source/download.rst
@@ -1,8 +1,35 @@
-Downloading
-=================
+Downloading the installer
+==========================
 
-Installers are available for Windows (XP, Vista, 7, 8) and for Max OS X (from 10.5 to 10.8).
+Installers are available for Windows (XP/Vista/7/8/10) and for MacOS 
+(from 10.6 to 10.12).
 
-To download the latest pre-compiled version of pyo, go to the pyo's googlecode `download <http://code.google.com/p/pyo/downloads/list>`_ page.
+To download the latest pre-compiled version of pyo, go to the pyo's 
+`web page <http://ajaxsoundstudio.com/software/pyo/>`_.
 
-Under Debian distros, you can get pyo from the package manager. The library's name is **python-pyo**.
+Under Debian and Fedora distros, you can get pyo from the package manager. 
+The library's name is **python-pyo**. 
+
+If you are running Arch linux, the package is called **python2-pyo**.
+
+
+Content of the installer
+----------------------------
+
+The installer installs two distinct softwares on the system. First, it will 
+install the pyo module (compiled for both single and double precision) and its 
+dependencies under the current python distribution. Secondly, it will install 
+E-Pyo, a simple text editor especially tuned to edit and run audio python script. 
+
+Pyo is a python module...
+-----------------------------
+
+... which means that python must be present (version 2.7.x is the current one, 
+version 3.5.x is experimental but everything seems to work well so far) on the 
+system. If python is not installed, you can download it on 
+`python.org <https://www.python.org/downloads/>`_.
+
+Pyo also offers some GUI facilities to control or visualize the audio processing.
+If you want to use all of pyo's GUI features, you must install WxPython 3.0 
+(**classic** for python 2.7.x and **phoenix** for python 3.5.x), available on 
+`wxpython.org <http://wxpython.org/download.php>`_.
\ No newline at end of file
diff --git a/doc-sphinx/source/gettingstarted.rst b/doc-sphinx/source/gettingstarted.rst
index f4ed369..785da52 100644
--- a/doc-sphinx/source/gettingstarted.rst
+++ b/doc-sphinx/source/gettingstarted.rst
@@ -1,26 +1,45 @@
-Getting Started
+Getting started
 =================================
 
-Here is quick introduction to Pyo. It assumes you already know Python and basics about Object-oriented programming.
+Here is quick introduction to Pyo. It assumes you already know Python and 
+basics about OOP (Object-Oriented Programming).
 
 The Pyo Server and GUI
 -----------------------
 
-The first thing you need to do to use Pyo is import the pyo python module and boot the server. This audio server will open audio and midi interfaces and will be ready to send to them the audio and MIDI produced by other pyo objects. You then need to make some sound:
+The first thing you need to do to use Pyo is import the pyo python module and 
+boot the server. This audio server will open audio and midi interfaces and 
+will be ready to send to them the audio and MIDI produced by other pyo objects. 
+You then need to make some sound:
 
 >>> from pyo import *
 >>> s = Server().boot()
 >>> s.start()
 >>> a = Sine(mul=0.01).out()
 
-The `s` variable holds the Server instance, which has been booted, using the boot function. Booting the server includes opening audio and MIDI interfaces, and setting up the sample rate and number of channels, but the server will not be processing audio until its start() method is called. Then we create a Sine object, and store it in variable a, after calling its out method. The Sine class defines a Sine wave oscillator. The out method from this class connects the output of the oscillator to the server audio outputs. I have set the mul attribute of the Sine object to make sure you don't blow your ears when you play this, as the default amplitude multiplier is 1, i.e. a sine wave at the maximum amplitude before clipping! (But I'll talk about attributes later...) You can stop the server with:
+The `s` variable holds the Server instance, which has been booted, using the 
+boot function. Booting the server includes opening audio and MIDI interfaces, 
+and setting up the sample rate and number of channels, but the server will 
+not be processing audio until its start() method is called. Then we create a 
+Sine object, and store it in variable a, after calling its out method. The 
+Sine class defines a Sine wave oscillator. The out method from this class 
+connects the output of the oscillator to the server audio outputs. I have 
+set the mul attribute of the Sine object to make sure you don't blow your 
+ears when you play this, as the default amplitude multiplier is 1, i.e. a 
+sine wave at the maximum amplitude before clipping! (But I'll talk about 
+attributes later...) You can stop the server with:
 
 >>> s.stop()
 
 To interact or not to interact
 --------------------------------
 
-If you tried the above script from an interactive python shell you would have heard a sine tone, but if you ran it from a python script non-interactively, you are probably asking yourself why you haven't heard anything. The reason is that the script has finished before the server has sent any audio to the outputs! So if you are using python non-interactively, the way to hear this example is:
+If you tried the above script from an interactive python shell you would have 
+heard a sine tone, but if you ran it from a python script non-interactively, 
+you are probably asking yourself why you haven't heard anything. The reason 
+is that the script has finished before the server has sent any audio to the 
+outputs! So if you are using python non-interactively, the way to hear this 
+example is:
 
 .. code-block:: python
 
@@ -30,7 +49,14 @@ If you tried the above script from an interactive python shell you would have he
     a = Sine(mul=0.01).out()
     s.gui(locals())
 
-In the last line, you can see a very handy method from the Server class, which creates a small control GUI for the current instance. The gui method for the Server object, keeps a script running and allows you to start and stop the server, control the output volume and record to an audio file the sound generated in the server. A handy feature of the server GUI is the interpreter text box in the bottom. From it you can send commands interactively to the interpreter, to start and stop objects, create or destroy them, etc.
+In the last line, you can see a very handy method from the Server class, 
+which creates a small control GUI for the current instance. The gui method 
+for the Server object, keeps a script running and allows you to start and 
+stop the server, control the output volume and record to an audio file the 
+sound generated in the server. A handy feature of the server GUI is the 
+interpreter text box in the bottom. From it you can send commands 
+interactively to the interpreter, to start and stop objects, create or 
+destroy them, etc.
 
 Changing Object Characteristics
 ----------------------------------
@@ -41,7 +67,11 @@ The Sine class constructor is defined as:
 
     Sine(self, freq=1000, phase=0, mul=1, add=0)
 
-So you can give it a frequency, starting phase, multiplier and DC offset value when you create it. Also, if you want to do without the server gui, you can use the server method start() from your script, but you might need to use the sleep function from the time module to have your script run the server for a while if you are running Python non-interactively:
+So you can give it a frequency, starting phase, multiplier and DC offset 
+value when you create it. Also, if you want to do without the server gui, 
+you can use the server method start() from your script, but you might need 
+to use the sleep function from the time module to have your script run the 
+server for a while if you are running Python non-interactively:
 
 .. code-block:: python
 
@@ -53,13 +83,17 @@ So you can give it a frequency, starting phase, multiplier and DC offset value w
     time.sleep(1)
     s.stop()
 
-Notice that you can set the parameters for Sine in the order in which they are defined, but you can also give the parameters a name if you want to leave the rest at their default:
+Notice that you can set the parameters for Sine in the order in which they 
+are defined, but you can also give the parameters a name if you want to leave 
+the rest at their default:
 
 .. code-block:: python
 
     a = Sine(mul=0.1).out()
 
-Once the object has been created, you can modify its attributes using the access methods. For example, to modify the frequency of the a oscillator object after it has been created you can use:
+Once the object has been created, you can modify its attributes using the 
+access methods. For example, to modify the frequency of the a oscillator 
+object after it has been created you can use:
 
 .. code-block:: python
 
@@ -74,7 +108,8 @@ But you can also set the attributes directly:
 Chaining objects
 -----------------
 
-Oscillators like the Sine class can be used as inputs to other classes, for example for frequency modulation:
+Oscillators like the Sine class can be used as inputs to other classes, for 
+example for frequency modulation:
 
 .. code-block:: python
 
@@ -98,7 +133,8 @@ You can create an envelope for a sine wave like this:
 Class examples
 ----------------
 
-All Classes in Pyo come with an example which shows how it can be used. To execute the example you can do:
+All Classes in Pyo come with an example which shows how it can be used. To 
+execute the example you can do:
 
 >>> from pyo import *
 >>> example(Harmonizer)
diff --git a/doc-sphinx/source/index.rst b/doc-sphinx/source/index.rst
index abf1888..a1c6bf5 100644
--- a/doc-sphinx/source/index.rst
+++ b/doc-sphinx/source/index.rst
@@ -3,21 +3,61 @@
    You can adapt this file completely to your liking, but it should at least
    contain the root `toctree` directive.
 
-Welcome to the Pyo 0.6.8 documentation
+Welcome to the pyo 0.8.7 documentation
 ===================================================
 
+.. image:: E-PyoIcon.png
+   :scale: 50 %
+   :align: center
+
+Pyo is a Python module written in C to help digital signal processing script 
+creation. It provides a complete set of classes to build audio softwares, 
+compose algorithmic musics or simply explore audio processing with a simple, 
+mature and powerful programming language.
+
+Parts of the documentation
+--------------------------
+
 .. toctree::
    :maxdepth: 1
 
    about
    download
    compiling
+   structure
    gettingstarted
-   tutorials/index
+   perftips
    api/index
 
+Examples
+---------------
+
+.. toctree::
+   :maxdepth: 1
+   
+   First steps <examples/01-intro/index>
+   Parameter control <examples/02-controls/index>
+   Synthesis generators <examples/03-generators/index>
+   Playing with soundfiles <examples/04-soundfiles/index>
+   Amplitude envelopes <examples/05-envelopes/index>
+   Filtering <examples/06-filters/index>
+   Creating sound effects <examples/07-effects/index>
+   Multicore audio programming <examples/18-multicore/index>
+
+Much more to come... Stay tuned!
+
+Advanced tutorials
+--------------------------
+
+.. toctree::
+   :maxdepth: 1
+
+   tutorials/pyoobject1
+   tutorials/pyoobject2
+   tutorials/pyotableobject1
+
 Indices and tables
-==================
+------------------
 
 * :ref:`genindex`
 * :ref:`search`
diff --git a/doc-sphinx/source/perftips.rst b/doc-sphinx/source/perftips.rst
new file mode 100644
index 0000000..e52f048
--- /dev/null
+++ b/doc-sphinx/source/perftips.rst
@@ -0,0 +1,450 @@
+How to improve performance of your pyo programs
+===============================================
+
+This document lists various tips that help to improve the performance of your
+pyo programs.
+
+Python tips
+-----------
+
+There is not much you can do at the Python level because once the script has
+finished its execution run, almost all computations are done in the C level
+of pyo. Nevertheless, there is these two tricks to consider:
+
+Adjust the interpreter's "check interval"
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+You can change how often the interpreter checks for periodic things with
+`sys.setcheckinterval(interval)`. The defaults is 100, which means the check
+is performed every 100 Python virtual instructions. Setting it to a larger
+value may increase performance for programs using threads.
+
+Use the subprocess or multiprocessing modules
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+You can use the subprocess or multiprocessing modules to spawn your processes
+on multiple processors. From the python docs:
+
+  The multiprocessing package offers both local and remote concurrency,
+  effectively side-stepping the Global Interpreter Lock by using subprocesses
+  instead of threads. Due to this, the multiprocessing module allows the
+  programmer to fully leverage multiple processors on a given machine.
+  It runs on both Unix and Windows.
+
+Here is a little example of using the multiprocessing module to spawn a lot of
+sine wave computations to multiple processors.
+
+.. code-block:: python
+
+    #!/usr/bin/env python
+    # encoding: utf-8
+    """
+    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.
+
+    """
+    import time
+    import multiprocessing
+    from random import uniform
+    from pyo import Server, SineLoop
+
+    class Group(multiprocessing.Process):
+        def __init__(self, num_of_sines):
+            super(Group, self).__init__()
+            self.daemon = True
+            self._terminated = False
+            self.num_of_sines = num_of_sines
+
+        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(self.num_of_sines)]
+            self.oscs = SineLoop(freq=freqs, feedback=0.1, mul=.005).out()
+
+            # Keeps the process alive...
+            while not self._terminated:
+                time.sleep(0.001)
+
+            self.server.stop()
+
+        def stop(self):
+            self._terminated = True
+
+    if __name__ == '__main__':
+        # 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
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Dynamic memory allocation (malloc/calloc/realloc) tends to be
+nondeterministic; the time taken to allocate memory may not be predictable,
+making it inappropriate for real time systems. To be sure that the audio
+callback will run smoothly all the time, it is better to create all audio
+objects at the program's initialization and call their `stop()`, `play()`,
+`out()` methods when needed.
+
+Be aware that a simple arithmetic operation involving an audio object will
+create a `Dummy` object (to hold the modified signal), thus will allocate
+memory for its audio stream AND add a processing task on the CPU. Run this
+simple example and watch the process's CPU growing:
+
+.. code-block:: python
+
+    from pyo import *
+    import random
+
+    s = Server().boot()
+
+    env = Fader(0.005, 0.09, 0.1, mul=0.2)
+    jit = Randi(min=1.0, max=1.02, freq=3)
+    sig = RCOsc(freq=[100,100], mul=env).out()
+
+    def change():
+        freq = midiToHz(random.randrange(60, 72, 2))
+        # Because `jit` is a PyoObject, both `freq+jit` and `freq-jit` will
+        # create a `Dummy` object, for which a reference will be created and
+        # saved in the `sig` object. The result is both memory and CPU
+        # increase until something bad happens!
+        sig.freq = [freq+jit, freq-jit]
+        env.play()
+
+    pat = Pattern(change, time=0.125).play()
+
+    s.gui(locals())
+
+An efficient version of this program should look like this:
+
+.. code-block:: python
+
+    from pyo import *
+    import random
+
+    s = Server().boot()
+
+    env = Fader(0.005, 0.09, 0.1, mul=0.2)
+    jit = Randi(min=1.0, max=1.02, freq=3)
+    # Create a `Sig` object to hold the frequency value.
+    frq = Sig(100)
+    # Create the `Dummy` objects only once at initialization.
+    sig = RCOsc(freq=[frq+jit, frq-jit], mul=env).out()
+
+    def change():
+        freq = midiToHz(random.randrange(60, 72, 2))
+        # Only change the `value` attribute of the Sig object.
+        frq.value = freq
+        env.play()
+
+    pat = Pattern(change, time=0.125).play()
+
+    s.gui(locals())
+
+Don't do anything that can trigger the garbage collector
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The garbage collector of python is another nondeterministic process. You
+should avoid doing anything that can trigger it. So, instead of deleting
+an audio object, which can turn out to delete many stream objects, you
+should just call its `stop()` method to remove it from the server's
+processing loop.
+
+Pyo tips
+--------
+
+Here is a list of tips specific to pyo that you should consider when trying to
+reduce the CPU consumption of your audio program.
+
+Mix down before applying effects
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+It is very easy to over-saturate the CPU with pyo, especially if you use the
+multi-channel expansion feature. If your final output uses less channels than
+the number of audio streams in an object, don't forget to mix it down (call
+its `mix()` method) before applying effects on the sum of the signals.
+
+Consider the following snippet, which create a chorus of 50 oscillators and
+apply a phasing effect on the resulting sound:
+
+.. code-block:: python
+
+    src = SineLoop(freq=[random.uniform(190,210) for i in range(50)],
+                   feedback=0.1, mul=0.01)
+    lfo = Sine(.25).range(200, 400)
+    phs = Phaser(src, freq=lfo, q=20, feedback=0.95).out()
+
+
+This version uses around 47% of the CPU on my Thinkpad T430, i5 3320M @ 2.6GHz.
+The problem is that the 50 oscillators given in input of the Phaser object
+creates 50 identical Phaser objects, one for each oscillator. That is a big
+waste of CPU. The next version mixes the oscillators into a stereo stream
+before applying the effect and the CPU consumption drops to ~7% !
+
+.. code-block:: python
+
+    src = SineLoop(freq=[random.uniform(190,210) for i in range(50)],
+                   feedback=0.1, mul=0.01)
+    lfo = Sine(.25).range(200, 400)
+    phs = Phaser(src.mix(2), freq=lfo, q=20, feedback=0.95).out()
+
+
+When costly effects are involved, this can have a very drastic impact on the
+CPU usage.
+
+Stop your unused audio objects
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Whenever you don't use an audio object (but you want to keep it for future
+uses), call its `stop()` method. This will inform the server to remove it from
+the computation loop. Setting the volume to 0 does not save CPU (everything is
+computed then multiplied by 0), the `stop()` method does. My own synth classes
+often looks like something like this:
+
+.. code-block:: python
+
+    class Glitchy:
+        def __init__(self):
+            self.feed = Lorenz(0.002, 0.8, True, 0.49, 0.5)
+            self.amp = Sine(0.2).range(0.01, 0.3)
+            self.src = SineLoop(1, self.feed, mul=self.amp)
+            self.filt = ButLP(self.src, 10000)
+
+        def play(self, chnl=0):
+            self.feed.play()
+            self.amp.play()
+            self.src.play()
+            self.filt.out(chnl)
+            return self
+
+        def stop(self):
+            self.feed.stop()
+            self.amp.stop()
+            self.src.stop()
+            self.filt.stop()
+            return self
+
+Control attribute with numbers instead of PyoObjects
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Objects internal processing functions are optimized when plain numbers are
+given to their attributes. Unless you really need audio control over some
+parameters, don't waste CPU cycles and give fixed numbers to every attribute
+that don't need to change over time. See this comparison:
+
+.. code-block:: python
+
+    n = Noise(.2)
+
+    # ~5% CPU
+    p1 = Phaser(n, freq=[100,105], spread=1.2, q=10,
+                feedback=0.9, num=48).out()
+
+    # ~14% CPU
+    p2 = Phaser(n, freq=[100,105], spread=Sig(1.2), q=10,
+                feedback=0.9, num=48).out()
+
+Making the `spread` attribute of `p2` an audio signal causes the frequency of
+the 48 notches to be recalculated every sample, which can be a very costly
+process.
+
+Check for denormal numbers
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+From wikipedia:
+
+  In computer science, denormal numbers or denormalized numbers (now
+  often called subnormal numbers) fill the underflow gap around zero in
+  floating-point arithmetic. Any non-zero number with magnitude smaller
+  than the smallest normal number is 'subnormal'.
+
+The problem is that some processors compute denormal numbers very
+slowly, which makes grow the CPU consumption very quickly. The solution is to
+wrap the objects that are subject to denormals (any object with an internal
+recursive delay line, ie. filters, delays, reverbs, harmonizers, etc.) in a
+`Denorm` object. `Denorm` adds a little amount of noise, with a magnitude
+just above the smallest normal number, to its input. Of course, you can use
+the same noise for multiple denormalizations:
+
+.. code-block:: python
+
+    n = Noise(1e-24) # low-level noise for denormals
+
+    src = SfPlayer(SNDS_PATH+"/transparent.aif")
+    dly = Delay(src+n, delay=.1, feedback=0.8, mul=0.2).out()
+    rev = WGVerb(src+n).out()
+
+Use a PyoObject when available
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Always look first if a PyoObject does what you want, it will always more
+efficient than a the same process written from scratch.
+
+This construct, although pedagogically valid, will never be more efficient, in
+term of CPU and memory usage, than a native PyoObject (Phaser) written in C.
+
+.. code-block:: python
+
+    a = BrownNoise(.02).mix(2).out()
+
+    lfo = Sine(.25).range(.75, 1.25)
+    filters = []
+    for i in range(24):
+        freq = rescale(i, xmin=0, xmax=24, ymin=100, ymax=10000)
+        filter = Allpass2(a, freq=lfo*freq, bw=freq/2, mul=0.2).out()
+        filters.append(filter)
+
+It is also more efficient to use `Biquadx(stages=4)` than a cascade of four
+`Biquad` objects with identical arguments.
+
+Avoid trigonometric computation
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Avoid trigonometric functions computed at audio rate (`Sin`, `Cos`, `Tan`,
+`Atan2`, etc.), use simple approximations instead. For example, you can
+replace a clean `Sin/Cos` panning function with a cheaper one based on `Sqrt`:
+
+.. code-block:: python
+
+    # Heavier
+    pan = Linseg([(0,0), (2, 1)]).play()
+    left = Cos(pan * math.pi * 0.5, mul=0.5)
+    right = Sin(pan * math.pi * 0.5, mul=0.5)
+    a = Noise([left, right]).out()
+
+    # Cheaper
+    pan2 = Linseg([(0,0), (2, 1)]).play()
+    left2 = Sqrt(1 - pan2, mul=0.5)
+    right2 = Sqrt(pan2, mul=0.5)
+    a2 = Noise([left2, right2]).out()
+
+Use approximations if absolute precision is not needed
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+When absolute precision is not really important, you can save precious CPU
+cycles by using approximations instead of the real function. `FastSine` is an
+approximation of the `sin` function that can be almost twice cheaper than a
+lookup table (Sine). I plan to add more approximations like this one in the
+future.
+
+Re-use your generators
+^^^^^^^^^^^^^^^^^^^^^^
+
+Some times it possible to use the same signal for parallel purposes. Let's
+study the next process:
+
+.. code-block:: python
+
+    # single white noise
+    noise = Noise()
+
+    # denormal signal
+    denorm = noise * 1e-24
+    # little jitter around 1 used to modulate frequency
+    jitter = noise * 0.0007 + 1.0
+    # excitation signal of the waveguide
+    source = noise * 0.7
+
+    env = Fader(fadein=0.001, fadeout=0.01, dur=0.015).play()
+    src = ButLP(source, freq=1000, mul=env)
+    wg = Waveguide(src+denorm, freq=100*jitter, dur=30).out()
+
+Here the same white noise is used for three purposes at the same time. First,
+it is used to generate a denormal signal. Then, it is used to generate a
+little jitter applied to the frequency of the waveguide (that adds a little
+buzz to the string sound) and finally, we use it as the excitation of the
+waveguide. This is surely cheaper than generating three different white noises
+without noticeable difference in the sound.
+
+Leave 'mul' and 'add' attributes to their defaults when possible
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+There is an internal condition that bypass the object "post-processing"
+function when `mul=1` and `add=0`. It is a good practice to apply amplitude
+control in one place instead of messing with the `mul` attribute of each
+objects.
+
+.. code-block:: python
+
+    # wrong
+    n = Noise(mul=0.7)
+    bp1 = ButBP(n, freq=500, q=10, mul=0.5)
+    bp2 = ButBP(n, freq=1500, q=10, mul=0.5)
+    bp3 = ButBP(n, freq=2500, q=10, mul=0.5)
+    rev = Freeverb(bp1+bp2+bp3, size=0.9, bal=0.3, mul=0.7).out()
+
+    # good
+    n = Noise(mul=0.25)
+    bp1 = ButBP(n, freq=500, q=10)
+    bp2 = ButBP(n, freq=1500, q=10)
+    bp3 = ButBP(n, freq=2500, q=10)
+    rev = Freeverb(bp1+bp2+bp3, size=0.9, bal=0.3).out()
+
+Avoid graphical updates
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Even if they run in different threads, with different priorities, the audio
+callback and the graphical interface of a python program are parts of a unique
+process, sharing the same CPU. Don't use the Server's GUI if you don't need to
+see the meters or use the volume slider. Instead, you could start the script
+from command line with `-i` flag to leave the interpreter alive.
+
+.. code-block:: bash
+
+    $ python -i myscript.py
+
+List of CPU intensive objects
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Here is a non-exhaustive list of the most CPU intensive objects of the library.
+
+- Analysis
+    - Yin
+    - Centroid
+    - Spectrum
+    - Scope
+- Arithmetic
+    - Sin
+    - Cos
+    - Tan
+    - Tanh
+    - Atan2
+- Dynamic
+    - Compress
+    - Gate
+- Special Effects
+    - Convolve
+- Prefix Expression Evaluator
+    - Expr
+- Filters
+    - Phaser
+    - Vocoder
+    - IRWinSinc
+    - IRAverage
+    - IRPulse
+    - IRFM
+- Fast Fourier Transform
+    - CvlVerb
+- Phase Vocoder
+    - Almost every objects!
+- Signal Generators
+    - LFO
+- Matrix Processing
+    - MatrixMorph
+- Table Processing
+    - Granulator
+    - Granule
+    - Particule
+    - OscBank
+- Utilities
+    - Resample
diff --git a/doc-sphinx/source/structure.rst b/doc-sphinx/source/structure.rst
new file mode 100644
index 0000000..84c8595
--- /dev/null
+++ b/doc-sphinx/source/structure.rst
@@ -0,0 +1,8 @@
+Structure of the library
+==========================
+
+This diagram shows the internal structure of the library.
+
+.. image:: _static/structure.png
+   :scale: 70
+   :align: center
diff --git a/doc-sphinx/source/tutorials/index.rst b/doc-sphinx/source/tutorials/index.rst
deleted file mode 100644
index 8aaf72c..0000000
--- a/doc-sphinx/source/tutorials/index.rst
+++ /dev/null
@@ -1,9 +0,0 @@
-Tutorials
-==============
-
-.. toctree::
-   :maxdepth: 1
-
-   pyoobject1
-   pyoobject2
-   pyotableobject1
diff --git a/doc-sphinx/source/tutorials/pyoobject1.rst b/doc-sphinx/source/tutorials/pyoobject1.rst
index 18e7e40..cda0d75 100644
--- a/doc-sphinx/source/tutorials/pyoobject1.rst
+++ b/doc-sphinx/source/tutorials/pyoobject1.rst
@@ -1,5 +1,5 @@
-Tutorial on creating a custom PyoObject (RingMod)
-==================================================
+Tutorial about creating a custom PyoObject (RingMod)
+=====================================================
 
 There are few steps we need to take care of in order to create a class with all 
 of the PyoObject behaviors.
diff --git a/doc-sphinx/source/tutorials/pyoobject2.rst b/doc-sphinx/source/tutorials/pyoobject2.rst
index db3db1c..881bd19 100644
--- a/doc-sphinx/source/tutorials/pyoobject2.rst
+++ b/doc-sphinx/source/tutorials/pyoobject2.rst
@@ -1,5 +1,5 @@
-Tutorial on creating a custom PyoObject (Flanger)
-==================================================
+Another tutorial about creating a custom PyoObject (Flanger)
+=============================================================
 
 There are few steps we need to take care of in order to create a class with all 
 of the PyoObject behaviors.
@@ -30,7 +30,7 @@ First of all, we need to import the pyo module
 Step 1 - Declaring the class
 ------------------------------
 
-We will create a new class called RingMod with PyoObject as its parent class. 
+We will create a new class called Flanger with PyoObject as its parent class. 
 Another good habit is to put a __doc__ string at the beginning of our classes. 
 Doing so will allow other users to retrieve the object's documentation with the 
 standard python help() function.
diff --git a/doc-sphinx/source/tutorials/pyotableobject1.rst b/doc-sphinx/source/tutorials/pyotableobject1.rst
index de3a66b..c3cdae0 100644
--- a/doc-sphinx/source/tutorials/pyotableobject1.rst
+++ b/doc-sphinx/source/tutorials/pyotableobject1.rst
@@ -1,5 +1,5 @@
-Example of a custom PyoTableObject
-====================================
+Tutorial about creating a custom PyoTableObject (TriTable)
+===========================================================
 
 .. code-block:: python
 
diff --git a/embedded/bela/PyoClass.cpp b/embedded/bela/PyoClass.cpp
new file mode 100644
index 0000000..7ffe0a6
--- /dev/null
+++ b/embedded/bela/PyoClass.cpp
@@ -0,0 +1,286 @@
+#include "PyoClass.h"
+
+/*
+** Creates a python interpreter and initialize a pyo server inside it.
+** This function must be called, once per Pyo object, before any other
+** calls.
+**
+** arguments:
+**   nChannels : int, number of in/out channels.
+**   bufferSize : int, number of samples per buffer.
+**   sampleRate : int, sample rate frequency.
+**   nAnalogChannels : int, number of analog channels.
+**
+** All arguments should be equal to the host audio settings.
+*/
+void Pyo::setup(int _nChannels, int _bufferSize, int _sampleRate, int _nAnalogChannels) {
+    nChannels = _nChannels;
+    bufferSize = _bufferSize;
+    sampleRate = _sampleRate;
+    nAnalogChannels = _nAnalogChannels;
+    nTotalChannels = nChannels+nAnalogChannels;
+    interpreter = pyo_new_interpreter(sampleRate, bufferSize, nTotalChannels);
+    pyoInBuffer = reinterpret_cast<float*>(pyo_get_input_buffer_address(interpreter));
+    pyoOutBuffer = reinterpret_cast<float*>(pyo_get_output_buffer_address(interpreter));
+    pyoCallback = reinterpret_cast<callPtr*>(pyo_get_embedded_callback_address(interpreter));
+    pyoId = pyo_get_server_id(interpreter);
+}
+
+/*
+** Terminates this object's interpreter.
+*/
+Pyo::~Pyo() {
+    pyo_end_interpreter(interpreter);
+}
+
+/*
+** This function fills pyo's input buffers with new samples. Should be called
+** once per process block, inside the host's render function.
+**
+** arguments:
+**   *buffer : float *, float pointer pointing to the host's input buffers.
+*/
+void Pyo::fillin(float *buffer) {
+    for (int i=0; i<bufferSize; i++) {
+	    for (int j=0; j<nChannels; j++) {
+	        pyoInBuffer[i*nTotalChannels+j] = buffer[i*nChannels+j];
+	    }
+    }
+}
+
+/*
+** This function fills pyo's reminaing input buffers (after audio voices)
+** with samples coming from analog inputs. Should be called once per 
+** process block, inside the host's render function.
+**
+** arguments:
+**   *buffer : float *, float pointer pointing to the host's analog buffers.
+*/
+void Pyo::analogin(float *buffer) {
+    switch (nAnalogChannels) {
+        case 2:
+            for (int i=0; i<bufferSize; i++) {
+	            for (int j=0; j<nAnalogChannels; j++) {
+	                pyoInBuffer[i*nTotalChannels+j+nChannels] = buffer[i*2*nAnalogChannels+j];
+	            }
+            }
+            break;
+         case 4:
+            for (int i=0; i<bufferSize; i++) {
+	            for (int j=0; j<nAnalogChannels; j++) {
+	                pyoInBuffer[i*nTotalChannels+j+nChannels] = buffer[i*nAnalogChannels+j];
+	            }
+            }
+            break;
+         case 8:
+            int ioff, joff;
+            for (int i=0; i<bufferSize/2; i++) {
+                ioff = i * 2 * nTotalChannels;
+	            for (int j=0; j<nAnalogChannels; j++) {
+                    joff = ioff + nChannels + j;
+	                pyoInBuffer[joff] = pyoInBuffer[joff+nTotalChannels] = buffer[i*nAnalogChannels+j];
+	            }
+            }
+            break;
+     }
+}
+
+/*
+** This function tells pyo to process a buffer of samples and fills the host's
+** output buffer with new samples. Should be called once per process block,
+** inside the host's render function.
+**
+** arguments:
+**   *buffer : float *, float pointer pointing to the host's output buffers.
+*/
+void Pyo::process(float *buffer) {
+    pyoCallback(pyoId);
+    for (int i=0; i<bufferSize; i++) {
+        for (int j=0; j<nChannels; j++) {
+            buffer[i*nChannels+j] = pyoOutBuffer[i*nTotalChannels+j];
+        }
+    }
+}
+
+/*
+** This function fills the host's analog output buffer with new samples. 
+** Should be called once per process block, after a process() call, inside 
+** the host's render function.
+**
+** arguments:
+**   *buffer : float *, float pointer pointing to the host's analog output buffers.
+*/
+void Pyo::analogout(float *buffer) {
+    switch (nAnalogChannels) {
+        case 2:
+            int bufpos;
+            for (int i=0; i<bufferSize; i++) {
+                for (int j=0; j<nAnalogChannels; j++) {
+                    bufpos = i * 2 * nAnalogChannels + j;
+                    buffer[bufpos] = buffer[bufpos+nAnalogChannels] = pyoOutBuffer[i*nTotalChannels+j+nChannels];
+                }
+            }
+            break;
+         case 4:
+            for (int i=0; i<bufferSize; i++) {
+                for (int j=0; j<nAnalogChannels; j++) {
+                    buffer[i*nAnalogChannels+j] = pyoOutBuffer[i*nTotalChannels+j+nChannels];
+                }
+            }
+            break;
+         case 8:
+            for (int i=0; i<bufferSize/2; i++) {
+                for (int j=0; j<nAnalogChannels; j++) {
+                    buffer[i*nAnalogChannels+j] = pyoOutBuffer[i*2*nTotalChannels+j+nChannels];
+                }
+            }
+            break;
+     }
+}
+
+/*
+** Execute a python script "file" in the objectès thread's interpreter.
+** An integer "add" is needed to indicate if the pyo server should be
+** reboot or not.
+**
+** arguments:
+**   file : char *, filename to execute as a python script. The file is first
+**                  searched in the current working directory. If not found,
+**                  the module will try to open it as an absolute path.
+**   add, int, if positive, the commands in the file will be added to whatever
+**             is already running in the pyo server. If 0, the server will be
+**             cleared before executing the file.
+*/
+int Pyo::loadfile(const char *file, int add) {
+    return pyo_exec_file(interpreter, file, pyoMsg, add);
+}
+
+/*
+** Sends a numerical value to an existing Sig or SigTo object.
+**
+** arguments:
+**   name : const char *, variable name of the object.
+**   value : float, value to be assigned.
+**
+** Example:
+**
+** inside the script file:
+**
+** freq = SigTo(value=440, time=0.1, init=440)
+**
+** Inside the host (for a Pyo object named `pyo`):
+**
+** pyo.value("freq", 880);
+*/
+int Pyo::value(const char *name, float value) {
+    sprintf(pyoMsg, "%s.value=%f", name, value);
+    return pyo_exec_statement(interpreter, pyoMsg, 0);
+}
+
+/*
+** Sends an array of numerical values to an existing Sig or SigTo object.
+**
+** arguments:
+**   name : const char *, variable name of the object.
+**   value : float *, array of floats.
+**   len : int, number of elements in the array.
+**
+** Example:
+**
+** inside the script file:
+**
+** freq = SigTo(value=[100,200,300,400], time=0.1, init=[100,200,300,400])
+**
+** Inside the host (for a Pyo object named `pyo`):
+**
+** float frequencies[4] = {150, 250, 350, 450};
+** pyo.value("freq", frequencies, 4);
+*/
+int Pyo::value(const char *name, float *value, int len) {
+    char fchar[32];
+    sprintf(pyoMsg, "%s.value=[", name);
+    for (int i=0; i<len; i++) {
+        sprintf(fchar, "%f,", value[i]);
+        strcat(pyoMsg, fchar);
+    }
+    strcat(pyoMsg, "]");
+    return pyo_exec_statement(interpreter, pyoMsg, 0);
+}
+
+/*
+** Sends a numerical value to a Pyo object's attribute.
+**
+** arguments:
+**   name : const char *, object name and attribute separated by a dot.
+**   value : float, value to be assigned.
+**
+** Example:
+**
+** inside the script file:
+**
+** filter = Biquad(input=Noise(0.5), freq=1000, q=4, type=2)
+**
+** Inside the host (for a Pyo object named `pyo`):
+**
+** pyo.set("filter.freq", 2000);
+*/
+int Pyo::set(const char *name, float value) {
+    sprintf(pyoMsg, "%s=%f", name, value);
+    return pyo_exec_statement(interpreter, pyoMsg, 0);
+}
+
+/*
+** Sends an array of numerical values to a Pyo object's attribute.
+**
+** arguments:
+**   name : const char *, object name and attribute separated by a dot.
+**   value : float *, array of floats.
+**   len : int, number of elements in the array.
+**
+** Example:
+**
+** inside the script file:
+**
+** filters = Biquad(input=Noise(0.5), freq=[250, 500, 1000, 2000], q=5, type=2)
+**
+** Inside the host (for a Pyo object named `pyo`):
+**
+** float frequencies[4] = {350, 700, 1400, 2800};
+** pyo.set("filters.freq", frequencies, 4);
+*/
+int Pyo::set(const char *name, float *value, int len) {
+    char fchar[32];
+    sprintf(pyoMsg, "%s=[", name);
+    for (int i=0; i<len; i++) {
+        sprintf(fchar, "%f,", value[i]);
+        strcat(pyoMsg, fchar);
+    }
+    strcat(pyoMsg, "]");
+    return pyo_exec_statement(interpreter, pyoMsg, 0);
+}
+
+/*
+** Executes any raw valid python statement. With this function, one can dynamically
+** creates and manipulates audio objects and algorithms.
+**
+** arguments:
+**   msg : const char *, pointer to a string containing the statement to execute.
+**
+** Example (for a Pyo object named `pyo`):
+**
+** pyo.exec("pits = [0.001, 0.002, 0.003, 0.004]")
+** pyo.exec("fr = Rossler(pitch=pits, chaos=0.9, mul=250, add=500)")
+** pyo.exec("b = SumOsc(freq=fr, ratio=0.499, index=0.4, mul=0.2).out()")
+*/
+int Pyo::exec(const char *_msg) {
+    strcpy(pyoMsg, _msg);
+    return pyo_exec_statement(interpreter, pyoMsg, 0);
+}
+
+/*
+** Shutdown and reboot the pyo server while keeping current in/out buffers.
+** This will erase audio objects currently active within the server.
+**
+*/void Pyo::clear() {
+    pyo_server_reboot(interpreter);
+}
diff --git a/embedded/bela/PyoClass.h b/embedded/bela/PyoClass.h
new file mode 100644
index 0000000..19b639c
--- /dev/null
+++ b/embedded/bela/PyoClass.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include "m_pyo.h"
+
+typedef int callPtr(int);
+
+class Pyo {
+    public:
+        ~Pyo();
+        void setup(int nChannels, int bufferSize, int sampleRate, int nAnalogChannels);
+        void process(float *buffer);
+        void fillin(float *buffer);
+        void analogin(float *buffer);
+        void analogout(float *buffer);
+        void clear();
+        int loadfile(const char *file, int add);
+        int exec(const char *msg);
+        int value(const char *name, float value);
+        int value(const char *name, float *value, int len);
+        int set(const char *name, float value);
+        int set(const char *name, float *value, int len);
+
+    private:
+        int nChannels;
+        int bufferSize;
+        int sampleRate;
+        int nAnalogChannels;
+        int nTotalChannels;
+        PyThreadState *interpreter;
+        float *pyoInBuffer;
+        float *pyoOutBuffer;
+        callPtr *pyoCallback;
+        int pyoId;
+        char pyoMsg[262144];
+};
diff --git a/embedded/bela/README b/embedded/bela/README
new file mode 100644
index 0000000..b6057e0
--- /dev/null
+++ b/embedded/bela/README
@@ -0,0 +1,67 @@
+Introduction on how to use pyo on the BeagleBone Black with bela
+================================================================ 
+
+------------------------------------------------------------------------
+------------------------------------------------------------------------
+Step 1 - Changes made to the image bela_stable_2016.04.19.img
+
+1) Need the python-dev package
+
+    sudo apt-get install python-dev
+
+2) Compile a minimalistic pyo (libsndfile as only dependency)
+
+    git -c http.sslVerify=false clone https://github.com/belangeo/pyo.git
+    cd pyo
+    sudo python setup.py install --minimal
+
+3) Modify the Makefile to compile and link with python
+
+line 11:
+    
+LIBS := -lrt -lnative -lxenomai -lsndfile `python-config --ldflags`
+
+line 20:
+    
+CPP_FLAGS := -O3 -march=armv7-a -mtune=cortex-a8 -mfloat-abi=hard -mfpu=neon -ftree-vectorize `python-config --cflags`
+
+
+------------------------------------------------------------------------
+------------------------------------------------------------------------
+Step 2 - On the host computer, clone the beaglert repository:
+    
+    hg clone https://code.soundsoftware.ac.uk/hg/beaglert
+
+------------------------------------------------------------------------
+Step 3 - Create a folder "pyo" in the beaglert/projects directory and copy:
+these files into it:
+
+- from the folder pyo/embedded:
+m_pyo.h
+
+- from the folder pyo/embedded/bela:
+main.cpp
+render.cpp
+main.py
+PyoClass.cpp
+PyoClass.h
+
+------------------------------------------------------------------------
+Step 3 - From the script folder, with the bbb plugged to the host computer,
+comple and run your project:
+    
+    ./build_project.sh ../projects/pyo
+
+See the bela wiki for more options when building projects on the bbb board.
+
+https://code.soundsoftware.ac.uk/projects/beaglert/wiki/_Compiling_Bela_projects_on_the_board
+
+Documentation
+=============
+
+For a complete description of functions that can be used to communicate 
+with the pyo embedded processes, see documentation comments in the file 
+PyoClass.cpp.
+
+(c) 2016 - belangeo
+
diff --git a/embedded/bela/examples/analog-in-out.py b/embedded/bela/examples/analog-in-out.py
new file mode 100644
index 0000000..7174e84
--- /dev/null
+++ b/embedded/bela/examples/analog-in-out.py
@@ -0,0 +1,15 @@
+"""
+This example shows how to manage analog inputs and outputs.
+
+"""
+
+# Analog inputs comes right after the stereo audio channels.
+i1 = Tone(Input(2), 8) # analog in 0
+i2 = Tone(Input(3), 8) # analog in 1
+
+lfo = Sine([8,10], mul=0.2)
+
+# Analog outputs comes right after the stereo audio channels.
+o1 = Clip(i1+lfo[0], 0, 1).out(2) # analog out 0
+o2 = Clip(i2+lfo[1], 0, 1).out(3) # analog out 1
+
diff --git a/embedded/bela/examples/music-box.py b/embedded/bela/examples/music-box.py
new file mode 100644
index 0000000..02d2c90
--- /dev/null
+++ b/embedded/bela/examples/music-box.py
@@ -0,0 +1,22 @@
+"""
+Music box - Four voices randomly choosing frequencies 
+over a common scale.
+
+"""
+# Set to True to control the global gain with analog input 0.
+WITH_ANALOG_INPUT = False
+
+if WITH_ANALOG_INPUT:
+    v = Tone(Input(2), 8) # knob 1 - global gain
+else:
+    v = 0.5
+
+mid_freqs = [midiToHz(m+7) for m in [60,62,63.93,65,67.01,69,71,72]]
+high_freqs = [midiToHz(m+7) for m in [72,74,75.93,77,79.01]]
+freqs = [mid_freqs,mid_freqs,high_freqs,high_freqs]
+
+chx = Choice(choice=freqs, freq=[2,3,3,4])
+port = Port(chx, risetime=.001, falltime=.001)
+sines = SineLoop(port, feedback=[.057,.033,.035,.016], 
+		         mul=[.1,.1,.05,.05]*v).out()
+
diff --git a/embedded/bela/examples/ring-mod.py b/embedded/bela/examples/ring-mod.py
new file mode 100644
index 0000000..ae2804d
--- /dev/null
+++ b/embedded/bela/examples/ring-mod.py
@@ -0,0 +1,58 @@
+"""
+01-Simple FX - Stereo ring modulator.
+
+This example shows how to build a ring modulation effect 
+with modulator's frequency and brightness control with
+analog inputs (use audio inputs after the stereo audio
+channels, ie. Input(2) is analog-in 0, Input(3) is 
+analog-in 1, etc.).
+
+It also show how to send signal to analog outputs. Again,
+use the outputs after the stereo audio channels, ie.
+.out(2) writes to analog-out 0, .out(3) to analog-out 1,
+etc.).
+
+"""
+# Set to True if you want to control the modulator 
+# frequency and brightness with analog inputs.
+WITH_ANALOG_INPUT = True
+# If False, set frequency and brightness values.
+FREQUENCY = 500     # Hz
+BRIGHTNESS = 0.05   # 0 -> 0.2
+
+# If True, a positive value is sent on analog-out 0 and 1
+# whenever there is an output signal (can be used to build 
+# a cheap vumeter with leds).
+WITH_ANALOG_OUTPUT = True
+
+# stereo input
+src = Input([0,1])
+
+# Don't know if the noise comes from my mic,
+# but it sounds better with a gate on the input!
+gate = Gate(src.mix(), thresh=-60, risetime=.005, 
+            falltime=.02, lookahead=1, outputAmp=True)
+srcg = src * gate
+
+if WITH_ANALOG_INPUT:
+    # analog-in 0 (modulator's frequency)
+    i0 = Tone(Input(2), 8) 
+    freq = Scale(i0, 0, 1, 1, 1000, 3)
+
+    # analog-in 1 (modulator's brightness)
+    i1 = Tone(Input(3), 8) 
+    feed = i1 * 0.2
+else:
+    freq = FREQUENCY
+    feed = BRIGHTNESS
+
+# Modulation oscillator
+mod = SineLoop(freq, feed)
+
+# Ring modulation and stereo output
+out = (srcg * mod).out()
+
+if WITH_ANALOG_OUTPUT:
+    # analog out 0-1 (stereo vumeter) 
+    fol = Sqrt(Clip(Follower(out, mul=4))).out(2)
+
diff --git a/embedded/bela/main.cpp b/embedded/bela/main.cpp
new file mode 100644
index 0000000..76d9c56
--- /dev/null
+++ b/embedded/bela/main.cpp
@@ -0,0 +1,95 @@
+/*
+ * main.cpp
+ *
+ *  Created on: Oct 24, 2014
+ *      Author: parallels
+ */
+#include <unistd.h>
+#include <iostream>
+#include <cstdlib>
+#include <libgen.h>
+#include <signal.h>
+#include <getopt.h>
+#include <BeagleRT.h>
+
+using namespace std;
+
+// Handle Ctrl-C by requesting that the audio rendering stop
+void interrupt_handler(int var)
+{
+	gShouldStop = true;
+}
+
+// Print usage information
+void usage(const char * processName)
+{
+	cerr << "Usage: " << processName << " [options]" << endl;
+
+	BeagleRT_usage();
+
+	cerr << "   --help [-h]:                Print this menu\n";
+}
+
+int main(int argc, char *argv[])
+{
+	BeagleRTInitSettings settings;	// Standard audio settings
+
+	struct option customOptions[] =
+	{
+		{"help", 0, NULL, 'h'},
+		{NULL, 0, NULL, 0}
+	};
+
+	// Set default settings
+	BeagleRT_defaultSettings(&settings);
+	// Set the buffer size
+	settings.periodSize = 64;
+	// Set the number of Analog channels (2, 4 or 8)
+	settings.numAnalogChannels = 8;
+
+	// Parse command-line arguments
+	while (1) {
+		int c;
+		if ((c = BeagleRT_getopt_long(argc, argv, "hf:", customOptions, &settings)) < 0)
+				break;
+		switch (c) {
+		case 'h':
+				usage(basename(argv[0]));
+				exit(0);
+		case '?':
+		default:
+				usage(basename(argv[0]));
+				exit(1);
+		}
+	}
+
+	// Initialise the PRU audio device
+	if(BeagleRT_initAudio(&settings, 0) != 0) {
+		cout << "Error: unable to initialise audio" << endl;
+		return -1;
+	}
+
+	// Start the audio device running
+	if(BeagleRT_startAudio()) {
+		cout << "Error: unable to start real-time audio" << endl;
+		return -1;
+	}
+
+	// Set up interrupt handler to catch Control-C and SIGTERM
+	signal(SIGINT, interrupt_handler);
+	signal(SIGTERM, interrupt_handler);
+
+	// Run until told to stop
+	while(!gShouldStop) {
+		usleep(100000);
+	}
+
+	// Stop the audio device
+	BeagleRT_stopAudio();
+
+	// Clean up any resources allocated for audio
+	BeagleRT_cleanupAudio();
+
+	// All done!
+	return 0;
+}
diff --git a/embedded/bela/main.py b/embedded/bela/main.py
new file mode 100644
index 0000000..02d2c90
--- /dev/null
+++ b/embedded/bela/main.py
@@ -0,0 +1,22 @@
+"""
+Music box - Four voices randomly choosing frequencies 
+over a common scale.
+
+"""
+# Set to True to control the global gain with analog input 0.
+WITH_ANALOG_INPUT = False
+
+if WITH_ANALOG_INPUT:
+    v = Tone(Input(2), 8) # knob 1 - global gain
+else:
+    v = 0.5
+
+mid_freqs = [midiToHz(m+7) for m in [60,62,63.93,65,67.01,69,71,72]]
+high_freqs = [midiToHz(m+7) for m in [72,74,75.93,77,79.01]]
+freqs = [mid_freqs,mid_freqs,high_freqs,high_freqs]
+
+chx = Choice(choice=freqs, freq=[2,3,3,4])
+port = Port(chx, risetime=.001, falltime=.001)
+sines = SineLoop(port, feedback=[.057,.033,.035,.016], 
+		         mul=[.1,.1,.05,.05]*v).out()
+
diff --git a/embedded/bela/render.cpp b/embedded/bela/render.cpp
new file mode 100644
index 0000000..16b7f53
--- /dev/null
+++ b/embedded/bela/render.cpp
@@ -0,0 +1,35 @@
+#include <BeagleRT.h>
+#include <cmath>
+#include <iostream>
+#include <Utilities.h>
+#include "PyoClass.h"
+
+Pyo pyo;
+
+bool setup(BeagleRTContext *context, void *userData)
+{
+    // Initialize a pyo server.
+    pyo.setup(context->audioChannels, context->audioFrames, 
+              context->audioSampleRate, context->analogChannels);
+    // Load a python file.
+    pyo.loadfile("/root/BeagleRT/source/main.py", 0);
+
+    return true;
+}
+
+void render(BeagleRTContext *context, void *userData)
+{
+    // Fill pyo input buffer (channels 0-1) with audio samples.
+    pyo.fillin(context->audioIn);
+    // Fill pyo input buffer (channels 2+) with analog inputs.
+    pyo.analogin(context->analogIn);
+    // Call pyo processing function and retrieve back stereo outputs.
+    pyo.process(context->audioOut);
+    // Get back pyo output channels 2+ as analog outputs.
+    pyo.analogout(context->analogOut);
+}
+
+void cleanup(BeagleRTContext *context, void *userData)
+{
+}
+
diff --git a/embedded/juceplugin/PyoClass.cpp b/embedded/juceplugin/PyoClass.cpp
new file mode 100644
index 0000000..b61bb23
--- /dev/null
+++ b/embedded/juceplugin/PyoClass.cpp
@@ -0,0 +1,268 @@
+#include "PyoClass.h"
+
+/*
+** Creates a python interpreter and initialize a pyo server inside it.
+** This function must be called, once per Pyo object, before any other
+** calls.
+**
+** arguments:
+**   nChannels : int, number of in/out channels.
+**   bufferSize : int, number of samples per buffer.
+**   sampleRate : int, sample rate frequency.
+**
+** All arguments should be equal to the host audio settings.
+*/
+void Pyo::setup(int _nChannels, int _bufferSize, int _sampleRate) {
+    nChannels = _nChannels;
+    bufferSize = _bufferSize;
+    sampleRate = _sampleRate;
+    interpreter = pyo_new_interpreter(sampleRate, bufferSize, nChannels);
+    pyoInBuffer = reinterpret_cast<float*>(pyo_get_input_buffer_address(interpreter));
+    pyoOutBuffer = reinterpret_cast<float*>(pyo_get_output_buffer_address(interpreter));
+    pyoCallback = reinterpret_cast<callPtr*>(pyo_get_embedded_callback_address(interpreter));
+    pyoId = pyo_get_server_id(interpreter);
+    pyo_set_server_params(interpreter, sampleRate, bufferSize);
+}
+
+/*
+** Terminates this object's interpreter.
+*/
+Pyo::~Pyo() {
+    pyo_end_interpreter(interpreter);
+}
+
+/*
+** This function fills pyo's input buffers with new samples, tells pyo to
+** process a buffer of samples and fills the host's output buffer with new
+** samples. Should be called once per process block, inside the host's
+** processBlock function.
+**
+** arguments:
+**   buffer : AudioSampleBuffer&, Juce's audio buffer object.
+*/
+void Pyo::process(AudioSampleBuffer& buffer) {
+    for (int channel = 0; channel < nChannels; ++channel) {
+        float *channelData = buffer.getWritePointer(channel);
+        for (int sample = 0; sample < bufferSize; sample++) {
+            pyoInBuffer[sample*nChannels+channel] = channelData[sample];
+        }
+    }
+    pyoCallback(pyoId);
+    for (int channel = 0; channel < nChannels; ++channel) {
+        float *channelData = buffer.getWritePointer(channel);
+        for (int sample = 0; sample < bufferSize; sample++) {
+            channelData[sample] = pyoOutBuffer[sample*nChannels+channel];
+        }
+    }
+}
+
+/*
+** Execute a python script "file" in the objectès thread's interpreter.
+** An integer "add" is needed to indicate if the pyo server should be
+** reboot or not.
+**
+** arguments:
+**   file : const char * or const String &,
+**             filename to execute as a python script. The file is first
+**             searched in the current working directory. If not found,
+**             the module will try to open it as an absolute path.
+**   add, int, if positive, the commands in the file will be added to whatever
+**             is already running in the pyo server. If 0, the server will be
+**             cleared before executing the file.
+*/
+int Pyo::loadfile(const char *file, int add) {
+    return pyo_exec_file(interpreter, file, pyoMsg, add);
+}
+
+int Pyo::loadfile(const String &file, int add) {
+    return pyo_exec_file(interpreter, file.getCharPointer(), pyoMsg, add);
+}
+
+/*
+** Sends a numerical value to an existing Sig or SigTo object.
+**
+** arguments:
+**   name : const char * or const String &,
+**          variable name of the object.
+**   value : float, value to be assigned.
+**
+** Example:
+**
+** inside the script file:
+**
+** freq = SigTo(value=440, time=0.1, init=440)
+**
+** Inside OpenFrameworks (for a Pyo object named `pyo`):
+**
+** pyo.value("freq", 880);
+*/
+int Pyo::value(const char *name, float value) {
+    sprintf(pyoMsg, "%s.value=%f", name, value);
+    return pyo_exec_statement(interpreter, pyoMsg, 0);
+}
+
+int Pyo::value(const String &name, float value) {
+    const char * _name = name.getCharPointer();
+    sprintf(pyoMsg, "%s.value=%f", _name, value);
+    return pyo_exec_statement(interpreter, pyoMsg, 0);
+}
+
+/*
+** Sends an array of numerical values to an existing Sig or SigTo object.
+**
+** arguments:
+**   name : const char * or const String &,
+**          variable name of the object.
+**   value : float *, array of floats.
+**   len : int, number of elements in the array.
+**
+** Example:
+**
+** inside the script file:
+**
+** freq = SigTo(value=[100,200,300,400], time=0.1, init=[100,200,300,400])
+**
+** Inside OpenFrameworks (for a Pyo object named `pyo`):
+**
+** float frequencies[4] = {150, 250, 350, 450};
+** pyo.value("freq", frequencies, 4);
+*/
+int Pyo::value(const char *name, float *value, int len) {
+    char fchar[32];
+    sprintf(pyoMsg, "%s.value=[", name);
+    for (int i=0; i<len; i++) {
+        sprintf(fchar, "%f,", value[i]);
+        strcat(pyoMsg, fchar);
+    }
+    strcat(pyoMsg, "]");
+    return pyo_exec_statement(interpreter, pyoMsg, 0);
+}
+
+int Pyo::value(const String &name, float *value, int len) {
+    char fchar[32];
+    const char * _name = name.getCharPointer();
+    sprintf(pyoMsg, "%s.value=[", _name);
+    for (int i=0; i<len; i++) {
+        sprintf(fchar, "%f,", value[i]);
+        strcat(pyoMsg, fchar);
+    }
+    strcat(pyoMsg, "]");
+    return pyo_exec_statement(interpreter, pyoMsg, 0);
+}
+
+/*
+** Sends a numerical value to a Pyo object's attribute.
+**
+** arguments:
+**   name : const char * or const String &,
+**          object name and attribute separated by a dot.
+**   value : float, value to be assigned.
+**
+** Example:
+**
+** inside the script file:
+**
+** filter = Biquad(input=Noise(0.5), freq=1000, q=4, type=2)
+**
+** Inside OpenFrameworks (for a Pyo object named `pyo`):
+**
+** pyo.set("filter.freq", 2000);
+*/
+int Pyo::set(const char *name, float value) {
+    sprintf(pyoMsg, "%s=%f", name, value);
+    return pyo_exec_statement(interpreter, pyoMsg, 0);
+}
+
+int Pyo::set(const String &name, float value) {
+    const char * _name = name.getCharPointer();
+    sprintf(pyoMsg, "%s=%f", _name, value);
+    return pyo_exec_statement(interpreter, pyoMsg, 0);
+}
+
+/*
+** Sends an array of numerical values to a Pyo object's attribute.
+**
+** arguments:
+**   name : const char * or const String &,
+**          object name and attribute separated by a dot.
+**   value : float *, array of floats.
+**   len : int, number of elements in the array.
+**
+** Example:
+**
+** inside the script file:
+**
+** filters = Biquad(input=Noise(0.5), freq=[250, 500, 1000, 2000], q=5, type=2)
+**
+** Inside OpenFrameworks (for a Pyo object named `pyo`):
+**
+** float frequencies[4] = {350, 700, 1400, 2800};
+** pyo.set("filters.freq", frequencies, 4);
+*/
+int Pyo::set(const char *name, float *value, int len) {
+    char fchar[32];
+    sprintf(pyoMsg, "%s=[", name);
+    for (int i=0; i<len; i++) {
+        sprintf(fchar, "%f,", value[i]);
+        strcat(pyoMsg, fchar);
+    }
+    strcat(pyoMsg, "]");
+    return pyo_exec_statement(interpreter, pyoMsg, 0);
+}
+
+int Pyo::set(const String &name, float *value, int len) {
+    char fchar[32];
+    const char * _name = name.getCharPointer();
+    sprintf(pyoMsg, "%s=[", _name);
+    for (int i=0; i<len; i++) {
+        sprintf(fchar, "%f,", value[i]);
+        strcat(pyoMsg, fchar);
+    }
+    strcat(pyoMsg, "]");
+    return pyo_exec_statement(interpreter, pyoMsg, 0);
+}
+
+/*
+** Executes any raw valid python statement. With this function, one can
+** dynamically creates and manipulates audio objects and algorithms.
+**
+** arguments:
+**   msg : const char * or const String &
+**         pointer to a string containing the statement to execute.
+**
+** Example (for a Pyo object named `pyo`):
+**
+** pyo.exec("pits = [0.001, 0.002, 0.003, 0.004]")
+** pyo.exec("fr = Rossler(pitch=pits, chaos=0.9, mul=250, add=500)")
+** pyo.exec("b = SumOsc(freq=fr, ratio=0.499, index=0.4, mul=0.2).out()")
+*/
+int Pyo::exec(const char *_msg) {
+    strcpy(pyoMsg, _msg);
+    return pyo_exec_statement(interpreter, pyoMsg, 0);
+}
+
+int Pyo::exec(const String &_msg) {
+    strcpy(pyoMsg, _msg.getCharPointer());
+    return pyo_exec_statement(interpreter, pyoMsg, 0);
+}
+
+/*
+** Sends a MIDI messges to the Server.
+**
+** Example (for a Pyo object named `pyo`):
+**
+** pyo.midi(144, 60, 127) //Send a Note on message on channel 1 for note # 60
+** pyo.midi(128, 60, 0)   //Send a Note off messge on channel 1 for note # 60
+*/
+
+void Pyo::midi(int status, int data1, int data2) {
+    return pyo_add_midi_event(interpreter, status, data1, data2);
+}
+
+/*
+** Shutdown and reboot the pyo server while keeping current in/out buffers.
+** This will erase audio objects currently active within the server.
+**
+*/void Pyo::clear() {
+    pyo_server_reboot(interpreter);
+}
diff --git a/embedded/juceplugin/PyoClass.h b/embedded/juceplugin/PyoClass.h
new file mode 100644
index 0000000..7749d9d
--- /dev/null
+++ b/embedded/juceplugin/PyoClass.h
@@ -0,0 +1,41 @@
+#ifndef PYOCLASS_H_INCLUDED
+#define PYOCLASS_H_INCLUDED
+
+#include "m_pyo.h"
+#include "../JuceLibraryCode/JuceHeader.h"
+
+typedef int callPtr(int);
+
+class Pyo {
+    public:
+        ~Pyo();
+        void setup(int nChannels, int bufferSize, int sampleRate);
+        void process(AudioSampleBuffer& buffer);
+        void clear();
+        int loadfile(const char *file, int add);
+        int loadfile(const String &file, int add);
+        int exec(const char *msg);
+        int exec(const String &msg);
+        int value(const char *name, float value);
+        int value(const String &name, float value);
+        int value(const char *name, float *value, int len);
+        int value(const String &name, float *value, int len);
+        int set(const char *name, float value);
+        int set(const String &name, float value);
+        int set(const char *name, float *value, int len);
+        int set(const String &name, float *value, int len);
+        void midi(int status, int data1, int data2);
+
+    private:
+        int nChannels;
+        int bufferSize;
+        int sampleRate;
+        PyThreadState *interpreter;
+        float *pyoInBuffer;
+        float *pyoOutBuffer;
+        callPtr *pyoCallback;
+        int pyoId;
+        char pyoMsg[262144];
+};
+
+#endif  // PYOCLASS_H_INCLUDED
diff --git a/embedded/juceplugin/README b/embedded/juceplugin/README
new file mode 100644
index 0000000..5e6e7e5
--- /dev/null
+++ b/embedded/juceplugin/README
@@ -0,0 +1,162 @@
+Introduction on how to use pyo inside a Juce audio plugin.
+========================================================== 
+
+To use pyo inside a Juce audio plugin, first you need a working 
+install of pyo on your system. After installing pyo, you can move 
+on and create a Juce audio plugin project.
+
+------------------------------------------------------------------------------
+Step 1 - Create an Audio Plug-In project with the Introjucer. 
+
+------------------------------------------------------------------------------
+Step 2 - Add pyo files to your project. You only need to copy 
+these files in your project "Source" folder:
+
+- from this folder:
+PyoClass.cpp
+PyoClass.h
+
+- from the folder "embedded":
+m_pyo.h
+
+------------------------------------------------------------------------------
+Step 3 - Make sure that your project includes flags for compiling 
+and linking against Python. Within the Introjucer, you can set extra
+flags in the "Config" tab. For example, on linux, if you select "Linux
+Makefile", you can add extra compiler and linker flags. Add these in
+the specific fields:
+
+Extra linker flags : `python-config --ldflags`
+Extra compiler flags : `python-config --cflags`
+
+------------------------------------------------------------------------------
+Step 4 - Make sure that your project links to the Steinberg's VST SDK.
+VST SDK can be freely downloaded from Steinberg web site:
+http://www.steinberg.net/en/company/developers/
+Enter the path in the field "VST Folder" in the export configuration.
+
+------------------------------------------------------------------------------
+Step 5 - Create a python file, named "stereoDelay.py", with these lines in 
+it:
+
+# Retrieve the stereo input of the plugin.
+st_input = Input([0,1])
+# Parameters to change.
+dtime = SigTo(.5, 0.05, .5)
+feed = SigTo(.5, 0.05, .5)
+# Simple process. Stereo delay -> reverb.
+st_delay = SmoothDelay(st_input, delay=dtime, feedback=feed)
+st_rev = WGVerb(st_delay, feedback=0.8, cutoff=4000, bal=0.25).out()
+
+Save "stereoDelay.py" in the "Source" folder, add it to the project in the
+Introjucer and ensure that the option "Add to Binary Resources" is checked.
+Save your project. This should add two files, "BinaryData.h" and 
+"BinaryData.cpp", in the "JuceLibraryCode" folder.
+ 
+------------------------------------------------------------------------------
+Step 6 - Edit Source/PluginProcessor.h
+
+- Include PyoClass definition:
+
+#include "PyoClass.h"
+
+- Add a Pyo object to the public attributes of the XXXAudioProcessor class:
+
+    Pyo pyo;
+
+------------------------------------------------------------------------------
+Step 7 - Edit Source/PluginProcessor.cpp
+
+- Add these line to XXXAudioProcessor::prepareToPlay method:
+
+    pyo.setup(getNumOutputChannels(), samplesPerBlock, sampleRate);
+    pyo.exec(BinaryData::stereoDelay_py);
+
+- Replace the content of XXXAudioProcessor::processBlock method with
+this line:
+
+    pyo.process(buffer);
+
+------------------------------------------------------------------------------
+Here you go! Compile, Run and Enjoy!
+
+Adding GUI controls to your plugin
+==================================
+
+Now, we will add two sliders to control the delay time and the feedback
+of our process.
+
+------------------------------------------------------------------------------
+Step 8 - Edit Source/PluginEditor.h
+
+- Add the inheritance to Slider::Listener to your XXXAudioProcessorEditor
+class definition:
+    
+class XXXAudioProcessorEditor  : public AudioProcessorEditor, 
+                                 private Slider::Listener
+ 
+- Add the default callback function in the public attributes of the class:
+    
+    void sliderValueChanged(Slider* slider) override;
+
+- Create two sliders in the public attributes of the class:
+    
+    Slider p1;
+    Slider p2;
+
+------------------------------------------------------------------------------
+Step 9 - Edit Source/PluginEditor.cpp
+
+- Set the sliders properties in the editor constructor function named
+XXXAudioProcessorEditor::XXXAudioProcessorEditor (this is the first function
+in the PluginEditor.cpp file). Add these lines at the end of the function:
+    
+    // these define the parameters of our slider object
+    p1.setSliderStyle(Slider::LinearBarVertical);
+    p1.setRange(0.0, 1.0, 0.01);
+    p1.setTextBoxStyle(Slider::NoTextBox, false, 90, 0);
+    p1.setPopupDisplayEnabled(true, this);
+    p1.setTextValueSuffix(" Delay Time");
+    p1.setValue(0.5);
+    p1.addListener(this);
+    // this function adds the slider to the editor
+    addAndMakeVisible(&p1);
+
+    p2.setSliderStyle(Slider::LinearBarVertical);
+    p2.setRange(0.0, 1.0, 0.01);
+    p2.setTextBoxStyle(Slider::NoTextBox, false, 90, 0);
+    p2.setPopupDisplayEnabled(true, this);
+    p2.setTextValueSuffix(" Delay Feedback");
+    p2.setValue(0.5);
+    p2.addListener(this);
+    addAndMakeVisible(&p2);
+
+- Set the size and position of the sliders. Add these lines in 
+XXXAudioProcessorEditor::resized() function:
+    
+    p1.setBounds(40, 30, 20, getHeight() - 60);
+    p2.setBounds(70, 30, 20, getHeight() - 60);
+
+------------------------------------------------------------------------------
+Step 10 - Connect the sliders to the audio proces
+
+- At the end of the file PluginEditor.cpp, create the slider's callback 
+function which will pass the values to the audio processing objects:
+    
+void XXXAudioProcessorEditor::sliderValueChanged (Slider* slider)
+{
+    processor.pyo.value("dtime", p1.getValue());
+    processor.pyo.value("feed", p2.getValue());
+}
+
+------------------------------------------------------------------------------
+That's it! Compile and Run...
+
+Documentation
+=============
+
+For a complete description of functions used to communicate with the pyo 
+embedded processes, see documentation comments in the file PyoClass.cpp.
+
+
+(c) 2015 - belangeo
diff --git a/embedded/juceplugin/test.py b/embedded/juceplugin/test.py
new file mode 100644
index 0000000..ad0a4ed
--- /dev/null
+++ b/embedded/juceplugin/test.py
@@ -0,0 +1,9 @@
+import random
+
+# Get the input sound and apply a stereo delay on it.
+feed = SigTo(0, 0.05, 0)
+freq = SigTo(0.1, 0.05, 0.1)
+freq_sc = Scale(freq, 0, 1, 100, 10000, 4)
+st_input = Input([0,1])
+st_filter = ButBP(st_input, freq_sc)
+st_delay = Delay(st_filter, delay=[random.uniform(.1, .9) for i in range(2)], feedback=feed).out()
diff --git a/embedded/m_pyo.h b/embedded/m_pyo.h
new file mode 100644
index 0000000..832b1a6
--- /dev/null
+++ b/embedded/m_pyo.h
@@ -0,0 +1,355 @@
+#include <stdlib.h>
+#include "Python.h"
+
+#ifndef __m_pyo_h_
+
+#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
+extern "C" {
+#endif
+
+/* Unicode/string handling. */
+#if PY_MAJOR_VERSION >= 3
+#define PyInt_AsLong PyLong_AsLong
+#define PY_STRING_CHECK(a) PyUnicode_Check(arg) 
+#define PY_STRING_AS_STRING(a) PyUnicode_AsUTF8(a)
+#else
+#define PY_STRING_CHECK(a) (PyUnicode_Check(a) || PyBytes_Check(a))
+#define PY_STRING_AS_STRING(a) PyBytes_AsString(a)
+#endif
+
+/*
+** Creates a new python interpreter and starts a pyo server in it.
+** Each instance of pyo, in order to be fully independent of other
+** instances, must be started in its own interpreter. An instance
+** can be an object in a programming language or a plugin in a daw.
+**
+** arguments:
+**  sr : float, host sampling rate.
+**  bufsize : int, host buffer size.
+**  chnls : int, number of in/out channels of the pyo server.
+**
+** returns the new python thread's interpreter state.
+*/
+inline PyThreadState * pyo_new_interpreter(float sr, int bufsize, int chnls) {
+    char msg[64];
+    PyThreadState *interp;
+    if(!Py_IsInitialized()) {
+        Py_InitializeEx(0);
+        PyEval_InitThreads();
+        PyEval_ReleaseLock();
+    }
+    PyEval_AcquireLock();              /* get the GIL */
+    interp = Py_NewInterpreter();      /* add a new sub-interpreter */
+    PyRun_SimpleString("from pyo import *");
+    sprintf(msg, "_s_ = Server(%f, %d, %d, 1, 'embedded')", sr, chnls, bufsize);
+    PyRun_SimpleString(msg);
+    PyRun_SimpleString("_s_.boot()\n_s_.start()\n_s_.setServer()");
+    PyRun_SimpleString("_in_address_ = _s_.getInputAddr()");
+    PyRun_SimpleString("_out_address_ = _s_.getOutputAddr()");
+    PyRun_SimpleString("_server_id_ = _s_.getServerID()");
+    PyRun_SimpleString("_emb_callback_ = _s_.getEmbedICallbackAddr()");
+    PyEval_ReleaseThread(interp);
+    return interp;
+}
+
+/*
+** Returns the address, as unsigned long, of the pyo input buffer.
+** Used this function if pyo's audio samples resolution is 32-bit.
+**
+** arguments:
+**  interp : pointer, pointer to the targeted Python thread state.
+**
+** returns an "unsigned long" that should be recast to a float pointer.
+*/
+inline unsigned long pyo_get_input_buffer_address(PyThreadState *interp) {
+    PyObject *module, *obj;
+    char *address;
+    unsigned long uadd;
+    PyEval_AcquireThread(interp);
+    module = PyImport_AddModule("__main__");
+    obj = PyObject_GetAttrString(module, "_in_address_");
+    address = PY_STRING_AS_STRING(obj);
+    uadd = strtoul(address, NULL, 0);
+    PyEval_ReleaseThread(interp);
+    return uadd;
+}
+
+/*
+** Returns the address, as unsigned long long, of the pyo input buffer.
+** Used this function if pyo's audio samples resolution is 64-bit.
+**
+** arguments:
+**  interp : pointer, pointer to the targeted Python thread state.
+**
+** returns an "unsigned long long" that should be recast to a double pointer.
+*/
+inline unsigned long long pyo_get_input_buffer_address_64(PyThreadState *interp) {
+    PyObject *module, *obj;
+    char *address;
+    unsigned long long uadd;
+    PyEval_AcquireThread(interp);
+    module = PyImport_AddModule("__main__");
+    obj = PyObject_GetAttrString(module, "_in_address_");
+    address = PY_STRING_AS_STRING(obj);
+    uadd = strtoull(address, NULL, 0);
+    PyEval_ReleaseThread(interp);
+    return uadd;
+}
+
+/*
+** Returns the address, as unsigned long, of the pyo output buffer.
+** Used this function if pyo's audio samples resolution is 32-bit.
+**
+** arguments:
+**  interp : pointer, pointer to the targeted Python thread state.
+**
+** returns an "unsigned long" that should be recast to a float pointer.
+*/
+inline unsigned long pyo_get_output_buffer_address(PyThreadState *interp) {
+    PyObject *module, *obj;
+    char *address;
+    unsigned long uadd;
+    PyEval_AcquireThread(interp);
+    module = PyImport_AddModule("__main__");
+    obj = PyObject_GetAttrString(module, "_out_address_");
+    address = PY_STRING_AS_STRING(obj);
+    uadd = strtoul(address, NULL, 0);
+    PyEval_ReleaseThread(interp);
+    return uadd;
+}
+
+/*
+** Returns the address, as unsigned long, of the pyo embedded callback.
+** This callback must be called in the host's perform routine whenever
+** pyo has to compute a new buffer of samples.
+**
+** arguments:
+**  interp : pointer, pointer to the targeted Python thread state.
+**
+** returns an "unsigned long" that should be recast to a void pointer.
+**
+** The callback should be called with the server id (int) as argument.
+**
+** Prototype:
+** void (*callback)(int);
+*/
+inline unsigned long pyo_get_embedded_callback_address(PyThreadState *interp) {
+    PyObject *module, *obj;
+    char *address;
+    unsigned long uadd;
+    PyEval_AcquireThread(interp);
+    module = PyImport_AddModule("__main__");
+    obj = PyObject_GetAttrString(module, "_emb_callback_");
+    address = PY_STRING_AS_STRING(obj);
+    uadd = strtoul(address, NULL, 0);
+    PyEval_ReleaseThread(interp);
+    return uadd;
+}
+
+/*
+** Returns the pyo server id of this thread, as an integer.
+** The id must be pass as argument to the callback function.
+**
+** arguments:
+**  interp : pointer, pointer to the targeted Python thread state.
+**
+** returns an integer.
+*/
+inline int pyo_get_server_id(PyThreadState *interp) {
+    PyObject *module, *obj;
+    int id;
+    PyEval_AcquireThread(interp);
+    module = PyImport_AddModule("__main__");
+    obj = PyObject_GetAttrString(module, "_server_id_");
+    id = PyInt_AsLong(obj);
+    PyEval_ReleaseThread(interp);
+    return id;
+}
+
+/*
+** Closes the interpreter linked to the thread state given as argument.
+**
+** arguments:
+**  interp : pointer, pointer to the targeted Python thread state.
+*/
+inline void pyo_end_interpreter(PyThreadState *interp) {
+    PyEval_AcquireThread(interp);
+    PyRun_SimpleString("_s_.setServer()\n_s_.stop()\n_s_.shutdown()");
+    PyEval_ReleaseThread(interp);
+
+    /* Old method (causing segfault) */
+    //PyEval_AcquireThread(interp);
+    //Py_EndInterpreter(interp);
+    //PyEval_ReleaseLock();
+
+    /* New method (seems to be ok) */
+    PyThreadState_Swap(interp);
+    PyThreadState_Swap(NULL);
+    PyThreadState_Clear(interp);
+    PyThreadState_Delete(interp);
+}
+
+/*
+** Shutdown and reboot the pyo server while keeping current in/out buffers.
+**
+** arguments:
+**  interp : pointer, pointer to the targeted Python thread state.
+*/
+inline void pyo_server_reboot(PyThreadState *interp) {
+    PyEval_AcquireThread(interp);
+    PyRun_SimpleString("_s_.setServer()\n_s_.stop()\n_s_.shutdown()");
+    PyRun_SimpleString("_s_.boot(newBuffer=False).start()");
+    PyEval_ReleaseThread(interp);
+}
+
+/*
+** Reboot the pyo server with new sampling rate and buffer size.
+**
+** arguments:
+**  interp : pointer, pointer to the targeted Python thread state.
+**  sr : float, host sampling rate.
+**  bufsize : int, host buffer size.
+*/
+inline void pyo_set_server_params(PyThreadState *interp, float sr, int bufsize) {
+    char msg[64];
+    PyEval_AcquireThread(interp);
+    PyRun_SimpleString("_s_.setServer()\n_s_.stop()\n_s_.shutdown()");
+    sprintf(msg, "_s_.setSamplingRate(%f)", sr);
+    PyRun_SimpleString(msg);
+    sprintf(msg, "_s_.setBufferSize(%d)", bufsize);
+    PyRun_SimpleString(msg);
+    PyRun_SimpleString("_s_.boot(newBuffer=False).start()");
+    PyEval_ReleaseThread(interp);
+}
+
+/*
+** Add a MIDI event in the pyo server processing chain. When used in 
+** an embedded framework, pyo can't open MIDI ports by itself. MIDI
+** inputs must be handled by the host program and sent to pyo with
+** the pyo_add_midi_event function.
+**
+** arguments:
+**  interp : pointer, pointer to the targeted Python thread state.
+**  status : int, status byte.
+**  data1 : int, first data byte.
+**  data2 : int, second data byte.
+*/
+inline void pyo_add_midi_event(PyThreadState *interp, int status, int data1, int data2) {
+    char msg[64];
+    PyEval_AcquireThread(interp);
+    sprintf(msg, "_s_.addMidiEvent(%d, %d, %d)", status, data1, data2);
+    PyRun_SimpleString(msg);
+    PyEval_ReleaseThread(interp);
+}
+
+/*
+** Returns 1 if the pyo server is started for the given thread,
+** Otherwise returns 0.
+**
+** arguments:
+**  interp : pointer, pointer to the targeted Python thread state.
+*/
+inline int pyo_is_server_started(PyThreadState *interp) {
+    int started;
+    PyObject *module, *obj;
+    PyEval_AcquireThread(interp);
+    PyRun_SimpleString("started = _s_.getIsStarted()");
+    module = PyImport_AddModule("__main__");
+    obj = PyObject_GetAttrString(module, "started");
+    started = PyInt_AsLong(obj);
+    PyEval_ReleaseThread(interp);
+    return started;
+}
+
+/*
+** Execute a python script "file" in the given thread's interpreter (interp).
+** A pre-allocated string "msg" must be given to create the python command
+** used for error handling. An integer "add" is needed to indicate if the
+** pyo server should be reboot or not.
+**
+** arguments:
+**  interp : pointer, pointer to the targeted Python thread state.
+**  file : char *, filename to execute as a python script. The file is first
+**                 searched in the current working directory. If not found,
+**                 the module will try to open it as an absolute path.
+**  msg : char *, pre-allocated string used to create the python command
+**                used for error handling.
+**  add, int, if positive, the commands in the file will be added to whatever
+**            is already running in the pyo server. If 0, the server will be
+**            shutdown and reboot before executing the file.
+*/
+inline int pyo_exec_file(PyThreadState *interp, const char *file, char *msg, int add) {
+    int ok, err = 0;
+    PyObject *module, *obj;
+    PyEval_AcquireThread(interp);
+    sprintf(msg, "import os\n_ok_ = os.path.isfile('./%s')", file);
+    PyRun_SimpleString(msg);
+    sprintf(msg, "if not _ok_:\n    _ok_ = os.path.isfile('%s')", file);
+    PyRun_SimpleString(msg);
+    module = PyImport_AddModule("__main__");
+    obj = PyObject_GetAttrString(module, "_ok_");
+    ok = PyInt_AsLong(obj);
+    if (ok) {
+        sprintf(msg, "try:\n    exec(open('./%s').read())\nexcept:\n    exec(open('%s').read())",
+                file, file);
+        if (!add) {
+            PyRun_SimpleString("_s_.setServer()\n_s_.stop()\n_s_.shutdown()");
+            PyRun_SimpleString("_s_.boot(newBuffer=False).start()");
+        }
+        PyRun_SimpleString(msg);
+    }
+    else
+        err = 1;
+    PyEval_ReleaseThread(interp);
+    return err;
+}
+
+/*
+** Execute a python statement "msg" in the thread's interpreter "interp".
+** If "debug" is true, the statement will be executed in a try - except
+** block. The error message, if any, will be write back in the *msg
+** pointer and the function will return 1. If no error occured, the
+** function returned 0. If debug is false, the statement is executed
+** without any error checking (unsafe but faster).
+**
+** arguments:
+**  interp : pointer, pointer to the targeted Python thread state.
+**  msg : char *, pointer to a string containing the statement to execute.
+**                In debug mode, if an error occured, the output log will
+**                be write back in this string.
+**  debug, int, if positive, the commands will be executed in a try-except
+**              statement. If 0, there will be no error checking, which is
+**              much faster.
+*/
+inline int pyo_exec_statement(PyThreadState *interp, char *msg, int debug) {
+    int err = 0;
+    if (debug) {
+        PyObject *module, *obj;
+        char pp[26] = "_error_=None\ntry:\n    ";
+        memmove(msg + strlen(pp), msg, strlen(msg)+1);
+        memmove(msg, pp, strlen(pp));
+        strcat(msg, "\nexcept Exception, _e_:\n    _error_=str(_e_)");
+        PyEval_AcquireThread(interp);
+        PyRun_SimpleString(msg);
+        module = PyImport_AddModule("__main__");
+        obj = PyObject_GetAttrString(module, "_error_");
+        if (obj != Py_None) {
+            strcpy(msg, PY_STRING_AS_STRING(obj));
+            err = 1;
+        }
+        PyEval_ReleaseThread(interp);
+    }
+    else {
+        PyEval_AcquireThread(interp);
+        PyRun_SimpleString(msg);
+        PyEval_ReleaseThread(interp);
+    }
+    return err;
+}
+
+#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
+}
+#endif
+
+#define __m_pyo_h_
+#endif /* __m_pyo_h_  */
diff --git a/embedded/openframeworks/PyoClass.cpp b/embedded/openframeworks/PyoClass.cpp
new file mode 100644
index 0000000..bed1d65
--- /dev/null
+++ b/embedded/openframeworks/PyoClass.cpp
@@ -0,0 +1,203 @@
+#include "PyoClass.h"
+
+/*
+** Creates a python interpreter and initialize a pyo server inside it.
+** This function must be called, once per Pyo object, before any other
+** calls.
+**
+** arguments:
+**   nChannels : int, number of in/out channels.
+**   bufferSize : int, number of samples per buffer.
+**   sampleRate : int, sample rate frequency.
+**
+** All arguments should be equal to the host audio settings.
+*/
+void Pyo::setup(int _nChannels, int _bufferSize, int _sampleRate) {
+    nChannels = _nChannels;
+    bufferSize = _bufferSize;
+    sampleRate = _sampleRate;
+    interpreter = pyo_new_interpreter(sampleRate, bufferSize, nChannels);
+    pyoInBuffer = reinterpret_cast<float*>(pyo_get_input_buffer_address(interpreter));
+    pyoOutBuffer = reinterpret_cast<float*>(pyo_get_output_buffer_address(interpreter));
+    pyoCallback = reinterpret_cast<callPtr*>(pyo_get_embedded_callback_address(interpreter));
+    pyoId = pyo_get_server_id(interpreter);
+}
+
+/*
+** Terminates this object's interpreter.
+*/
+Pyo::~Pyo() {
+    pyo_end_interpreter(interpreter);
+}
+
+/*
+** This function fills pyo's input buffers with new samples. Should be called
+** once per process block, inside the host's audioIn function.
+**
+** arguments:
+**   *buffer : float *, float pointer pointing to the host's input buffers.
+*/
+void Pyo::fillin(float *buffer) {
+    for (int i=0; i<(bufferSize*nChannels); i++) pyoInBuffer[i] = buffer[i];
+}
+
+
+/*
+** This function tells pyo to process a buffer of samples and fills the host's
+** output buffer with new samples. Should be called once per process block,
+** inside the host's audioOut function.
+**
+** arguments:
+**   *buffer : float *, float pointer pointing to the host's output buffers.
+*/
+void Pyo::process(float *buffer) {
+    pyoCallback(pyoId);
+    for (int i=0; i<(bufferSize*nChannels); i++) buffer[i] = pyoOutBuffer[i];
+}
+
+/*
+** Execute a python script "file" in the objectès thread's interpreter.
+** An integer "add" is needed to indicate if the pyo server should be
+** reboot or not.
+**
+** arguments:
+**   file : char *, filename to execute as a python script. The file is first
+**                  searched in the current working directory. If not found,
+**                  the module will try to open it as an absolute path.
+**   add, int, if positive, the commands in the file will be added to whatever
+**             is already running in the pyo server. If 0, the server will be
+**             cleared before executing the file.
+*/
+int Pyo::loadfile(const char *file, int add) {
+    return pyo_exec_file(interpreter, file, pyoMsg, add);
+}
+
+/*
+** Sends a numerical value to an existing Sig or SigTo object.
+**
+** arguments:
+**   name : const char *, variable name of the object.
+**   value : float, value to be assigned.
+**
+** Example:
+**
+** inside the script file:
+**
+** freq = SigTo(value=440, time=0.1, init=440)
+**
+** Inside OpenFrameworks (for a Pyo object named `pyo`):
+**
+** pyo.value("freq", 880);
+*/
+int Pyo::value(const char *name, float value) {
+    sprintf(pyoMsg, "%s.value=%f", name, value);
+    return pyo_exec_statement(interpreter, pyoMsg, 0);
+}
+
+/*
+** Sends an array of numerical values to an existing Sig or SigTo object.
+**
+** arguments:
+**   name : const char *, variable name of the object.
+**   value : float *, array of floats.
+**   len : int, number of elements in the array.
+**
+** Example:
+**
+** inside the script file:
+**
+** freq = SigTo(value=[100,200,300,400], time=0.1, init=[100,200,300,400])
+**
+** Inside OpenFrameworks (for a Pyo object named `pyo`):
+**
+** float frequencies[4] = {150, 250, 350, 450};
+** pyo.value("freq", frequencies, 4);
+*/
+int Pyo::value(const char *name, float *value, int len) {
+    char fchar[32];
+    sprintf(pyoMsg, "%s.value=[", name);
+    for (int i=0; i<len; i++) {
+        sprintf(fchar, "%f,", value[i]);
+        strcat(pyoMsg, fchar);
+    }
+    strcat(pyoMsg, "]");
+    return pyo_exec_statement(interpreter, pyoMsg, 0);
+}
+
+/*
+** Sends a numerical value to a Pyo object's attribute.
+**
+** arguments:
+**   name : const char *, object name and attribute separated by a dot.
+**   value : float, value to be assigned.
+**
+** Example:
+**
+** inside the script file:
+**
+** filter = Biquad(input=Noise(0.5), freq=1000, q=4, type=2)
+**
+** Inside OpenFrameworks (for a Pyo object named `pyo`):
+**
+** pyo.set("filter.freq", 2000);
+*/
+int Pyo::set(const char *name, float value) {
+    sprintf(pyoMsg, "%s=%f", name, value);
+    return pyo_exec_statement(interpreter, pyoMsg, 0);
+}
+
+/*
+** Sends an array of numerical values to a Pyo object's attribute.
+**
+** arguments:
+**   name : const char *, object name and attribute separated by a dot.
+**   value : float *, array of floats.
+**   len : int, number of elements in the array.
+**
+** Example:
+**
+** inside the script file:
+**
+** filters = Biquad(input=Noise(0.5), freq=[250, 500, 1000, 2000], q=5, type=2)
+**
+** Inside OpenFrameworks (for a Pyo object named `pyo`):
+**
+** float frequencies[4] = {350, 700, 1400, 2800};
+** pyo.set("filters.freq", frequencies, 4);
+*/
+int Pyo::set(const char *name, float *value, int len) {
+    char fchar[32];
+    sprintf(pyoMsg, "%s=[", name);
+    for (int i=0; i<len; i++) {
+        sprintf(fchar, "%f,", value[i]);
+        strcat(pyoMsg, fchar);
+    }
+    strcat(pyoMsg, "]");
+    return pyo_exec_statement(interpreter, pyoMsg, 0);
+}
+
+/*
+** Executes any raw valid python statement. With this function, one can dynamically
+** creates and manipulates audio objects and algorithms.
+**
+** arguments:
+**   msg : const char *, pointer to a string containing the statement to execute.
+**
+** Example (for a Pyo object named `pyo`):
+**
+** pyo.exec("pits = [0.001, 0.002, 0.003, 0.004]")
+** pyo.exec("fr = Rossler(pitch=pits, chaos=0.9, mul=250, add=500)")
+** pyo.exec("b = SumOsc(freq=fr, ratio=0.499, index=0.4, mul=0.2).out()")
+*/
+int Pyo::exec(const char *_msg) {
+    strcpy(pyoMsg, _msg);
+    return pyo_exec_statement(interpreter, pyoMsg, 0);
+}
+
+/*
+** Shutdown and reboot the pyo server while keeping current in/out buffers.
+** This will erase audio objects currently active within the server.
+**
+*/void Pyo::clear() {
+    pyo_server_reboot(interpreter);
+}
diff --git a/embedded/openframeworks/PyoClass.h b/embedded/openframeworks/PyoClass.h
new file mode 100644
index 0000000..2ca65b4
--- /dev/null
+++ b/embedded/openframeworks/PyoClass.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include "m_pyo.h"
+
+typedef int callPtr(int);
+
+class Pyo {
+    public:
+        ~Pyo();
+        void setup(int nChannels, int bufferSize, int sampleRate);
+        void process(float *buffer);
+        void fillin(float *buffer);
+        void clear();
+        int loadfile(const char *file, int add);
+        int exec(const char *msg);
+        int value(const char *name, float value);
+        int value(const char *name, float *value, int len);
+        int set(const char *name, float value);
+        int set(const char *name, float *value, int len);
+
+    private:
+        int nChannels;
+        int bufferSize;
+        int sampleRate;
+        PyThreadState *interpreter;
+        float *pyoInBuffer;
+        float *pyoOutBuffer;
+        callPtr *pyoCallback;
+        int pyoId;
+        char pyoMsg[262144];
+};
diff --git a/embedded/openframeworks/README b/embedded/openframeworks/README
new file mode 100644
index 0000000..6d02d4d
--- /dev/null
+++ b/embedded/openframeworks/README
@@ -0,0 +1,106 @@
+Introduction on how to use pyo inside an OpenFrameworks project.
+================================================================ 
+
+To use pyo inside an OpenFrameworks project, first you need a 
+working install of pyo on your system. After installing pyo,
+you can move on and create an OpenFrameworks project.
+
+------------------------------------------------------------------------
+Step 1 - Create a default project with the project generator. To avoid
+any include or linking problem, you should save your project in the 
+default location (OF_ROOT/apps/myApps).
+
+------------------------------------------------------------------------
+Step 2 - Add pyo files to your project. You only need to copy 
+these files in your project's src folder:
+
+- from the folder pyo/embedded:
+m_pyo.h
+
+- from the folder pyo/embedded/openframeworks:
+PyoClass.cpp
+PyoClass.h
+
+------------------------------------------------------------------------
+Step 3 - Make sure that your project includes flags for compiling 
+and linking against Python. On Unix systems, you can set the Python 
+flags in the file config.make. Uncomment and complete these lines:
+
+PROJECT_LDFLAGS = `python-config --ldflags` # linker flags for Python
+PROJECT_CFLAGS = `python-config --cflags` # compiler flags for Python
+
+------------------------------------------------------------------------
+Step 4 - Make a scripts folder at the root level of your project and 
+create a python file, named "stereoDelay.py", with these lines in it:
+
+# Get the input sound and apply a stereo delay + reverb on it.
+st_input = Input([0,1])
+st_delay = Delay(st_input, delay=[.4, .5], feedback=0.7)
+st_rev = WGVerb(st_delay, feedback=0.8, cutoff=4000, bal=0.25).out()
+
+------------------------------------------------------------------------
+Step 5 - Edit src/ofApp.h
+
+- Include PyoClass definition:
+
+#include "PyoClass.h"
+
+- Add audio in/out callbacks to the public attributes of the ofApp class:
+
+void audioIn(float * input, int bufferSize, int nChannels);
+void audioOut(float * input, int bufferSize, int nChannels);
+
+- Add an ofSoundStream object to the public attributes of the ofApp class:
+
+ofSoundStream soundStream;
+
+- Add a Pyo object to the public attributes of the ofApp class:
+
+Pyo pyo;
+
+------------------------------------------------------------------------
+Step 6 - Edit src/ofApp.cpp
+
+- Creates the setup() function:
+
+void ofApp::setup(){
+    // define audio properties
+    int sampleRate = 44100;
+    int bufferSize = 256;
+    int nChannels = 2;
+    // initialize a pyo server
+    pyo.setup(nChannels, bufferSize, sampleRate);
+    // load a python file
+    pyo.loadfile("../scripts/stereoDelay.py", 0);
+    // initialize OpenFrameworks audio streaming channels 
+    //soundStream.listDevices()     // Uncomment if you need to
+    //soundStream.setDeviceID(1);   // change the audio device.
+	soundStream.setup(this, nChannels, nChannels, sampleRate, bufferSize, 4);
+}
+
+- Creates audio in/out functions:
+
+void ofApp::audioIn(float * input, int bufferSize, int nChannels){
+    // send audio samples to pyo
+    pyo.fillin(input);
+}
+
+void ofApp::audioOut(float * output, int bufferSize, int nChannels){
+    // process and get new audio samples from pyo
+    pyo.process(output);
+}
+
+------------------------------------------------------------------------
+Here you go! Compile, Run and Enjoy!
+
+Documentation
+=============
+
+For a complete description of functions that can be used to communicate 
+with the pyo embedded processes, see documentation comments in the file 
+PyoClass.cpp.
+
+
+(c) 2015 - belangeo
+
+
diff --git a/embedded/puredata/Makefile b/embedded/puredata/Makefile
new file mode 100644
index 0000000..6637883
--- /dev/null
+++ b/embedded/puredata/Makefile
@@ -0,0 +1,467 @@
+## Pd library template version 1.0.13
+# For instructions on how to use this template, see:
+#  http://puredata.info/docs/developer/MakefileTemplate
+LIBRARY_NAME = pyo~
+
+# add your .c source files, one object per file, to the SOURCES
+# variable, help files will be included automatically, and for GUI
+# objects, the matching .tcl file too
+SOURCES = pyo~.c
+
+# list all pd objects (i.e. myobject.pd) files here, and their helpfiles will
+# be included automatically
+PDOBJECTS = pyo~.pd
+
+# example patches and related files, in the 'examples' subfolder
+EXAMPLES = 
+
+# manuals and related files, in the 'manual' subfolder
+MANUAL = manual.txt
+
+# if you want to include any other files in the source and binary tarballs,
+# list them here.  This can be anything from header files, test patches,
+# documentation, etc.  README.txt and LICENSE.txt are required and therefore
+# automatically included
+EXTRA_DIST = m_pyo.h
+
+# unit tests and related files here, in the 'unittests' subfolder
+UNITTESTS = 
+
+# added to support the multiple shared source files
+SHARED_SOURCE = 
+SHARED_LIB = lib$(LIBRARY_NAME).$(SHARED_EXTENSION)
+
+
+#------------------------------------------------------------------------------#
+#
+# things you might need to edit if you are using other C libraries
+#
+#------------------------------------------------------------------------------#
+UNAME := $(shell uname -s)
+ifeq (MINGW,$(findstring MINGW,$(UNAME)))
+    ALL_CFLAGS = -I"$(PD_INCLUDE)" -I.. -Wno-unused-parameter -I/c/Python27/include
+    ALL_LDFLAGS =  -lpython27
+    SHARED_LDFLAGS =
+    ALL_LIBS = -L/c/Python27/libs
+endif
+ifeq ($(UNAME),Darwin)
+    MAC_SDK =                # put the path to your base SDK if you have problem to compile with the one given by python (ex: /Developer/SDKs/MacOSX10.6.sdk)
+    ARCH_TYPE = i386         # can put multiple architectures if they are available with your environment (ex: ppc i386)
+    ifeq ($(MAC_SDK),)
+        PYTHONFLAGS = $(shell python-config --cflags)
+    else
+        PYTHONFLAGS = $(patsubst /%, $(MAC_SDK), $(shell python-config --cflags))
+    endif
+    ALL_CFLAGS = -I"$(PD_INCLUDE)" -I.. -Wno-unused-parameter $(PYTHONFLAGS)
+    ALL_LDFLAGS = $(shell python-config --ldflags)
+    SHARED_LDFLAGS =
+    # ALL_LIBS = $(shell python-config --libs)
+    ALL_LIBS = -ldl -framework CoreFoundation -framework Python
+endif
+ifeq ($(UNAME),Linux)
+    ALL_CFLAGS = -I"$(PD_INCLUDE)" -I.. -Wno-unused-parameter $(shell python-config --cflags)
+    ALL_LDFLAGS =  $(shell python-config --ldflags)
+    SHARED_LDFLAGS =
+    ALL_LIBS = $(shell python-config --libs)
+endif
+
+#------------------------------------------------------------------------------#
+#
+# you shouldn't need to edit anything below here, if we did it right :)
+#
+#------------------------------------------------------------------------------#
+
+# these can be set from outside without (usually) breaking the build
+CFLAGS = -Wall -W -g
+LDFLAGS =
+LIBS =
+
+# get library version from meta file
+LIBRARY_VERSION = $(shell sed -n 's|^\#X text [0-9][0-9]* [0-9][0-9]* VERSION \(.*\);|\1|p' $(LIBRARY_NAME)-meta.pd)
+
+ALL_CFLAGS += -DPD -DVERSION='"$(LIBRARY_VERSION)"'
+
+PD_INCLUDE = $(PD_PATH)/include/pd
+# where to install the library, overridden below depending on platform
+prefix = /usr/local
+libdir = $(prefix)/lib
+pkglibdir = $(libdir)/pd-externals
+objectsdir = $(pkglibdir)
+
+INSTALL = install
+INSTALL_PROGRAM = $(INSTALL) -p -m 644
+INSTALL_DATA = $(INSTALL) -p -m 644
+INSTALL_DIR     = $(INSTALL) -p -m 755 -d
+
+ALLSOURCES := $(SOURCES) $(SOURCES_android) $(SOURCES_cygwin) $(SOURCES_macosx) \
+	         $(SOURCES_iphoneos) $(SOURCES_linux) $(SOURCES_windows)
+
+DISTDIR=$(LIBRARY_NAME)-$(LIBRARY_VERSION)
+ORIGDIR=pd-$(LIBRARY_NAME:~=)_$(LIBRARY_VERSION)
+
+UNAME := $(shell uname -s)
+ifeq ($(UNAME),Darwin)
+  CPU := $(shell uname -p)
+  ifeq ($(CPU),arm) # iPhone/iPod Touch
+    SOURCES += $(SOURCES_iphoneos)
+    EXTENSION = pd_darwin
+    SHARED_EXTENSION = dylib
+    OS = iphoneos
+    PD_PATH = /Applications/Pd-extended.app/Contents/Resources
+    IPHONE_BASE=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin
+    CC=$(IPHONE_BASE)/gcc
+    CPP=$(IPHONE_BASE)/cpp
+    CXX=$(IPHONE_BASE)/g++
+    ISYSROOT = -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk
+    IPHONE_CFLAGS = -miphoneos-version-min=3.0 $(ISYSROOT) -arch armv6
+    OPT_CFLAGS = -fast -funroll-loops -fomit-frame-pointer
+    ALL_CFLAGS := $(IPHONE_CFLAGS) $(ALL_CFLAGS)
+    ALL_LDFLAGS += -arch armv6 -bundle -undefined dynamic_lookup $(ISYSROOT)
+    SHARED_LDFLAGS += -arch armv6 -dynamiclib -undefined dynamic_lookup $(ISYSROOT)
+    ALL_LIBS += -lc $(LIBS_iphoneos)
+    STRIP = strip -x
+    DISTBINDIR=$(DISTDIR)-$(OS)
+  else # Mac OS X
+    SOURCES += $(SOURCES_macosx)
+    EXTENSION = pd_darwin
+    SHARED_EXTENSION = dylib
+    OS = macosx
+    PD_PATH = /Applications/Pd-extended.app/Contents/Resources
+    OPT_CFLAGS = -ftree-vectorize -ftree-vectorizer-verbose=2 -fast
+# build universal 32-bit on 10.4 and 32/64 on newer
+    ifeq ($(shell uname -r | sed 's|\([0-9][0-9]*\)\.[0-9][0-9]*\.[0-9][0-9]*|\1|'), 8)
+      # FAT_FLAGS = -arch ppc -arch i386 -mmacosx-version-min=10.5
+      ARCHWITHOUT64 := $(filter-out x86_64,$(ARCH_TYPE))
+      FAT_FLAGS = $(patsubst %,-arch %, $(ARCHWITHOUT64)) -mmacosx-version-min=10.5
+    else
+      # FAT_FLAGS = -arch ppc -arch i386 -arch x86_64 -mmacosx-version-min=10.5
+      FAT_FLAGS = $(patsubst %,-arch %, $(ARCH_TYPE)) -mmacosx-version-min=10.5
+      SOURCES += $(SOURCES_iphoneos)
+    endif
+    ALL_CFLAGS += $(FAT_FLAGS) -fPIC -I/sw/include
+    # if the 'pd' binary exists, check the linking against it to aid with stripping
+    BUNDLE_LOADER = $(shell test ! -e $(PD_PATH)/bin/pd || echo -bundle_loader $(PD_PATH)/bin/pd)
+    ALL_LDFLAGS += $(FAT_FLAGS) -headerpad_max_install_names -bundle $(BUNDLE_LOADER) \
+	-undefined dynamic_lookup -L/sw/lib
+    SHARED_LDFLAGS += $(FAT_FLAGS) -dynamiclib -undefined dynamic_lookup \
+	-install_name @loader_path/$(SHARED_LIB) -compatibility_version 1 -current_version 1.0
+    ALL_LIBS += -lc $(LIBS_macosx)
+    STRIP = strip -x
+    DISTBINDIR=$(DISTDIR)-$(OS)
+# install into ~/Library/Pd on Mac OS X since /usr/local isn't used much
+    pkglibdir=$(HOME)/Library/Pd
+  endif
+endif
+# Tho Android uses Linux, we use this fake uname to provide an easy way to
+# setup all this things needed to cross-compile for Android using the NDK
+ifeq ($(UNAME),ANDROID)
+  CPU := arm
+  SOURCES += $(SOURCES_android)
+  EXTENSION = pd_linux
+  SHARED_EXTENSION = so
+  OS = android
+  PD_PATH = /usr
+  NDK_BASE := /usr/local/android-ndk
+  NDK_PLATFORM_VERSION := 5
+  NDK_SYSROOT=$(NDK_BASE)/platforms/android-$(NDK_PLATFORM_VERSION)/arch-arm
+  NDK_UNAME := $(shell uname -s | tr '[A-Z]' '[a-z]')
+  NDK_TOOLCHAIN_BASE=$(NDK_BASE)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/$(NDK_UNAME)-x86
+  CC := $(NDK_TOOLCHAIN_BASE)/bin/arm-linux-androideabi-gcc --sysroot=$(NDK_SYSROOT)
+  OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
+  CFLAGS += 
+  LDFLAGS += -rdynamic -shared
+  SHARED_LDFLAGS += -Wl,-soname,$(SHARED_LIB) -shared
+  LIBS += -lc $(LIBS_android)
+  STRIP := $(NDK_TOOLCHAIN_BASE)/bin/arm-linux-androideabi-strip \
+	--strip-unneeded -R .note -R .comment
+  DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m)
+endif
+ifeq ($(UNAME),Linux)
+  CPU := $(shell uname -m)
+  SOURCES += $(SOURCES_linux)
+  EXTENSION = pd_linux
+  SHARED_EXTENSION = so
+  OS = linux
+  PD_PATH = /usr
+  OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
+  ALL_CFLAGS += -fPIC
+  ALL_LDFLAGS += -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags
+  SHARED_LDFLAGS += -Wl,-soname,$(SHARED_LIB) -shared
+  ALL_LIBS += -lc $(LIBS_linux)
+  STRIP = strip --strip-unneeded -R .note -R .comment
+  DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m)
+endif
+ifeq ($(UNAME),GNU)
+  # GNU/Hurd, should work like GNU/Linux for basically all externals
+  CPU := $(shell uname -m)
+  SOURCES += $(SOURCES_linux)
+  EXTENSION = pd_linux
+  SHARED_EXTENSION = so
+  OS = linux
+  PD_PATH = /usr
+  OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
+  ALL_CFLAGS += -fPIC
+  ALL_LDFLAGS += -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags
+  SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB)
+  ALL_LIBS += -lc $(LIBS_linux)
+  STRIP = strip --strip-unneeded -R .note -R .comment
+  DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m)
+endif
+ifeq ($(UNAME),GNU/kFreeBSD)
+  # Debian GNU/kFreeBSD, should work like GNU/Linux for basically all externals
+  CPU := $(shell uname -m)
+  SOURCES += $(SOURCES_linux)
+  EXTENSION = pd_linux
+  SHARED_EXTENSION = so
+  OS = linux
+  PD_PATH = /usr
+  OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
+  ALL_CFLAGS += -fPIC
+  ALL_LDFLAGS += -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags
+  SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB)
+  ALL_LIBS += -lc $(LIBS_linux)
+  STRIP = strip --strip-unneeded -R .note -R .comment
+  DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m)
+endif
+ifeq (CYGWIN,$(findstring CYGWIN,$(UNAME)))
+  CPU := $(shell uname -m)
+  SOURCES += $(SOURCES_cygwin)
+  EXTENSION = dll
+  SHARED_EXTENSION = dll
+  OS = cygwin
+  PD_PATH = $(shell cygpath $$PROGRAMFILES)/pd
+  OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer
+  ALL_CFLAGS += 
+  ALL_LDFLAGS += -rdynamic -shared -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin"
+  SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB)
+  ALL_LIBS += -lc -lpd $(LIBS_cygwin)
+  STRIP = strip --strip-unneeded -R .note -R .comment
+  DISTBINDIR=$(DISTDIR)-$(OS)
+endif
+ifeq (MINGW,$(findstring MINGW,$(UNAME)))
+  CPU := $(shell uname -m)
+  SOURCES += $(SOURCES_windows)
+  EXTENSION = dll
+  SHARED_EXTENSION = dll
+  OS = windows
+  PD_PATH = $(shell cd "$$PROGRAMFILES/pd" && pwd)
+  # MinGW doesn't seem to include cc so force gcc
+  CC=gcc
+  OPT_CFLAGS = -O3 -funroll-loops -fomit-frame-pointer
+  ALL_CFLAGS += -mms-bitfields
+  ALL_LDFLAGS += -s -shared -Wl,--enable-auto-import
+  SHARED_LDFLAGS += -shared
+  ALL_LIBS += -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin" -L"$(PD_PATH)/obj" \
+	-lpd -lwsock32 -lkernel32 -luser32 -lgdi32 -liberty $(LIBS_windows)
+  STRIP = strip --strip-unneeded -R .note -R .comment
+  DISTBINDIR=$(DISTDIR)-$(OS)
+endif
+
+# in case somebody manually set the HELPPATCHES above
+HELPPATCHES ?= $(SOURCES:.c=-help.pd) $(PDOBJECTS:.pd=-help.pd)
+
+ALL_CFLAGS := $(ALL_CFLAGS) $(CFLAGS) $(OPT_CFLAGS)
+ALL_LDFLAGS := $(LDFLAGS) $(ALL_LDFLAGS)
+ALL_LIBS := $(LIBS) $(ALL_LIBS)
+
+SHARED_SOURCE ?= $(wildcard lib$(LIBRARY_NAME).c)
+SHARED_HEADER ?= $(shell test ! -e $(LIBRARY_NAME).h || echo $(LIBRARY_NAME).h)
+SHARED_LIB ?= $(SHARED_SOURCE:.c=.$(SHARED_EXTENSION))
+SHARED_TCL_LIB = $(wildcard lib$(LIBRARY_NAME).tcl)
+
+.PHONY = install libdir_install single_install install-doc install-examples install-manual install-unittests clean distclean dist etags $(LIBRARY_NAME)
+
+all: $(SOURCES:.c=.$(EXTENSION)) $(SHARED_LIB)
+
+%.o: %.c
+	$(CC) $(ALL_CFLAGS) -o "$*.o" -c "$*.c"
+
+%.$(EXTENSION): %.o $(SHARED_LIB)
+	$(CC) $(ALL_LDFLAGS) -o "$*.$(EXTENSION)" "$*.o"  $(ALL_LIBS) $(SHARED_LIB)
+	chmod a-x "$*.$(EXTENSION)"
+
+# this links everything into a single binary file
+$(LIBRARY_NAME): $(SOURCES:.c=.o) $(LIBRARY_NAME).o lib$(LIBRARY_NAME).o
+	$(CC) $(ALL_LDFLAGS) -o $(LIBRARY_NAME).$(EXTENSION) $(SOURCES:.c=.o) \
+		$(LIBRARY_NAME).o lib$(LIBRARY_NAME).o $(ALL_LIBS)
+	chmod a-x $(LIBRARY_NAME).$(EXTENSION)
+
+$(SHARED_LIB): $(SHARED_SOURCE:.c=.o)
+	$(CC) $(SHARED_LDFLAGS) -o $(SHARED_LIB) $(SHARED_SOURCE:.c=.o) $(ALL_LIBS)
+
+install: single_install
+
+# The meta and help files are explicitly installed to make sure they are
+# actually there.  Those files are not optional, then need to be there.
+libdir_install: $(SOURCES:.c=.$(EXTENSION)) $(SHARED_LIB) install-doc install-examples install-manual install-unittests
+	$(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+	$(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd \
+		$(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+	test -z "$(strip $(SOURCES))" || (\
+		$(INSTALL_PROGRAM) $(SOURCES:.c=.$(EXTENSION)) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) && \
+		$(STRIP) $(addprefix $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/,$(SOURCES:.c=.$(EXTENSION))))
+	test -z "$(strip $(SHARED_LIB))" || \
+		$(INSTALL_DATA) $(SHARED_LIB) \
+			$(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+	test -z "$(strip $(wildcard $(SOURCES:.c=.tcl)))" || \
+		$(INSTALL_DATA) $(wildcard $(SOURCES:.c=.tcl)) \
+			$(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+	test -z "$(strip $(PDOBJECTS))" || \
+		$(INSTALL_DATA) $(PDOBJECTS) \
+			$(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+	test -z "$(strip $(SHARED_TCL_LIB))" || \
+		$(INSTALL_DATA) $(SHARED_TCL_LIB) \
+			$(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+
+# install library linked as single binary
+single_install: $(LIBRARY_NAME) install-doc install-examples install-manual install-unittests
+	$(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+	$(INSTALL_PROGRAM) $(LIBRARY_NAME).$(EXTENSION) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+	$(STRIP) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/$(LIBRARY_NAME).$(EXTENSION)
+
+install-doc:
+	$(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+	test -z "$(strip $(SOURCES) $(PDOBJECTS))" || \
+		$(INSTALL_DATA) $(HELPPATCHES) \
+			$(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)
+	$(INSTALL_DATA) README.txt $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/README.txt
+	$(INSTALL_DATA) LICENSE.txt $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/LICENSE.txt
+
+install-examples:
+	test -z "$(strip $(EXAMPLES))" || \
+		$(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/examples && \
+		for file in $(EXAMPLES); do \
+			$(INSTALL_DATA) examples/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/examples; \
+		done
+
+install-manual:
+	test -z "$(strip $(MANUAL))" || \
+		$(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/manual && \
+		for file in $(MANUAL); do \
+			$(INSTALL_DATA) manual/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/manual; \
+		done
+
+install-unittests:
+	test -z "$(strip $(UNITTESTS))" || \
+		$(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/unittests && \
+		for file in $(UNITTESTS); do \
+			$(INSTALL_DATA) unittests/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/unittests; \
+		done
+
+clean:
+	-rm -f -- $(SOURCES:.c=.o) $(SOURCES_LIB:.c=.o) $(SHARED_SOURCE:.c=.o)
+	-rm -f -- $(SOURCES:.c=.$(EXTENSION))
+	-rm -f -- $(LIBRARY_NAME).o
+	-rm -f -- $(LIBRARY_NAME).$(EXTENSION)
+	-rm -f -- $(SHARED_LIB)
+
+distclean: clean
+	-rm -f -- $(DISTBINDIR).tar.gz
+	-rm -rf -- $(DISTBINDIR)
+	-rm -f -- $(DISTDIR).tar.gz
+	-rm -rf -- $(DISTDIR)
+	-rm -f -- $(ORIGDIR).tar.gz
+	-rm -rf -- $(ORIGDIR)
+
+
+$(DISTBINDIR):
+	$(INSTALL_DIR) $(DISTBINDIR)
+
+libdir: all $(DISTBINDIR)
+	$(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd  $(DISTBINDIR)
+	$(INSTALL_DATA) $(SOURCES) $(SHARED_SOURCE) $(SHARED_HEADER) $(DISTBINDIR)
+	$(INSTALL_DATA) $(HELPPATCHES) $(DISTBINDIR)
+	test -z "$(strip $(EXTRA_DIST))" || \
+		$(INSTALL_DATA) $(EXTRA_DIST)    $(DISTBINDIR)
+#	tar --exclude-vcs -czpf $(DISTBINDIR).tar.gz $(DISTBINDIR)
+
+$(DISTDIR):
+	$(INSTALL_DIR) $(DISTDIR)
+
+$(ORIGDIR):
+	$(INSTALL_DIR) $(ORIGDIR)
+
+dist: $(DISTDIR)
+	$(INSTALL_DATA) Makefile  $(DISTDIR)
+	$(INSTALL_DATA) README.txt $(DISTDIR)
+	$(INSTALL_DATA) LICENSE.txt $(DISTDIR)
+	$(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd  $(DISTDIR)
+	test -z "$(strip $(ALLSOURCES))" || \
+		$(INSTALL_DATA) $(ALLSOURCES)  $(DISTDIR)
+	test -z "$(strip $(wildcard $(ALLSOURCES:.c=.tcl)))" || \
+		$(INSTALL_DATA) $(wildcard $(ALLSOURCES:.c=.tcl))  $(DISTDIR)
+	test -z "$(strip $(wildcard $(LIBRARY_NAME).c))" || \
+		$(INSTALL_DATA) $(LIBRARY_NAME).c  $(DISTDIR)
+	test -z "$(strip $(SHARED_HEADER))" || \
+		$(INSTALL_DATA) $(SHARED_HEADER)  $(DISTDIR)
+	test -z "$(strip $(SHARED_SOURCE))" || \
+		$(INSTALL_DATA) $(SHARED_SOURCE)  $(DISTDIR)
+	test -z "$(strip $(SHARED_TCL_LIB))" || \
+		$(INSTALL_DATA) $(SHARED_TCL_LIB)  $(DISTDIR)
+	test -z "$(strip $(PDOBJECTS))" || \
+		$(INSTALL_DATA) $(PDOBJECTS)  $(DISTDIR)
+	test -z "$(strip $(HELPPATCHES))" || \
+		$(INSTALL_DATA) $(HELPPATCHES) $(DISTDIR)
+	test -z "$(strip $(EXTRA_DIST))" || \
+		$(INSTALL_DATA) $(EXTRA_DIST)    $(DISTDIR)
+	test -z "$(strip $(EXAMPLES))" || \
+		$(INSTALL_DIR) $(DISTDIR)/examples && \
+		for file in $(EXAMPLES); do \
+			$(INSTALL_DATA) examples/$$file $(DISTDIR)/examples; \
+		done
+	test -z "$(strip $(MANUAL))" || \
+		$(INSTALL_DIR) $(DISTDIR)/manual && \
+		for file in $(MANUAL); do \
+			$(INSTALL_DATA) manual/$$file $(DISTDIR)/manual; \
+		done
+	test -z "$(strip $(UNITTESTS))" || \
+		$(INSTALL_DIR) $(DISTDIR)/unittests && \
+		for file in $(UNITTESTS); do \
+			$(INSTALL_DATA) unittests/$$file $(DISTDIR)/unittests; \
+		done
+	tar --exclude-vcs -czpf $(DISTDIR).tar.gz $(DISTDIR)
+
+# make a Debian source package
+dpkg-source:
+	debclean
+	make distclean dist
+	mv $(DISTDIR) $(ORIGDIR)
+	tar --exclude-vcs -czpf ../$(ORIGDIR).orig.tar.gz $(ORIGDIR)
+	rm -f -- $(DISTDIR).tar.gz
+	rm -rf -- $(DISTDIR) $(ORIGDIR)
+	cd .. && dpkg-source -b $(LIBRARY_NAME)
+
+etags: TAGS
+
+TAGS: $(wildcard $(PD_INCLUDE)/*.h) $(SOURCES) $(SHARED_SOURCE) $(SHARED_HEADER)
+	etags $(wildcard $(PD_INCLUDE)/*.h)
+	etags -a *.h $(SOURCES) $(SHARED_SOURCE) $(SHARED_HEADER)
+	etags -a --language=none --regex="/proc[ \t]+\([^ \t]+\)/\1/" *.tcl
+
+showsetup:
+	@echo "CC: $(CC)"
+	@echo "CFLAGS: $(CFLAGS)"
+	@echo "LDFLAGS: $(LDFLAGS)"
+	@echo "LIBS: $(LIBS)"
+	@echo "ALL_CFLAGS: $(ALL_CFLAGS)"
+	@echo "ALL_LDFLAGS: $(ALL_LDFLAGS)"
+	@echo "ALL_LIBS: $(ALL_LIBS)"
+	@echo "PD_INCLUDE: $(PD_INCLUDE)"
+	@echo "PD_PATH: $(PD_PATH)"
+	@echo "objectsdir: $(objectsdir)"
+	@echo "LIBRARY_NAME: $(LIBRARY_NAME)"
+	@echo "LIBRARY_VERSION: $(LIBRARY_VERSION)"
+	@echo "SOURCES: $(SOURCES)"
+	@echo "SHARED_HEADER: $(SHARED_HEADER)"
+	@echo "SHARED_SOURCE: $(SHARED_SOURCE)"
+	@echo "SHARED_LIB: $(SHARED_LIB)"
+	@echo "SHARED_TCL_LIB: $(SHARED_TCL_LIB)"
+	@echo "PDOBJECTS: $(PDOBJECTS)"
+	@echo "ALLSOURCES: $(ALLSOURCES)"
+	@echo "ALLSOURCES TCL: $(wildcard $(ALLSOURCES:.c=.tcl))"
+	@echo "UNAME: $(UNAME)"
+	@echo "CPU: $(CPU)"
+	@echo "pkglibdir: $(pkglibdir)"
+	@echo "DISTDIR: $(DISTDIR)"
+	@echo "ORIGDIR: $(ORIGDIR)"
+
diff --git a/embedded/puredata/examples/cvlverb.py b/embedded/puredata/examples/cvlverb.py
new file mode 100644
index 0000000..739e176
--- /dev/null
+++ b/embedded/puredata/examples/cvlverb.py
@@ -0,0 +1,3 @@
+bal = SigTo(0.25, 0.005, 0.25)
+ins = Input([0,1])
+dist = CvlVerb(ins, size=512, bal=bal, mul=0.3).out()
\ No newline at end of file
diff --git a/embedded/puredata/examples/midi_synth.py b/embedded/puredata/examples/midi_synth.py
new file mode 100644
index 0000000..518e1ed
--- /dev/null
+++ b/embedded/puredata/examples/midi_synth.py
@@ -0,0 +1,11 @@
+notein = Notein(scale=1)
+modwheel = Midictl(1, maxscale=0.2)
+
+amp = MidiAdsr(notein["velocity"], 0.001, 0.01, 0.7, 0.05)
+
+lfo = Sine(5, mul=modwheel, add=1)
+synth1 = RCOsc(freq=notein["pitch"]*lfo, sharp=0.75, mul=amp)
+synth2 = RCOsc(freq=notein["pitch"]*lfo*1.01, sharp=0.74, mul=amp)
+stereo = Mix([synth1.mix(1), synth2.mix(1)], voices=2)
+rev = STRev(stereo, inpos=[0,1], revtime=2, bal=0.25, mul=0.2).out()
+
diff --git a/embedded/puredata/examples/random_waves.py b/embedded/puredata/examples/random_waves.py
new file mode 100644
index 0000000..6b9cc90
--- /dev/null
+++ b/embedded/puredata/examples/random_waves.py
@@ -0,0 +1,13 @@
+import random
+
+feed = SigTo(0.05, 0.05, 0.05)
+amp = Fader(fadein=0.005, fadeout=0.12, dur=0.125)
+syn = SineLoop(freq=[500,510], feedback=feed, mul=amp*amp)
+rev = WGVerb(syn, feedback=0.85, cutoff=4500, bal=0.1).out()
+
+def choose(a, b):
+    x = random.randint(a, b)
+    deg = [0,2,3,5,7,8,11][x%7]
+    hz = midiToHz(deg + (x / 7 * 12 + 36))
+    syn.freq = [hz,hz*1.005]
+    amp.play()
diff --git a/embedded/puredata/examples/resonators.py b/embedded/puredata/examples/resonators.py
new file mode 100644
index 0000000..233ae54
--- /dev/null
+++ b/embedded/puredata/examples/resonators.py
@@ -0,0 +1,8 @@
+reson = SigTo(2, 0.005, 2)
+freqs = SigTo([50,100,150,200,250,300,350,400], time=0.2)
+
+ins = Input([0,1])
+wgs = Waveguide(ins, freq=freqs, dur=reson, mul=0.1)
+wgss = wgs.mix(2)
+wgss.out()
+
diff --git a/embedded/puredata/examples/resonators_add_delays.py b/embedded/puredata/examples/resonators_add_delays.py
new file mode 100644
index 0000000..554ecce
--- /dev/null
+++ b/embedded/puredata/examples/resonators_add_delays.py
@@ -0,0 +1,3 @@
+deltime = SigTo(.25, 0.005, 0.25)
+delfeed = SigTo(.25, 0.005, 0.25)
+dd = Delay(wgs, delay=deltime, feedback=delfeed).out(0)
diff --git a/embedded/puredata/pyo~-help.pd b/embedded/puredata/pyo~-help.pd
new file mode 100644
index 0000000..730d8c2
--- /dev/null
+++ b/embedded/puredata/pyo~-help.pd
@@ -0,0 +1,380 @@
+#N canvas 249 157 1013 410 10;
+#X obj 28 118 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 144 118 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 13 244 *~;
+#X obj 51 244 *~;
+#X obj 13 266 dac~;
+#X obj 72 223 hsl 128 15 0 1 0 1 empty empty master_gain -2 -8 0 10
+-262144 -1 -1 12700 1;
+#X obj 274 233 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1
+1;
+#X msg 274 253 \; pd dsp \$1;
+#X obj 13 69 r msg_to_pyo;
+#X text 161 117 play;
+#X obj 13 176 pyo~ 2;
+#X text 66 178 argument sets the number of audio ins/outs (defaults
+to 2).;
+#N canvas 1 75 824 583 resonators_example 0;
+#X obj 35 103 hsl 128 15 0.01 30 1 0 empty empty resonance -2 -8 0
+10 -262144 -1 -1 0 0;
+#X floatatom 32 120 5 0 0 0 - - -, f 5;
+#X obj 21 530 s msg_to_pyo;
+#X obj 98 387 hsl 128 15 0 1 0 0 empty empty delay_time -2 -8 0 10
+-262144 -1 -1 0 0;
+#X floatatom 95 403 5 0 0 0 - - -, f 5;
+#X msg 95 418 value deltime \$1;
+#X obj 111 454 hsl 128 15 0 1 0 0 empty empty delay_feedback -2 -8
+0 10 -262144 -1 -1 0 0;
+#X floatatom 108 470 5 0 0 0 - - -, f 5;
+#X msg 108 485 value delfeed \$1;
+#X msg 32 136 value reson \$1;
+#X obj 52 177 vsl 15 80 50 500 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 0;
+#X obj 71 177 vsl 15 80 50 500 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 0;
+#X obj 91 177 vsl 15 80 50 500 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 0;
+#X obj 110 177 vsl 15 80 50 500 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 0;
+#X obj 130 177 vsl 15 80 50 500 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 0;
+#X obj 149 177 vsl 15 80 50 500 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 0;
+#X obj 169 177 vsl 15 80 50 500 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 0;
+#X obj 189 177 vsl 15 80 50 500 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 0 0;
+#X msg 52 306 value freqs \$1 \$2 \$3 \$4 \$5 \$6 \$7 \$8;
+#X obj 52 264 bondo 8 ____________;
+#X obj 52 285 pack f f f f f f f f;
+#X msg 21 66 read examples/resonators.py;
+#X msg 73 351 read -a examples/resonators_add_delays.py;
+#X text 52 159 resonator frequencies;
+#X text 20 30 load pyo processing file (audio signal must be given
+in pyo~ inputs).;
+#X text 168 103 adjust resonance in seconds;
+#X text 214 209 play with resonator frequencies;
+#X text 380 352 add a stereo delay taking resonator outputs as its
+input;
+#X text 234 387 adjust delay time;
+#X text 246 453 adjust delay feedback;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 3 0 4 0;
+#X connect 4 0 5 0;
+#X connect 5 0 2 0;
+#X connect 6 0 7 0;
+#X connect 7 0 8 0;
+#X connect 8 0 2 0;
+#X connect 9 0 2 0;
+#X connect 10 0 19 0;
+#X connect 11 0 19 1;
+#X connect 12 0 19 2;
+#X connect 13 0 19 3;
+#X connect 14 0 19 4;
+#X connect 15 0 19 5;
+#X connect 16 0 19 6;
+#X connect 17 0 19 7;
+#X connect 18 0 2 0;
+#X connect 19 0 20 0;
+#X connect 19 1 20 1;
+#X connect 19 2 20 2;
+#X connect 19 3 20 3;
+#X connect 19 4 20 4;
+#X connect 19 5 20 5;
+#X connect 19 6 20 6;
+#X connect 19 7 20 7;
+#X connect 20 0 18 0;
+#X connect 21 0 2 0;
+#X connect 22 0 2 0;
+#X restore 531 36 pd resonators_example;
+#X msg 553 171 clear;
+#X obj 531 199 s msg_to_pyo;
+#X text 598 172 shutdown and reboot the server;
+#N canvas 1 75 450 300 synthesis_example 0;
+#N canvas 1 75 375 358 choose_sines 0;
+#X obj 57 77 metro 125;
+#X obj 78 109 hsl 128 15 0 36 0 0 empty empty empty -2 -8 0 10 -262144
+-1 -1 4233 1;
+#X obj 127 144 hsl 128 15 0 36 0 0 empty empty empty -2 -8 0 10 -262144
+-1 -1 4233 1;
+#X floatatom 75 125 5 0 0 0 - - -, f 5;
+#X floatatom 124 160 5 0 0 0 - - -, f 5;
+#X obj 124 209 +;
+#X obj 124 179 t b f;
+#X obj 75 144 t f f;
+#X obj 57 240 int;
+#X obj 124 232 int;
+#X msg 57 288 call choose \$1 \$2;
+#X obj 57 311 outlet;
+#X obj 57 54 inlet;
+#X obj 57 265 pack 24 24;
+#X text 7 3 Choose a random midi pitch between x and x+y;
+#X text 213 109 x;
+#X text 263 142 y;
+#X obj 224 42 loadbang;
+#X msg 224 64 12;
+#X obj 117 54 inlet speed;
+#X connect 0 0 8 0;
+#X connect 1 0 3 0;
+#X connect 2 0 4 0;
+#X connect 3 0 7 0;
+#X connect 4 0 6 0;
+#X connect 5 0 9 0;
+#X connect 6 0 5 0;
+#X connect 6 1 5 1;
+#X connect 7 0 8 1;
+#X connect 7 1 5 0;
+#X connect 8 0 13 0;
+#X connect 9 0 13 1;
+#X connect 10 0 11 0;
+#X connect 12 0 0 0;
+#X connect 13 0 10 0;
+#X connect 17 0 18 0;
+#X connect 18 0 1 0;
+#X connect 18 0 2 0;
+#X connect 19 0 0 1;
+#X restore 53 130 pd choose_sines;
+#X obj 41 246 s msg_to_pyo;
+#X obj 53 96 tgl 25 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1
+;
+#X obj 67 172 hsl 128 15 0 0.25 0 0 empty empty brightness -2 -8 0
+10 -262144 -1 -1 0 0;
+#X floatatom 64 188 5 0 0 0 - - -, f 5;
+#X msg 64 203 value feed \$1;
+#X obj 158 75 hsl 128 15 50 500 0 0 empty empty metro_speed -2 -8 0
+10 -262144 -1 -1 0 1;
+#X floatatom 155 93 5 0 0 0 - - -, f 5;
+#X floatatom 222 186 5 0 0 0 - - -, f 5;
+#X msg 222 216 set amp.fadeout \$1;
+#X msg 281 184 set amp.dur \$1;
+#X floatatom 281 165 5 0 0 0 - - -, f 5;
+#X obj 222 132 * 0.001;
+#X obj 221 111 - 20;
+#X obj 222 165 - 0.005;
+#X msg 41 33 read -a examples/random_waves.py;
+#X text 54 80 GO!;
+#X connect 0 0 1 0;
+#X connect 2 0 0 0;
+#X connect 3 0 4 0;
+#X connect 4 0 5 0;
+#X connect 5 0 1 0;
+#X connect 6 0 7 0;
+#X connect 7 0 0 1;
+#X connect 7 0 13 0;
+#X connect 8 0 9 0;
+#X connect 9 0 1 0;
+#X connect 10 0 1 0;
+#X connect 11 0 10 0;
+#X connect 12 0 11 0;
+#X connect 12 0 14 0;
+#X connect 13 0 12 0;
+#X connect 14 0 8 0;
+#X connect 15 0 1 0;
+#X restore 531 60 pd synthesis_example;
+#N canvas 2 85 629 295 loop_soundfile 0;
+#X obj 43 42 openpanel;
+#X obj 43 64 t a b;
+#X obj 43 172 soundfiler;
+#X obj 236 80 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 43 20 inlet open file;
+#X obj 419 16 inlet start;
+#X obj 236 52 sel 1;
+#X obj 236 205 outlet~;
+#X obj 366 163 spigot 1;
+#X obj 43 128 pack s s s;
+#X obj 76 86 symbol \$0-table_l;
+#X obj 110 106 symbol \$0-table_r;
+#X msg 43 150 read -resize \$1 \$2 \$3;
+#X obj 44 200 table \$0-table_l;
+#X obj 44 223 table \$0-table_r;
+#X obj 442 206 outlet~;
+#X obj 236 140 tabplay~ \$0-table_l;
+#X obj 443 140 tabplay~ \$0-table_r;
+#X connect 0 0 1 0;
+#X connect 1 0 9 0;
+#X connect 1 1 10 0;
+#X connect 1 1 11 0;
+#X connect 3 0 16 0;
+#X connect 3 0 17 0;
+#X connect 4 0 0 0;
+#X connect 5 0 6 0;
+#X connect 5 0 8 1;
+#X connect 6 0 3 0;
+#X connect 8 0 16 0;
+#X connect 8 0 17 0;
+#X connect 9 0 12 0;
+#X connect 10 0 9 1;
+#X connect 11 0 9 2;
+#X connect 12 0 2 0;
+#X connect 16 0 7 0;
+#X connect 16 1 8 0;
+#X connect 17 0 15 0;
+#X restore 28 136 pd loop_soundfile;
+#X text 44 118 load file;
+#N canvas 302 92 532 224 conv_reverb_example 0;
+#X obj 24 110 hsl 128 15 0 1 0 0 empty empty balance -2 -8 0 10 -262144
+-1 -1 0 0;
+#X floatatom 21 127 5 0 0 0 - - -, f 5;
+#X msg 21 143 value bal \$1;
+#X obj -3 170 s msg_to_pyo;
+#X msg -3 74 read examples/cvlverb.py;
+#X text -5 38 load pyo processing file (audio signal must be given
+in pyo~ inputs).;
+#X text 162 110 balance between dry and wet signal;
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X connect 4 0 3 0;
+#X restore 531 12 pd conv_reverb_example;
+#X text 26 96 play a soundfile to send audio signals to pyo;
+#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.2;
+#X text 15 108 pyo website : http://ajaxsoundstudio.com/software/pyo/
+;
+#X text 15 10 pyo~ : Embedded pyo scripting inside puredata.;
+#X text 15 135 pyo sources : https://github.com/belangeo/pyo;
+#X text 15 163 For more details about how pyo can be embedded inside
+an host program \, see m_pyo.h in the "embedded" folder of pyo sources.
+;
+#X restore 406 237 pd README;
+#N canvas 182 106 1046 508 MESSAGES 0;
+#X text 20 53 read [-a] path/to/python/script;
+#X text 37 74 The message "read" executes the commands contained in
+the specified python script into the object's internal interpreter.
+If the "-a" flag is given \, new commands will be added to previously
+executed ones. Without the flag \, the server is shut down (this will
+erase actual processing) before the execution of the script.;
+#X text 18 164 value varname \$1 [\$2 \$3 ...];
+#X text 19 250 set varname.attribute \$1 [\$2 \$3 ...];
+#X text 19 379 call function [arg1 arg2 ...];
+#X text 498 250 clear;
+#X text 515 271 Shutdown and reboot pyo's server. This message will
+erase the current processing loaded into the object.;
+#X text 36 185 The messsage "value" sends value(s) to a pyo's Sig or
+SigTo object (with variable name "varname"). Values can be pyo's variables
+(already created in the loaded file) \, float or list (composed of
+floats and/or pyo objects).;
+#X text 36 399 The message "call" executes the function (or object's
+method) with optional arguments. If the callable is a method \, the
+syntax will looks like:;
+#X text 35 439 call varname.method [arg1 arg2 ...];
+#X text 36 351 set frequencies 100 200 300 400 500 600;
+#X text 499 56 create varname object [\$1 \$2 ...];
+#X text 513 75 The message "create" creates a new python object of
+the class "object" \, stored in variable "varname" \, with optional
+initialization arguments. Arguments can be of the form freq=500 or
+mul=0.3 \, without spaces. Named arguments can't be followed by unamed
+arguments.;
+#X text 36 272 The messsage "set" sends value(s) to an attribute of
+any pyo object (with variable name "varname"). Values can be pyo's
+variables (already created in the loaded file) \, float or list (composed
+of floats and/or pyo objects). This message can be used to create a
+standard python variable like (to create a list of floats in variable
+"frequencies"):;
+#X text 498 312 debug \$1;
+#X text 515 333 If \$1 is positive \, messages to pyo will be sent
+through an Exception handler. This is safer and can help to debug messages
+to pyo but it is slower. For a faster execution \, turn off debug mode.
+;
+#X text 498 161 midi \$1 [\$2 \$3];
+#X text 512 180 The message "midi" sends a MIDI event to the object
+processing. Arguments are the status byte (\$1) \, the first data byte
+(\$2) and the second data byte (\$3). Data bytes can be ommited and
+defaults to 0;
+#X text 7 3 Here are the messages that can be used to control the internal
+processing of the pyo~ object.;
+#X text 4 31 --------------------------------------------------------
+;
+#X restore 406 258 pd MESSAGES;
+#X msg 567 321 call b.out;
+#X text 11 7 pyo~ object allows to execute processing with pyo (python
+dsp module) inside a puredata patch \, with any number of audio in/out
+channels.;
+#X obj 531 121 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X msg 531 144 debug \$1;
+#X text 549 113 Verbose mode. If on \, error messages from pyo will
+be printed to the Pd window.;
+#X obj 532 347 s msg_to_pyo;
+#X msg 567 258 set pits 0.001 0.002 0.003 0.004;
+#X msg 567 279 create fr Rossler pitch=pits chaos=0.9 mul=250 add=500
+;
+#X msg 567 300 create b SumOsc freq=fr ratio=0.499 index=0.4 mul=0.2
+;
+#N canvas 669 129 722 427 midi_synth_example 0;
+#X obj 34 365 s msg_to_pyo;
+#X msg 34 56 read examples/midi_synth.py;
+#X msg 97 108 midi 144 72 127;
+#X obj 129 172 hsl 128 15 0 127 0 0 empty empty empty -2 -8 0 10 -262144
+-1 -1 700 1;
+#X msg 126 195 midi 176 1 \$1;
+#X obj 448 43 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0
+1;
+#X obj 448 63 metro 125;
+#X obj 448 249 makenote 127 100;
+#X obj 448 271 pack;
+#X msg 448 293 midi 144 \$1 \$2;
+#X msg 111 130 midi 144 72 0;
+#X text 212 108 note on;
+#X text 213 131 note off;
+#X text 228 196 control change (mod wheel);
+#X floatatom 448 228 5 0 0 0 - - -, f 5;
+#X obj 448 183 int;
+#X obj 448 161 + 0.5;
+#X obj 448 139 * 1.76;
+#X obj 448 115 random 8;
+#X obj 448 85 t b b;
+#X obj 526 115 random 3;
+#X obj 526 137 + 5;
+#X obj 526 159 * 12;
+#X obj 448 206 +;
+#X text 467 43 random melody;
+#X connect 1 0 0 0;
+#X connect 2 0 0 0;
+#X connect 3 0 4 0;
+#X connect 4 0 0 0;
+#X connect 5 0 6 0;
+#X connect 6 0 19 0;
+#X connect 7 0 8 0;
+#X connect 7 1 8 1;
+#X connect 8 0 9 0;
+#X connect 9 0 0 0;
+#X connect 10 0 0 0;
+#X connect 14 0 7 0;
+#X connect 15 0 23 0;
+#X connect 16 0 15 0;
+#X connect 17 0 16 0;
+#X connect 18 0 17 0;
+#X connect 19 0 18 0;
+#X connect 19 1 20 0;
+#X connect 20 0 21 0;
+#X connect 21 0 22 0;
+#X connect 22 0 23 1;
+#X connect 23 0 14 0;
+#X restore 531 84 pd midi_synth_example;
+#X text 563 238 Create a pyo script from scratch!;
+#X connect 0 0 17 0;
+#X connect 1 0 17 1;
+#X connect 2 0 4 0;
+#X connect 3 0 4 1;
+#X connect 5 0 3 1;
+#X connect 5 0 2 1;
+#X connect 6 0 7 0;
+#X connect 8 0 10 0;
+#X connect 10 0 2 0;
+#X connect 10 1 3 0;
+#X connect 13 0 14 0;
+#X connect 17 0 10 0;
+#X connect 17 1 10 1;
+#X connect 23 0 28 0;
+#X connect 25 0 26 0;
+#X connect 26 0 14 0;
+#X connect 29 0 28 0;
+#X connect 30 0 28 0;
+#X connect 31 0 28 0;
diff --git a/embedded/puredata/pyo~-meta.pd b/embedded/puredata/pyo~-meta.pd
new file mode 100644
index 0000000..18a355f
--- /dev/null
+++ b/embedded/puredata/pyo~-meta.pd
@@ -0,0 +1,6 @@
+#N canvas 15 49 200 200 10;
+#N canvas 25 49 420 300 META 1;
+#X text 13 41 NAME pyo~;
+#X text 10 25 AUTHOR belangeo at gmail.com;
+#X text 10 10 VERSION 0.1;
+#X restore 10 10 pd META;
diff --git a/embedded/puredata/pyo~.c b/embedded/puredata/pyo~.c
new file mode 100644
index 0000000..240b93a
--- /dev/null
+++ b/embedded/puredata/pyo~.c
@@ -0,0 +1,263 @@
+#include <stdlib.h>
+#include <m_pd.h>
+#include "Python.h"
+#include "m_pyo.h"
+
+static t_class *pyo_tilde_class;
+
+typedef struct _pyo_tilde {
+    t_object  obj;
+    t_sample  f;
+    int debug;
+    int bs;
+    int add;
+    int chnls;
+    float sr;
+    char *file;
+    t_sample **in;
+    t_sample **out;
+    int id;                 /* pyo server id */
+    float *inbuf;           /* pyo input buffer */
+    float *outbuf;          /* pyo output buffer */
+    char *msg;              /* preallocated string to construct message for pyo */
+    void (*callback)(int);  /* pointer to pyo embedded server callback */
+    PyThreadState *interp;  /* Python thread state linked to this sub interpreter */
+} t_pyo_tilde;
+
+t_int *pyo_tilde_perform(t_int *w) {
+    int i, j, n;
+    t_pyo_tilde *x = (t_pyo_tilde *)(w[1]); /* pointer to instance struct */
+    n = (int)(w[2]);                        /* vector size */
+    t_sample **in = x->in;
+    t_sample **out = x->out;
+    for (i=0; i<n; i++) {
+        for (j=0; j<x->chnls; j++) {
+            x->inbuf[i*x->chnls+j] = in[j][i];
+        }
+    }
+    (*x->callback)(x->id);
+    for (i=0; i<n; i++) {
+        for (j=0; j<x->chnls; j++) {
+            out[j][i] = x->outbuf[i*x->chnls+j];
+        }
+    }
+    return (w+3);
+}
+
+void pyo_tilde_dsp(t_pyo_tilde *x, t_signal **sp) {
+    int i, err;
+    t_sample **dummy = x->in;
+    for (i=0; i<x->chnls; i++)
+        *dummy++ = sp[i]->s_vec;
+    dummy = x->out;
+    for (i=x->chnls; i<x->chnls*2; i++)
+        *dummy++ = sp[i]->s_vec;
+    /* reset pyo only if sampling rate or buffer size have changed */
+    if ((float)sp[0]->s_sr != x->sr || (int)sp[0]->s_n != x->bs) {
+        x->sr = (float)sp[0]->s_sr;
+        x->bs = (int)sp[0]->s_n;
+        pyo_set_server_params(x->interp, x->sr, x->bs);
+        if (x->file != NULL) {
+            err = pyo_exec_file(x->interp, x->file, x->msg, x->add);
+            if (err) {
+                post("Unable to open file < %s >", x->file);
+                x->file = NULL;
+            }
+        }
+    }
+    dsp_add(pyo_tilde_perform, 2, x, sp[0]->s_n);
+}
+
+void *pyo_tilde_new(t_floatarg f) {
+    int i;
+    t_pyo_tilde *x = (t_pyo_tilde *)pd_new(pyo_tilde_class);
+
+    x->chnls = (f) ? f : 2;
+    x->bs = 64;
+    x->sr = 44100.0;
+    x->file = NULL;
+    x->add = 0;
+    x->debug = 0;
+
+    /* create signal inlets (first is done in pyo_tilde_setup) */
+    for (i=1; i<x->chnls; i++)
+        inlet_new(&x->obj, &x->obj.ob_pd, &s_signal, &s_signal);
+    /* create signal outlets */
+    for (i=0; i<x->chnls; i++)
+        outlet_new(&x->obj, &s_signal);
+
+    x->in = (t_sample **)getbytes(x->chnls * sizeof(t_sample **));
+    x->out = (t_sample **)getbytes(x->chnls * sizeof(t_sample **));
+    x->msg = (char *)getbytes(262144 * sizeof(char *));
+
+    for (i=0; i<x->chnls; i++)
+        x->in[i] = x->out[i] = 0;
+
+    x->interp = pyo_new_interpreter(x->sr, x->bs, x->chnls);
+    
+    x->inbuf = (float *)pyo_get_input_buffer_address(x->interp);
+    x->outbuf = (float *)pyo_get_output_buffer_address(x->interp);
+    x->callback = (void *)pyo_get_embedded_callback_address(x->interp);
+    x->id = pyo_get_server_id(x->interp);
+
+    return (void *)x;
+}
+
+void pyo_tilde_free(t_pyo_tilde *x) {
+    freebytes(x->in, sizeof(x->in));
+    freebytes(x->out, sizeof(x->out));
+    freebytes(x->msg, sizeof(x->msg));
+    pyo_end_interpreter(x->interp);
+}
+
+void pyo_tilde_set_value(t_pyo_tilde *x, char *att, int argc, t_atom *argv) {
+    int err, bracket = 0;
+    char fchar[32];
+    t_symbol *c = atom_getsymbol(argv);
+    argc--; argv++;
+    sprintf(x->msg, "%s%s=", c->s_name, att);
+    if (argc > 1) {
+        strcat(x->msg, "[");
+        bracket = 1;    
+    }
+    while (argc-- > 0) {
+        if (argv->a_type == A_SYMBOL) {
+            strcat(x->msg, atom_getsymbol(argv)->s_name);
+        }
+        else if (argv->a_type == A_FLOAT) {
+            sprintf(fchar, "%.6f", atom_getfloat(argv));
+            strcat(x->msg, fchar);
+        }
+        if (argc > 0)
+            strcat(x->msg, ",");
+        argv++;
+    }
+    if (bracket)
+        strcat(x->msg, "]");
+    err = pyo_exec_statement(x->interp, x->msg, x->debug);
+    if (err)
+        post("pyo~: %s", x->msg);
+}
+
+void pyo_tilde_value(t_pyo_tilde *x, t_symbol *s, int argc, t_atom *argv) {
+    char *att = ".value";
+    pyo_tilde_set_value(x, att, argc, argv);
+}
+void pyo_tilde_set(t_pyo_tilde *x, t_symbol *s, int argc, t_atom *argv) {
+    char *att = "";
+    pyo_tilde_set_value(x, att, argc, argv);
+}
+
+void pyo_tilde_create(t_pyo_tilde *x, t_symbol *s, int argc, t_atom *argv) {
+    int err;
+    char *varname, *object;
+    char fchar[32];
+    t_symbol *c = atom_getsymbol(argv);
+    varname = c->s_name;
+    argc--; argv++;
+    c = atom_getsymbol(argv);
+    object = c->s_name;
+    argc--; argv++;
+    sprintf(x->msg, "%s=%s(", varname, object);
+    while (argc-- > 0) {
+        if (argv->a_type == A_SYMBOL) {
+            strcat(x->msg, atom_getsymbol(argv)->s_name);
+        }
+        else if (argv->a_type == A_FLOAT) {
+            sprintf(fchar, "%f", atom_getfloat(argv));
+            strcat(x->msg, fchar);
+        }
+        if (argc > 0)
+            strcat(x->msg, ",");
+        argv++;
+    }
+    strcat(x->msg, ")");
+    err = pyo_exec_statement(x->interp, x->msg, x->debug);
+    if (err)
+        post("pyo~: %s", x->msg);
+}
+
+void pyo_tilde_midi_event(t_pyo_tilde *x, t_symbol *s, int argc, t_atom *argv) {
+    int status = 0, data1 = 0, data2 = 0;
+    if (argc > 0)
+        status = (int)atom_getfloat(argv);
+    if (argc > 1)
+        data1 = (int)atom_getfloat(++argv);
+    if (argc > 2)
+        data2 = (int)atom_getfloat(++argv);
+    pyo_add_midi_event(x->interp, status, data1, data2);
+}
+
+void pyo_tilde_clear(t_pyo_tilde *x) {
+    pyo_server_reboot(x->interp);
+}
+
+void pyo_tilde_debug(t_pyo_tilde *x, t_float debug) {
+    x->debug = debug <= 0 ? 0 : 1;
+}
+
+void pyo_tilde_read(t_pyo_tilde *x, t_symbol *s, int argc, t_atom *argv) {
+    int err;
+    switch (argc) {
+        case 1:
+            x->add = 0;
+            x->file = atom_getsymbol(argv)->s_name;
+            break;
+        case 2:
+            x->add = strcmp(atom_getsymbol(argv++)->s_name, "-a") == 0 ? 1 : 0;
+            x->file = atom_getsymbol(argv)->s_name;
+            break;
+    }
+    if (pyo_is_server_started(x->interp)) { 
+        err = pyo_exec_file(x->interp, x->file, x->msg, x->add);
+        if (err) {
+            post("Unable to open file < %s >", x->file);
+            x->file = NULL;
+        }
+    }
+}
+
+void pyo_tilde_call(t_pyo_tilde *x, t_symbol *s, int argc, t_atom *argv) {
+    int err;
+    char fchar[32];
+    sprintf(x->msg, "%s(", atom_getsymbol(argv)->s_name);
+    argc--; argv++;
+    while (argc-- > 0) {
+        if (argv->a_type == A_SYMBOL) {
+            strcat(x->msg, atom_getsymbol(argv)->s_name);
+        }
+        else if (argv->a_type == A_FLOAT) {
+            sprintf(fchar, "%f", atom_getfloat(argv));
+            strcat(x->msg, fchar);
+        }
+        if (argc > 0)
+            strcat(x->msg, ", ");
+        argv++;
+    }
+    strcat(x->msg, ")");
+    err = pyo_exec_statement(x->interp, x->msg, x->debug);
+    if (err)
+        post("pyo~: %s", x->msg);
+}
+
+void pyo_tilde_setup(void) {
+    pyo_tilde_class = class_new(gensym("pyo~"), (t_newmethod)pyo_tilde_new,
+        (t_method)pyo_tilde_free, sizeof(t_pyo_tilde), CLASS_DEFAULT, A_DEFFLOAT, 0);
+    class_addmethod(pyo_tilde_class, (t_method)pyo_tilde_dsp, gensym("dsp"), 0);
+    class_addmethod(pyo_tilde_class, (t_method)pyo_tilde_clear, gensym("clear"), 0);
+    class_addmethod(pyo_tilde_class, (t_method)pyo_tilde_value, gensym("value"), 
+                    A_GIMME, 0); /* send value(s) to a Sig or SigTo object */
+    class_addmethod(pyo_tilde_class, (t_method)pyo_tilde_set, gensym("set"), 
+                    A_GIMME, 0); /* send value(s) to any object's attribute */
+    class_addmethod(pyo_tilde_class, (t_method)pyo_tilde_read, gensym("read"), 
+                    A_GIMME, 0); /* read a script file */
+    class_addmethod(pyo_tilde_class, (t_method)pyo_tilde_call, gensym("call"), 
+                    A_GIMME, 0); /* call a function or a method */
+    class_addmethod(pyo_tilde_class, (t_method)pyo_tilde_create, gensym("create"), 
+                    A_GIMME, 0); /* create a python object */
+    class_addmethod(pyo_tilde_class, (t_method)pyo_tilde_midi_event, gensym("midi"), 
+                    A_GIMME, 0); /* create a python object */
+    class_addmethod(pyo_tilde_class, (t_method)pyo_tilde_debug, gensym("debug"), 
+                    A_DEFFLOAT, 0); /* set the debug (verbose) mode */
+    CLASS_MAINSIGNALIN(pyo_tilde_class, t_pyo_tilde, f);
+}
diff --git a/examples/01-intro/01-audio-server.py b/examples/01-intro/01-audio-server.py
new file mode 100644
index 0000000..dc354ea
--- /dev/null
+++ b/examples/01-intro/01-audio-server.py
@@ -0,0 +1,30 @@
+"""
+01-audio-server.py - Booting the audio server.
+
+A Server object needs to be created before any other audio object.
+It is the one that handles the communication with the audio and midi
+drivers and also the one that keeps track of the processing chain.
+
+"""
+from pyo import *
+
+# Creates a Server object with default arguments.
+# See the manual about how to change the sampling rate, the buffer
+# size, the number of channels or one of the other global settings.
+s = Server()
+
+# Boots the server. This step initializes audio and midi streams.
+# Audio and midi configurations (if any) must be done before that call.
+s.boot()
+
+# Starts the server. This step activates the server processing loop.
+s.start()
+
+# Here comes the processing chain...
+
+# The Server object provides a Graphical User Interface with the
+# gui() method. One of its purpose is to keep the program alive
+# while computing samples over time. If the locals dictionary is
+# given as argument, the user can continue to send commands to the
+# python interpreter from the GUI.
+s.gui(locals())
diff --git a/examples/01-intro/02-sine-tone.py b/examples/01-intro/02-sine-tone.py
new file mode 100644
index 0000000..1b441aa
--- /dev/null
+++ b/examples/01-intro/02-sine-tone.py
@@ -0,0 +1,21 @@
+"""
+02-sine-tone.py - The "hello world" of audio programming!
+
+This script simply plays a 1000 Hz sine tone.
+
+"""
+from pyo import *
+
+# Creates and boots the server.
+# The user should send the "start" command from the GUI.
+s = Server().boot()
+# Drops the gain by 20 dB.
+s.amp = 0.1
+
+# Creates a sine wave player.
+# The out() method starts the processing
+# and sends the signal to the output.
+a = Sine().out()
+
+# Opens the server graphical interface.
+s.gui(locals())
diff --git a/examples/01-intro/03-parallel-proc.py b/examples/01-intro/03-parallel-proc.py
new file mode 100644
index 0000000..f2e008a
--- /dev/null
+++ b/examples/01-intro/03-parallel-proc.py
@@ -0,0 +1,31 @@
+"""
+03-parallel-proc.py - Multiple processes on a single source.
+
+This example shows how to play different audio objects side-by-side.
+Every processing object (ie the ones that modify an audio source) have
+a first argument called "input". This argument takes the audio object
+to process.
+
+Note the input variable given to each processing object and the call
+to the out() method of each object that should send its samples to the
+output.
+
+"""
+from pyo import *
+
+s = Server().boot()
+s.amp = 0.1
+
+# Creates a sine wave as the source to process.
+a = Sine()
+
+# Passes the sine wave through an harmonizer.
+hr = Harmonizer(a).out()
+
+# Also through a chorus.
+ch = Chorus(a).out()
+
+# And through a frequency shifter.
+sh = FreqShift(a).out()
+
+s.gui(locals())
diff --git a/examples/01-intro/04-serial-proc.py b/examples/01-intro/04-serial-proc.py
new file mode 100644
index 0000000..53e32cf
--- /dev/null
+++ b/examples/01-intro/04-serial-proc.py
@@ -0,0 +1,32 @@
+"""
+04-serial-proc.py - Chaining processes on a single source.
+
+This example shows how to chain processes on a single source.
+Every processing object (ie the ones that modify an audio source) have
+a first argument called "input". This argument takes the audio object
+to process.
+
+Note the input variable given to each Harmonizer.
+
+"""
+from pyo import *
+
+s = Server().boot()
+s.amp = 0.1
+
+# Creates a sine wave as the source to process.
+a = Sine().out()
+
+# Passes the sine wave through an harmonizer.
+h1 = Harmonizer(a).out()
+
+# Then the harmonized sound through another harmonizer.
+h2 = Harmonizer(h1).out()
+
+# And again...
+h3 = Harmonizer(h2).out()
+
+# And again...
+h4 = Harmonizer(h3).out()
+
+s.gui(locals())
diff --git a/examples/01-intro/05-output-channels.py b/examples/01-intro/05-output-channels.py
new file mode 100644
index 0000000..f4b558a
--- /dev/null
+++ b/examples/01-intro/05-output-channels.py
@@ -0,0 +1,31 @@
+"""
+05-output-channels.py - Sending signals to different physical outputs.
+
+The simplest way to choose the output channel where to send the sound
+is to give it as the first argument of the out() method. In fact, the
+signature of the out() method reads as:
+
+.out(chnl=0, inc=1, dur=0, delay=0)
+
+`chnl` is the output where to send the first audio channel (stream) of
+the object. `inc` is the output increment for other audio channels.
+`dur` is the living duration, in seconds, of the process and `delay`
+is a delay, in seconds, before activating the process. A duration of
+0 means play forever.
+
+"""
+from pyo import *
+
+s = Server().boot()
+s.amp = 0.1
+
+# Creates a source (white noise)
+n = Noise()
+
+# Sends the bass frequencies (below 1000 Hz) to the left
+lp = ButLP(n).out()
+
+# Sends the high frequencies (above 1000 Hz) to the right
+hp = ButHP(n).out(1)
+
+s.gui(locals())
diff --git a/examples/02-controls/01-fixed-control.py b/examples/02-controls/01-fixed-control.py
new file mode 100644
index 0000000..72252ae
--- /dev/null
+++ b/examples/02-controls/01-fixed-control.py
@@ -0,0 +1,28 @@
+"""
+01-fixed-control.py - Number as argument.
+
+Audio objects behaviour can be controlled by passing
+value to their arguments at initialization time.
+
+"""
+from pyo import *
+
+s = Server().boot()
+s.amp = 0.1
+
+# Sets fundamental frequency
+freq = 200
+
+# Approximates a triangle waveform by adding odd harmonics with
+# amplitude proportional to the inverse square of the harmonic number.
+h1 = Sine(freq=freq, mul=1).out()
+h2 = Sine(freq=freq*3, phase=0.5, mul=1./pow(3,2)).out()
+h3 = Sine(freq=freq*5, mul=1./pow(5,2)).out()
+h4 = Sine(freq=freq*7, phase=0.5, mul=1./pow(7,2)).out()
+h5 = Sine(freq=freq*9, mul=1./pow(9,2)).out()
+h6 = Sine(freq=freq*11, phase=0.5, mul=1./pow(11,2)).out()
+
+# Displays the final waveform
+sp = Scope(h1+h2+h3+h4+h5+h6)
+
+s.gui(locals())
diff --git a/examples/02-controls/02-dynamic-control.py b/examples/02-controls/02-dynamic-control.py
new file mode 100644
index 0000000..09223aa
--- /dev/null
+++ b/examples/02-controls/02-dynamic-control.py
@@ -0,0 +1,23 @@
+"""
+02-dynamic-control.py - Graphical control for parameters.
+
+With pyo, it's easy to quickly try some parameter combination
+with the controller window already configured for each object.
+To open the controller window, just call the ctrl() method on
+the object you want to control.
+
+"""
+from pyo import *
+
+s = Server().boot()
+s.amp = 0.1
+
+# Creates two objects with cool parameters, one per channel.
+a = FM().out()
+b = FM().out(1)
+
+# Opens the controller windows.
+a.ctrl(title="Frequency modulation left channel")
+b.ctrl(title="Frequency modulation right channel")
+
+s.gui(locals())
diff --git a/examples/02-controls/03-output-range.py b/examples/02-controls/03-output-range.py
new file mode 100644
index 0000000..b26a8f1
--- /dev/null
+++ b/examples/02-controls/03-output-range.py
@@ -0,0 +1,41 @@
+"""
+03-output-range.py - The `mul` and `add` attributes.
+
+Almost all audio objects have a `mul` and `add` attributes.
+These are defined inside the PyoObject, which is the base
+class for all objects generating audio signal. The manual
+page of the PyoObject explains all behaviours common to
+audio objects.
+
+An audio signal outputs samples as floating-point numbers in
+the range -1 to 1. The `mul` and `add` attributes can be used
+to change the output range. Common uses are for modulating the
+amplitude of a sound or for building control signals like low
+frequency oscillators.
+
+A shortcut to automatically manipulate both `mul` and `add`
+attributes is to call the range(min, max) method of the
+PyoObject. This method sets `mul` and `add` attributes
+according to the desired `min` and `max` output values. It
+assumes that the generated signal is in the range -1 to 1.
+
+"""
+from pyo import *
+
+s = Server().boot().start()
+
+# The `mul` attribute multiplies each sample by its value.
+a = Sine(freq=100, mul=0.1)
+
+# The `add` attribute adds an offset to each sample.
+# The multiplication is applied before the addition.
+b = Sine(freq=100, mul=0.5, add=0.5)
+
+# Using the range(min, max) method allows to automatically
+# compute both `mul` and `add` attributes.
+c = Sine(freq=100).range(-0.25, 0.5)
+
+# Displays the waveforms
+sc = Scope([a, b, c])
+
+s.gui(locals())
diff --git a/examples/02-controls/04-building-lfo.py b/examples/02-controls/04-building-lfo.py
new file mode 100644
index 0000000..f2c4921
--- /dev/null
+++ b/examples/02-controls/04-building-lfo.py
@@ -0,0 +1,39 @@
+"""
+04-building-lfo.py - Audio control of parameters.
+
+One of the most important thing with computer music is the
+trajectories taken by parameters over time. This is what
+gives life to the synthesized sound.
+
+One way to create moving values is by connecting a low
+frequency oscillator to an object's attribute. This script
+shows that process.
+
+Other possibilities that will be covered later use random
+class objects or feature extraction from an audio signal.
+
+"""
+from pyo import *
+
+s = Server().boot()
+
+# Creates a noise source
+n = Noise()
+
+# Creates an LFO oscillating +/- 500 around 1000 (filter's frequency)
+lfo1 = Sine(freq=.1, mul=500, add=1000)
+# Creates an LFO oscillating between 2 and 8 (filter's Q)
+lfo2 = Sine(freq=.4).range(2, 8)
+# Creates a dynamic bandpass filter applied to the noise source
+bp1 = ButBP(n, freq=lfo1, q=lfo2).out()
+
+# The LFO object provides more waveforms than just a sine wave
+
+# Creates a ramp oscillating +/- 1000 around 12000 (filter's frequency)
+lfo3 = LFO(freq=.25, type=1, mul=1000, add=1200)
+# Creates a square oscillating between 4 and 12 (filter's Q)
+lfo4 = LFO(freq=4, type=2).range(4, 12)
+# Creates a second dynamic bandpass filter applied to the noise source
+bp2 = ButBP(n, freq=lfo3, q=lfo4).out(1)
+
+s.gui(locals())
diff --git a/examples/02-controls/05-math-ops.py b/examples/02-controls/05-math-ops.py
new file mode 100644
index 0000000..9a1a2dc
--- /dev/null
+++ b/examples/02-controls/05-math-ops.py
@@ -0,0 +1,49 @@
+"""
+05-math-ops.py - Audio objects and arithmetic expresssions.
+
+This script shows how a PyoObject reacts when used inside an
+arithmetic expression.
+
+Multiplication, addition, division and substraction can be applied
+between pyo objects or between pyo objects and numbers. Doing so
+returns a Dummy object that outputs the result of the operation.
+
+A Dummy object is only a place holder to keep track of arithmetic
+operations on audio objects.
+
+PyoObject can also be used in expression with the exponent (**),
+modulo (%) and unary negative (-) operators.
+
+"""
+from __future__ import print_function
+from pyo import *
+
+s = Server().boot()
+s.amp = 0.1
+
+# Full scale sine wave
+a = Sine()
+
+# Creates a Dummy object `b` with `mul` attribute
+# set to 0.5 and leaves `a` unchanged.
+b = a * 0.5
+b.out()
+
+# Instance of Dummy class
+print(b)
+
+# Computes a ring modulation between two PyoObjects
+# and scales the amplitude of the resulting signal.
+c = Sine(300)
+d = a * c * 0.3
+d.out()
+
+# PyoObject can be used with Exponent operator.
+e = c ** 10 * 0.4
+e.out(1)
+
+# Displays the ringmod and the rectified signals.
+sp = Spectrum([d, e])
+sc = Scope([d, e])
+
+s.gui(locals())
diff --git a/examples/02-controls/06-multichannel-expansion.py b/examples/02-controls/06-multichannel-expansion.py
new file mode 100644
index 0000000..b59f0ce
--- /dev/null
+++ b/examples/02-controls/06-multichannel-expansion.py
@@ -0,0 +1,55 @@
+"""
+06-multichannel-expansion.py - What is a `Stream`? Polyphonic objects.
+
+List expansion is a powerful technique for generating many audio
+streams at once.
+
+What is a "stream"? A "stream" is a monophonic channel of samples.
+It is the basic structure over which all the library is built. Any
+PyoObject can handle as many streams as necessary to represent the
+defined process. When a polyphonic (ie more than one stream) object
+is asked to send its signals to the output, the server will use the
+arguments (`chnl` and `inc`) of the out() method to distribute the
+streams over the available output channels.
+
+Almost all attributes of all objects of the library accept list of
+values instead of a single value. The object will create internally
+the same number of streams than the length of the largest list
+given to an attribute at the initialization time. Each value of the
+list is used to generate one stream. Shorter lists will wrap around
+when reaching the end of the list.
+
+A PyoObject is considered by other object as a list. The function
+`len(obj)` returns the number of streams managed by the object. This
+feature is useful to create a polyphonic dsp chain.
+
+"""
+from pyo import *
+
+s = Server().boot()
+
+### Using multichannel-expansion to create a square wave ###
+
+# Sets fundamental frequency.
+freq = 100
+# Sets the highest harmonic.
+high = 20
+
+# Generates the list of harmonic frequencies (odd only).
+harms = [freq * i for i in range(1, high) if i%2 == 1]
+# Generates the list of harmonic amplitudes (1 / n).
+amps = [0.33 / i for i in range(1, high) if i%2 == 1]
+
+# Creates all sine waves at once.
+a = Sine(freq=harms, mul=amps)
+# Prints the number of streams managed by "a".
+print(len(a))
+
+# The mix(voices) method (defined in PyoObject) mixes
+# the object streams into `voices` streams.
+b = a.mix(voices=1).out()
+
+# Displays the waveform.
+sc = Scope(b)
+
+s.gui(locals())
diff --git a/examples/02-controls/07-multichannel-expansion-2.py b/examples/02-controls/07-multichannel-expansion-2.py
new file mode 100644
index 0000000..eb65c7b
--- /dev/null
+++ b/examples/02-controls/07-multichannel-expansion-2.py
@@ -0,0 +1,24 @@
+"""
+07-multichannel-expansion-2.py - Extended multichannel expansion.
+
+When using multichannel expansion with lists of different lengths,
+the longer list is used to set the number of streams and smaller
+lists will be wrap-around to fill the holes.
+
+This feature is very useful to create complex sonorities.
+
+"""
+from pyo import *
+
+s = Server().boot()
+
+# 12 streams with different combinations of `freq` and `ratio`.
+a = SumOsc(freq=[100, 150.2, 200.5, 250.7],
+           ratio=[0.501, 0.753, 1.255],
+           index=[.3, .4, .5, .6, .7, .4, .5, .3, .6, .7, .3, .5],
+           mul=.05)
+
+# Adds a stereo reverberation to the signal
+rev = Freeverb(a.mix(2), size=0.80, damp=0.70, bal=0.30).out()
+
+s.gui(locals())
diff --git a/examples/02-controls/08-handling-channels.py b/examples/02-controls/08-handling-channels.py
new file mode 100644
index 0000000..f5b8c50
--- /dev/null
+++ b/examples/02-controls/08-handling-channels.py
@@ -0,0 +1,41 @@
+"""
+08-handling-channels.py - Managing object's internal audio streams.
+
+Because audio objects expand their number of streams according to lists
+given to their arguments and the fact that an audio object is considered
+as a list, if a multi-streams object is given as an argument to another
+audio object, the later will also be expanded in order to process all
+given streams. This is really powerful to create polyphonic processes
+without copying long chunks of code but it can be very CPU expensive.
+
+In this example, we create a square from a sum of sine waves. After that,
+a chorus is applied to the resulting waveform. If we don't mix down the
+square wave, we got tens of Chorus objects in the processing chain (one
+per sine). This can easily overrun the CPU. The exact same result can
+be obtained with only one Chorus applied to the sum of the sine waves.
+The `mix(voices)` method of the PyoObject helps the handling of channels
+in order to save CPU cycles. Here, we down mix all streams to only two
+streams (to maintain the stereo) before processing the Chorus arguments.
+
+"""
+from pyo import *
+
+s = Server().boot()
+
+# Sets fundamental frequency and highest harmonic.
+freq = 100
+high = 20
+
+# Generates lists for frequencies and amplitudes
+harms = [freq * i for i in range(1, high) if i%2 == 1]
+amps = [0.33 / i for i in range(1, high) if i%2 == 1]
+
+# Creates a square wave by additive synthesis.
+a = Sine(freq=harms, mul=amps)
+print("Number of Sine streams: %d" % len(a))
+
+# Mix down the number of streams of "a" before computing the Chorus.
+b = Chorus(a.mix(2), feedback=0.5).out()
+print("Number of Chorus streams: %d" % len(b))
+
+s.gui(locals())
diff --git a/examples/02-controls/09-handling-channels-2.py b/examples/02-controls/09-handling-channels-2.py
new file mode 100644
index 0000000..b50b96e
--- /dev/null
+++ b/examples/02-controls/09-handling-channels-2.py
@@ -0,0 +1,26 @@
+"""
+09-handling-channels-2.py - The `out` method and the physical outputs.
+
+In a multichannel environment, we can carefully choose which stream
+goes to which output channel. To achieve this, we use the `chnl` and
+`inc` arguments of the out method.
+
+chnl : Physical output assigned to the first audio stream of the object.
+inc : Output channel increment value.
+
+"""
+from pyo import *
+
+# Creates a Server with 8 channels
+s = Server(nchnls=8).boot()
+
+# Generates a sine wave
+a = Sine(freq=500, mul=0.3)
+
+# Mixes it up to four streams
+b = a.mix(4)
+
+# Outputs to channels 0, 2, 4 and 6
+b.out(chnl=0, inc=2)
+
+s.gui(locals())
diff --git a/examples/02-controls/10-handling-channels-3.py b/examples/02-controls/10-handling-channels-3.py
new file mode 100644
index 0000000..7362f36
--- /dev/null
+++ b/examples/02-controls/10-handling-channels-3.py
@@ -0,0 +1,23 @@
+"""
+10-handling-channels-3.py - Random multichannel outputs.
+
+If `chnl` is negative, streams begin at 0, increment the output
+number by inc and wrap around the global number of channels.
+Then, the list of streams is scrambled.
+
+"""
+from pyo import *
+
+# Creates a Server with 8 channels
+s = Server(nchnls=8).boot()
+
+amps = [.05,.1,.15,.2,.25,.3,.35,.4]
+
+# Generates 8 sine waves with
+# increasing amplitudes
+a = Sine(freq=500, mul=amps)
+
+# Shuffles physical output channels
+a.out(chnl=-1)
+
+s.gui(locals())
diff --git a/examples/02-controls/11-handling-channels-4.py b/examples/02-controls/11-handling-channels-4.py
new file mode 100644
index 0000000..f9f9a50
--- /dev/null
+++ b/examples/02-controls/11-handling-channels-4.py
@@ -0,0 +1,22 @@
+"""
+11-handling-channels-4.py - Explicit control of the physical outputs.
+
+If `chnl` is a list, successive values in the list will be assigned
+to successive streams.
+
+"""
+from pyo import *
+
+# Creates a Server with 8 channels
+s = Server(nchnls=8).boot()
+
+amps = [.05,.1,.15,.2,.25,.3,.35,.4]
+
+# Generates 8 sine waves with
+# increasing amplitudes
+a = Sine(freq=500, mul=amps)
+
+# Sets the output channels ordering
+a.out(chnl=[3,4,2,5,1,6,0,7])
+
+s.gui(locals())
diff --git a/examples/03-generators/01-complex-oscs.py b/examples/03-generators/01-complex-oscs.py
new file mode 100644
index 0000000..447094d
--- /dev/null
+++ b/examples/03-generators/01-complex-oscs.py
@@ -0,0 +1,57 @@
+"""
+01-complex-oscs.py - Complex spectrum oscillators.
+
+This tutorial presents four objects of the library which are
+useful to generate complex spectrums by means of synthesis.
+
+Blit:
+Impulse train generator with control over the number of harmonics.
+
+RCOsc:
+Aproximation of a RC circuit (a capacitor and a resistor in series).
+
+SineLoop:
+Sine wave oscillator with feedback.
+
+SuperSaw:
+Roland JP-8000 Supersaw emulator.
+
+Use the "voice" slider of the window "Input interpolator" to
+interpolate between the four waveforms. Each one have an LFO
+applied to the argument that change the tone of the sound.
+
+"""
+from pyo import *
+
+s = Server().boot()
+
+# Sets fundamental frequency.
+freq = 200
+
+# Impulse train generator.
+lfo1 = Sine(.1).range(1, 50)
+osc1 = Blit(freq=freq, harms=lfo1, mul=0.3)
+
+# RC circuit.
+lfo2 = Sine(.1, mul=0.5, add=0.5)
+osc2 = RCOsc(freq=freq, sharp=lfo2, mul=0.3)
+
+# Sine wave oscillator with feedback.
+lfo3 = Sine(.1).range(0, .18)
+osc3 = SineLoop(freq=freq, feedback=lfo3, mul=0.3)
+
+# Roland JP-8000 Supersaw emulator.
+lfo4 = Sine(.1).range(0.1, 0.75)
+osc4 = SuperSaw(freq=freq, detune=lfo4, mul=0.3)
+
+# Interpolates between input objects to produce a single output
+sel = Selector([osc1, osc2, osc3, osc4]).out()
+sel.ctrl(title="Input interpolator (0=Blit, 1=RCOsc, 2=SineLoop, 3=SuperSaw)")
+
+# Displays the waveform of the chosen source
+sc = Scope(sel)
+
+# Displays the spectrum contents of the chosen source
+sp = Spectrum(sel)
+
+s.gui(locals())
diff --git a/examples/03-generators/02-band-limited-oscs.py b/examples/03-generators/02-band-limited-oscs.py
new file mode 100644
index 0000000..bbd41db
--- /dev/null
+++ b/examples/03-generators/02-band-limited-oscs.py
@@ -0,0 +1,46 @@
+"""
+02-band-limited-oscs.py - Oscillators whose spectrum is kept under the Nyquist frequency.
+
+This tutorial presents an object (misnamed LFO but it's too late
+to change its name!) that implements various band-limited waveforms.
+A band-limited signal is a signal that none of its partials exceeds
+the nyquist frequency (sr/2).
+
+The LFO object, despite its name, can be use as a standard oscillator,
+with very high fundamental frequencies. At lower frequencies (below 20 Hz)
+this object will give a true LFO with various shapes.
+
+The "type" slider in the controller window lets choose between these
+particular waveforms:
+
+0. Saw up (default)
+1. Saw down
+2. Square
+3. Triangle
+4. Pulse
+5. Bipolar pulse
+6. Sample and hold
+7. Modulated Sine
+
+"""
+from pyo import *
+
+s = Server().boot()
+
+# Sets fundamental frequency.
+freq = 200
+
+# LFO applied to the `sharp` attribute
+lfo = Sine(.2, mul=0.5, add=0.5)
+
+# Various band-limited waveforms
+osc = LFO(freq=freq, sharp=lfo, mul=0.4).out()
+osc.ctrl()
+
+# Displays the waveform
+sc = Scope(osc)
+
+# Displays the spectrum contents
+sp = Spectrum(osc)
+
+s.gui(locals())
diff --git a/examples/03-generators/03-fm-generators.py b/examples/03-generators/03-fm-generators.py
new file mode 100644
index 0000000..b15d932
--- /dev/null
+++ b/examples/03-generators/03-fm-generators.py
@@ -0,0 +1,38 @@
+"""
+03-fm-generators.py - Frequency modulation synthesis.
+
+There two objects in the library that implement frequency
+modulation algorithms. These objects are very simple, although
+powerful. It is also relatively simple to build a custom FM
+algorithm, this will be covered in the tutorials on custom
+synthesis algorithms.
+
+Use the "voice" slider of the window "Input interpolator" to
+interpolate between the two sources. Use the controller windows
+to change the parameters of the FM algorithms.
+
+Note what happened in the controller window when we give a
+list of floats to an object's argument.
+
+"""
+from pyo import *
+
+s = Server().boot()
+
+# FM implements the basic Chowning algorithm
+fm1 = FM(carrier=250, ratio=[1.5,1.49], index=10, mul=0.3)
+fm1.ctrl()
+
+# CrossFM implements a frequency modulation synthesis where the
+# output of both oscillators modulates the frequency of the other one.
+fm2 = CrossFM(carrier=250, ratio=[1.5,1.49], ind1=10, ind2=2, mul=0.3)
+fm2.ctrl()
+
+# Interpolates between input objects to produce a single output
+sel = Selector([fm1, fm2]).out()
+sel.ctrl(title="Input interpolator (0=FM, 1=CrossFM)")
+
+# Displays the spectrum contents of the chosen source
+sp = Spectrum(sel)
+
+s.gui(locals())
diff --git a/examples/03-generators/04-noise-generators.py b/examples/03-generators/04-noise-generators.py
new file mode 100644
index 0000000..b78f379
--- /dev/null
+++ b/examples/03-generators/04-noise-generators.py
@@ -0,0 +1,41 @@
+"""
+04-noise-generators.py - Different pseudo-random noise generators.
+
+There are three noise generators (beside random generators that
+will be covered later) in the library. These are the classic
+white noise, pink noise and brown noise.
+
+Noise:
+White noise generator, flat spectrum.
+
+PinkNoise:
+Pink noise generator, 3dB rolloff per octave.
+
+BrownNoise:
+Brown noise generator, 6dB rolloff per octave.
+
+Use the "voice" slider of the window "Input interpolator" to
+interpolate between the three sources.
+
+"""
+from pyo import *
+
+s = Server().boot()
+
+# White noise
+n1 = Noise(0.3)
+
+# Pink noise
+n2 = PinkNoise(0.3)
+
+# Brown noise
+n3 = BrownNoise(0.3)
+
+# Interpolates between input objects to produce a single output
+sel = Selector([n1, n2, n3]).out()
+sel.ctrl(title="Input interpolator (0=White, 1=Pink, 2=Brown)")
+
+# Displays the spectrum contents of the chosen source
+sp = Spectrum(sel)
+
+s.gui(locals())
diff --git a/examples/03-generators/05-strange-attractors.py b/examples/03-generators/05-strange-attractors.py
new file mode 100644
index 0000000..4241df1
--- /dev/null
+++ b/examples/03-generators/05-strange-attractors.py
@@ -0,0 +1,58 @@
+"""
+05-strange-attractors.py - Non-linear ordinary differential equations.
+
+Oscilloscope part of the tutorial
+---------------------------------
+
+A strange attractor is a system of three non-linear ordinary
+differential equations. These differential equations define a
+continuous-time dynamical system that exhibits chaotic dynamics
+associated with the fractal properties of the attractor.
+
+There is three strange attractors in the library, the Rossler,
+the Lorenz and the ChenLee objects. Each one can output stereo
+signal if the `stereo` argument is set to True.
+
+Use the "voice" slider of the window "Input interpolator" to
+interpolate between the three sources.
+
+Audio part of the tutorial
+--------------------------
+
+It's possible to create very interesting LFO with strange
+attractors. The last part of this tutorial shows the use of
+Lorenz's output to drive the frequency of two sine wave oscillators.
+
+"""
+from pyo import *
+
+s = Server().boot()
+
+### Oscilloscope ###
+
+# LFO applied to the `chaos` attribute
+lfo = Sine(0.2).range(0, 1)
+
+# Rossler attractor
+n1 = Rossler(pitch=0.5, chaos=lfo, stereo=True)
+
+# Lorenz attractor
+n2 = Lorenz(pitch=0.5, chaos=lfo, stereo=True)
+
+# ChenLee attractor
+n3 = ChenLee(pitch=0.5, chaos=lfo, stereo=True)
+
+# Interpolates between input objects to produce a single output
+sel = Selector([n1, n2, n3])
+sel.ctrl(title="Input interpolator (0=Rossler, 1=Lorenz, 2=ChenLee)")
+
+# Displays the waveform of the chosen attractor
+sc = Scope(sel)
+
+### Audio ###
+
+# Lorenz with very low pitch value that acts as a LFO
+freq = Lorenz(0.005, chaos=0.7, stereo=True, mul=250, add=500)
+a = Sine(freq, mul=0.3).out()
+
+s.gui(locals())
diff --git a/examples/03-generators/06-random-generators.py b/examples/03-generators/06-random-generators.py
new file mode 100644
index 0000000..e822131
--- /dev/null
+++ b/examples/03-generators/06-random-generators.py
@@ -0,0 +1,44 @@
+"""
+06-random-generators.py - Overview of some random generators of pyo.
+
+The pyo's random category contains many objects that can be used
+for different purposes. This category really deserves to be studied.
+
+In this tutorial, we use three random objects (Choice, Randi, RandInt)
+to control the pitches, the amplitude and the tone of a simple synth.
+
+We will come back to random generators when we will talk about musical
+algorithms.
+
+"""
+from pyo import *
+
+s = Server().boot()
+
+# Two streams of midi pitches chosen randomly in a predefined list.
+# The argument `choice` of Choice object can be a list of lists to
+# list-expansion.
+mid = Choice(choice=[60,62,63,65,67,69,71,72], freq=[2,3])
+
+# Two small jitters applied on frequency streams.
+# Randi interpolates between old and new values.
+jit = Randi(min=0.993, max=1.007, freq=[4.3,3.5])
+
+# Converts midi pitches to frequencies and applies the jitters.
+fr = MToF(mid, mul=jit)
+
+# Chooses a new feedback value, between 0 and 0.15, every 4 seconds.
+fd = Randi(min=0, max=0.15, freq=0.25)
+
+# RandInt generates a pseudo-random integer number between 0 and `max`
+# values at a frequency specified by `freq` parameter. It holds the
+# value until the next generation.
+# Generates an new LFO frequency once per second.
+sp = RandInt(max=6, freq=1, add=8)
+# Creates an LFO oscillating between 0 and 0.4.
+amp = Sine(sp, mul=0.2, add=0.2)
+
+# A simple synth...
+a = SineLoop(freq=fr, feedback=fd, mul=amp).out()
+
+s.gui(locals())
diff --git a/examples/04-soundfiles/01-read-from-disk.py b/examples/04-soundfiles/01-read-from-disk.py
new file mode 100644
index 0000000..5948579
--- /dev/null
+++ b/examples/04-soundfiles/01-read-from-disk.py
@@ -0,0 +1,26 @@
+"""
+01-read-from-disk.py - Soundfile playback from disk.
+
+SfPlayer and friends read samples from a file on disk with control
+over playback speed and looping mode.
+
+Player family:
+    - **SfPlayer** : Reads many soundfile formats from disk.
+    - **SfMarkerLooper** : AIFF with markers soundfile looper.
+    - **SfMarkerShuffler** : AIFF with markers soundfile shuffler.
+
+Reading sound file from disk can save a lot of RAM, especially if
+the soundfile is big, but it is more CPU expensive than loading
+the sound file in memory in a first pass.
+
+"""
+from pyo import *
+
+s = Server().boot()
+
+path = SNDS_PATH + "/transparent.aif"
+
+# stereo playback with a slight shift between the two channels.
+sf = SfPlayer(path, speed=[1, 0.995], loop=True, mul=0.4).out()
+
+s.gui(locals())
diff --git a/examples/04-soundfiles/02-read-from-disk-2.py b/examples/04-soundfiles/02-read-from-disk-2.py
new file mode 100644
index 0000000..ba5a9b8
--- /dev/null
+++ b/examples/04-soundfiles/02-read-from-disk-2.py
@@ -0,0 +1,46 @@
+"""
+02-read-from-disk-2.py - Catching the `end-of-file` signal from the SfPlayer object.
+
+This example demonstrates how to use the `end-of-file` signal
+of the SfPlayer object to trigger another playback (possibly
+with another sound, another speed, etc.).
+
+When a SfPlayer reaches the end of the file, it sends a trigger
+(more on trigger later) that the user can retrieve with the
+syntax :
+
+variable_name["trig"]
+
+"""
+from pyo import *
+import random
+
+s = Server().boot()
+
+# Sound bank
+folder = "../snds/"
+sounds = ["alum1.wav", "alum2.wav", "alum3.wav", "alum4.wav"]
+
+# Creates the left and right players
+sfL = SfPlayer(folder+sounds[0], speed=1, mul=0.5).out()
+sfR = SfPlayer(folder+sounds[0], speed=1, mul=0.5).out(1)
+
+# Function to choose a new sound and a new speed for the left player
+def newL():
+    sfL.path = folder + sounds[random.randint(0, 3)]
+    sfL.speed = random.uniform(0.75, 1.5)
+    sfL.out()
+
+# The "end-of-file" signal triggers the function "newL"
+tfL = TrigFunc(sfL["trig"], newL)
+
+# Function to choose a new sound and a new speed for the right player
+def newR():
+    sfR.path = folder + sounds[random.randint(0, 3)]
+    sfR.speed = random.uniform(0.75, 1.5)
+    sfR.out(1)
+
+# The "end-of-file" signal triggers the function "newR"
+tfR = TrigFunc(sfR["trig"], newR)
+
+s.gui(locals())
diff --git a/examples/04-soundfiles/03-read-from-ram.py b/examples/04-soundfiles/03-read-from-ram.py
new file mode 100644
index 0000000..bc693e0
--- /dev/null
+++ b/examples/04-soundfiles/03-read-from-ram.py
@@ -0,0 +1,30 @@
+"""
+03-read-from-ram.py - Soundfile playback from RAM.
+
+Reading a sound file from the RAM gives the advantage of a very
+fast access to every loaded samples. This is very useful for a
+lot of processes, such as granulation, looping, creating envelopes
+and waveforms and many others.
+
+The simplest way of loading a sound in RAM is to use the SndTable
+object. This example loads a sound file and reads it in loop.
+We will see some more evolved processes later...
+
+"""
+from pyo import *
+
+s = Server().boot()
+
+path = SNDS_PATH + "/transparent.aif"
+
+# Loads the sound file in RAM. Beginning and ending points
+# can be controlled with "start" and "stop" arguments.
+t = SndTable(path)
+
+# Gets the frequency relative to the table length.
+freq = t.getRate()
+
+# Simple stereo looping playback (right channel is 180 degrees out-of-phase).
+osc = Osc(table=t, freq=freq, phase=[0, 0.5], mul=0.4).out()
+
+s.gui(locals())
diff --git a/examples/04-soundfiles/04-record-perf.py b/examples/04-soundfiles/04-record-perf.py
new file mode 100644
index 0000000..c22a487
--- /dev/null
+++ b/examples/04-soundfiles/04-record-perf.py
@@ -0,0 +1,48 @@
+"""
+04-record-perf.py - Recording the performance on disk.
+
+The Server object allow the recording of the overall playback
+(that is exactly what your hear). The "Rec Start" button of the
+Server's window is doing that with default parameters. It'll
+record a file called "pyo_rec.wav" (16-bit, 44100 Hz) on the
+user's desktop.
+
+You can control the recording with the Server's method called
+`recordOptions`, the arguments are:
+
+- dur : The duration of the recording, a value of -1 means
+        record forever (recstop() must be called by the user).
+- filename : Indicates the location of the recorded file.
+- fileformat : The format of the audio file (see documentation
+               for available formats).
+- sampletype : The sample type of the audio file (see documentation
+               for available types).
+
+The recording can be triggered programmatically with the Server's
+methods `recstart()` and `recstop()`. In order to record multiple files
+from a unique performance, it is possible to set the filename
+with an argument to `recstart()`.
+
+
+"""
+from pyo import *
+import os
+
+s = Server().boot()
+
+# Path of the recorded sound file.
+path = os.path.join(os.path.expanduser("~"), "Desktop", "synth.wav")
+# Record for 10 seconds a 24-bit wav file.
+s.recordOptions(dur=10, filename=path, fileformat=0, sampletype=1)
+
+# Creates an amplitude envelope
+amp = Fader(fadein=1, fadeout=1, dur=10, mul=0.3).play()
+
+# A Simple synth
+lfo = Sine(freq=[0.15, 0.16]).range(1.25, 1.5)
+fm2 = CrossFM(carrier=200, ratio=lfo, ind1=10, ind2=2, mul=amp).out()
+
+# Starts the recording for 10 seconds...
+s.recstart()
+
+s.gui(locals())
diff --git a/examples/04-soundfiles/05-record-streams.py b/examples/04-soundfiles/05-record-streams.py
new file mode 100644
index 0000000..9c552ea
--- /dev/null
+++ b/examples/04-soundfiles/05-record-streams.py
@@ -0,0 +1,55 @@
+"""
+05-record-streams.py - Recording individual audio streams on disk.
+
+The Record object can be used to record specific audio streams
+from a performance. It can be useful to record a sound in mutiple
+tracks to make post-processing on individual part easier. This
+example record the bass, the mid and the higher part in three
+separated files on the user's desktop.
+
+The `fileformat` and `sampletype` arguments are the same as in
+the Server's `recordOptions` method.
+
+"""
+from pyo import *
+import os
+
+s = Server().boot()
+
+# Defines sound file paths.
+path = os.path.join(os.path.expanduser("~"), "Desktop")
+bname = os.path.join(path, "bass.wav")
+mname = os.path.join(path, "mid.wav")
+hname = os.path.join(path, "high.wav")
+
+# Creates an amplitude envelope
+amp = Fader(fadein=1, fadeout=1, dur=10, mul=0.3).play()
+
+# Bass voice
+blfo = Sine(freq=[0.15, 0.16]).range(78, 82)
+bass = RCOsc(freq=blfo, mul=amp).out()
+
+# Mid voice
+mlfo = Sine(freq=[0.18, 0.19]).range(0.24, 0.26)
+mid = FM(carrier=1600, ratio=mlfo, index=5, mul=amp*0.3).out()
+
+# High voice
+hlfo = Sine(freq=[0.1, 0.11, 0.12, 0.13]).range(7000, 8000)
+high = Sine(freq=hlfo, mul=amp*0.1).out()
+
+# Creates the recorders
+brec = Record(bass, filename=bname, chnls=2, fileformat=0, sampletype=1)
+mrec = Record(mid, filename=mname, chnls=2, fileformat=0, sampletype=1)
+hrec = Record(high, filename=hname, chnls=2, fileformat=0, sampletype=1)
+
+# After 10.1 seconds, recorder objects will be automatically deleted.
+# This will trigger their stop method and properly close the sound files.
+clean = Clean_objects(10.1, brec, mrec, hrec)
+
+# Starts the internal timer of Clean_objects. Use its own thread.
+clean.start()
+
+# Starts the Server, in order to be sync with the cleanup process.
+s.start()
+
+s.gui(locals())
diff --git a/examples/04-soundfiles/06-record-table.py b/examples/04-soundfiles/06-record-table.py
new file mode 100644
index 0000000..9f8a9e8
--- /dev/null
+++ b/examples/04-soundfiles/06-record-table.py
@@ -0,0 +1,37 @@
+"""
+06-record-table.py - Recording live sound in RAM.
+
+By recording a stream of sound in RAM, one can quickly re-use the
+samples in the current process. A combination NewTable - TableRec
+is all what one need to record any stream in a table.
+
+The NewTable object has a `feedback` argument, allowing overdub.
+
+The TableRec object starts a new recording (records until the table
+is full) every time its method `play()` is called.
+
+"""
+from pyo import *
+import os
+
+# Audio inputs must be available.
+s = Server(duplex=1).boot()
+
+# Path of the recorded sound file.
+path = os.path.join(os.path.expanduser("~"), "Desktop", "synth.wav")
+
+# Creates a two seconds stereo empty table. The "feedback" argument
+# is the amount of old data to mix with a new recording (overdub).
+t = NewTable(length=2, chnls=2, feedback=0.5)
+
+# Retrieves the stereo input
+inp = Input([0,1])
+
+# Table recorder. Call rec.play() to start a recording, it stops
+# when the table is full. Call it multiple times to overdub.
+rec = TableRec(inp, table=t, fadetime=0.05)
+
+# Reads the content of the table in loop.
+osc = Osc(table=t, freq=t.getRate(), mul=0.5).out()
+
+s.gui(locals())
diff --git a/examples/05-envelopes/01-data-signal-conversion.py b/examples/05-envelopes/01-data-signal-conversion.py
new file mode 100644
index 0000000..f7ec208
--- /dev/null
+++ b/examples/05-envelopes/01-data-signal-conversion.py
@@ -0,0 +1,31 @@
+"""
+01-data-signal-conversion.py - Conversion from number to audio stream.
+
+The Stream object is a new type introduced by pyo to represent an
+audio signal as a vector of floats. It is sometimes useful to be
+able to convert simple numbers (python's floats or integers) to
+audio signal or to extract numbers from an audio stream.
+
+The Sig object converts a number to an audio stream.
+
+The PyoObject.get() method extracts a float from an audio stream.
+
+"""
+from __future__ import print_function
+from pyo import *
+
+s = Server().boot()
+
+# A python integer (or float).
+anumber = 100
+
+# Conversion from number to an audio stream (vector of floats).
+astream = Sig(anumber)
+
+# Use a Print (capital "P") object to print an audio stream.
+pp = Print(astream, interval=0.1, message="Audio stream value")
+
+# Use the get() method to extract a float from an audio stream.
+print("Float from audio stream : ", astream.get())
+
+s.gui(locals())
diff --git a/examples/05-envelopes/02-linear-ramp.py b/examples/05-envelopes/02-linear-ramp.py
new file mode 100644
index 0000000..98aa3a5
--- /dev/null
+++ b/examples/05-envelopes/02-linear-ramp.py
@@ -0,0 +1,41 @@
+"""
+02-linear-ramp.py - Portamento, glissando, ramping.
+
+The SigTo object allows to create audio glissando between the
+current value and the target value, within a user-defined time.
+The target value can be a float or another PyoObject. A new ramp
+is created everytime the target value changes.
+
+Also:
+
+The VarPort object acts similarly but works only with float and
+can call a user-defined callback when the ramp reaches the target
+value.
+
+The PyoObject.set() method is another way create a ramp for any
+given parameter that accept audio signal but is not already
+controlled with a PyoObject.
+
+"""
+from pyo import *
+
+s = Server().boot()
+
+# 2 seconds linear ramp starting at 0.0 and ending at 0.3.
+amp = SigTo(value=0.3, time=2.0, init=0.0)
+
+# Pick a new value four times per second.
+pick = Choice([200,250,300,350,400], freq=4)
+
+# Print the chosen frequency
+pp = Print(pick, method=1, message="Frequency")
+
+# Add a little portamento on an audio target and detune a second frequency.
+freq = SigTo(pick, time=0.01, mul=[1, 1.005])
+# Play with portamento time.
+freq.ctrl([SLMap(0, 0.25, "lin", "time", 0.01, dataOnly=True)])
+
+# Play a simple wave.
+sig = RCOsc(freq, sharp=0.7, mul=amp).out()
+
+s.gui(locals())
diff --git a/examples/05-envelopes/03-exponential-ramp.py b/examples/05-envelopes/03-exponential-ramp.py
new file mode 100644
index 0000000..a0b18ee
--- /dev/null
+++ b/examples/05-envelopes/03-exponential-ramp.py
@@ -0,0 +1,33 @@
+"""
+03-exponential-ramp.py - Exponential portamento with rising and falling times.
+
+The Port object is designed to lowpass filter an audio signal with
+different coefficients for rising and falling signals. A lowpass
+filter is a good and efficient way of creating an exponential ramp
+from a signal containing abrupt changes. The rising and falling
+coefficients are controlled in seconds.
+
+"""
+from pyo import *
+
+s = Server().boot()
+
+# 2 seconds linear ramp starting at 0.0 and ending at 0.3.
+amp = SigTo(value=0.3, time=2.0, init=0.0)
+
+# Pick a new value four times per second.
+pick = Choice([200,250,300,350,400], freq=4)
+
+# Print the chosen frequency
+pp = Print(pick, method=1, message="Frequency")
+
+# Add an exponential portamento on an audio target and detune a second frequency.
+# Sharp attack for rising notes and long release for falling notes.
+freq = Port(pick, risetime=0.001, falltime=0.25, mul=[1, 1.005])
+# Play with portamento times.
+freq.ctrl()
+
+# Play a simple wave.
+sig = RCOsc(freq, sharp=0.7, mul=amp).out()
+
+s.gui(locals())
diff --git a/examples/05-envelopes/04-simple-envelopes.py b/examples/05-envelopes/04-simple-envelopes.py
new file mode 100644
index 0000000..c16b1f0
--- /dev/null
+++ b/examples/05-envelopes/04-simple-envelopes.py
@@ -0,0 +1,46 @@
+"""
+04-simple-envelopes.py - ASR and ADSR envelopes.
+
+The Fader object is a simple way to setup an Attack/Sustain/Release envelope.
+This envelope allows to apply fadein and fadeout on audio streams.
+
+If the `dur` argument of the Fader object is set to 0 (the default), the
+object waits for a stop() command before activating the release part of
+the envelope. Otherwise, the sum of `fadein` and `fadeout` must be less
+than or egal to `dur` and the envelope runs to the end on a play() command.
+
+The Adsr object (Attack/Decay/Sustain/Release) acts exactly like the Fader
+object, with a more flexible (and so common) kind of envelope.
+
+"""
+from pyo import *
+import random
+
+s = Server().boot()
+
+# Infinite sustain for the global envelope.
+globalamp = Fader(fadein=2, fadeout=2, dur=0).play()
+
+# Envelope for discrete events, sharp attack, long release.
+env = Adsr(attack=0.01, decay=0.1, sustain=0.5, release=1.5, dur=2, mul=0.5)
+# setExp method can be used to create exponential or logarithmic envelope.
+env.setExp(0.75)
+
+# Initialize  a simple wave player and apply both envelopes.
+sig = SuperSaw(freq=[100,101], detune=0.6, bal=0.8, mul=globalamp*env).out()
+
+def play_note():
+    "Play a new note with random frequency and jitterized envelope."
+    freq = random.choice(midiToHz([36, 38, 41, 43, 45]))
+    sig.freq = [freq, freq*1.005]
+    env.attack = random.uniform(0.002, 0.01)
+    env.decay = random.uniform(0.1, 0.5)
+    env.sustain = random.uniform(0.3, 0.6)
+    env.release = random.uniform(0.8, 1.4)
+    # Start the envelope for the event.
+    env.play()
+
+# Periodically call a function.
+pat = Pattern(play_note, time=2).play()
+
+s.gui(locals())
diff --git a/examples/05-envelopes/05-breakpoints-functions.py b/examples/05-envelopes/05-breakpoints-functions.py
new file mode 100644
index 0000000..8ddc614
--- /dev/null
+++ b/examples/05-envelopes/05-breakpoints-functions.py
@@ -0,0 +1,53 @@
+"""
+05-breakpoints-functions.py - Multi-segments envelopes.
+
+Linseg and Expseg objects draw a series of line segments between 
+specified break-points, either linear or exponential.
+
+These objects wait for play() call to start reading the envelope.
+
+They have methods to set loop mode, call pause/play without reset,
+and replace the breakpoints.
+
+One can use the graph() method to open a graphical display of the current 
+envelope, edit it, and copy the points (in the list format) to the 
+clipboard (Menu "File" of the graph display => "Copy all Points ..."). 
+This makes it easier to explore and paste the result into the python 
+script when happy with the envelope!
+
+"""
+from pyo import *
+import random
+
+s = Server().boot()
+
+# Randomly built 10-points amplitude envelope.
+t = 0
+points = [(0.0, 0.0), (2.0, 0.0)]
+for i in range(8):
+    t += random.uniform(.1, .2)
+    v = random.uniform(.1, .9)
+    points.insert(-1, (t, v))
+
+amp = Expseg(points, exp=3, mul=0.3)
+amp.graph(title="Amplitude envelope")
+
+sig = RCOsc(freq=[150,151], sharp=0.85, mul=amp)
+
+# A simple linear function to vary the amount of frequency shifting.
+sft = Linseg([(0.0, 0.0), (0.5, 20.0), (2, 0.0)])
+sft.graph(yrange=(0.0, 20.0), title="Frequency shift")
+
+fsg = FreqShift(sig, shift=sft).out()
+
+rev = WGVerb(sig+fsg, feedback=0.9, cutoff=3500, bal=0.3).out()
+
+def playnote():
+    "Start the envelopes to play an event."
+    amp.play()
+    sft.play()
+
+# Periodically call a function.
+pat = Pattern(playnote, 2).play()
+
+s.gui(locals())
diff --git a/examples/06-filters/01-lowpass-filters.py b/examples/06-filters/01-lowpass-filters.py
new file mode 100644
index 0000000..87857dc
--- /dev/null
+++ b/examples/06-filters/01-lowpass-filters.py
@@ -0,0 +1,41 @@
+"""
+01-lowpass-filters.py - The effect of the order of a filter.
+
+For this first example about filtering, we compare the frequency
+spectrum of three common lowpass filters.
+
+- Tone : IIR first-order lowpass
+- ButLP : IIR second-order lowpass (Butterworth)
+- MoogLP : IIR fourth-order lowpass (+ resonance as an extra parameter)
+
+Complementary highpass filters for the Tone and ButLP objects are Atone
+and ButHP. Another common highpass filter is the DCBlock object, which
+can be used to remove DC component from an audio signal.
+
+The next example will present bandpass filters.
+
+"""
+from pyo import *
+
+s = Server().boot()
+
+# White noise generator
+n = Noise(.5)
+
+# Common cutoff frequency control
+freq = Sig(1000)
+freq.ctrl([SLMap(50, 5000, "lin", "value", 1000)], title="Cutoff Frequency")
+
+# Three different lowpass filters
+tone = Tone(n, freq)
+butlp = ButLP(n, freq)
+mooglp = MoogLP(n, freq)
+
+# Interpolates between input objects to produce a single output
+sel = Selector([tone, butlp, mooglp]).out()
+sel.ctrl(title="Filter selector (0=Tone, 1=ButLP, 2=MoogLP)")
+
+# Displays the spectrum contents of the chosen source
+sp = Spectrum(sel)
+
+s.gui(locals())
diff --git a/examples/06-filters/02-bandpass-filters.py b/examples/06-filters/02-bandpass-filters.py
new file mode 100644
index 0000000..dbc3705
--- /dev/null
+++ b/examples/06-filters/02-bandpass-filters.py
@@ -0,0 +1,37 @@
+"""
+02-bandpass-filters.py - Narrowing a bandpass filter bandwidth.
+
+This example illustrates the difference between a simple IIR second-order
+bandpass filter and a cascade of second-order bandpass filters. A cascade
+of four bandpass filters with a high Q can be used as a efficient resonator
+on the signal.
+
+"""
+from pyo import *
+
+s = Server().boot()
+
+# White noise generator
+n = Noise(.5)
+
+# Common cutoff frequency control
+freq = Sig(1000)
+freq.ctrl([SLMap(50, 5000, "lin", "value", 1000)], title="Cutoff Frequency")
+
+# Common filter's Q control
+q = Sig(5)
+q.ctrl([SLMap(0.7, 20, "log", "value", 5)], title="Filter's Q")
+
+# Second-order bandpass filter
+bp1 = Reson(n, freq, q=q)
+# Cascade of second-order bandpass filters
+bp2 = Resonx(n, freq, q=q, stages=4)
+
+# Interpolates between input objects to produce a single output
+sel = Selector([bp1, bp2]).out()
+sel.ctrl(title="Filter selector (0=Reson, 1=Resonx)")
+
+# Displays the spectrum contents of the chosen source
+sp = Spectrum(sel)
+
+s.gui(locals())
diff --git a/examples/06-filters/03-complex-resonator.py b/examples/06-filters/03-complex-resonator.py
new file mode 100644
index 0000000..cdbbc32
--- /dev/null
+++ b/examples/06-filters/03-complex-resonator.py
@@ -0,0 +1,33 @@
+"""
+03-complex-resonator.py - Filtering by mean of a complex multiplication.
+
+ComplexRes implements a resonator derived from a complex
+multiplication, which is very similar to a digital filter.
+
+It is used here to create a rhythmic chime with varying resonance.
+
+"""
+from pyo import *
+import random
+
+s = Server().boot()
+
+# Six random frequencies.
+freqs = [random.uniform(1000, 3000) for i in range(6)]
+
+# Six different plucking speeds.
+pluck = Metro([.9,.8,.6,.4,.3,.2]).play()
+
+# LFO applied to the decay of the resonator.
+decay = Sine(.1).range(.01, .15)
+
+# Six ComplexRes filters.
+rezos = ComplexRes(pluck, freqs, decay, mul=5).out()
+
+# Change chime frequencies every 7.2 seconds
+def new():
+    freqs = [random.uniform(1000, 3000) for i in range(6)]
+    rezos.freq = freqs
+pat = Pattern(new, 7.2).play()
+
+s.gui(locals())
diff --git a/examples/06-filters/04-phasing.py b/examples/06-filters/04-phasing.py
new file mode 100644
index 0000000..ca42ace
--- /dev/null
+++ b/examples/06-filters/04-phasing.py
@@ -0,0 +1,39 @@
+"""
+04-phasing.py - The phasing effect.
+
+The Phaser object implements a variable number of second-order
+allpass filters, allowing to quickly build complex phasing effects.
+
+    A phaser is an electronic sound processor used to filter a signal
+    by creating a series of peaks and troughs in the frequency spectrum.
+    The position of the peaks and troughs of the waveform being affected
+    is typically modulated so that they vary over time, creating a sweeping
+    effect. For this purpose, phasers usually include a low-frequency
+    oscillator. - https://en.wikipedia.org/wiki/Phaser_(effect)
+
+A phase shifter unit can be built from scratch with the Allpass2 object,
+which implement a second-order allpass filter that create, when added to
+the original source, one notch in the spectrum.
+
+"""
+from pyo import *
+
+s = Server().boot()
+
+# Simple fadein.
+fade = Fader(fadein=.5, mul=.2).play()
+
+# Noisy source.
+a = PinkNoise(fade)
+
+# These LFOs modulate the `freq`, `spread` and `q` arguments of
+# the Phaser object. We give a list of two frequencies in order
+# to create two-streams LFOs, therefore a stereo phasing effect.
+lf1 = Sine(freq=[.1, .15], mul=100, add=250)
+lf2 = Sine(freq=[.18, .13], mul=.4, add=1.5)
+lf3 = Sine(freq=[.07, .09], mul=5, add=6)
+
+# Apply the phasing effect with 20 notches.
+b = Phaser(a, freq=lf1, spread=lf2, q=lf3, num=20, mul=.5).out()
+
+s.gui(locals())
diff --git a/examples/06-filters/05-convolution-filters.py b/examples/06-filters/05-convolution-filters.py
new file mode 100644
index 0000000..0c57ac1
--- /dev/null
+++ b/examples/06-filters/05-convolution-filters.py
@@ -0,0 +1,76 @@
+"""
+05-convolution-filters.py - Circular convolution.
+
+A circular convolution is defined as the integral of the
+product of two functions after one is reversed and shifted.
+
+Circular convolution allows to implement very complex FIR
+filters, at a CPU cost that is related to the filter impulse
+response (kernel) length.
+
+Within pyo, there is a family of IR* filter objects using
+circular convolution with predefined kernel:
+
+- IRAverage : moving average filter
+- IRFM : FM-like filter
+- IRPulse : comb-like filter
+- RWinSinc : break wall filters (lp, hp, hp, br)
+
+For general circular convolution, use the Convolve object
+with a PyoTableObject as the kernel, as in this example:
+
+A white noise is filtered by four impulses taken from the input mic. 
+
+Call r1.play(), r2.play(), r3.play() or r4.play() in the Interpreter 
+field while making some noise in the mic to fill the impulse response 
+tables. The slider handles the morphing between the four kernels.
+
+Call t1.view(), t2.view(), t3.view() or t4.view() to view impulse 
+response tables.
+
+Because circular convolution is very expensive, TLEN (in samples) 
+should be keep small.
+
+"""
+from pyo import *
+
+# duplex=1 to tell the Server we need both input and output sounds.
+s = Server(duplex=1).boot()
+
+# Length of the impulse response in samples.
+TLEN = 512
+
+# Conversion to seconds for NewTable objects.
+DUR = sampsToSec(TLEN)
+
+# Excitation signal for the filters.
+sf = Noise(.5)
+
+# Signal from the mic to record the kernels.
+inmic = Input()
+
+# Four tables and recorders.
+t1 = NewTable(length=DUR, chnls=1)
+r1 = TableRec(inmic, table=t1, fadetime=.001)
+
+t2 = NewTable(length=DUR, chnls=1)
+r2 = TableRec(inmic, table=t2, fadetime=.001)
+
+t3 = NewTable(length=DUR, chnls=1)
+r3 = TableRec(inmic, table=t3, fadetime=.001)
+
+t4 = NewTable(length=DUR, chnls=1)
+r4 = TableRec(inmic, table=t4, fadetime=.001)
+
+# Interpolation control between the tables.
+pha = Sig(0)
+pha.ctrl(title="Impulse responses morphing")
+
+# Morphing between the four impulse responses.
+res = NewTable(length=DUR, chnls=1)
+morp = TableMorph(pha, res, [t1,t2,t3,t4])
+
+# Circular convolution between the excitation and the morphed kernel.
+a = Convolve(sf, table=res, size=res.getSize(), mul=.1).mix(2).out()
+
+s.gui(locals())
diff --git a/examples/06-filters/06-vocoder.py b/examples/06-filters/06-vocoder.py
new file mode 100644
index 0000000..542f893
--- /dev/null
+++ b/examples/06-filters/06-vocoder.py
@@ -0,0 +1,35 @@
+"""
+06-vocoder.py - Analysis/resynthesis vocoder effect.
+
+A vocoder is an analysis/resynthesis process that
+uses the spectral envelope of a first sound to shape
+the spectrum of a second sound. Usually (for the best
+results) the first sound should present a dynamic
+spectrum (for both frequencies and amplitudes) and the
+second sound should contain a rich and stable spectrum.
+
+In this example, LFOs are applied to every dynamic argument
+of the Vocoder object to show the range of sound effects
+the user can get with a vocoder.
+
+"""
+from pyo import *
+from random import random
+
+s = Server().boot()
+
+# First sound - dynamic spectrum.
+spktrm = SfPlayer("../snds/baseballmajeur_m.aif", speed=[1,1.001], loop=True)
+
+# Second sound - rich and stable spectrum.
+excite = Noise(0.2)
+
+# LFOs to modulated every parameters of the Vocoder object.
+lf1 = Sine(freq=0.1, phase=random()).range(60, 100)
+lf2 = Sine(freq=0.11, phase=random()).range(1.05, 1.5)
+lf3 = Sine(freq=0.07, phase=random()).range(1, 20)
+lf4 = Sine(freq=0.06, phase=random()).range(0.01, 0.99)
+
+voc = Vocoder(spktrm, excite, freq=lf1, spread=lf2, q=lf3, slope=lf4, stages=32).out()
+
+s.gui(locals())
diff --git a/examples/06-filters/07-hilbert-transform.py b/examples/06-filters/07-hilbert-transform.py
new file mode 100644
index 0000000..b084319
--- /dev/null
+++ b/examples/06-filters/07-hilbert-transform.py
@@ -0,0 +1,51 @@
+"""
+07-hilbert-transform.py - Barberpole-like phasing effect.
+
+This example uses two frequency shifters (based on complex
+modulation) linearly shifting the frequency content of a sound.
+
+Frequency shifting is similar to ring modulation, except the
+upper and lower sidebands are separated into individual outputs.
+
+"""
+from pyo import *
+
+class ComplexMod:
+    """
+    Complex modulation used to shift the frequency
+    spectrum of the input sound.
+    """
+    def __init__(self, hilb, freq):
+        # Quadrature oscillator (sine, cosine).
+        self._quad = Sine(freq, [0, 0.25])
+        # real * cosine.
+        self._mod1 = hilb['real'] * self._quad[1]
+        # imaginary * sine.
+        self._mod2 = hilb['imag'] * self._quad[0]
+        # Up shift corresponds to the sum frequencies.
+        self._up = (self._mod1 + self._mod2) * 0.7
+
+    def out(self, chnl=0):
+        self._up.out(chnl)
+        return self
+
+s = Server().boot()
+
+# Large spectrum source.
+src = PinkNoise(.2)
+
+# Apply the Hilbert transform.
+hilb = Hilbert(src)
+
+# LFOs controlling the amount of frequency shifting.
+lf1 = Sine(.03, mul=6)
+lf2 = Sine(.05, mul=6)
+
+# Stereo Single-Sideband Modulation.
+wetl = ComplexMod(hilb, lf1).out()
+wetr = ComplexMod(hilb, lf2).out(1)
+
+# Mixed with the dry sound.
+dry = src.mix(2).out()
+
+s.gui(locals())
diff --git a/examples/07-effects/01-flanger.py b/examples/07-effects/01-flanger.py
new file mode 100644
index 0000000..9a52bdf
--- /dev/null
+++ b/examples/07-effects/01-flanger.py
@@ -0,0 +1,42 @@
+"""
+01-flanger.py - Hand-made simple flanger.
+
+A flanger is an audio effect produced by mixing two identical signals
+together, one signal delayed by a small and gradually changing period.
+This produces a swept comb filter effect: peaks and notches are produced
+in the resulting frequency spectrum, related to each other in a linear
+harmonic series. Varying the time delay causes these to sweep up and
+down the frequency spectrum. 
+
+"""
+from pyo import *
+
+s = Server().boot()
+
+# Rich frequency spectrum as stereo input source.
+amp = Fader(fadein=0.25, mul=0.5).play()
+src = PinkNoise(amp).mix(2)
+
+# Flanger parameters                        == unit ==
+middelay = 0.005                            # seconds
+
+depth = Sig(0.99)                           # 0 --> 1
+depth.ctrl(title="Modulation Depth")
+lfospeed = Sig(0.2)                         # Hertz
+lfospeed.ctrl(title="LFO Frequency in Hz")
+feedback = Sig(0.5, mul=0.95)               # 0 --> 1
+feedback.ctrl(title="Feedback")
+
+# LFO with adjusted output range to control the delay time in seconds.
+lfo = Sine(freq=lfospeed, mul=middelay*depth, add=middelay)
+
+# Dynamically delayed signal. The source passes through a DCBlock
+# to ensure there is no DC offset in the signal (with feedback, DC
+# offset can be fatal!).
+flg = Delay(DCBlock(src), delay=lfo, feedback=feedback)
+
+# Mix the original source with its delayed version.
+# Compress the mix to normalize the output signal.
+cmp = Compress(src+flg, thresh=-20, ratio=4).out()
+
+s.gui(locals())
diff --git a/examples/07-effects/02-schroeder-reverb.py b/examples/07-effects/02-schroeder-reverb.py
new file mode 100755
index 0000000..3b03b3f
--- /dev/null
+++ b/examples/07-effects/02-schroeder-reverb.py
@@ -0,0 +1,44 @@
+"""
+02-schroeder-reverb.py - Simple reverberator based on Schroeder's algorithms.
+
+An artificial reverberation based on the work of Manfred Schroeder.
+
+This reverberator takes a monopkonic input and outputs two uncorrelated
+reverberated signals. 
+
+This algorithm presents four parallel comb filters fedding two serial
+allpass filters. An additional lowpass filter is used at the end to 
+control the brightness of the reverberator.
+
+The manual example for the Allpass object presents an other Schroeder
+reverberator.
+
+"""
+from pyo import *
+
+s = Server(duplex=0).boot()
+
+soundfile = SndTable(SNDS_PATH + "/transparent.aif")
+
+src = Looper(soundfile, dur=2, xfade=0, mul=0.3)
+src2 = src.mix(2).out()
+
+# Four parallel stereo comb filters. The delay times are chosen 
+# to be as uncorrelated as possible. Prime numbers are a good
+# choice for delay lengths in samples.
+comb1 = Delay(src, delay=[0.0297, 0.0277], feedback=0.65)
+comb2 = Delay(src, delay=[0.0371, 0.0393], feedback=0.51)
+comb3 = Delay(src, delay=[0.0411, 0.0409], feedback=0.5)
+comb4 = Delay(src, delay=[0.0137, 0.0155], feedback=0.73)
+
+combsum = src + comb1 + comb2 + comb3 + comb4
+
+# The sum of the original signal and the comb filters
+# feeds two serial allpass filters.
+all1 = Allpass(combsum, delay=[.005, .00507], feedback=0.75)
+all2 = Allpass(all1, delay=[.0117, .0123], feedback=0.61)
+
+# Brightness control.
+lowp = Tone(all2, freq=3500, mul=.25).out()
+
+s.gui(locals())
diff --git a/examples/18-multicore/01-processes-spawning.py b/examples/18-multicore/01-processes-spawning.py
new file mode 100644
index 0000000..dcd5f9a
--- /dev/null
+++ b/examples/18-multicore/01-processes-spawning.py
@@ -0,0 +1,37 @@
+"""
+01-processes-spawning.py - Simple processes spawning, no synchronization. 
+
+Need at least 4 cores to be really effective.
+
+Usage:
+    python3 -i 01-processes-spawning.py
+
+"""
+import time, random, multiprocessing
+from pyo import *
+
+class Proc(multiprocessing.Process):
+    def __init__(self, pitch):
+        super(Proc, self).__init__()
+        self.daemon = True
+        self.pitch = pitch
+
+    def run(self):
+        self.server = Server(audio="jack")
+        self.server.deactivateMidi()
+        self.server.boot().start()
+
+        # 200 randomized band-limited square wave oscillators.
+        self.amp = Fader(fadein=5, mul=0.01).play()
+        lo, hi = midiToHz((self.pitch - 0.1, self.pitch + 0.1))
+        self.fr = Randi(lo, hi, [random.uniform(.2, .4) for i in range(200)])
+        self.sh = Randi(0.1, 0.9, [random.uniform(.2, .4) for i in range(200)])
+        self.osc = LFO(self.fr, sharp=self.sh, type=2, mul=self.amp).out()
+
+        time.sleep(30) # Play for 30 seconds.
+        self.server.stop()
+
+if __name__ == '__main__':
+    # C major chord (one note per process).
+    p1, p2, p3, p4 = Proc(48), Proc(52), Proc(55), Proc(60)
+    p1.start(); p2.start(); p3.start(); p4.start()
diff --git a/examples/18-multicore/02-sharing-audio.py b/examples/18-multicore/02-sharing-audio.py
new file mode 100644
index 0000000..faef36c
--- /dev/null
+++ b/examples/18-multicore/02-sharing-audio.py
@@ -0,0 +1,48 @@
+"""
+02-sharing-audio.py - Sharing audio signals between processes.
+
+Usage:
+    python3 -i 02-sharing-audio.py
+
+"""
+import time, random, multiprocessing
+from pyo import *
+
+class Proc(multiprocessing.Process):
+    def __init__(self, create):
+        super(Proc, self).__init__()
+        self.daemon = True
+        self.create = create
+
+    def run(self):
+        self.server = Server(audio="jack")
+        self.server.deactivateMidi()
+        self.server.boot().start()
+        bufsize = self.server.getBufferSize()
+
+        nbands = 50
+        names = ["/f%02d" % i for i in range(nbands)]
+
+        if self.create: # 50 bands frequency splitter.
+            freq = [20 * 1.1487 ** i for i in range(nbands)]
+            amp = [pow(10, (i*-1)*0.05) * 8 for i in range(nbands)]
+            self.input = SfPlayer(SNDS_PATH+"/transparent.aif", loop=True)
+            self.filts = IRWinSinc(self.input, freq, freq, 3, 128, amp)
+            self.table = SharedTable(names, create=True, size=bufsize)
+            self.recrd = TableFill(self.filts, self.table)
+        else: # Independent transposition per band.
+            self.table = SharedTable(names, create=False, size=bufsize)
+            self.tscan = TableScan(self.table)
+            transpofac = [random.uniform(0.98,1.02) for i in range(nbands)]
+            self.pvana = PVAnal(self.tscan, size=1024, overlaps=4)
+            self.pvtra = PVTranspose(self.pvana, transpo=transpofac)
+            self.pvsyn = PVSynth(self.pvtra).out()
+
+        time.sleep(30)
+        self.server.stop()
+
+if __name__ == '__main__':
+    analysis = Proc(create=True)
+    synthesis = Proc(create=False)
+    analysis.start()
+    synthesis.start()
diff --git a/examples/18-multicore/03-synchronization.py b/examples/18-multicore/03-synchronization.py
new file mode 100644
index 0000000..e9edc95
--- /dev/null
+++ b/examples/18-multicore/03-synchronization.py
@@ -0,0 +1,76 @@
+"""
+03-synchronization.py - Synchronizing multiple processes.
+
+Usage:
+    python3 -i 03-synchronization.py
+
+"""
+import time, random, multiprocessing
+from pyo import *
+
+RECORD = False
+
+class Main(multiprocessing.Process):
+    def __init__(self):
+        super(Main, self).__init__()
+        self.daemon = True
+
+    def run(self):
+        self.server = Server(audio="jack")
+        self.server.deactivateMidi()
+        self.server.boot().start()
+        bufsize = self.server.getBufferSize()
+        if RECORD:
+            self.server.recstart("synchronization.wav")
+
+        self.tab1 = SharedTable("/audio-1", create=False, size=bufsize)
+        self.tab2 = SharedTable("/audio-2", create=False, size=bufsize)
+        self.out1 = TableScan(self.tab1).out()
+        self.out2 = TableScan(self.tab2).out(1)
+
+        time.sleep(30)
+        self.server.stop()
+
+class Proc(multiprocessing.Process):
+    def __init__(self, voice, conn):
+        super(Proc, self).__init__()
+        self.voice = voice
+        self.connection = conn
+        self.daemon = True
+
+    def run(self):
+        self.server = Server(audio="jack")
+        self.server.deactivateMidi()
+        self.server.boot()
+        bufsize = self.server.getBufferSize()
+
+        name = "/audio-%d" % self.voice
+        self.audiotable = SharedTable(name, create=True, size=bufsize)
+
+        onsets = random.sample([5,6,7,8,9], 2)
+        self.tab = CosTable([(0,0), (32,1), (512,0.5), (4096,0.5), (8191,0)])
+        self.ryt = Euclide(time=.125, taps=16, onsets=onsets, poly=1).play()
+        self.mid = TrigXnoiseMidi(self.ryt, dist=12, mrange=(60, 96))
+        self.frq = Snap(self.mid, choice=[0,2,3,5,7,8,10], scale=1)
+        self.amp = TrigEnv(self.ryt, table=self.tab, dur=self.ryt['dur'], 
+                           mul=self.ryt['amp'])
+        self.sig = SineLoop(freq=self.frq, feedback=0.08, mul=self.amp*0.3)
+        self.fil = TableFill(self.sig, self.audiotable)
+
+        # Wait for an incoming signal before starting the server.
+        while not self.connection.poll():
+            pass
+        self.server.start()
+
+        time.sleep(30)
+        self.server.stop()
+
+if __name__ == '__main__':
+    signal, child = multiprocessing.Pipe()
+    p1, p2 = Proc(1, child), Proc(2, child)
+    main = Main()
+    p1.start(); p2.start();
+    time.sleep(.05)
+    main.start()
+    time.sleep(.05)
+    signal.send(1)
diff --git a/examples/18-multicore/04-data-control.py b/examples/18-multicore/04-data-control.py
new file mode 100644
index 0000000..e35d884
--- /dev/null
+++ b/examples/18-multicore/04-data-control.py
@@ -0,0 +1,73 @@
+"""
+04-data-control.py - Multicore midi synthesizer.
+
+Need at least 4 cores to be really effective.
+
+Usage:
+    python3 -i 04-data-control.py
+
+"""
+import time, multiprocessing
+from random import uniform
+from pyo import *
+
+VOICES_PER_CORE = 4
+
+class Proc(multiprocessing.Process):
+    def __init__(self, pipe):
+        super(Proc, self).__init__()
+        self.daemon = True
+        self.pipe = pipe
+
+    def run(self):
+        self.server = Server(audio="jack")
+        self.server.deactivateMidi()
+        self.server.boot().start()
+
+        self.mid = Notein(poly=VOICES_PER_CORE, scale=1, first=0, last=127)
+        self.amp = MidiAdsr(self.mid['velocity'], 0.005, .1, .7, 0.5, mul=.1)
+        self.pit = self.mid['pitch'] * [uniform(.99, 1.01) for i in range(40)]
+        self.rc1 = RCOsc(self.pit, sharp=0.8, mul=self.amp).mix(1)
+        self.rc2 = RCOsc(self.pit*0.99, sharp=0.8, mul=self.amp).mix(1)
+        self.mix = Mix([self.rc1, self.rc2], voices=2)
+        self.rev = STRev(Denorm(self.mix), [.1, .9], 2, bal=0.30).out()
+
+        while True:
+            if self.pipe.poll():
+                data = self.pipe.recv()
+                self.server.addMidiEvent(*data)
+            time.sleep(0.001)
+
+        self.server.stop()
+
+if __name__ == '__main__':
+    main1, child1 = multiprocessing.Pipe()
+    main2, child2 = multiprocessing.Pipe()
+    main3, child3 = multiprocessing.Pipe()
+    main4, child4 = multiprocessing.Pipe()
+    mains = [main1, main2, main3, main4]
+    p1, p2, p3, p4 = Proc(child1), Proc(child2), Proc(child3), Proc(child4)
+    p1.start(); p2.start(); p3.start(); p4.start()
+
+    playing = {0: [], 1: [], 2: [], 3: []}
+    currentcore = 0
+    def callback(status, data1, data2):
+        global currentcore
+        if status == 0x80 or status == 0x90 and data2 == 0: 
+            for i in range(4):
+                if data1 in playing[i]:
+                    playing[i].remove(data1)
+                    mains[i].send([status, data1, data2])
+                    break
+        elif status == 0x90:
+            for i in range(4):
+                currentcore = (currentcore + 1) % 4
+                if len(playing[currentcore]) < VOICES_PER_CORE:
+                    playing[currentcore].append(data1)
+                    mains[currentcore].send([status, data1, data2])
+                    break
+
+    s = Server()
+    s.setMidiInputDevice(99) # Open all devices.
+    s.boot().start()
+    raw = RawMidi(callback)
diff --git a/examples/algorithmic/01_music_box.py b/examples/algorithmic/01_music_box.py
index 56f86a8..cd99c25 100644
--- a/examples/algorithmic/01_music_box.py
+++ b/examples/algorithmic/01_music_box.py
@@ -4,18 +4,23 @@
 Music box. 5 voices randomly choosing frequencies over a common scale.
 
 """
+
 from pyo import *
 
 s = Server(duplex=0).boot()
 
+#--> set list of frequencies
 low_freqs = [midiToHz(m+7) for m in [36,43.01,48,55.01,60]]
 mid_freqs = [midiToHz(m+7) for m in [60,62,63.93,65,67.01,69,71,72]]
 high_freqs = [midiToHz(m+7) for m in [72,74,75.93,77,79.01]]
 freqs = [low_freqs,low_freqs,mid_freqs,mid_freqs,high_freqs]
+#<--
 
+#-->
 chx = Choice(choice=freqs, freq=[1,2,3,3,4])
 port = Port(chx, risetime=.001, falltime=.001)
 sines = SineLoop(port, feedback=[.06,.057,.033,.035,.016], mul=[.15,.15,.1,.1,.06])
 pan = SPan(sines, pan=[0, 1, .2, .8, .5]).out()
+#<--
 
-s.gui(locals())
\ No newline at end of file
+s.gui(locals())
diff --git a/examples/algorithmic/02_scale_snap.py b/examples/algorithmic/02_scale_snap.py
index 28a678a..9303a4a 100644
--- a/examples/algorithmic/02_scale_snap.py
+++ b/examples/algorithmic/02_scale_snap.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
 """
 Algorithmic melody patterns snapped on a specific scale...
 
@@ -24,7 +25,7 @@ def changeScl():
     global curscl
     curscl = (curscl + 1) % len(scls)
     snp.choice = scls[curscl]
-    print snp.choice
+    print(snp.choice)
 
 metscl = Metro(time=8).play()
 tr = TrigFunc(metscl, function=changeScl)
@@ -36,5 +37,3 @@ d2 = Osc(table=wav, freq=snp*1.002, mul=c).out()
 d3 = Osc(table=wav, freq=snp*0.997, mul=c).out()
 
 s.gui(locals())
-
-
diff --git a/examples/algorithmic/03_melody_algo.py b/examples/algorithmic/03_melody_algo.py
index f8871cc..bdda065 100644
--- a/examples/algorithmic/03_melody_algo.py
+++ b/examples/algorithmic/03_melody_algo.py
@@ -7,11 +7,12 @@ The Melo class records 16 notes in a table and reads it at variable speed.
 from pyo import *
 import random
 
-s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot()
+s = Server(duplex=0).boot()
 
 SCALES = [[0,2,5,7,9,11], [0,2,3,7,8,11], [0,3,5,7,8,10]]
 
 class Melo:
+
     def __init__(self, amp=.1, speed=1, midirange=(48,84)):
         # table to record new melody fragment
         self.table = NewTable(2)
@@ -50,4 +51,4 @@ objs = [a,b,c]
 
 pat = Pattern(time=20, function=choose_scale).play()
 
-s.gui(locals())
\ No newline at end of file
+s.gui(locals())
diff --git a/examples/algorithmic/04_drum_machine.py b/examples/algorithmic/04_drum_machine.py
index 8b3c973..3b52f29 100644
--- a/examples/algorithmic/04_drum_machine.py
+++ b/examples/algorithmic/04_drum_machine.py
@@ -9,23 +9,23 @@ from pyo import *
 # Set this constant to True to loop over preset bank
 WITH_PRESET = False
 
-snds3 = ['../snds/alum1.wav', '../snds/alum2.wav', 
+snds3 = ['../snds/alum1.wav', '../snds/alum2.wav',
         '../snds/alum3.wav', '../snds/alum4.wav']
 
-presets = [[[16, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0], 
-            [16, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0], 
-            [16, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0]], 
-           [[16, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1], 
-            [16, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0], 
-            [16, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0]], 
-           [[16, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1], 
-            [16, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0], 
-            [16, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0]], 
-           [[16, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1], 
-            [16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0], 
+presets = [[[16, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0],
+            [16, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0],
+            [16, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0]],
+           [[16, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1],
+            [16, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0],
+            [16, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0]],
+           [[16, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1],
+            [16, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0],
+            [16, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0]],
+           [[16, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1],
+            [16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0],
             [16, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1]]]
 
-s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot()
+s = Server(duplex=0).boot()
 
 tm = Xnoise(dist=9, freq=2.34, x1=.5, x2=3, mul=.0025, add=.12)
 b = Beat(time=tm, w1=[90,30,30,20], w2=[30,90,50,40], w3=[0,30,30,40])
diff --git a/examples/control/01_ctrl_slider.py b/examples/control/01_ctrl_slider.py
index 15a9fe4..619aff8 100644
--- a/examples/control/01_ctrl_slider.py
+++ b/examples/control/01_ctrl_slider.py
@@ -19,4 +19,4 @@ a.ctrl(title="Frequency modulation controls")
 b = a.mix(2)
 b.out()
 
-s.gui(locals())
\ No newline at end of file
+s.gui(locals())
diff --git a/examples/control/02_ctrl_multislider.py b/examples/control/02_ctrl_multislider.py
index ea49091..d7413f0 100644
--- a/examples/control/02_ctrl_multislider.py
+++ b/examples/control/02_ctrl_multislider.py
@@ -15,4 +15,4 @@ a = BrownNoise()
 b = Biquadx(a, freq=[200, 400, 800, 1600, 3200, 6400], q=10, type=2).out()
 b.ctrl(title="Bank of bandpass filters")
 
-s.gui(locals())
\ No newline at end of file
+s.gui(locals())
diff --git a/examples/control/03_table_grapher.py b/examples/control/03_table_grapher.py
index 101ad50..f33128f 100644
--- a/examples/control/03_table_grapher.py
+++ b/examples/control/03_table_grapher.py
@@ -18,7 +18,7 @@ http://www.wxpython.org/
 """
 from pyo import *
 
-s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot()
+s = Server(duplex=0).boot()
 
 NOTE_DUR = 2
 
@@ -44,4 +44,4 @@ ind = TrigEnv(met, table=ind_table, dur=NOTE_DUR)
 
 fm = FM(carrier=freq, ratio=[.997, 1.002], index=ind, mul=amp).out()
 
-s.gui(locals())
\ No newline at end of file
+s.gui(locals())
diff --git a/examples/control/04_set_example.py b/examples/control/04_set_example.py
index 72115e0..dd303f3 100644
--- a/examples/control/04_set_example.py
+++ b/examples/control/04_set_example.py
@@ -9,10 +9,10 @@ call reset() to get back initial values.
 from pyo import *
 from random import uniform
 
-s = Server(sr=44100, nchnls=2, buffersize=1024, duplex=0).boot()
+s = Server(duplex=0).boot()
 
-a = FM(carrier=[uniform(197,203) for i in range(10)], 
-       ratio=[uniform(0.49,0.51) for i in range(10)], 
+a = FM(carrier=[uniform(197,203) for i in range(10)],
+       ratio=[uniform(0.49,0.51) for i in range(10)],
        index=[uniform(10,15) for i in range(10)], mul=.05).out()
 
 def go():
@@ -21,9 +21,8 @@ def go():
     a.set("index", [uniform(5,9) for i in range(10)], 23)
 
 def reset():
-    a.carrier=[uniform(197,203) for i in range(10)]
-    a.ratio=[uniform(0.49,0.51) for i in range(10)]
-    a.index=[uniform(8,12) for i in range(10)]
-    
-s.gui(locals())
+    a.carrier = [uniform(197,203) for i in range(10)]
+    a.ratio = [uniform(0.49,0.51) for i in range(10)]
+    a.index = [uniform(8,12) for i in range(10)]
 
+s.gui(locals())
diff --git a/examples/control/05_mixer.py b/examples/control/05_mixer.py
index 31eb20f..4cf4f52 100644
--- a/examples/control/05_mixer.py
+++ b/examples/control/05_mixer.py
@@ -1,12 +1,13 @@
 #!/usr/bin/env python
 # encoding: utf-8
+from __future__ import print_function
 """
 Mixing multiple inputs to multiple outputs with fade time.
 
 """
 from pyo import *
 
-s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot()
+s = Server(duplex=0).boot()
 
 # Inputs
 a = SfPlayer("../snds/ounkmaster.aif", loop=True, mul=.3)
@@ -42,9 +43,9 @@ def assign():
     vin = random.randint(0, 2)
     vout = random.randint(0, 2)
     amp = random.choice([0,0,.25,.33])
-    print "%s -> %s, amp = %f" % (inputs[vin], outputs[vout], amp)
+    print("%s -> %s, amp = %f" % (inputs[vin], outputs[vout], amp))
     mm.setAmp(vin=vin, vout=vout, amp=amp)
 
 pat = Pattern(function=assign, time=3).play()
 
-s.gui(locals())
\ No newline at end of file
+s.gui(locals())
diff --git a/examples/control/06_lfo_controls.py b/examples/control/06_lfo_controls.py
index bdeb860..893363c 100644
--- a/examples/control/06_lfo_controls.py
+++ b/examples/control/06_lfo_controls.py
@@ -6,7 +6,7 @@ Audio control with LFOs.
 """
 from pyo import *
 
-s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot()
+s = Server(duplex=0).boot()
 
 # LFO (sine wave) +/- 5 (mul) around 10 (add), range = 5 -> 15.
 # Control the frequency of the square wave LFO.
@@ -18,4 +18,4 @@ feedctl = LFO(freq=freqctl, sharp=.8, type=2, mul=.05, add=.07)
 
 synth = SineLoop(freq=[201.32,199.76,200,201.55], feedback=feedctl, mul=.1).out()
 
-s.gui(locals())
\ No newline at end of file
+s.gui(locals())
diff --git a/examples/effects/01_flanger.py b/examples/effects/01_flanger.py
index 4d52111..c77d411 100644
--- a/examples/effects/01_flanger.py
+++ b/examples/effects/01_flanger.py
@@ -6,11 +6,15 @@ Simple flanger.
 """
 from pyo import *
 
-s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot()
+s = Server(duplex=0).boot()
 
+#-->
 src = BrownNoise(.1).mix(2).out()
+#<--
 
+#-->
 lf = Sine(freq=.2, mul=.0045, add=.005)
 flg = Delay(src, delay=lf, feedback=.25).out()
+#<--
 
-s.gui(locals())
\ No newline at end of file
+s.gui(locals())
diff --git a/examples/effects/02_chorus.py b/examples/effects/02_chorus.py
index 57262ef..cd592ed 100644
--- a/examples/effects/02_chorus.py
+++ b/examples/effects/02_chorus.py
@@ -6,11 +6,14 @@ Hand-written 8 delay lines chorus.
 """
 from pyo import *
 
-s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot()
+s = Server(duplex=0).boot()
 
+#--> Start a sound
 sf = SfPlayer('../snds/baseballmajeur_m.aif', speed=1, loop=True, mul=.3)
 sf2 = sf.mix(2).out()
+#<--
 
+#--> Sets values for 8 delay lines
 # delay line frequencies
 freqs = [.254, .465, .657, .879, 1.23, 1.342, 1.654, 1.879]
 # delay line center delays
@@ -19,8 +22,11 @@ cdelay = [.0087, .0102, .0111, .01254, .0134, .01501, .01707, .0178]
 adelay = [.001, .0012, .0013, .0014, .0015, .0016, .002, .0023]
 # modulation depth
 depth = Sig(1)
+#<--
 
+#--> Add the delay lines to the source sound
 lfos = Sine(freqs, mul=adelay*depth, add=cdelay)
 delays = Delay(sf, lfos, feedback=.5, mul=.5).out()
+#<--
 
 s.gui(locals())
diff --git a/examples/effects/03_detuned_waveguides.py b/examples/effects/03_detuned_waveguides.py
index 2a73e27..ec294c3 100644
--- a/examples/effects/03_detuned_waveguides.py
+++ b/examples/effects/03_detuned_waveguides.py
@@ -7,7 +7,7 @@ Detuned waveguide bank.
 from pyo import *
 import random
 
-s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot()
+s = Server(duplex=0).boot()
 
 src = SfPlayer("../snds/ounkmaster.aif", loop=True, mul=.1)
 
diff --git a/examples/effects/04_harmonizer.py b/examples/effects/04_harmonizer.py
index 98d9113..3082d67 100644
--- a/examples/effects/04_harmonizer.py
+++ b/examples/effects/04_harmonizer.py
@@ -6,11 +6,11 @@ Hand-written harmonizer.
 """
 from pyo import *
 
-s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot()
+s = Server(duplex=0).boot()
 
 sf = SfPlayer('../snds/flute.aif', speed=1, loop=True, mul=.5).out()
 
-env = WinTable(7)
+env = WinTable(8)
 
 wsize = .1
 trans = -7
diff --git a/examples/effects/05_fuzz_disto.py b/examples/effects/05_fuzz_disto.py
index db9360e..4353c5d 100644
--- a/examples/effects/05_fuzz_disto.py
+++ b/examples/effects/05_fuzz_disto.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # encoding: utf-8
 """
-Fuzz distortion. High gain followed by, asymmetrical clipping, 
+Fuzz distortion. High gain followed by, asymmetrical clipping,
 hard clip on top, soft compression on bottom.
 
 """
@@ -12,33 +12,33 @@ s = Server(duplex=0).boot()
 SOURCE = "../snds/flute.aif"
 BP_CENTER_FREQ = 250
 BP_Q = 2
-BOOST = 5
+BOOST = 25
 LP_CUTOFF_FREQ = 3500
-BALANCE = 0.8
+BALANCE = 1
 
 src = SfPlayer(SOURCE, loop=True).mix(2)
 
 # Transfert function for signal lower than 0
-low_table = ExpTable([(0,-.25),(4096,0),(8192,0)], exp=10)
+table = ExpTable([(0,-.25),(4096,0),(8192,0)], exp=10)
+table.view()
 # Transfert function for signal higher than 0
 high_table = CosTable([(0,0),(4096,0),(4598,1),(8192,1)])
 
+table.add(high_table)
+
 # Bandpass filter and boost gain applied on input signal
 bp = Biquad(src, freq=BP_CENTER_FREQ, q=BP_Q, type=2)
 boost = Sig(bp, mul=BOOST)
 
-# Split signal into positive and negative part
-sign = Compare(boost, comp=0, mode=">=")
-sw = Switch(boost, outs=2, voice=sign)
-
 # Apply transfert function
-lowsig = Lookup(low_table, sw[0])
-highsig = Lookup(high_table, sw[1])
+sig = Lookup(table, boost)
 
 # Lowpass filter on distorted signal
-lp = Tone(lowsig+highsig, freq=LP_CUTOFF_FREQ, mul=.3)
+lp = ButLP(sig, freq=LP_CUTOFF_FREQ, mul=.7)
 
 # Balance between dry and wet signals
 out = Interp(src, lp, interp=BALANCE).out()
 
-s.gui(locals())
\ No newline at end of file
+sc = Scope(out)
+
+s.gui(locals())
diff --git a/examples/effects/06_simple_reverb.py b/examples/effects/06_simple_reverb.py
index ced6de4..15747d1 100644
--- a/examples/effects/06_simple_reverb.py
+++ b/examples/effects/06_simple_reverb.py
@@ -21,4 +21,4 @@ c2 = Tone(b2, 3000, mul=0.2).out()
 c3 = Tone(b3, 1500, mul=0.2).out()
 c4 = Tone(b4, 500, mul=0.2).out()
 
-s.gui(locals())
\ No newline at end of file
+s.gui(locals())
diff --git a/examples/effects/07_simple_reverb2.py b/examples/effects/07_simple_reverb2.py
index 042f602..58bf39b 100644
--- a/examples/effects/07_simple_reverb2.py
+++ b/examples/effects/07_simple_reverb2.py
@@ -23,4 +23,4 @@ all2 = Allpass(all1, delay=[.0117,.0123], feedback=0.61)
 lowp = Tone(all2, freq=3500, mul=.2).out()
 
 
-s.gui(locals())
\ No newline at end of file
+s.gui(locals())
diff --git a/examples/effects/08_vocoder_main.py b/examples/effects/08_vocoder_main.py
index 1e0c16e..cb8f998 100644
--- a/examples/effects/08_vocoder_main.py
+++ b/examples/effects/08_vocoder_main.py
@@ -6,7 +6,7 @@ Main script using hand-written vocoder (defined in vocoder_lib.py).
 """
 from pyo import *
 from vocoder_lib import MyVocoder
-                
+
 s = Server(sr=44100, nchnls=2, duplex=0).boot()
 
 a = SfPlayer('../snds/baseballmajeur_m.aif', loop=True)
diff --git a/examples/effects/vocoder_lib.py b/examples/effects/vocoder_lib.py
index 6b7f02a..a480213 100644
--- a/examples/effects/vocoder_lib.py
+++ b/examples/effects/vocoder_lib.py
@@ -11,10 +11,10 @@ class MyVocoder(PyoObject):
     """
     Vocoder effect.
 
-    A vocoder is an analysis/synthesis system. In the encoder, the input is passed 
-    through a multiband filter, each band is passed through an envelope follower, 
-    and the control signals from the envelope followers are communicated to the 
-    decoder. The decoder applies these (amplitude) control signals to corresponding 
+    A vocoder is an analysis/synthesis system. In the encoder, the input is passed
+    through a multiband filter, each band is passed through an envelope follower,
+    and the control signals from the envelope followers are communicated to the
+    decoder. The decoder applies these (amplitude) control signals to corresponding
     filters in the (re)synthesizer.
 
 
@@ -27,7 +27,7 @@ class MyVocoder(PyoObject):
     in2 : PyoObject
         Audio source exciting the bank of filters.
     base : float or PyoObject, optional
-        Base frequency used to compute filter notch frequencies. 
+        Base frequency used to compute filter notch frequencies.
         Defaults to 50.
     spread : float or PyoObject, optional
         Spreading of the filter notch frequencies. Defaults to 1.5.
@@ -86,7 +86,7 @@ class MyVocoder(PyoObject):
 
         # Convert all arguments to lists for "list expansion"
         # convertArgsToLists function returns variables in argument as lists + maximum list size
-        in1_fader, in2_fader, base, spread, q, mul, add, lmax = convertArgsToLists(self._in1_fader, 
+        in1_fader, in2_fader, base, spread, q, mul, add, lmax = convertArgsToLists(self._in1_fader,
                                                             self._in2_fader, base, spread, q, mul, add)
 
         # Init some lists to keep track of created objects
@@ -100,7 +100,7 @@ class MyVocoder(PyoObject):
 
         # self._base_objs is the audio output seen by the outside world!
         # .play(), .out(), .stop() and .mix() methods act on this list
-        # "mul" and "add" attributes are also applied on this list's objects 
+        # "mul" and "add" attributes are also applied on this list's objects
         self._base_objs = []
 
         # Each cycle of the loop creates a mono stream of sound
@@ -151,11 +151,11 @@ class MyVocoder(PyoObject):
         [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._amps)]
         [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._excs)]
         [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._outs)]
-        if type(chnl) == ListType:
+        if type(chnl) == list:
             self._base_objs = [obj.out(wrap(chnl,i), wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_objs)]
         else:
             if chnl < 0:
-                self._base_objs = [obj.out(i*inc, wrap(dur,i), wrap(delay,i)) \
+                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:
                 self._base_objs = [obj.out(chnl+i*inc, wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_objs)]
diff --git a/examples/fft/01_fft_filter.py b/examples/fft/01_fft_filter.py
index 942c6a4..fad1a37 100644
--- a/examples/fft/01_fft_filter.py
+++ b/examples/fft/01_fft_filter.py
@@ -4,6 +4,7 @@
 Spectral domain filter.
 
 """
+from __future__ import division
 from pyo import *
 
 s = Server(duplex=0).boot()
@@ -12,11 +13,11 @@ a = Noise(.1).mix(2)
 
 size = 1024
 olaps = 4
-filter_init = [(0,0.0000),(5,0.9337),(13,0.0000),(21,0.4784),(32,0.0000),(37,0.1927),(size/2,0.0000)]
+filter_init = [(0,0.0000),(5,0.9337),(13,0.0000),(21,0.4784),(32,0.0000),(37,0.1927),(size//2,0.0000)]
 
 fin = FFT(a, size=size, overlaps=olaps, wintype=2)
 
-t = ExpTable(filter_init, size=size/2)
+t = ExpTable(filter_init, size=size//2)
 t.graph(title="Filter shape")
 amp = TableIndex(t, fin["bin"])
 
diff --git a/examples/fft/02_fft_cross.py b/examples/fft/02_fft_cross.py
index 313f9d5..cce72fd 100644
--- a/examples/fft/02_fft_cross.py
+++ b/examples/fft/02_fft_cross.py
@@ -33,4 +33,3 @@ def setSize(x):
     fout.size = x
 
 s.gui(locals())
-
diff --git a/examples/fft/04_fft_gate.py b/examples/fft/04_fft_gate.py
index 3681278..e1a4f9f 100644
--- a/examples/fft/04_fft_gate.py
+++ b/examples/fft/04_fft_gate.py
@@ -12,7 +12,7 @@ snd = "../snds/flute.aif"
 chnls = sndinfo(snd)[3]
 src = SfPlayer(snd, loop=True, mul=.5)
 
-size = 1024 
+size = 1024
 olaps = 4
 
 # bin-by-bin amplitude threshold
@@ -27,7 +27,7 @@ fin = FFT(src, size=size, overlaps=olaps)
 
 mag = Sqrt(fin["real"]*fin["real"] + fin["imag"]*fin["imag"])
 amp = Compare(mag*50, thresh, ">")
-scl = amp * (1 - mult) + mult 
+scl = amp * (1 - mult) + mult
 re = fin["real"] * scl
 im = fin["imag"] * scl
 
@@ -35,4 +35,3 @@ fout = IFFT(re, im, size=size, overlaps=olaps)
 ffout = Mix(fout, chnls, mul=.5).out()
 
 s.gui(locals())
-
diff --git a/examples/fft/05_fft_delay.py b/examples/fft/05_fft_delay.py
index 660bfaa..d37f58f 100644
--- a/examples/fft/05_fft_delay.py
+++ b/examples/fft/05_fft_delay.py
@@ -4,6 +4,7 @@
 Apply spectral delays on a sound.
 
 """
+from __future__ import division
 from pyo import *
 
 s = Server(duplex=0).boot()
@@ -27,7 +28,7 @@ binmax = duplicate([5,15,30,40,80,145], num)
 delays = duplicate([80,20,40,100,60,120], num)
 # delays conversion : number of frames -> seconds
 for i in range(len(delays)):
-    delays[i] = delays[i] * (size/2) / s.getSamplingRate()
+    delays[i] = delays[i] * (size//2) / s.getSamplingRate()
 
 fin = FFT(src*1.25, size=size, overlaps=olaps)
 
diff --git a/examples/fft/06_fft_vectral.py b/examples/fft/06_fft_vectral.py
index 7244437..9011261 100644
--- a/examples/fft/06_fft_vectral.py
+++ b/examples/fft/06_fft_vectral.py
@@ -30,7 +30,7 @@ mult = Sig(.1)
 mult.ctrl([SLMap(0.0001,1,"log","value",0.0001)], title="Gate Attenuation")
 
 amp = Compare(pol["mag"]*50, thresh, ">")
-scl = amp * (1 - mult) + mult 
+scl = amp * (1 - mult) + mult
 
 delta = Vectral(pol["mag"]*scl, framesize=size, overlaps=olaps, down=.35)
 delta.ctrl(title="Blur controls")
diff --git a/examples/fft/07_fft_stretch.py b/examples/fft/07_fft_stretch.py
index 067f8d9..8b3e9c7 100644
--- a/examples/fft/07_fft_stretch.py
+++ b/examples/fft/07_fft_stretch.py
@@ -4,9 +4,10 @@
 Time stretching using FFT/IFFT.
 
 """
+from __future__ import division
 from pyo import *
 
-s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot()
+s = Server(duplex=0).boot()
 
 # Settings #
 snd = '../snds/flute.aif'
@@ -17,12 +18,12 @@ wintype = 7
 
 info = sndinfo(snd)
 chnls = info[3]
-hop = size/olaps
-nframes = info[0] / size
+hop = size // olaps
+nframes = info[0] // size
 
 a = SfPlayer(snd, mul=.1)
 
-# "overlaps * chnls" Matrices of width FFTSIZE and height NUM_OF_FRAMES 
+# "overlaps * chnls" Matrices of width FFTSIZE and height NUM_OF_FRAMES
 # to record magnitude and phase analysis frames
 m_mag = [NewMatrix(width=size, height=nframes) for i in range(olaps*chnls)]
 m_pha = [NewMatrix(width=size, height=nframes) for i in range(olaps*chnls)]
diff --git a/examples/fft/08_fft_spec.py b/examples/fft/08_fft_spec.py
index 406975b..f8ad6a6 100644
--- a/examples/fft/08_fft_spec.py
+++ b/examples/fft/08_fft_spec.py
@@ -4,10 +4,11 @@
 Display the sonogram of a sound using a PyoMatrixObject.
 A better display can be achieved by using a custom drawing.
 
-After the playback ending, call "m.view()" from the 
+After the playback ending, call "m.view()" from the
 interpreter widget of the Server window to show the spectrum.
 
 """
+from __future__ import division
 from pyo import *
 
 s = Server(duplex=0).boot()
@@ -17,7 +18,7 @@ info = sndinfo(son)
 a = SfPlayer(son, mul=.25).mix(1).out()
 
 size = 512
-m = NewMatrix(width=size, height=info[0]/size)
+m = NewMatrix(width=size, height=info[0]//size)
 
 fin = FFT(a*100, overlaps=1)
 mag = Sqrt(fin["real"]*fin["real"] + fin["imag"]*fin["imag"])
diff --git a/examples/matrix/01_wave_terrain.py b/examples/matrix/01_wave_terrain.py
index fbe0d24..d9fee03 100644
--- a/examples/matrix/01_wave_terrain.py
+++ b/examples/matrix/01_wave_terrain.py
@@ -7,7 +7,7 @@ Simple wave terrain synthesis. The terrain is generated with sin functions.
 from pyo import *
 import random, math
 
-s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot()
+s = Server(duplex=0).boot()
 
 def terrain(size=256, freq=1, phase=16):
     l = []
diff --git a/examples/matrix/02_matrix_record.py b/examples/matrix/02_matrix_record.py
index 5cf5b4f..7acd679 100644
--- a/examples/matrix/02_matrix_record.py
+++ b/examples/matrix/02_matrix_record.py
@@ -1,12 +1,13 @@
 #!/usr/bin/env python
 # encoding: utf-8
+from __future__ import print_function
 """
 Wave terrain synthesis of a live recording of FM synthesis in the matrix.
 
 """
 from pyo import *
 
-s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot()
+s = Server(duplex=0).boot()
 
 SIZE = 256
 mm = NewMatrix(SIZE, SIZE)
@@ -24,7 +25,7 @@ c = MatrixPointer(matrix=mm, x=x, y=y, mul=.25)
 filt = Tone(input=c, freq=3000).out()
 
 def func():
-    print "End of recording"
+    print("End of recording")
 
 tr = TrigFunc(rec['trig'], func)
 
diff --git a/examples/matrix/03_matrix_algo.py b/examples/matrix/03_matrix_algo.py
index 025534d..6877382 100644
--- a/examples/matrix/03_matrix_algo.py
+++ b/examples/matrix/03_matrix_algo.py
@@ -1,13 +1,13 @@
 #!/usr/bin/env python
 # encoding: utf-8
 """
-This script demonstrates how to use a matrix to do some 
+This script demonstrates how to use a matrix to do some
 algorithmic generation of notes.
 
 """
 from pyo import *
 
-s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot()
+s = Server(duplex=0).boot()
 
 mat = [[36,41,43,48], [48,51,53,57], [60,62,67,68], [70,72,74,77]]
 
diff --git a/examples/sampling/01_sound_cloud.py b/examples/sampling/01_sound_cloud.py
index 5733054..0ce20c3 100644
--- a/examples/sampling/01_sound_cloud.py
+++ b/examples/sampling/01_sound_cloud.py
@@ -7,7 +7,7 @@ Exponential cloud of sounds...
 
 from pyo import *
 
-s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot()
+s = Server(duplex=0).boot()
 
 snds = ['../snds/snd_%d.aif' % i for i in range(1,7)]
 num = len(snds)
@@ -33,4 +33,4 @@ for j in range(olaps):
 mix = Mix(trtabs, voices=2)
 out = Freeverb(mix, size=.9, damp=.95, bal=.1, mul=.3).out()
 
-s.gui(locals())
\ No newline at end of file
+s.gui(locals())
diff --git a/examples/sampling/02_live_looper.py b/examples/sampling/02_live_looper.py
index af1942a..ff73058 100644
--- a/examples/sampling/02_live_looper.py
+++ b/examples/sampling/02_live_looper.py
@@ -2,14 +2,14 @@
 # encoding: utf-8
 """
 To record sound from input mic in the buffer (4 seconds), call:
-rec.play() 
+rec.play()
 
 The buffer is looped with some funny parameters...
 
 """
 from pyo import *
 
-s = Server(sr=44100, nchnls=2, buffersize=512, duplex=1).boot()
+s = Server(duplex=1).boot()
 
 tab = NewTable(4)
 rec = TableRec(Input(), tab)
@@ -22,10 +22,10 @@ a = Looper( table=tab, # table to loop in
             start=start, # loop start position
             dur=dur, # loop duration
             xfade=20, # crossfade duration in %
-            mode=1, # looping mode 
+            mode=1, # looping mode
             xfadeshape=0, # crossfade shape
             startfromloop=False, # first start position, False means from beginning of the table
             interp=4 # interpolation method
             ).out()
 
-s.gui(locals())
\ No newline at end of file
+s.gui(locals())
diff --git a/examples/sampling/03_rec_and_loop.py b/examples/sampling/03_rec_and_loop.py
index d1da2d9..61999fd 100644
--- a/examples/sampling/03_rec_and_loop.py
+++ b/examples/sampling/03_rec_and_loop.py
@@ -8,7 +8,7 @@ Call r.play() (as many times as you want) to record a buffer from the input mic.
 """
 from pyo import *
 
-s = Server(sr=44100, nchnls=2, buffersize=512, duplex=1).boot()
+s = Server(duplex=1).boot()
 
 buffer_length = 1 # seconds
 
@@ -25,4 +25,4 @@ t = NewTable(length=buffer_length, chnls=2)
 r = TableRec(mic, table=t, fadetime=0.1)
 tr = TrigFunc(r["trig"], function=cp)
 
-s.gui(locals())
\ No newline at end of file
+s.gui(locals())
diff --git a/examples/sampling/04_live_convolution.py b/examples/sampling/04_live_convolution.py
index a02527c..6f5f0f5 100644
--- a/examples/sampling/04_live_convolution.py
+++ b/examples/sampling/04_live_convolution.py
@@ -14,7 +14,7 @@ Circular convolution is very expensive, so keep TLEN (in samples) small.
 """
 from pyo import *
 
-s = Server(sr=44100, nchnls=2, buffersize=512, duplex=1).boot()
+s = Server(duplex=1).boot()
 
 sf = Noise(.5)
 
@@ -41,4 +41,4 @@ t = NewTable(length=sampsToSec(TLEN), chnls=1)
 m = TableMorph(pha, t, [t1,t2,t3,t4])
 a = Convolve(sf, table=t, size=t.getSize(), mul=.1).mix(2).out()
 
-s.gui(locals())
\ No newline at end of file
+s.gui(locals())
diff --git a/examples/sequencing/01_starttime_duration.py b/examples/sequencing/01_starttime_duration.py
index c0251b7..cd13f98 100644
--- a/examples/sequencing/01_starttime_duration.py
+++ b/examples/sequencing/01_starttime_duration.py
@@ -7,7 +7,7 @@ methods to sequence events over time.
 """
 from pyo import *
 
-s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot()
+s = Server(duplex=0).boot()
 
 num = 70
 freqs = [random.uniform(100,1000) for i in range(num)]
@@ -18,7 +18,7 @@ a = SineLoop(freqs, feedback=.05, mul=fade1).out(dur=5, delay=start1)
 start2 = 30
 dur2 = 40
 snds = ['../snds/alum1.wav', '../snds/alum2.wav', '../snds/alum3.wav', '../snds/alum4.wav']
-tabs = SndTable(snds) 
+tabs = SndTable(snds)
 fade2 = Fader(.05, 10, dur2, mul=.7).play(dur=dur2, delay=start2)
 b = Beat(time=.125, w1=[90,30,30,20], w2=[30,90,50,40], w3=[0,30,30,40], poly=1).play(dur=dur2, delay=start2)
 out = TrigEnv(b, tabs, b['dur'], mul=b['amp']*fade2).out(dur=dur2, delay=start2)
@@ -28,4 +28,4 @@ dur3 = 30
 fade3 = Fader(15, 15, dur3, mul=.02).play(dur=dur3, delay=start3)
 fm = FM(carrier=[149,100,151,50]*3, ratio=[.2499,.501,.75003], index=10, mul=fade3).out(dur=dur3, delay=start3)
 
-s.gui(locals())
\ No newline at end of file
+s.gui(locals())
diff --git a/examples/sequencing/02_random_score.py b/examples/sequencing/02_random_score.py
index e1146e9..60c3026 100644
--- a/examples/sequencing/02_random_score.py
+++ b/examples/sequencing/02_random_score.py
@@ -2,12 +2,12 @@
 # encoding: utf-8
 """
 Calling Python function from an audio stream with the Score object.
- 
+
 """
 from pyo import *
 import random
 
-s = Server(sr=44100, nchnls=2, buffersize=256, duplex=0).boot()
+s = Server(duplex=0).boot()
 
 # Frequency of event generation in Hz
 GEN_FREQ = .25
@@ -22,19 +22,19 @@ camp = Linseg([(0,0),(1./GEN_FREQ,1),(2./GEN_FREQ,0)], mul=.25).stop()
 csyn = FM(carrier=[100,100], ratio=[.49,.5], index=6, mul=camp).out()
 
 def event_0():
-    print "playing chaotic attractor"
+    print("playing chaotic attractor")
     asyn.pitch = random.uniform(0.25,0.75)
     asyn.chaos = random.uniform(0.2,0.8)
     aamp.play()
 
 def event_1():
-    print "playing looped oscillator"
-    bsyn.freq = [random.choice(range(50,501,50))*random.uniform(0.99,1.01) for i in range(2)]
+    print("playing looped oscillator")
+    bsyn.freq = [random.choice(list(range(50,501,50)))*random.uniform(0.99,1.01) for i in range(2)]
     bsyn.feedback = random.uniform(0.01, 0.1)
     bamp.play()
 
 def event_2():
-    print "playing frequency modulation"
+    print("playing frequency modulation")
     csyn.carrier = [random.choice([50,100,150,200,250])*random.uniform(0.99,1.01) for i in range(2)]
     csyn.ratio = [random.choice([.1251,.249,.502,.7501,1.003]) for i in range(2)]
     camp.play()
@@ -42,4 +42,4 @@ def event_2():
 tr = RandInt(max=3, freq=GEN_FREQ)
 sc = Score(input=tr, fname='event_')
 
-s.gui(locals())
\ No newline at end of file
+s.gui(locals())
diff --git a/examples/sequencing/03_function_call.py b/examples/sequencing/03_function_call.py
index cdbab85..3283bf2 100644
--- a/examples/sequencing/03_function_call.py
+++ b/examples/sequencing/03_function_call.py
@@ -1,5 +1,6 @@
 #!/usr/bin/env python
 # encoding: utf-8
+from __future__ import print_function
 """
 Python function regularly called with a Pattern object.
 
@@ -23,9 +24,9 @@ def change():
     f4 = random.uniform(2000,4000)
     lst = [f1, f2, f3, f4]
     frs.value = lst
-    print "%.2f, %.2f, %.2f, %.2f" % tuple(lst)
+    print("%.2f, %.2f, %.2f, %.2f" % tuple(lst))
 
 lfo = Sine(freq=.1, mul=.5, add=.75)
 pat = Pattern(function=change, time=lfo).play()
 
-s.gui(locals())
\ No newline at end of file
+s.gui(locals())
diff --git a/examples/synthesis/01_pulsar_synthesis.py b/examples/synthesis/01_pulsar_synthesis.py
index ac6b866..eb7a2bb 100644
--- a/examples/synthesis/01_pulsar_synthesis.py
+++ b/examples/synthesis/01_pulsar_synthesis.py
@@ -7,7 +7,7 @@ Hand-written pulsar synthesis.
 from pyo import *
 import random
 
-s = Server(sr=48000, nchnls=2, buffersize=512, duplex=0).boot()
+s = Server(duplex=0).boot()
 
 # simple pulsar waveform
 t = HarmTable([1,0,.3,0,.2,0,0,.1], size=32768)
@@ -24,4 +24,4 @@ scl = a * (a <= frac) * (1. / frac)
 c = Pointer(table=HannTable(), index=scl, mul=.05)
 d = Pointer(table=t, index=scl, mul=c).out()
 
-s.gui(locals())
\ No newline at end of file
+s.gui(locals())
diff --git a/examples/synthesis/02_FM3.py b/examples/synthesis/02_FM3.py
index 6805dfc..02b2bc2 100644
--- a/examples/synthesis/02_FM3.py
+++ b/examples/synthesis/02_FM3.py
@@ -7,10 +7,11 @@
 from pyo import *
 import math
 
-s = Server(sr=48000, nchnls=2, buffersize=512, duplex=0).boot()
+s = Server(duplex=0).boot()
 
 t = HarmTable([1,0.1])
 class FM3:
+
     def __init__(self, fcar, ratio1, ratio2, index1, index2, out=0):
         self.fmod = fcar * ratio1
         self.fmodmod = self.fmod * ratio2
diff --git a/examples/synthesis/03_cos_waveshaping.py b/examples/synthesis/03_cos_waveshaping.py
index fa5ff8c..e7c9598 100644
--- a/examples/synthesis/03_cos_waveshaping.py
+++ b/examples/synthesis/03_cos_waveshaping.py
@@ -30,5 +30,5 @@ a = OscBank(t, freq=frs, spread=.0001, slope=1, num=24, fjit=True, mul=f)
 b = Cos(math.pi * a + phi)
 b1 = DCBlock(b*phiscl)
 c = Sig(b1 / amp, mul=.2).out()
-    
-s.gui(locals())
\ No newline at end of file
+
+s.gui(locals())
diff --git a/examples/synthesis/04_degrade_synthesis.py b/examples/synthesis/04_degrade_synthesis.py
index 5c2da79..a60ee9b 100644
--- a/examples/synthesis/04_degrade_synthesis.py
+++ b/examples/synthesis/04_degrade_synthesis.py
@@ -27,4 +27,4 @@ b = Lookup(t, a, 1.-lf)
 c = Degrade(b, bitdepth=5.967, srscale=0.0233, mul=f).out()
 c.ctrl()
 
-s.gui(locals())
\ No newline at end of file
+s.gui(locals())
diff --git a/examples/synthesis/05_ring_mod_class.py b/examples/synthesis/05_ring_mod_class.py
index f0467c6..dc9672b 100644
--- a/examples/synthesis/05_ring_mod_class.py
+++ b/examples/synthesis/05_ring_mod_class.py
@@ -12,6 +12,7 @@ tab_m = HarmTable([1,0,0,0,0,.3,0,0,0,0,0,.2,0,0,0,0,0,.1,0,0,0,0,.05]).normaliz
 tab_p = HarmTable([1,0,.33,0,.2,0,.143,0,.111])
 
 class Ring:
+
     def __init__(self, fport=250, fmod=100, amp=.3):
         self.mod = Osc(tab_m, freq=fmod, mul=amp)
         self.port = Osc(tab_p, freq=fport, mul=self.mod)
@@ -19,7 +20,7 @@ class Ring:
     def out(self):
         self.port.out()
         return self
-    
+
     def sig(self):
         return self.port
 
@@ -30,4 +31,4 @@ rg = Ring(fport = [random.choice([62.5,125,187.5,250]) * random.uniform(.99,1.01
 
 res = Waveguide(rg.sig(), freq=[30.1,60.05,119.7,181,242.5,303.33], dur=30, mul=.1).out()
 
-s.gui(locals())
\ No newline at end of file
+s.gui(locals())
diff --git a/examples/synthesis/06_paf.py b/examples/synthesis/06_paf.py
index 8470df0..fd7adc8 100644
--- a/examples/synthesis/06_paf.py
+++ b/examples/synthesis/06_paf.py
@@ -7,6 +7,7 @@ twopi = math.pi * 2
 s = Server(duplex=0).boot()
 
 class PAF:
+
     def __init__(self, f0, fc, bw, fs, amp):
         self.bell = WinTable(8) # half-sine
         self.shape = WinTable(4) # {4, 5 or 6}
@@ -33,9 +34,9 @@ for_tenor = {"ou": [290, 750, 2300, 3080], "o": [360, 770, 2530, 3200], "oo": [5
         "oee": [570, 1560, 2560, 3450], "oe": [500, 1330, 2370, 3310], "eu": [350, 1350, 2250, 3170],
         "e": [420, 2050, 2630, 3340], "u": [250, 1750, 2160, 3060], "i": [250, 2250, 2980, 3280]}
 
-amp_tenor = {"ou": [-10, -21, -52, -64], "o": [-10, -21, -52, -64], "oo": [-10, -20, -53, -65], 
-        "aa": [-8, -27, -52, -60], "a": [-8, -25, -50, -59], "ee": [-10, -30, -47, -57], 
-        "oee": [-8, -27, -52, -60], "oe": [-10, -44, -49, -64], "eu": [-10, -46, -49, -64], 
+amp_tenor = {"ou": [-10, -21, -52, -64], "o": [-10, -21, -52, -64], "oo": [-10, -20, -53, -65],
+        "aa": [-8, -27, -52, -60], "a": [-8, -25, -50, -59], "ee": [-10, -30, -47, -57],
+        "oee": [-8, -27, -52, -60], "oe": [-10, -44, -49, -64], "eu": [-10, -46, -49, -64],
         "e": [-10, -30, -52, -60], "u": [-10, -44, -49, -64], "i": [-10, -40, -52, -57]}
 
 bw_tenor = {"ou": [30, 35, 45, 50], "o": [30, 35, 54, 59], "oo": [35, 40, 54, 59], "aa": [40, 45, 59, 64],
@@ -73,5 +74,5 @@ def set(new):
     c.bw.value = vo[2]
     d.bw.value = vo[3]
     e.bw.value = vo[3] + 10
-    
+
 s.gui(locals())
diff --git a/examples/synthesis/07_split_sideband_synthesis.py b/examples/synthesis/07_split_sideband_synthesis.py
index 5a62155..0ca80ee 100644
--- a/examples/synthesis/07_split_sideband_synthesis.py
+++ b/examples/synthesis/07_split_sideband_synthesis.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # encoding: utf-8
 """
-Split-Sideband Synthesis. Variation of three well known distortion techniques, 
+Split-Sideband Synthesis. Variation of three well known distortion techniques,
 Waveshaping, Singlesideband modulation and Frequency Modulation.
 
 Based on the article :
@@ -12,7 +12,7 @@ Ann Arbor, MPublishing, University of Michigan Library, August 2008
 from pyo import *
 import math
 
-s = Server(sr=48000, nchnls=2, buffersize=512, duplex=0).boot()
+s = Server(duplex=0).boot()
 
 twopi = 2 * math.pi
 oneOverTwoPi = 1.0 / twopi
@@ -59,4 +59,4 @@ soddLower = soddReal - soddImag
 
 mix = Mix([sevenLower, sevenUpper], voices=2, mul=.2).out()
 
-s.gui(locals())
\ No newline at end of file
+s.gui(locals())
diff --git a/examples/synthesis/08_bucket_brigade_device.py b/examples/synthesis/08_bucket_brigade_device.py
index c78d799..a1534ee 100644
--- a/examples/synthesis/08_bucket_brigade_device.py
+++ b/examples/synthesis/08_bucket_brigade_device.py
@@ -8,7 +8,7 @@ filter inside each delay line. The delay lines are feeded with a sine wave.
 """
 from pyo import *
 
-s = Server(sr=48000, nchnls=2, buffersize=512, duplex=0).boot()
+s = Server(duplex=0).boot()
 
 t = HarmTable(size=32768)
 src = Osc(t, 100)
diff --git a/examples/tables/01_curve_table.py b/examples/tables/01_curve_table.py
index 509e96f..e351c6c 100644
--- a/examples/tables/01_curve_table.py
+++ b/examples/tables/01_curve_table.py
@@ -6,7 +6,7 @@ Curve table variations used as an amplitude envelope.
 """
 from pyo import *
 
-s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot()
+s = Server(duplex=0).boot()
 
 t = CurveTable([(0,0),(2048,.5),(4096, .2),(6144,.5),(8192,0)], tension=0, bias=20).normalize()
 t.view(title="Waveform at initialization")
@@ -19,7 +19,7 @@ synth2 = FM(carrier=[100,50], ratio=[.495,1.01], index=10, mul=a).out()
 
 # LFO from 0 to 20
 c = Sine(.1, 0, 10, 10)
- 
+
 # Modifying the bias parameter 10 times per second
 def change():
     # get the current value of the LFO
@@ -30,4 +30,4 @@ def change():
 
 p = Pattern(change, .1).play()
 
-s.gui(locals())
\ No newline at end of file
+s.gui(locals())
diff --git a/examples/tables/02_scrubbing.py b/examples/tables/02_scrubbing.py
index 5db7547..13bb1ef 100644
--- a/examples/tables/02_scrubbing.py
+++ b/examples/tables/02_scrubbing.py
@@ -1,5 +1,6 @@
 #!/usr/bin/env python
 # encoding: utf-8
+from __future__ import print_function
 
 """
 Scrubbing in a sound window.
@@ -8,10 +9,10 @@ Give the focus to the Scrubbing window then click and move the mouse...
 """
 
 from pyo import *
-s = Server(buffersize=512, duplex=0).boot()
+s = Server(duplex=0).boot()
 
 def mouse(mpos):
-    print "X = %.2f, Y = %.2f" % tuple(mpos)
+    print("X = %.2f, Y = %.2f" % tuple(mpos))
     pos.value = mpos[0]
     l, r = 1. - mpos[1], mpos[1]
     mul.value = [l, r]
diff --git a/examples/tables/03_granulation.py b/examples/tables/03_granulation.py
index 94be9d5..8681cb3 100644
--- a/examples/tables/03_granulation.py
+++ b/examples/tables/03_granulation.py
@@ -8,7 +8,7 @@ Classical granulation stretching...
 
 from pyo import *
 
-s = Server(buffersize=512, duplex=0).boot()
+s = Server(duplex=0).boot()
 
 snd = SndTable('../snds/baseballmajeur_m.aif')
 snd.view()
@@ -16,8 +16,7 @@ snd.view()
 pos = Phasor(freq=snd.getRate()*.25, mul=snd.getSize(), add=Noise(3))
 dur = Noise(.001, .1)
 
-gran = Granulator(table=snd, env=WinTable(7), pitch=[.999, 1.0011], 
+gran = Granulator(table=snd, env=WinTable(7), pitch=[.999, 1.0011],
                   pos=pos, dur=dur, grains=40, basedur=.1, mul=.05).out()
 
 s.gui(locals())
-
diff --git a/examples/tables/04_granule.py b/examples/tables/04_granule.py
index fb2c48f..354341e 100644
--- a/examples/tables/04_granule.py
+++ b/examples/tables/04_granule.py
@@ -23,4 +23,4 @@ env = TrigEnv(met, t2, dur=grain_dur, mul=.05)
 ind = TrigEnv(met, t3, dur=grain_dur, mul=jit*(grain_dur/snd_dur), add=pos)
 snd = Pointer(t1, ind, env).out()
 
-s.gui(locals())
\ No newline at end of file
+s.gui(locals())
diff --git a/examples/tables/05_table_maker.py b/examples/tables/05_table_maker.py
index 7213bb3..f93bfff 100644
--- a/examples/tables/05_table_maker.py
+++ b/examples/tables/05_table_maker.py
@@ -7,13 +7,14 @@ Creates a new sound table from random chunks of a soundfile.
 from pyo import *
 import random, os
 
-s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot()
+s = Server(duplex=0).boot()
 
 path = "../snds/baseballmajeur_m.aif"
 dur = sndinfo(path)[1]
 
 t = SndTable(path, start=0, stop=1)
-a = Looper(t, pitch=[1.,1.], dur=t.getDur(), xfade=5, mul=.4).out()
+amp = Fader(fadein=0.005, fadeout=0.005, dur=0, mul=0.4).play()
+a = Looper(t, pitch=[1.,1.], dur=t.getDur(), xfade=5, mul=amp).out()
 
 def addsnd():
     start = random.uniform(0, dur*0.7)
@@ -22,15 +23,21 @@ def addsnd():
     cross = random.uniform(0.04, duration/2)
     t.insert(path, pos=pos, crossfade=cross, start=start, stop=start+duration)
 
-def gen():
+def delayed_generation():
     start = random.uniform(0, dur*0.7)
     duration = random.uniform(.1, .3)
     t.setSound(path, start=start, stop=start+duration)
     for i in range(10):
         addsnd()
-
     a.dur = t.getDur()
+    a.reset()
+    amp.play()
+
+caller = CallAfter(function=delayed_generation, time=0.005).stop()
+def gen():
+    amp.stop()
+    caller.play()
 
 gen()
 
-s.gui(locals())
\ No newline at end of file
+s.gui(locals())
diff --git a/examples/utilities/01_get_example.py b/examples/utilities/01_get_example.py
index e1701db..d049da2 100644
--- a/examples/utilities/01_get_example.py
+++ b/examples/utilities/01_get_example.py
@@ -1,5 +1,6 @@
 #!/usr/bin/env python
 # encoding: utf-8
+from __future__ import print_function
 
 """
 The PyoObject.get() method can be used to convert audio stream to usable python data.
@@ -7,15 +8,15 @@ The PyoObject.get() method can be used to convert audio stream to usable python
 """
 from pyo import *
 
-s = Server(sr=44100, nchnls=2, buffersize=512, duplex=0).boot()
+s = Server(duplex=0).boot()
 
 lfos = Sine(freq=[.1,.2,.4,.3], mul=100, add=500)
 synth = SineLoop(freq=lfos, feedback=.07, mul=.05).out()
 
 def print_val():
     # Print all four frequency values assigned to SineLoop's freq argument
-    print "%.2f, %.2f, %.2f, %.2f" % tuple(lfos.get(all=True))
+    print("%.2f, %.2f, %.2f, %.2f" % tuple(lfos.get(all=True)))
 
 pat = Pattern(print_val, .25).play()
 
-s.gui(locals())
\ No newline at end of file
+s.gui(locals())
diff --git a/examples/utilities/02_midi_ctl_scan.py b/examples/utilities/02_midi_ctl_scan.py
index 8332f58..aa0d123 100644
--- a/examples/utilities/02_midi_ctl_scan.py
+++ b/examples/utilities/02_midi_ctl_scan.py
@@ -1,25 +1,27 @@
 #!/usr/bin/env python
 # encoding: utf-8
-
 """
 Scan for Midi controller numbers. Launch this script from a terminal.
 
 """
 from pyo import *
-import time
+import time, sys
+
+if sys.version_info[0] < 3:
+    input = raw_input
 
 pm_list_devices()
 
-num = input("Enter your Midi interface number : ")
+num = eval(input("Enter your Midi interface number : "))
 
 s = Server(duplex=0)
 s.setMidiInputDevice(num)
 s.boot().start()
 
-print "Play with your Midi controllers..."
+print("Play with your Midi controllers...")
 
 def pp(x): 
-    print "controller number =", x
+    print("controller number =", x)
 
 scan = CtlScan(pp, False)
 
@@ -27,12 +29,11 @@ again = "y"
 while again == "y":
     time.sleep(10)
     scan.stop()
-    again = raw_input("Do you want to continue ? (y/n) : ")
+    again = input("Do you want to continue ? (y/n) : ")
     if again == "y":
-        print "Continue..."
+        print("Continue...")
         scan.play()
-    
+
 s.stop()
 time.sleep(1)
 exit()
-    
\ No newline at end of file
diff --git a/examples/utilities/02_osc_scan.py b/examples/utilities/02_osc_scan.py
new file mode 100644
index 0000000..d89f46c
--- /dev/null
+++ b/examples/utilities/02_osc_scan.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+# encoding: utf-8
+from __future__ import print_function
+"""
+Scan Open Sound Control inputs. Launch this script from a terminal.
+
+"""
+from pyo import *
+import time, sys
+
+if sys.version_info[0] < 3:
+    input = raw_input
+
+port = eval(input("Enter the incoming port number : "))
+
+s = Server().boot().start()
+
+print("Play with your OSC interface...")
+
+go = True
+def pp(address, *args):
+    if go:
+        print("Address =", address)
+        print("Values =", args)
+        print("---------------")
+
+scan = OscDataReceive(port, "*", pp)
+
+again = "y"
+while again == "y":
+    time.sleep(10)
+    go = False
+    again = input("Do you want to continue ? (y/n) : ")
+    if again == "y":
+        print("Continue...")
+        go = True
+
+s.stop()
+time.sleep(1)
+sys.exit()
diff --git a/examples/utilities/03_savefile.py b/examples/utilities/03_savefile.py
index fadc063..3256f6c 100644
--- a/examples/utilities/03_savefile.py
+++ b/examples/utilities/03_savefile.py
@@ -16,4 +16,4 @@ dur = 5
 chnls = 2
 
 samples = [[uniform(-0.5,0.5) for i in range(sr*dur)] for i in range(chnls)]
-savefile(samples=samples, path=path, sr=sr, channels=chnls, fileformat=1, sampletype=1)
\ No newline at end of file
+savefile(samples=samples, path=path, sr=sr, channels=chnls, fileformat=1, sampletype=1)
diff --git a/examples/utilities/04_batch_processing.py b/examples/utilities/04_batch_processing.py
index fa7b094..729addd 100644
--- a/examples/utilities/04_batch_processing.py
+++ b/examples/utilities/04_batch_processing.py
@@ -4,37 +4,46 @@
 This script demonstrates how to use pyo to do offline batch processing.
 
 """
-import os
 from pyo import *
-s = Server(duplex=0, audio="offline").boot()
-
-# input sound
-sndpath = SNDS_PATH + "/accord.aif"
-# output folder
-recpath = os.path.join(os.path.expanduser("~"), "Desktop", "pyo_batch")
-if not os.path.isdir(recpath):
-    os.mkdir(recpath)
-
-# output file duration
-dur = sndinfo(sndpath)[1]
-
-NUM = 10
-for i in range(NUM):
-    note = 12 + i
-    noteFreq = midiToHz(note)
-    s.recordOptions(dur=dur+.1, filename=os.path.join(recpath, "file_%02d.wav" % note), fileformat=0, sampletype=0)
-
-    ### processing goes here ###
-    osc = Sine(freq=noteFreq, mul=i*0.01+.02, add=1)
-    a = SfPlayer(sndpath, speed=osc, loop=False, mul=0.7).mix(2).out()
-
-    ############################
-
-    s.start() # s.stop() is automatically called when rendering is done
-    # do not reboot the server after the last pass
-    if i < (NUM-1):
-        s.shutdown()
-        s.boot()
-
-print "Batch processing done"
+import os
 
+s = Server(audio="offline")
+
+# path to your sound folder
+folder_path = SNDS_PATH
+# path to the processed sounds folder (user's home directory/batch)
+output_folder = os.path.join(os.path.expanduser("~"), "pyo_batch_fx")
+# create it if it does not exist
+if not os.path.isdir(output_folder):
+    os.mkdir(output_folder)
+
+# get the list of files to process
+sounds = [file for file in os.listdir(folder_path) if sndinfo(os.path.join(folder_path, file)) is not None]
+
+# enter the batch processing loop
+for sound in sounds:
+    # retrieve info about the sound
+    path = os.path.join(folder_path, sound)
+    info = sndinfo(path)
+    dur, sr, chnls = info[1], info[2], info[3]
+    fformat = ['WAVE', 'AIFF', 'AU', 'RAW', 'SD2', 'FLAC', 'CAF', 'OGG'].index(info[4])
+    samptype = ['16 bit int', '24 bit int', '32 bit int', '32 bit float',
+                '64 bits float', 'U-Law encoded', 'A-Law encoded'].index(info[5])
+
+    # set server parameters
+    s.setSamplingRate(sr)
+    s.setNchnls(chnls)
+    s.boot()
+    s.recordOptions(dur=dur, filename=os.path.join(output_folder, sound),
+                    fileformat=fformat, sampletype=samptype)
+
+    # processing
+    sf = SfPlayer(path)
+    bp = ButBP(sf, 1000, 2)
+    dt = Disto(bp, drive=0.9, slope=0.8)
+    mx = Interp(sf, dt, interp=0.5, mul=0.5).out()
+
+    # start the render
+    s.start()
+    # cleanup
+    s.shutdown()
diff --git a/examples/utilities/04_batch_synthesis.py b/examples/utilities/04_batch_synthesis.py
new file mode 100644
index 0000000..5e9bd62
--- /dev/null
+++ b/examples/utilities/04_batch_synthesis.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+# encoding: utf-8
+from __future__ import print_function
+"""
+This script demonstrates how to use pyo to do synthesis batch generation.
+
+"""
+import os
+from pyo import *
+s = Server(duplex=0, audio="offline")
+
+# output folder
+output_folder = os.path.join(os.path.expanduser("~"), "pyo_batch_synth")
+if not os.path.isdir(output_folder):
+    os.mkdir(output_folder)
+
+# output file duration
+dur = 2
+
+NUM = 12
+for i in range(NUM):
+    s.boot()
+    note = 60 + i
+    noteFreq = midiToHz(note)
+    s.recordOptions(dur=dur+.1, filename=os.path.join(output_folder, "file_%02d.wav" % note),
+                    fileformat=0, sampletype=0)
+
+    ### processing goes here ###
+    env = Adsr(attack=0.005, decay=0.15, sustain=0.7, release=1.7, dur=dur).play()
+    qenv = Pow(env, 4, mul=0.8)
+    osc1 = SineLoop(freq=noteFreq, feedback=0.075, mul=qenv).out()
+    osc2 = SineLoop(freq=noteFreq*1.01, feedback=0.075, mul=qenv).out(1)
+
+    # start th render
+    s.start()
+    # cleanup
+    s.shutdown()
+
+print("Batch processing done")
+
diff --git a/examples/utilities/05_high_sr_processing.py b/examples/utilities/05_high_sr_processing.py
index 50e0b37..ecc2bb1 100644
--- a/examples/utilities/05_high_sr_processing.py
+++ b/examples/utilities/05_high_sr_processing.py
@@ -1,7 +1,8 @@
 #!/usr/bin/env python
 # encoding: utf-8
+from __future__ import print_function
 """
-This script demonstrates how to use pyo to apply processing on an 
+This script demonstrates how to use pyo to apply processing on an
 up sampled sound. Steps are:
 
 1 - Up sampling the source.
@@ -22,10 +23,10 @@ DOWN_SND = os.path.join(os.path.expanduser("~"), "Desktop", "baseballmajeur_dist
 DUR = sndinfo(IN_SND)[1]
 SR = sndinfo(IN_SND)[2]
 
-print "Up sampling %i times..." % UP
+print("Up sampling %i times..." % UP)
 upsamp(IN_SND, UP_SND, UP, SIZE)
 
-print "Apply distortion at a sampling rate of %i Hz." % (SR*UP)
+print("Apply distortion at a sampling rate of %i Hz." % (SR*UP))
 s = Server(sr=SR*UP, nchnls=1, duplex=0, audio="offline").boot()
 s.recordOptions(dur=DUR+.1, filename=PROC_SND, fileformat=0, sampletype=0)
 sf = SfPlayer(IN_SND, loop=False, interp=4, mul=0.7)
@@ -33,10 +34,10 @@ dist = Disto(sf, drive=0.75, slope=0.7, mul=0.3)
 filt = Biquad(dist, freq=8000, q=0.7, type=0).out()
 s.start()
 
-print "Down sampling %i times..." % DOWN
+print("Down sampling %i times..." % DOWN)
 downsamp(PROC_SND, DOWN_SND, DOWN, SIZE)
 
 os.remove(UP_SND)
 os.remove(PROC_SND)
 
-print "Done"
+print("Done")
diff --git a/examples/utilities/06_separated_threads.py b/examples/utilities/06_separated_threads.py
index fa019c9..6492a3b 100644
--- a/examples/utilities/06_separated_threads.py
+++ b/examples/utilities/06_separated_threads.py
@@ -21,5 +21,3 @@ for i in range(20):
 # Stop the audio Server before exiting
 pipe.write("s.stop()\ntime.sleep(0.25)\n")
 pipe.close()
-
-
diff --git a/examples/utilities/07_scope.py b/examples/utilities/07_scope.py
new file mode 100644
index 0000000..f26608b
--- /dev/null
+++ b/examples/utilities/07_scope.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python
+# encoding: utf-8
+"""
+Simple scope example.
+
+"""
+from pyo import *
+
+class Scope:
+
+    def __init__(self, input, length=0.05):
+        self.input = input
+        self.table = NewTable(length=length, chnls=len(input))
+        self.table.view(title="Signal Scope")
+        self.trig = Metro(time=length).play()
+        self.rec = TrigTableRec(self.input, self.trig, self.table)
+        self.trf = TrigFunc(self.trig, function=self.update)
+
+    def start(self, x):
+        if x: self.trig.play()
+        else: self.trig.stop()
+
+    def update(self):
+        self.table.refreshView()
+
+s = Server(duplex=1).boot()
+
+CHNLS = 2
+LENGTH = 0.05
+
+inp = Input(chnl=list(range(CHNLS)))
+scope = Scope(inp, LENGTH)
+
+s.gui(locals())
diff --git a/examples/utilities/buffer_interface.py b/examples/utilities/buffer_interface.py
new file mode 100644
index 0000000..0b7c5ce
--- /dev/null
+++ b/examples/utilities/buffer_interface.py
@@ -0,0 +1,33 @@
+"""
+This example shows two things:
+    
+1) How to share memory from a PyoTableObject to a numpy array. Numpy 
+   functions can be used to modify the table's content without copying
+   every samples.
+
+2) How to register a `callback` function that the server will call at
+   the beginning of every processing loop (each `buffersize` samples).
+
+"""
+from pyo import *
+import numpy as np
+
+s = Server().boot()
+bs = s.getBufferSize()
+
+# Create a table of length `buffer size` and read it in loop.
+t = DataTable(size=bs)
+osc = TableRead(t, freq=t.getRate(), loop=True, mul=0.1).out()
+
+# Share the table's memory with a numpy array.
+arr = np.asarray(t.getBuffer())
+
+def process():
+    "Fill the array (so the table) with white noise."
+    arr[:] = np.random.normal(0.0, 0.5, size=bs)
+
+# Register the `process` function to be called at the beginning 
+# of every processing loop.
+s.setCallback(process)
+
+s.gui(locals())
diff --git a/examples/wxgui/01_gui_widgets_example.py b/examples/wxgui/01_gui_widgets_example.py
new file mode 100644
index 0000000..4c2f384
--- /dev/null
+++ b/examples/wxgui/01_gui_widgets_example.py
@@ -0,0 +1,240 @@
+"""
+Demo script for showing how GUI classes from pyo can be used to build
+audio programs with graphical interface.
+
+"""
+import wx, time, random
+from pyo import *
+
+NCHNLS = 2
+
+server = Server(nchnls=NCHNLS).boot()
+server.start()
+
+### A basic audio process ###
+snd = SndTable([SNDS_PATH+"/transparent.aif"]*NCHNLS)
+m = Metro(.125, poly=1).play()
+am = Iter(m, [1,0,0,0]*4)
+t2 = ExpTable([(0,1),(4096,10),(8191,10)], exp=4)
+q = TrigEnv(m, t2, m.time)
+pos = TrigLinseg(m, [(0.0,0.0), (m.time, 1,0)])
+n = Pointer(snd, pos, mul=am)
+fr = SigTo(1000, time=0.05, init=1000)
+f = ButBP(n, freq=fr, q=q).out()
+#pa = PeakAmp(f)
+sp = Spectrum(f)
+sc = Scope(f)
+
+class MyFrame(wx.Frame):
+
+    def __init__(self, parent, title, pos=(50, 50), size=(850, 600)):
+        wx.Frame.__init__(self, parent, -1, title, pos, size)
+        
+        self.Bind(wx.EVT_CLOSE, self.on_quit)
+
+        self.panel = wx.Panel(self)
+        vmainsizer = wx.BoxSizer(wx.VERTICAL)
+        mainsizer = wx.BoxSizer(wx.HORIZONTAL)
+        leftbox = wx.BoxSizer(wx.VERTICAL)
+        midbox = wx.BoxSizer(wx.VERTICAL)
+        rightbox = wx.BoxSizer(wx.VERTICAL)
+
+        ### PyoGuiControlSlider - logarithmic scale ###
+        sizer1 = self.createFreqSlider()
+
+        ### PyoGuiControlSlider - dB scale & VuMeter ###
+        sizer2 = self.createOutputBox()
+
+        ### PyoGuiGrapher - Filter's Q automation ###
+        sizer3 = self.createGrapher()
+
+        ### PyoGuiMultiSlider - Step Sequencer ###
+        sizer4 = self.createMultiSlider()
+
+        ### PyoGuiSpectrum - Frequency display ###
+        sizer5 = self.createSpectrum()
+
+        ### PyoGuiScope - oscilloscope display ###
+        sizer6 = self.createScope()
+
+        ### PyoGuiSndView - Soundfile display ###
+        sizer7 = self.createSndView()
+
+        leftbox.Add(sizer1, 0, wx.ALL | wx.EXPAND, 5)
+        leftbox.Add(sizer3, 1, wx.ALL | wx.EXPAND, 5)
+        leftbox.Add(sizer4, 1, wx.ALL | wx.EXPAND, 5)
+
+        midbox.Add(sizer5, 1, wx.ALL | wx.EXPAND, 5)
+        midbox.Add(sizer6, 1, wx.ALL | wx.EXPAND, 5)
+
+        rightbox.Add(sizer2, 1, wx.ALL | wx.EXPAND, 5)
+
+        mainsizer.Add(leftbox, 1, wx.ALL | wx.EXPAND, 5)
+        mainsizer.Add(midbox, 1, wx.ALL | wx.EXPAND, 5)
+        mainsizer.Add(rightbox, 0, wx.ALL | wx.EXPAND, 5)
+        vmainsizer.Add(mainsizer, 1, wx.ALL | wx.EXPAND, 5)
+        vmainsizer.Add(sizer7, 1, wx.ALL | wx.EXPAND, 5)
+        self.panel.SetSizerAndFit(vmainsizer)
+
+    def on_quit(self, evt):
+        server.stop()
+        time.sleep(0.25)
+        self.Destroy()
+
+    def createFreqSlider(self):
+        sizer = wx.BoxSizer(wx.VERTICAL)
+        label = wx.StaticText(self.panel, -1, "PyoGuiControlSlider: filter's center frequency (log scale)")
+        sizer.Add(label, 0, wx.CENTER|wx.ALL, 5)
+        self.freq = PyoGuiControlSlider(parent=self.panel,
+                                        minvalue=20,
+                                        maxvalue=20000,
+                                        init=1000,
+                                        pos=(0, 0),
+                                        size=(200, 16),
+                                        log=True,
+                                        integer=False,
+                                        powoftwo=False,
+                                        orient=wx.HORIZONTAL)
+        #print(self.freq.getRange())
+        #print(self.freq.isPowOfTwo())
+        self.freq.Bind(EVT_PYO_GUI_CONTROL_SLIDER, self.changeFreq)
+        sizer.Add(self.freq, 0, wx.ALL | wx.EXPAND, 5)
+        return sizer
+
+    def createOutputBox(self):
+        sizer = wx.BoxSizer(wx.VERTICAL)
+        label = wx.StaticText(self.panel, -1, "dB slider - PyoGuiVuMeter")
+        sizer.Add(label, 0, wx.CENTER|wx.ALL, 5)
+        sizer1 = wx.BoxSizer(wx.HORIZONTAL)
+        self.amp = PyoGuiControlSlider(parent=self.panel,
+                                        minvalue=-60,
+                                        maxvalue=18,
+                                        init=-12,
+                                        pos=(0, 0),
+                                        size=(200, 16),
+                                        log=False,
+                                        integer=False,
+                                        powoftwo=False,
+                                        orient=wx.VERTICAL)
+        self.amp.Bind(EVT_PYO_GUI_CONTROL_SLIDER, self.changeGain)
+        self.meter = PyoGuiVuMeter(parent=self.panel,
+                                   nchnls=NCHNLS,
+                                   pos=(0, 0),
+                                   size=(5*NCHNLS, 200),
+                                   orient=wx.VERTICAL,
+                                   style=0)
+        self.meter.setNchnls(8)
+        # Register the VuMeter in the Server object.
+        server.setMeter(self.meter)
+        # or register its `setRms` method in a PeakAmp object.
+        # pa.setFunction(self.meter.setRms)
+
+        sizer1.Add(self.amp, 0, wx.ALL | wx.EXPAND, 5)
+        sizer1.Add(self.meter, 0, wx.ALL | wx.EXPAND, 5)
+        sizer.Add(sizer1, 1, wx.CENTER | wx.ALL, 5)
+        return sizer
+
+    def createGrapher(self):
+        sizer = wx.BoxSizer(wx.VERTICAL)
+        label = wx.StaticText(self.panel, -1, "PyoGuiGrapher: Filter's Q automation")
+        sizer.Add(label, 0, wx.CENTER|wx.ALL, 5)
+        self.graph = PyoGuiGrapher(parent=self.panel,
+                                    xlen=8192,
+                                    yrange=(1.0, 10.0),
+                                    init=[(0.0, 0.0), (1.0, 1.0)],
+                                    mode=2,
+                                    exp=t2.exp,
+                                    inverse=True,
+                                    tension=0.75,
+                                    bias=8.0,
+                                    size=(300,100),
+                                    style=0)
+        self.graph.setValues(t2.getPoints())
+        self.graph.setYrange((0.1, 20))
+        self.graph.setInverse(False)
+        self.graph.Bind(EVT_PYO_GUI_GRAPHER, self.changeGraph)
+        sizer.Add(self.graph, 1, wx.ALL | wx.EXPAND, 5)
+        return sizer
+
+    def createMultiSlider(self):
+        sizer = wx.BoxSizer(wx.VERTICAL)
+        label = wx.StaticText(self.panel, -1, "PyoGuiMultiSlider: Step Sequencer")
+        sizer.Add(label, 0, wx.CENTER|wx.ALL, 5)
+        self.steps = PyoGuiMultiSlider(parent=self.panel,
+                                    xlen=16,
+                                    yrange=(0, 1),
+                                    init=[1,0,0,0]*4,
+                                    size=(300,100),
+                                    style=0)
+        self.steps.setYrange((0, 2))
+        self.steps.setValues([random.uniform(0, 2) for i in range(16)])
+        self.steps.Bind(EVT_PYO_GUI_MULTI_SLIDER, self.changeSteps)
+        sizer.Add(self.steps, 1, wx.ALL | wx.EXPAND, 5)
+        return sizer
+
+    def createSpectrum(self):
+        sizer = wx.BoxSizer(wx.VERTICAL)
+        label = wx.StaticText(self.panel, -1, "PyoGuiSpectrum: Frequency display")
+        sizer.Add(label, 0, wx.CENTER|wx.ALL, 5)
+        self.spectrum = PyoGuiSpectrum(parent=self.panel,
+                                    lowfreq=0,
+                                    highfreq=22050,
+                                    fscaling=1,
+                                    mscaling=1,
+                                    size=(300,150),
+                                    style=0)
+        self.spectrum.setAnalyzer(sp)
+        sizer.Add(self.spectrum, 1, wx.ALL | wx.EXPAND, 5)
+        return sizer
+
+    def createScope(self):
+        sizer = wx.BoxSizer(wx.VERTICAL)
+        label = wx.StaticText(self.panel, -1, "PyoGuiScope: Oscilloscope display")
+        sizer.Add(label, 0, wx.CENTER|wx.ALL, 5)
+        self.scope = PyoGuiScope(parent=self.panel,
+                                    length=0.05,
+                                    gain=1,
+                                    size=(300,150),
+                                    style=0)
+        self.scope.setAnalyzer(sc)
+        self.scope.setLength(0.05)
+        self.scope.setGain(0.67)
+        sizer.Add(self.scope, 1, wx.ALL | wx.EXPAND, 5)
+        return sizer
+
+    def createSndView(self):
+        sizer = wx.BoxSizer(wx.VERTICAL)
+        label = wx.StaticText(self.panel, -1, "PyoGuiSndView: Soundfile display")
+        sizer.Add(label, 0, wx.CENTER|wx.ALL, 5)
+        self.sndview = PyoGuiSndView(parent=self.panel,
+                                    size=(300,200),
+                                    style=0)
+        self.sndview.setTable(snd)
+        self.sndview.setSelection(0.51, 0.76)
+        self.sndview.Bind(EVT_PYO_GUI_SNDVIEW_MOUSE_POSITION, self.mousePos)
+        self.sndview.Bind(EVT_PYO_GUI_SNDVIEW_SELECTION, self.sndSelection)
+        sizer.Add(self.sndview, 1, wx.ALL | wx.EXPAND, 5)
+        return sizer
+
+    def changeFreq(self, evt):
+        fr.value = evt.value
+
+    def changeGain(self, evt):
+        am.mul = pow(10, evt.value * 0.05)
+
+    def changeGraph(self, evt):
+        t2.replace(evt.value)
+
+    def changeSteps(self, evt):
+        am.setChoice(evt.value)
+
+    def mousePos(self, evt):
+        print((evt.value))
+
+    def sndSelection(self, evt):
+        pos.replace([(0.0, evt.value[0]), (m.time, evt.value[1])])
+
+app = wx.App(False)
+mainFrame = MyFrame(None, title='Test Pyo GUI objects')
+mainFrame.Show()
+app.MainLoop()
diff --git a/externals/external-template.py b/externals/external-template.py
index 1ee8e92..3cdca10 100644
--- a/externals/external-template.py
+++ b/externals/external-template.py
@@ -41,12 +41,10 @@ class Gain(PyoObject):
     """
     # Do not forget "mul" and "add" attributes.
     def __init__(self, input, db=-3, mul=1, add=0):
-        PyoObject.__init__(self)
+        PyoObject.__init__(self, mul, add)
         # Keep trace of arguments (same name preceded by an underscore)
         self._input = input
         self._db = db
-        self._mul = mul
-        self._add = add
         # Always use InputFader for the input sound. That allows crossfade on input changes.  
         self._in_fader = InputFader(input)
         # Converts every arguments to lists (for multi-channel expansion).
diff --git a/externals/externalmodule-template.c b/externals/externalmodule-template.c
index c6079bb..9cb89a2 100644
--- a/externals/externalmodule-template.c
+++ b/externals/externalmodule-template.c
@@ -19,6 +19,7 @@
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
@@ -222,7 +223,7 @@ Gain_dealloc(Gain* self)
 {
     pyo_DEALLOC
     Gain_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 /**********************************************************************
@@ -401,7 +402,7 @@ static PyNumberMethods Gain_as_number = {
 (binaryfunc)Gain_add,                           /*nb_add*/
 (binaryfunc)Gain_sub,                           /*nb_subtract*/
 (binaryfunc)Gain_multiply,                      /*nb_multiply*/
-(binaryfunc)Gain_div,                           /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO    /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -415,16 +416,16 @@ static PyNumberMethods Gain_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)Gain_inplace_add,                   /*inplace_add*/
 (binaryfunc)Gain_inplace_sub,                   /*inplace_subtract*/
 (binaryfunc)Gain_inplace_multiply,              /*inplace_multiply*/
-(binaryfunc)Gain_inplace_div,                   /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -433,9 +434,9 @@ static PyNumberMethods Gain_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)Gain_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)Gain_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
@@ -445,8 +446,7 @@ where XXX is replaced by the name of the object.
 Fields in PyTypeObject that are not used should be 0.
 **************************************************************/
 PyTypeObject GainType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 /* How the object will be exposed to the 
 python interpreter. The name of the C component 
 of a PyoObject should be "XXX_base", where XXX
diff --git a/include/ad_coreaudio.h b/include/ad_coreaudio.h
new file mode 100644
index 0000000..d157fb0
--- /dev/null
+++ b/include/ad_coreaudio.h
@@ -0,0 +1,46 @@
+/**************************************************************************
+ * Copyright 2009-2016 Olivier Belanger                                   *
+ *                                                                        *
+ * This file is part of pyo, a python module to help digital signal       *
+ * processing script creation.                                            *
+ *                                                                        *
+ * pyo is free software: you can redistribute it and/or modify            *
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
+ *                                                                        *
+ * pyo is distributed in the hope that it will be useful,                 *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ * GNU 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/>.   *
+ *************************************************************************/
+
+#ifndef _AD_COREAUDIO_H
+#define _AD_COREAUDIO_H
+
+#include <CoreAudio/AudioHardware.h>
+#include "servermodule.h"
+
+OSStatus coreaudio_input_callback(AudioDeviceID device, const AudioTimeStamp* inNow,
+                                   const AudioBufferList* inInputData,
+                                   const AudioTimeStamp* inInputTime,
+                                   AudioBufferList* outOutputData,
+                                   const AudioTimeStamp* inOutputTime,
+                                   void* defptr);
+OSStatus coreaudio_output_callback(AudioDeviceID device, const AudioTimeStamp* inNow,
+                                   const AudioBufferList* inInputData,
+                                   const AudioTimeStamp* inInputTime,
+                                   AudioBufferList* outOutputData,
+                                   const AudioTimeStamp* inOutputTime,
+                                   void* defptr);
+int coreaudio_stop_callback(Server *self);
+int Server_coreaudio_init(Server *self);
+int Server_coreaudio_deinit(Server *self);
+int Server_coreaudio_start(Server *self);
+int Server_coreaudio_stop(Server *self);
+
+#endif 
+/* _AD_COREAUDIO_H */
diff --git a/include/ad_jack.h b/include/ad_jack.h
new file mode 100644
index 0000000..c41b874
--- /dev/null
+++ b/include/ad_jack.h
@@ -0,0 +1,47 @@
+/**************************************************************************
+ * Copyright 2009-2016 Olivier Belanger                                   *
+ *                                                                        *
+ * This file is part of pyo, a python module to help digital signal       *
+ * processing script creation.                                            *
+ *                                                                        *
+ * pyo is free software: you can redistribute it and/or modify            *
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
+ *                                                                        *
+ * pyo is distributed in the hope that it will be useful,                 *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ * GNU 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/>.   *
+ *************************************************************************/
+
+#ifndef _AD_JACK_H
+#define _AD_JACK_H
+
+#include <jack/jack.h>
+#include "servermodule.h"
+
+typedef struct {
+    jack_client_t *jack_client;
+    jack_port_t **jack_in_ports;
+    jack_port_t **jack_out_ports;
+} PyoJackBackendData;
+
+int jack_callback(jack_nframes_t nframes, void *arg);
+int jack_srate_cb(jack_nframes_t nframes, void *arg);
+int jack_bufsize_cb(jack_nframes_t nframes, void *arg);
+void jack_error_cb(const char *desc);
+void jack_shutdown_cb(void *arg);
+int jack_input_port_set_names(Server *self);
+int jack_output_port_set_names(Server *self);
+void Server_jack_autoconnect(Server *self);
+int Server_jack_init(Server *self);
+int Server_jack_deinit(Server *self);
+int Server_jack_start(Server *self);
+int Server_jack_stop(Server *self);
+
+#endif 
+/* _AD_JACK_H */
diff --git a/include/ad_portaudio.h b/include/ad_portaudio.h
new file mode 100644
index 0000000..1c338c0
--- /dev/null
+++ b/include/ad_portaudio.h
@@ -0,0 +1,64 @@
+/**************************************************************************
+ * Copyright 2009-2016 Olivier Belanger                                   *
+ *                                                                        *
+ * This file is part of pyo, a python module to help digital signal       *
+ * processing script creation.                                            *
+ *                                                                        *
+ * pyo is free software: you can redistribute it and/or modify            *
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
+ *                                                                        *
+ * pyo is distributed in the hope that it will be useful,                 *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ * GNU 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/>.   *
+ *************************************************************************/
+
+#ifndef _AD_PORTAUDIO_H
+#define _AD_PORTAUDIO_H
+
+#include <Python.h>
+#include "portaudio.h"
+#include "servermodule.h"
+
+typedef struct {
+    PaStream *stream;
+} PyoPaBackendData;
+
+int pa_callback_interleaved(const void *inputBuffer, void *outputBuffer,
+                            unsigned long framesPerBuffer,
+                            const PaStreamCallbackTimeInfo* timeInfo,
+                            PaStreamCallbackFlags statusFlags,
+                            void *arg);
+
+int pa_callback_nonInterleaved(const void *inputBuffer, void *outputBuffer,
+                               unsigned long framesPerBuffer,
+                               const PaStreamCallbackTimeInfo* timeInfo,
+                               PaStreamCallbackFlags statusFlags,
+                               void *arg);
+int Server_pa_init(Server *self);
+int Server_pa_deinit(Server *self);
+int Server_pa_start(Server *self);
+int Server_pa_stop(Server *self);
+
+/* Queries. */
+PyObject * portaudio_get_version();
+PyObject * portaudio_get_version_text();
+PyObject * portaudio_count_host_apis();
+PyObject * portaudio_list_host_apis();
+PyObject * portaudio_get_default_host_api();
+PyObject * portaudio_count_devices();
+PyObject * portaudio_list_devices();
+PyObject * portaudio_get_devices_infos();
+PyObject * portaudio_get_output_devices();
+PyObject * portaudio_get_output_max_channels(PyObject *self, PyObject *arg);
+PyObject * portaudio_get_input_max_channels(PyObject *self, PyObject *arg);
+PyObject * portaudio_get_input_devices();
+PyObject * portaudio_get_default_input();
+PyObject * portaudio_get_default_output();
+
+#endif /* _AD_PORTAUDIO_H */
diff --git a/include/dummymodule.h b/include/dummymodule.h
index e082a70..8ce3436 100644
--- a/include/dummymodule.h
+++ b/include/dummymodule.h
@@ -1,21 +1,21 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
@@ -25,7 +25,7 @@ typedef struct {
     pyo_audio_HEAD
     PyObject *input;
     Stream *input_stream;
-    int modebuffer[2]; // need at least 2 slots for mul & add 
+    int modebuffer[2]; // need at least 2 slots for mul & add
 } Dummy;
 
 extern PyObject * Dummy_initialize(Dummy *self);
@@ -33,4 +33,3 @@ extern PyObject * Dummy_initialize(Dummy *self);
 #define MAKE_NEW_DUMMY(self, type, rt_error)	\
 (self) = (Dummy *)(type)->tp_alloc((type), 0);	\
 if ((self) == rt_error) { return rt_error; }
-
diff --git a/include/fft.h b/include/fft.h
index 99f8d7d..a7019b5 100644
--- a/include/fft.h
+++ b/include/fft.h
@@ -1,29 +1,29 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 #include "pyomodule.h"
- 
+
 #ifndef _FFT_
 #define _FFT_
 /* in-place split-radix real fft */
 void realfft_split(MYFLT *data, MYFLT *outdata, int n, MYFLT **twiddle);
-void irealfft_split(MYFLT *data, MYFLT *outdata, int n, MYFLT **twiddle); 
+void irealfft_split(MYFLT *data, MYFLT *outdata, int n, MYFLT **twiddle);
 void fft_compute_split_twiddle(MYFLT **twiddle, int size);
 void fft_compute_window(MYFLT *window, int size, int wintype);
 /* in-place radix-2 real fft (not used actually) */
@@ -33,4 +33,3 @@ void irealfft_packed(MYFLT *data, MYFLT *outdata, int size, MYFLT *twiddle);
 void fft_compute_split_twiddle(MYFLT **twiddle, int size);
 void fft_compute_radix2_twiddle(MYFLT *twiddle, int size);
 #endif
-
diff --git a/include/interpolation.h b/include/interpolation.h
index 370c02c..5b3d042 100644
--- a/include/interpolation.h
+++ b/include/interpolation.h
@@ -1,21 +1,21 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 #include "pyomodule.h"
 
diff --git a/include/matrixmodule.h b/include/matrixmodule.h
index abcb1c3..72f5593 100644
--- a/include/matrixmodule.h
+++ b/include/matrixmodule.h
@@ -1,21 +1,21 @@
- /*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
  *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
  * processing script creation.                                            *
  *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    *
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
  * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include "Python.h"
diff --git a/include/md_portmidi.h b/include/md_portmidi.h
new file mode 100644
index 0000000..7788d6c
--- /dev/null
+++ b/include/md_portmidi.h
@@ -0,0 +1,54 @@
+/**************************************************************************
+ * Copyright 2009-2016 Olivier Belanger                                   *
+ *                                                                        *
+ * This file is part of pyo, a python module to help digital signal       *
+ * processing script creation.                                            *
+ *                                                                        *
+ * pyo is free software: you can redistribute it and/or modify            *
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
+ *                                                                        *
+ * pyo is distributed in the hope that it will be useful,                 *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ * GNU 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/>.   *
+ *************************************************************************/
+
+#ifndef _MD_PORTMIDI_H
+#define _MD_PORTMIDI_H
+
+#include <Python.h>
+#include "portmidi.h"
+#include "porttime.h"
+#include "servermodule.h"
+
+typedef struct {
+    PmStream *midiin[64];
+    PmStream *midiout[64];
+} PyoPmBackendData;
+
+void portmidiGetEvents(Server *self);
+int Server_pm_init(Server *self);
+int Server_pm_deinit(Server *self);
+void pm_noteout(Server *self, int pit, int vel, int chan, long timestamp);
+void pm_afterout(Server *self, int pit, int vel, int chan, long timestamp);
+void pm_ctlout(Server *self, int ctlnum, int value, int chan, long timestamp);
+void pm_programout(Server *self, int value, int chan, long timestamp);
+void pm_pressout(Server *self, int value, int chan, long timestamp);
+void pm_bendout(Server *self, int value, int chan, long timestamp);
+void pm_sysexout(Server *self, unsigned char *msg, long timestamp);
+long pm_get_current_time();
+
+/* Queries. */
+PyObject * portmidi_count_devices();
+PyObject * portmidi_list_devices();
+PyObject * portmidi_get_input_devices();
+PyObject * portmidi_get_output_devices();
+PyObject * portmidi_get_default_input();
+PyObject * portmidi_get_default_output();
+
+#endif /* _MD_PORTMIDI_H */
diff --git a/include/pvstreammodule.h b/include/pvstreammodule.h
index 5194e3e..d4ceb23 100644
--- a/include/pvstreammodule.h
+++ b/include/pvstreammodule.h
@@ -1,21 +1,21 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
@@ -56,6 +56,6 @@ extern PyTypeObject PVStreamType;
 /* include from other modules to use API */
 
 // #define Stream_setStreamObject(op, v) (((Stream *)(op))->streamobject = (v))
- 
+
 #endif
 /* __PVSTREAMMODULE */
\ No newline at end of file
diff --git a/include/py2to3.h b/include/py2to3.h
new file mode 100644
index 0000000..d0227d4
--- /dev/null
+++ b/include/py2to3.h
@@ -0,0 +1,87 @@
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
+ * This file is part of pyo, a python module to help digital signal       *
+ * processing script creation.                                            *
+ *                                                                        *
+ * pyo is free software: you can redistribute it and/or modify            *
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
+ *                                                                        *
+ * pyo is distributed in the hope that it will be useful,                 *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ * GNU 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/>.   *
+ *************************************************************************/
+
+// This header includes some compatibility code between python 2 and python 3
+
+#include "Python.h"
+
+#ifndef _PY_2TO3_H
+#define _PY_2TO3_H
+
+
+#if PY_MAJOR_VERSION >= 3
+/* This is the default on Python3 and constant has been removed. */
+#define Py_TPFLAGS_CHECKTYPES 0
+/* This seems to be a Python 2 thing only for compatibility with even older versions of Python.
+ * It has been removed in Python 3. */
+#define Py_TPFLAGS_HAVE_NEWBUFFER 0
+#define PyFloat_FromString(a,removed_parameter) PyFloat_FromString(a)
+
+/* PyInt -> PyLong remapping */
+#define PyInt_AsLong PyLong_AsLong
+#define PyInt_Check PyLong_Check
+#define PyInt_FromString PyLong_FromString
+#define PyInt_FromUnicode PyLong_FromUnicode
+#define PyInt_FromLong PyLong_FromLong
+#define PyInt_FromSize_t PyLong_FromSize_t
+#define PyInt_FromSsize_t PyLong_FromSsize_t
+#define PyInt_AsLong PyLong_AsLong
+// Note: Slightly different semantics, the macro does not do any error checking
+#define PyInt_AS_LONG PyLong_AsLong
+#define PyInt_AsSsize_t PyLong_AsSsize_t
+#define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask
+#define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask
+
+#define PyNumber_Int PyNumber_Long
+#define PyInt_Type PyLong_Type
+
+#endif /* PY_MAJOR_VERSION >= 3 */
+
+#endif
+
+// See PEP 238
+#define PyNumber_Divide PyNumber_TrueDivide
+#define PyNumber_InPlaceDivide PyNumber_InPlaceTrueDivide
+
+#if PY_MAJOR_VERSION >= 3
+// nb_coerce, nb_oct and nb_hex fields have been removed in Python 3
+#define INITIALIZE_NB_COERCE_ZERO
+#define INITIALIZE_NB_OCT_ZERO
+#define INITIALIZE_NB_HEX_ZERO
+#define INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO
+#define INITIALIZE_NB_DIVIDE_ZERO
+#else
+#define INITIALIZE_NB_COERCE_ZERO 0,
+#define INITIALIZE_NB_OCT_ZERO 0,
+#define INITIALIZE_NB_HEX_ZERO 0,
+#define INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO 0,
+#define INITIALIZE_NB_DIVIDE_ZERO 0,
+#endif
+
+/* Unicode/string handling. */
+#if PY_MAJOR_VERSION >= 3
+#define PY_STRING_CHECK(a) PyUnicode_Check(a) 
+#define PY_STRING_AS_STRING(a) PyUnicode_AsUTF8(a)
+#define PY_UNICODE_AS_UNICODE(a) PyUnicode_AsUTF8(a)
+#else
+#define PY_STRING_CHECK(a) (PyUnicode_Check(a) || PyBytes_Check(a))
+#define PY_STRING_AS_STRING(a) PyBytes_AsString(a)
+#define PY_UNICODE_AS_UNICODE(a) PyBytes_AsString(PyUnicode_AsASCIIString(a))
+#endif
diff --git a/include/pyomodule.h b/include/pyomodule.h
index ce4ba6c..7839e2a 100644
--- a/include/pyomodule.h
+++ b/include/pyomodule.h
@@ -1,27 +1,27 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include "Python.h"
 #include <math.h>
 
-#define PYO_VERSION "0.6.8"
+#define PYO_VERSION "0.8.7"
 
 #ifndef __MYFLT_DEF
 #define __MYFLT_DEF
@@ -38,6 +38,8 @@
 #define TYPE__FII "|fii"
 #define TYPE_F_II "f|ii"
 #define TYPE__FFF "|fff"
+#define TYPE_F_FFF "f|fff"
+#define TYPE_O_FIFFI "O|fiffi"
 #define TYPE_O_F "O|f"
 #define TYPE_O_FO "O|fO"
 #define TYPE__OF "|Of"
@@ -49,9 +51,13 @@
 #define TYPE_O_IF "O|if"
 #define TYPE_O_IFS "O|ifs"
 #define TYPE_S_IFF "s|iff"
+#define TYPE_P_IFF "s#|iff"
 #define TYPE_S_FIFF "s|fiff"
+#define TYPE_P_FIFF "s#|fiff"
 #define TYPE_S_FFIFF "s|ffiff"
+#define TYPE_P_FFIFF "s#|ffiff"
 #define TYPE_S__OIFI "s|Oifi"
+#define TYPE_P__OIFI "s#|Oifi"
 #define TYPE__FFFOO "|fffOO"
 #define TYPE__FFFIOO "|fffiOO"
 #define TYPE__FFFFFOO "|fffffOO"
@@ -71,8 +77,11 @@
 #define TYPE_F_OF "f|Of"
 #define TYPE__OFFI "|Offi"
 #define TYPE__OFII "|Ofii"
+#define TYPE__OFIOO "|OfiOO"
+#define TYPE__OOFOO "|OOfOO"
 #define TYPE__FIIOO "|fiiOO"
 #define TYPE_O_OFOO "O|OfOO"
+#define TYPE_O_OOOOFF "O|OOOOff"
 #define TYPE_O_IFFO "O|iffO"
 #define TYPE_O_OOIF "O|OOif"
 #define TYPE_O_FFFFIOO "O|ffffiOO"
@@ -84,6 +93,7 @@
 #define TYPE_O_OOFFOO "O|OOffOO"
 #define TYPE_O_OOOFOO "O|OOOfOO"
 #define TYPE_OO_OOOIFOO "OO|OOOifOO"
+#define TYPE__FFFFIFI "|ffffifi"
 
 #define SF_WRITE sf_write_float
 #define SF_READ sf_read_float
@@ -118,6 +128,8 @@
 #define TYPE__FII "|dii"
 #define TYPE_F_II "d|ii"
 #define TYPE__FFF "|ddd"
+#define TYPE_F_FFF "d|ddd"
+#define TYPE_O_FIFFI "O|diddi"
 #define TYPE_O_F "O|d"
 #define TYPE_O_FO "O|dO"
 #define TYPE__OF "|Od"
@@ -129,9 +141,13 @@
 #define TYPE_O_IF "O|id"
 #define TYPE_O_IFS "O|ids"
 #define TYPE_S_IFF "s|idd"
+#define TYPE_P_IFF "s#|idd"
 #define TYPE_S_FIFF "s|didd"
+#define TYPE_P_FIFF "s#|didd"
 #define TYPE_S_FFIFF "s|ddidd"
+#define TYPE_P_FFIFF "s#|ddidd"
 #define TYPE_S__OIFI "s|Oidi"
+#define TYPE_P__OIFI "s#|Oidi"
 #define TYPE__FFFOO "|dddOO"
 #define TYPE__FFFIOO "|dddiOO"
 #define TYPE__FFFFFOO "|dddddOO"
@@ -151,8 +167,11 @@
 #define TYPE_F_OF "d|Od"
 #define TYPE__OFFI "|Oddi"
 #define TYPE__OFII "|Odii"
+#define TYPE__OFIOO "|OdiOO"
+#define TYPE__OOFOO "|OOdOO"
 #define TYPE__FIIOO "|diiOO"
 #define TYPE_O_OFOO "O|OdOO"
+#define TYPE_O_OOOOFF "O|OOOOdd"
 #define TYPE_O_IFFO "O|iddO"
 #define TYPE_O_OOIF "O|OOid"
 #define TYPE_O_FFFFIOO "O|ddddiOO"
@@ -164,6 +183,7 @@
 #define TYPE_O_OOFFOO "O|OOddOO"
 #define TYPE_O_OOOFOO "O|OOOdOO"
 #define TYPE_OO_OOOIFOO "OO|OOOidOO"
+#define TYPE__FFFFIFI "|ddddidi"
 
 #define SF_WRITE sf_write_double
 #define SF_READ sf_read_double
@@ -186,7 +206,6 @@
 #define MYEXP exp
 #define MYROUND round
 
-
 #endif
 #endif
 
@@ -194,7 +213,22 @@
 #include "externalmodule.h"
 #endif
 
+#ifdef USE_PORTMIDI
+extern PyTypeObject MidiListenerType;
+extern PyTypeObject MidiDispatcherType;
+#endif
+#ifdef USE_OSC
+extern PyTypeObject OscListenerType;
+extern PyTypeObject OscSendType;
+extern PyTypeObject OscReceiveType;
+extern PyTypeObject OscReceiverType;
+extern PyTypeObject OscDataSendType;
+extern PyTypeObject OscDataReceiveType;
+extern PyTypeObject OscListReceiveType;
+extern PyTypeObject OscListReceiverType;
+#endif
 extern PyTypeObject SineType;
+extern PyTypeObject FastSineType;
 extern PyTypeObject SineLoopType;
 extern PyTypeObject FmType;
 extern PyTypeObject CrossFmType;
@@ -204,6 +238,8 @@ extern PyTypeObject RosslerType;
 extern PyTypeObject RosslerAltType;
 extern PyTypeObject LorenzType;
 extern PyTypeObject LorenzAltType;
+extern PyTypeObject ChenLeeType;
+extern PyTypeObject ChenLeeAltType;
 extern PyTypeObject PhasorType;
 extern PyTypeObject SuperSawType;
 extern PyTypeObject PointerType;
@@ -296,12 +332,14 @@ extern PyTypeObject IRAverageType;
 extern PyTypeObject IRFMType;
 extern PyTypeObject GranulatorType;
 extern PyTypeObject LooperType;
+extern PyTypeObject LooperTimeStreamType;
 extern PyTypeObject HarmonizerType;
 extern PyTypeObject MidictlType;
 extern PyTypeObject CtlScanType;
 extern PyTypeObject CtlScan2Type;
 extern PyTypeObject MidiNoteType;
 extern PyTypeObject NoteinType;
+extern PyTypeObject NoteinTrigType;
 extern PyTypeObject BendinType;
 extern PyTypeObject TouchinType;
 extern PyTypeObject PrograminType;
@@ -336,6 +374,7 @@ extern PyTypeObject SndTableType;
 extern PyTypeObject DataTableType;
 extern PyTypeObject NewTableType;
 extern PyTypeObject TableRecType;
+extern PyTypeObject TableWriteType;
 extern PyTypeObject TableRecTimeStreamType;
 extern PyTypeObject TableMorphType;
 extern PyTypeObject TrigTableRecType;
@@ -346,13 +385,6 @@ extern PyTypeObject MatrixPointerType;
 extern PyTypeObject MatrixRecType;
 extern PyTypeObject MatrixRecLoopType;
 extern PyTypeObject MatrixMorphType;
-extern PyTypeObject OscSendType;
-extern PyTypeObject OscReceiveType;
-extern PyTypeObject OscReceiverType;
-extern PyTypeObject OscDataSendType;
-extern PyTypeObject OscDataReceiveType;
-extern PyTypeObject OscListReceiveType;
-extern PyTypeObject OscListReceiverType;
 extern PyTypeObject TrigRandIntType;
 extern PyTypeObject TrigValType;
 extern PyTypeObject TrigRandType;
@@ -395,6 +427,7 @@ extern PyTypeObject ScaleType;
 extern PyTypeObject CentsToTranspoType;
 extern PyTypeObject TranspoToCentsType;
 extern PyTypeObject MToFType;
+extern PyTypeObject FToMType;
 extern PyTypeObject MToTType;
 extern PyTypeObject M_SinType;
 extern PyTypeObject M_CosType;
@@ -409,6 +442,8 @@ extern PyTypeObject M_Atan2Type;
 extern PyTypeObject M_FloorType;
 extern PyTypeObject M_CeilType;
 extern PyTypeObject M_RoundType;
+extern PyTypeObject M_TanhType;
+extern PyTypeObject M_ExpType;
 extern PyTypeObject FFTMainType;
 extern PyTypeObject FFTType;
 extern PyTypeObject IFFTType;
@@ -435,6 +470,7 @@ extern PyTypeObject ButLPType;
 extern PyTypeObject ButHPType;
 extern PyTypeObject ButBPType;
 extern PyTypeObject ButBRType;
+extern PyTypeObject MoogLPType;
 extern PyTypeObject PVAnalType;
 extern PyTypeObject PVSynthType;
 extern PyTypeObject PVTransposeType;
@@ -455,14 +491,45 @@ extern PyTypeObject PVBufTabLoopsType;
 extern PyTypeObject PVMixType;
 extern PyTypeObject GranuleType;
 extern PyTypeObject TableScaleType;
+extern PyTypeObject TrackHoldType;
+extern PyTypeObject ComplexResType;
+extern PyTypeObject STReverbType;
+extern PyTypeObject STRevType;
+extern PyTypeObject Pointer2Type;
+extern PyTypeObject CentroidType;
+extern PyTypeObject AttackDetectorType;
+extern PyTypeObject SmoothDelayType;
+extern PyTypeObject TrigBursterType;
+extern PyTypeObject TrigBurstType;
+extern PyTypeObject TrigBurstTapStreamType;
+extern PyTypeObject TrigBurstAmpStreamType;
+extern PyTypeObject TrigBurstDurStreamType;
+extern PyTypeObject TrigBurstEndStreamType;
+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
 #define PI M_PI
 #define TWOPI (2 * M_PI)
 
+#define PYO_RAND_MAX 4294967295u
+
 /* random uniform (0.0 -> 1.0) */
-#define RANDOM_UNIFORM rand()/((MYFLT)(RAND_MAX)+1)
+#define RANDOM_UNIFORM (pyorand()/((MYFLT)(PYO_RAND_MAX)+1))
 
 /* random objects identifier */
 #define BEATER_ID 0
@@ -492,6 +559,9 @@ extern PyTypeObject TableScaleType;
 #define FREEVERB_ID 24
 #define XNOISEDUR_ID 25
 #define URN_ID 26
+#define GRANULE_ID 27
+#define MAINPARTICLE_ID 28
+/* Do not forget to modify Server_generateSeed function */
 
 /* object headers */
 #define pyo_audio_HEAD \
@@ -507,8 +577,9 @@ extern PyTypeObject TableScaleType;
     Stream *add_stream; \
     int bufsize; \
     int nchnls; \
+    int ichnls; \
     double sr; \
-    MYFLT *data; 
+    MYFLT *data;
 
 #define pyo_table_HEAD \
     PyObject_HEAD \
@@ -527,62 +598,68 @@ extern PyTypeObject TableScaleType;
 
 /* VISIT & CLEAR */
 #define pyo_VISIT \
-    if (PyServer_get_server() != NULL) \
+    if (self->server != NULL) \
         Py_VISIT(self->server); \
-    Py_VISIT(self->stream); \
+    if (self->stream != NULL) \
+        Py_VISIT(self->stream); \
     Py_VISIT(self->mul); \
     Py_VISIT(self->mul_stream); \
     Py_VISIT(self->add); \
-    Py_VISIT(self->add_stream);    
+    Py_VISIT(self->add_stream);
 
 #define pyo_table_VISIT \
-    if (PyServer_get_server() != NULL) \
+    if (self->server != NULL) \
         Py_VISIT(self->server); \
-    Py_VISIT(self->tablestream); \
+    if (self->tablestream != NULL) \
+        Py_VISIT(self->tablestream); \
 
 #define pyo_matrix_VISIT \
-    if (PyServer_get_server() != NULL) \
+    if (self->server != NULL) \
         Py_VISIT(self->server); \
-    Py_VISIT(self->matrixstream); \
+    if (self->matrixstream != NULL) \
+        Py_VISIT(self->matrixstream); \
 
 #define pyo_CLEAR \
-    if (PyServer_get_server() != NULL) { \
-        Py_INCREF(self->server); \
-        Py_CLEAR(self->server); \
+    if (self->server != NULL) { \
+        self->server = NULL; \
     } \
-    Py_CLEAR(self->stream); \
+    if (self->stream != NULL) \
+        Py_CLEAR(self->stream); \
     Py_CLEAR(self->mul); \
     Py_CLEAR(self->mul_stream); \
     Py_CLEAR(self->add); \
     Py_CLEAR(self->add_stream); \
 
 #define pyo_table_CLEAR \
-    if (PyServer_get_server() != NULL) { \
-        Py_INCREF(self->server); \
-        Py_CLEAR(self->server); \
+    if (self->server != NULL) { \
+        self->server = NULL; \
     } \
-    Py_CLEAR(self->tablestream); \
+    if (self->tablestream != NULL) \
+        Py_CLEAR(self->tablestream); \
 
 #define pyo_matrix_CLEAR \
-    if (PyServer_get_server() != NULL) { \
-        Py_INCREF(self->server); \
-        Py_CLEAR(self->server); \
+    if (self->server != NULL) { \
+        self->server = NULL; \
     } \
-    Py_CLEAR(self->matrixstream); \
+    if (self->matrixstream != NULL) \
+        Py_CLEAR(self->matrixstream); \
 
 #define pyo_DEALLOC \
-    if (PyServer_get_server() != NULL) \
+    if (self->server != NULL && self->stream != NULL) \
         Server_removeStream((Server *)self->server, Stream_getStreamId(self->stream)); \
     free(self->data); \
 
+#define ASSERT_ARG_NOT_NULL \
+	if (arg == NULL) { \
+		Py_INCREF(Py_None); \
+		return Py_None; \
+	}
+
 /* INIT INPUT STREAM */
 #define INIT_INPUT_STREAM \
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "server") == 0 ) { \
-        PySys_WriteStderr("TypeError: \"input\" argument must be a PyoObject.\n"); \
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) { \
-            PyObject_CallMethod(self->server, "shutdown", NULL); \
-        } \
-        Py_Exit(1); \
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument must be a PyoObject.\n"); \
+        Py_RETURN_NONE; \
     } \
     Py_INCREF(inputtmp); \
     Py_XDECREF(self->input); \
@@ -609,6 +686,7 @@ extern PyTypeObject TableScaleType;
     self->bufsize = PyInt_AsLong(PyObject_CallMethod(self->server, "getBufferSize", NULL)); \
     self->sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL)); \
     self->nchnls = PyInt_AsLong(PyObject_CallMethod(self->server, "getNchnls", NULL)); \
+    self->ichnls = PyInt_AsLong(PyObject_CallMethod(self->server, "getIchnls", NULL)); \
     self->data = (MYFLT *)realloc(self->data, (self->bufsize) * sizeof(MYFLT)); \
     for (i=0; i<self->bufsize; i++) \
         self->data[i] = 0.0; \
@@ -628,7 +706,7 @@ extern PyTypeObject TableScaleType;
     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 \
@@ -637,13 +715,14 @@ extern PyTypeObject TableScaleType;
         PyErr_SetString(PyExc_TypeError, "The data must be a list of floats."); \
         return PyInt_FromLong(-1); \
     } \
-    self->size = PyList_Size(arg)-1; \
+    self->size = PyList_Size(arg); \
     self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT)); \
     TableStream_setSize(self->tablestream, self->size+1); \
  \
-    for (i=0; i<(self->size+1); i++) { \
-        self->data[i] = PyFloat_AS_DOUBLE(PyNumber_Float(PyList_GET_ITEM(arg, i))); \
+    for (i=0; i<(self->size); i++) { \
+        self->data[i] = PyFloat_AsDouble(PyList_GET_ITEM(arg, i)); \
     } \
+    self->data[self->size] = self->data[0]; \
     TableStream_setData(self->tablestream, self->data); \
  \
     Py_INCREF(Py_None); \
@@ -669,7 +748,7 @@ extern PyTypeObject TableScaleType;
     for(i=0; i<self->height; i++) { \
         innerlist = PyList_GetItem(arg, i); \
         for (j=0; j<self->width; j++) { \
-            self->data[i][j] = PyFloat_AS_DOUBLE(PyNumber_Float(PyList_GET_ITEM(innerlist, j))); \
+            self->data[i][j] = PyFloat_AsDouble(PyList_GET_ITEM(innerlist, j)); \
         } \
     } \
  \
@@ -686,7 +765,115 @@ extern PyTypeObject TableScaleType;
     } \
     self->data[self->size] = self->data[0]; \
     Py_RETURN_NONE; \
-    
+
+#define TABLE_ADD \
+    int i, tabsize; \
+    MYFLT x = 0.0; \
+    MYFLT *list = NULL; \
+    PyObject *table = NULL; \
+    if (PyNumber_Check(arg)) { \
+        x = PyFloat_AsDouble(arg); \
+        for (i=0; i<self->size; i++) { \
+            self->data[i] += x; \
+        } \
+    } \
+    else if ( PyObject_HasAttrString((PyObject *)arg, "getTableStream") == 1 ) { \
+        Py_XDECREF(table); \
+        table = PyObject_CallMethod((PyObject *)arg, "getTableStream", ""); \
+        list = TableStream_getData((TableStream *)table); \
+        tabsize = TableStream_getSize((TableStream *)table); \
+        if (self->size < tabsize) \
+            tabsize = self->size; \
+        for (i=0; i<tabsize; i++) { \
+            self->data[i] += list[i]; \
+        } \
+    } \
+    else if (PyList_Check(arg)) { \
+        tabsize = PyList_Size(arg); \
+        if (self->size < tabsize) \
+            tabsize = self->size; \
+        for (i=0; i<tabsize; i++) { \
+            self->data[i] += PyFloat_AsDouble(PyList_GET_ITEM(arg, i)); \
+        } \
+    } \
+ \
+    self->data[self->size] = self->data[0]; \
+ \
+    Py_INCREF(Py_None); \
+    return Py_None; \
+
+#define TABLE_SUB \
+    int i, tabsize; \
+    MYFLT x = 0.0; \
+    MYFLT *list = NULL; \
+    PyObject *table = NULL; \
+    if (PyNumber_Check(arg)) { \
+        x = PyFloat_AsDouble(arg); \
+        for (i=0; i<self->size; i++) { \
+            self->data[i] -= x; \
+        } \
+    } \
+    else if ( PyObject_HasAttrString((PyObject *)arg, "getTableStream") == 1 ) { \
+        Py_XDECREF(table); \
+        table = PyObject_CallMethod((PyObject *)arg, "getTableStream", ""); \
+        list = TableStream_getData((TableStream *)table); \
+        tabsize = TableStream_getSize((TableStream *)table); \
+        if (self->size < tabsize) \
+            tabsize = self->size; \
+        for (i=0; i<tabsize; i++) { \
+            self->data[i] -= list[i]; \
+        } \
+    } \
+    else if (PyList_Check(arg)) { \
+        tabsize = PyList_Size(arg); \
+        if (self->size < tabsize) \
+            tabsize = self->size; \
+        for (i=0; i<tabsize; i++) { \
+            self->data[i] -= PyFloat_AsDouble(PyList_GET_ITEM(arg, i)); \
+        } \
+    } \
+ \
+    self->data[self->size] = self->data[0]; \
+ \
+    Py_INCREF(Py_None); \
+    return Py_None; \
+
+#define TABLE_MUL \
+    int i, tabsize; \
+    MYFLT x = 0.0; \
+    MYFLT *list = NULL; \
+    PyObject *table = NULL; \
+    if (PyNumber_Check(arg)) { \
+        x = PyFloat_AsDouble(arg); \
+        for (i=0; i<self->size; i++) { \
+            self->data[i] *= x; \
+        } \
+    } \
+    else if ( PyObject_HasAttrString((PyObject *)arg, "getTableStream") == 1 ) { \
+        Py_XDECREF(table); \
+        table = PyObject_CallMethod((PyObject *)arg, "getTableStream", ""); \
+        list = TableStream_getData((TableStream *)table); \
+        tabsize = TableStream_getSize((TableStream *)table); \
+        if (self->size < tabsize) \
+            tabsize = self->size; \
+        for (i=0; i<tabsize; i++) { \
+            self->data[i] *= list[i]; \
+        } \
+    } \
+    else if (PyList_Check(arg)) { \
+        tabsize = PyList_Size(arg); \
+        if (self->size < tabsize) \
+            tabsize = self->size; \
+        for (i=0; i<tabsize; i++) { \
+            self->data[i] *= PyFloat_AsDouble(PyList_GET_ITEM(arg, i)); \
+        } \
+    } \
+ \
+    self->data[self->size] = self->data[0]; \
+ \
+    Py_INCREF(Py_None); \
+    return Py_None; \
+
 #define SET_TABLE \
     int i; \
     if (arg == NULL) { \
@@ -703,7 +890,7 @@ extern PyTypeObject TableScaleType;
         return PyInt_FromLong(-1); \
     } \
     for(i=0; i<self->size; i++) { \
-        self->data[i] = PyFloat_AS_DOUBLE(PyNumber_Float(PyList_GET_ITEM(arg, i))); \
+        self->data[i] = PyFloat_AsDouble(PyList_GET_ITEM(arg, i)); \
     } \
     self->data[self->size] = self->data[0]; \
     Py_RETURN_NONE; \
@@ -720,21 +907,44 @@ extern PyTypeObject TableScaleType;
     return samples;
 
 #define GET_VIEW_TABLE \
-    int i, y; \
-    int w = 500; \
-    int h = 200; \
-    int h2 = h/2; \
-    int amp = h2 - 2; \
-    float step = (float)self->size / (float)(w); \
-    PyObject *samples; \
+    int i, y, w, h, h2, amp; \
+    float step; \
+    PyObject *samples, *tuple, *sizetmp = NULL; \
+ \
+    static char *kwlist[] = {"size", NULL}; \
+ \
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &sizetmp)) \
+        return PyInt_FromLong(-1); \
  \
-    samples = PyList_New(w*4); \
+    if (sizetmp) { \
+        if (PyTuple_Check(sizetmp)) { \
+            w = PyInt_AsLong(PyTuple_GET_ITEM(sizetmp, 0)); \
+            h = PyInt_AsLong(PyTuple_GET_ITEM(sizetmp, 1)); \
+        } \
+        else if (PyList_Check(sizetmp)) { \
+            w = PyInt_AsLong(PyList_GET_ITEM(sizetmp, 0)); \
+            h = PyInt_AsLong(PyList_GET_ITEM(sizetmp, 1)); \
+        } \
+        else { \
+            w = 500; \
+            h = 200; \
+        } \
+    } \
+    else { \
+        w = 500; \
+        h = 200; \
+    } \
+    h2 = h/2; \
+    amp = h2 - 2; \
+    step = (float)self->size / (float)(w); \
+ \
+    samples = PyList_New(w); \
     for(i=0; i<w; i++) { \
-        y = self->data[(int)(i*step)] * amp + amp; \
-        PyList_SetItem(samples, i*4, PyInt_FromLong(i)); \
-        PyList_SetItem(samples, i*4+1, PyInt_FromLong(h-y)); \
-        PyList_SetItem(samples, i*4+2, PyInt_FromLong(i)); \
-        PyList_SetItem(samples, i*4+3, PyInt_FromLong(h-y)); \
+        y = self->data[(int)(i*step)] * amp + amp + 2; \
+        tuple = PyTuple_New(2); \
+        PyTuple_SetItem(tuple, 0, PyInt_FromLong(i)); \
+        PyTuple_SetItem(tuple, 1, PyInt_FromLong(h-y)); \
+        PyList_SetItem(samples, i, tuple); \
     } \
  \
     return samples;
@@ -776,6 +986,193 @@ extern PyTypeObject TableScaleType;
     Py_INCREF(Py_None); \
     return Py_None; \
 
+/* Table amplitude reverse */
+#define INVERT \
+    int i; \
+    for (i=0; i<self->size+1; i++) { \
+        self->data[i] = -self->data[i]; \
+    } \
+    Py_INCREF(Py_None); \
+    return Py_None; \
+
+/* Table positive rectify */
+#define RECTIFY \
+    int i; \
+    MYFLT x; \
+    for (i=0; i<self->size+1; i++) { \
+        x = self->data[i]; \
+        if (x < 0) \
+            self->data[i] = -x; \
+    } \
+    Py_INCREF(Py_None); \
+    return Py_None; \
+
+/* Table rotation */
+#define TABLE_ROTATE \
+    int i, j, pos; \
+    MYFLT tmp; \
+    static char *kwlist[] = {"pos", NULL}; \
+ \
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &pos)) \
+        return PyInt_FromLong(-1); \
+ \
+    pos = -pos; \
+    while (pos > self->size) pos -= self->size; \
+    while (pos < 0) pos += self->size; \
+ \
+    j = self->size; \
+    for (i=0; i<--j; i++) { \
+        tmp = self->data[i]; \
+        self->data[i] = self->data[j]; \
+        self->data[j] = tmp; \
+    } \
+    j = pos; \
+    for (i=0; i<--j; i++) { \
+        tmp = self->data[i]; \
+        self->data[i] = self->data[j]; \
+        self->data[j] = tmp; \
+    } \
+    j = self->size; \
+    for (i=pos; i<--j; i++) { \
+        tmp = self->data[i]; \
+        self->data[i] = self->data[j]; \
+        self->data[j] = tmp; \
+    } \
+ \
+    self->data[self->size] = self->data[0]; \
+ \
+    Py_RETURN_NONE;
+
+/* Table copy from table */
+#define TABLE_COPYDATA \
+    PyObject *tabletmp; \
+    int i, tabsize, srcpos=0, destpos=0, length=-1; \
+    PyObject *table = NULL; \
+    MYFLT *list = NULL; \
+    static char *kwlist[] = {"table", "srcpos", "destpos", "length", NULL}; \
+ \
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iii", kwlist, &tabletmp, &srcpos, &destpos, &length)) \
+        return PyInt_FromLong(-1); \
+ \
+    if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 1 ) { \
+        Py_XDECREF(table); \
+        table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", ""); \
+        tabsize = TableStream_getSize((TableStream *)table); \
+        if (length < 0) \
+            length = tabsize < self->size ? tabsize : self->size; \
+        if ((srcpos + length) > tabsize) \
+            length = tabsize - srcpos; \
+        if ((destpos + length) > self->size) \
+            length = self->size - destpos; \
+        list = TableStream_getData((TableStream *)table); \
+        for (i=0; i<length; i++) { \
+            self->data[destpos+i] = list[srcpos+i]; \
+        } \
+    } \
+ \
+    Py_RETURN_NONE;
+
+/* Table bipolar gain */
+#define TABLE_BIPOLAR_GAIN \
+    MYFLT gpos = 1.0, gneg = 1.0; \
+    int i; \
+    static char *kwlist[] = {"gpos", "gneg", NULL}; \
+ \
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__FF, kwlist, &gpos, &gneg)) \
+        return PyInt_FromLong(-1); \
+ \
+    for (i=0; i<self->size+1; i++) { \
+        if (self->data[i] < 0) \
+            self->data[i] *= gneg; \
+        else \
+            self->data[i] *= gpos; \
+    } \
+ \
+    Py_RETURN_NONE;
+
+/* Table power function */
+#define TABLE_POWER \
+    MYFLT x, exp; \
+    int i, sign; \
+    static char *kwlist[] = {"exp", NULL}; \
+ \
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_F, kwlist, &exp)) \
+        return PyInt_FromLong(-1); \
+ \
+    for (i=0; i<self->size+1; i++) { \
+        x = self->data[i]; \
+        sign = 1; \
+        if (x < 0) \
+            sign = -1; \
+        x = MYPOW(x, exp); \
+        if (sign == -1 && x > 0) \
+            x = -x; \
+        self->data[i] = x; \
+    } \
+ \
+    Py_RETURN_NONE;
+
+/* Table one-pole lowpass filter */
+#define TABLE_LOWPASS \
+    MYFLT freq, b, c, x, y; \
+    int i; \
+    double sr = PyFloat_AsDouble(PyObject_CallMethod(PyServer_get_server(), "getSamplingRate", NULL)); \
+    static char *kwlist[] = {"freq", NULL}; \
+ \
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_F, kwlist, &freq)) \
+        return PyInt_FromLong(-1); \
+ \
+    b = 2.0 - MYCOS(TWOPI * freq / sr); \
+    c = b - MYSQRT(b * b - 1.0); \
+    y = 0; \
+    for (i=0; i<self->size+1; i++) { \
+        x = self->data[i]; \
+        self->data[i] = y = x + (y - x) * c; \
+    } \
+ \
+    Py_RETURN_NONE;
+
+/* FADE IN, FADE OUT */
+#define TABLE_FADEIN \
+    MYFLT dur, inc; \
+    int i, samp; \
+    double sr = PyFloat_AsDouble(PyObject_CallMethod(PyServer_get_server(), "getSamplingRate", NULL)); \
+    static char *kwlist[] = {"dur", NULL}; \
+ \
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_F, kwlist, &dur)) \
+        return PyInt_FromLong(-1); \
+ \
+    samp = (int)(dur * sr); \
+    if (samp < 0 || samp >= self->size) \
+        Py_RETURN_NONE; \
+ \
+    inc = 1.0 / samp; \
+    for (i=0; i<samp; i++) { \
+        self->data[i] = self->data[i] * MYSQRT(inc * i); \
+    } \
+ \
+    Py_RETURN_NONE;
+
+#define TABLE_FADEOUT \
+    MYFLT dur, inc; \
+    int i, samp; \
+    double sr = PyFloat_AsDouble(PyObject_CallMethod(PyServer_get_server(), "getSamplingRate", NULL)); \
+    static char *kwlist[] = {"dur", NULL}; \
+ \
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_F, kwlist, &dur)) \
+        return PyInt_FromLong(-1); \
+ \
+    samp = (int)(dur * sr); \
+    if (samp < 0 || samp >= self->size) \
+        Py_RETURN_NONE; \
+ \
+    inc = 1.0 / samp; \
+    for (i=self->size; i>(self->size-samp); i--) { \
+        self->data[i] = self->data[i] * MYSQRT(inc * (self->size - i)); \
+    } \
+ \
+    Py_RETURN_NONE;
+
 /* Normalize */
 #define NORMALIZE \
 	int i; \
@@ -838,10 +1235,10 @@ extern PyTypeObject TableScaleType;
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_F_I, kwlist, &val, &pos)) \
         return PyInt_FromLong(-1); \
  \
-    if (pos >= self->size) { \
-        PyErr_SetString(PyExc_TypeError, "position outside of table boundaries!."); \
-        return PyInt_FromLong(-1); \
-    } \
+    if (pos >= self->size) \
+        pos = self->size - 1; \
+    else if (pos < 0) \
+        pos = 0; \
  \
     self->data[pos] = val; \
  \
@@ -955,6 +1352,25 @@ extern PyTypeObject TableScaleType;
  \
     return PyFloat_FromDouble(self->data[y][x]); \
 
+#define MATRIX_GET_INTERPOLATED \
+    MYFLT x = 0.0, y = 0.0; \
+    static char *kwlist[] = {"x", "y", NULL}; \
+ \
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__FF, kwlist, &x, &y)) \
+        return PyInt_FromLong(-1); \
+ \
+    if (x < 0.0 || x > 1.0) { \
+        PyErr_SetString(PyExc_TypeError, "X position outside of matrix boundaries!."); \
+        return PyInt_FromLong(-1); \
+    } \
+ \
+    if (y < 0.0 || y > 1.0) { \
+        PyErr_SetString(PyExc_TypeError, "Y position outside of matrix boundaries!."); \
+        return PyInt_FromLong(-1); \
+    } \
+ \
+    return PyFloat_FromDouble(MatrixStream_getInterpPointFromPos(self->matrixstream, x, y)); \
+
 /* GETS & SETS */
 #define GET_SERVER \
     if (self->server == NULL) { \
@@ -1033,7 +1449,7 @@ extern PyTypeObject TableScaleType;
     (*self->mode_func_ptr)(self); \
  \
     Py_INCREF(Py_None); \
-    return Py_None; 
+    return Py_None;
 
 #define SET_ADD \
     PyObject *tmp, *streamtmp; \
@@ -1064,7 +1480,7 @@ extern PyTypeObject TableScaleType;
     (*self->mode_func_ptr)(self); \
 \
     Py_INCREF(Py_None); \
-    return Py_None; 
+    return Py_None;
 
 #define SET_SUB \
     PyObject *tmp, *streamtmp; \
@@ -1095,7 +1511,7 @@ extern PyTypeObject TableScaleType;
     (*self->mode_func_ptr)(self); \
  \
     Py_INCREF(Py_None); \
-    return Py_None; 
+    return Py_None;
 
 #define SET_DIV \
     PyObject *tmp, *streamtmp; \
@@ -1110,9 +1526,9 @@ extern PyTypeObject TableScaleType;
     tmp = arg; \
     Py_INCREF(tmp); \
     if (isNumber == 1) { \
-        if (PyFloat_AsDouble(PyNumber_Float(tmp)) != 0.) { \
+        if (PyFloat_AsDouble(tmp) != 0.) { \
             Py_DECREF(self->mul); \
-            self->mul = PyNumber_Divide(PyFloat_FromDouble(1.), PyNumber_Float(tmp)); \
+            self->mul = PyNumber_TrueDivide(PyFloat_FromDouble(1.), PyNumber_Float(tmp)); \
             self->modebuffer[0] = 0; \
         } \
     } \
@@ -1129,7 +1545,7 @@ extern PyTypeObject TableScaleType;
     (*self->mode_func_ptr)(self); \
  \
     Py_INCREF(Py_None); \
-    return Py_None; 
+    return Py_None;
 
 /* Multiply, Add, inplace_multiply & inplace_add */
 #define MULTIPLY \
@@ -1184,6 +1600,8 @@ extern PyTypeObject TableScaleType;
 #define PLAY \
     float del = 0; \
     float dur = 0; \
+    float globdel = 0; \
+    float globdur = 0; \
     int nearestBuf = 0; \
     int i; \
  \
@@ -1192,17 +1610,31 @@ extern PyTypeObject TableScaleType;
     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); \
         Stream_setStreamActive(self->stream, 1); \
     } \
     else { \
-        Stream_setStreamActive(self->stream, 0); \
-        for (i=0; i<self->bufsize; i++) \
-            self->data[i] = 0.0; \
         nearestBuf = (int)roundf((del * self->sr) / self->bufsize); \
-        Stream_setBufferCountWait(self->stream, nearestBuf); \
+        if (nearestBuf <= 0) { \
+            Stream_setBufferCountWait(self->stream, 0); \
+            Stream_setStreamActive(self->stream, 1); \
+        } \
+        else { \
+            Stream_setStreamActive(self->stream, 0); \
+            for (i=0; i<self->bufsize; i++) \
+                self->data[i] = 0.0; \
+            Stream_setBufferCountWait(self->stream, nearestBuf); \
+        } \
     } \
     if (dur == 0) \
         Stream_setDuration(self->stream, 0); \
@@ -1217,6 +1649,8 @@ extern PyTypeObject TableScaleType;
     int chnltmp = 0; \
     float del = 0; \
     float dur = 0; \
+    float globdel = 0; \
+    float globdur = 0; \
     int nearestBuf = 0; \
     int i; \
 \
@@ -1225,6 +1659,14 @@ extern PyTypeObject TableScaleType;
     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) { \
@@ -1256,7 +1698,7 @@ extern PyTypeObject TableScaleType;
         self->data[i] = 0; \
     } \
     Py_INCREF(Py_None); \
-    return Py_None;    
+    return Py_None;
 
 /* Post processing (mul & add) macros */
 #define POST_PROCESSING_II \
@@ -1292,7 +1734,7 @@ extern PyTypeObject TableScaleType;
         old = self->data[i]; \
         val = mul * old + add[i]; \
         self->data[i] = val; \
-    } 
+    }
 
 #define POST_PROCESSING_AA \
     MYFLT old, val; \
@@ -1342,7 +1784,7 @@ extern PyTypeObject TableScaleType;
         old = self->data[i]; \
         val = mul * old - add[i]; \
         self->data[i] = val; \
-    } 
+    }
 
 #define POST_PROCESSING_AREVA \
     MYFLT old, val; \
@@ -1369,3 +1811,38 @@ extern PyTypeObject TableScaleType;
         self->data[i] = val; \
     }
 
+/* Tables buffer protocol. */
+#if PY_MAJOR_VERSION < 3
+#define TABLESTREAM_READ_WRITE_BUFFER \
+    if ( index != 0 ) { \
+        PySys_WriteStdout("Accessing non-existent bytes segment..."); \
+        return -1; \
+    } \
+    *ptr = (void *)self->data; \
+    return (Py_ssize_t)self->size * sizeof(MYFLT);
+
+#define TABLESTREAM_SEG_COUNT \
+    if ( lenp ) \
+        *lenp = (Py_ssize_t)self->size * sizeof(MYFLT); \
+    return 1;
+#endif
+
+#define TABLESTREAM_GET_BUFFER \
+    if (view == NULL) { \
+        PySys_WriteStdout("NULL view in getBuffer."); \
+        return -1; \
+    } \
+    self->shape[0] = self->size; \
+    view->obj = (PyObject *)self; \
+    view->buf = (void *)self->data; \
+    view->len = self->size * sizeof(MYFLT); \
+    view->readonly = 0; \
+    view->itemsize = sizeof(MYFLT); \
+    view->format = TYPE_F; \
+    view->ndim = 1; \
+    view->shape = self->shape; \
+    view->strides = NULL; \
+    view->suboffsets = NULL; \
+    view->internal = NULL; \
+    Py_INCREF(self); \
+    return 0;
diff --git a/include/servermodule.h b/include/servermodule.h
index 396ed16..85dba44 100644
--- a/include/servermodule.h
+++ b/include/servermodule.h
@@ -1,25 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *                                                                        *
- * Octobre 2013 : Multiple servers facility and embeded backend added by  *
- * Guillaume Barrette. See embeded possibilities at:                      *
- * https://github.com/guibarrette/PyoPlug                                 *
+ * Octobre 2013 : Multiple servers facility and embedded backend added    *
+ * by Guillaume Barrette.                                                 *
+ * 2014-2016 : Several improvements by Olivier Belanger.                  *
  *************************************************************************/
 
 #ifndef Py_SERVERMODULE_H
@@ -28,19 +28,9 @@
 extern "C" {
 #endif
 
-#include "portaudio.h"
-#include "portmidi.h"
 #include "sndfile.h"
 #include "pyomodule.h"
 
-#ifdef USE_JACK
-#include <jack/jack.h>
-#endif
-
-#ifdef USE_COREAUDIO
-# include <CoreAudio/AudioHardware.h>
-#endif
-
 typedef enum {
     PyoPortaudio = 0,
     PyoCoreaudio = 1,
@@ -50,33 +40,57 @@ typedef enum {
     PyoEmbedded
 } PyoAudioBackendType;
 
-typedef struct {
-    PaStream *stream;
-} PyoPaBackendData;
+typedef enum {
+    PyoPortmidi = 0
+} PyoMidiBackendType;
+
+/* Portmidi midi message and event type clones. */
+
+typedef long PyoMidiTimestamp;
 
+#define PyoMidi_Message(status, data1, data2) \
+         ((((data2) << 16) & 0xFF0000) | \
+          (((data1) << 8) & 0xFF00) | \
+          ((status) & 0xFF))
+#define PyoMidi_MessageStatus(msg) ((msg) & 0xFF)
+#define PyoMidi_MessageData1(msg) (((msg) >> 8) & 0xFF)
+#define PyoMidi_MessageData2(msg) (((msg) >> 16) & 0xFF)
+
+typedef long PyoMidiMessage; 
 typedef struct {
-#ifdef USE_JACK
-    jack_client_t *jack_client;
-    jack_port_t **jack_in_ports;
-    jack_port_t **jack_out_ports;
-#endif
-} PyoJackBackendData;
-  
+    PyoMidiMessage      message;
+    PyoMidiTimestamp    timestamp;
+} PyoMidiEvent;
+
+/************************************************/
+
 typedef struct {
     PyObject_HEAD
     PyObject *streams;
     PyoAudioBackendType audio_be_type;
+    PyoMidiBackendType midi_be_type;
     void *audio_be_data;
+    void *midi_be_data;
     char *serverName; /* Only used for jack client name */
     int jackautoin; /* jack port auto-connection (on by default) */
     int jackautoout; /* jack port auto-connection (on by default) */
-    PmStream *in;
-    PmStream *out;
-    PmEvent midiEvents[200];
+    PyObject *jackAutoConnectInputPorts; /* list of lists of jack auto-connection ports to pyo inputs */
+    PyObject *jackAutoConnectOutputPorts; /* list of lists of jack auto-connection ports from pyo outputs */
+    PyObject *jackInputPortNames; /* string or list of strings (input port short names for jack server */
+    PyObject *jackOutputPortNames; /* string or list of strings (output port short names for jack server */
+    int isJackTransportSlave;
+    int jack_transport_state; /* 0 = stopped, 1 = started */
+    PyoMidiEvent midiEvents[200];
+    int midiin_count;
+    int midiout_count;
     int midi_count;
+    long midi_time_offset;
     double samplingRate;
     int nchnls;
+    int ichnls;
     int bufferSize;
+    int currentResampling;
+    int lastResampling;
     int duplex;
     int input;
     int output;
@@ -86,13 +100,15 @@ typedef struct {
     int midi_output;
     int withPortMidi;
     int withPortMidiOut;
+    int midiActive;
+    int allowMMMapper;
     int server_started;
     int server_stopped; /* for fadeout */
     int server_booted;
     int stream_count;
     int record;
     int thisServerID;       /* To keep the reference index in the array of servers */
-    
+
     /* global amplitude */
     MYFLT amp;
     MYFLT resetAmp;
@@ -101,21 +117,22 @@ typedef struct {
     MYFLT stepVal;
     int timeStep;
     int timeCount;
-    
+
     MYFLT *input_buffer;
     float *output_buffer; /* Has to be float since audio callbacks must use floats */
-    
+
     /* rendering offline of the first "startoffset" seconds */
     double startoffset;
-    
+
     /* rendering settings */
     double recdur;
     char *recpath;
     int recformat;
     int rectype;
+    double recquality;
     SNDFILE *recfile;
     SF_INFO recinfo;
-    
+
     /* GUI VUMETER */
     int withGUI;
     int numPass;
@@ -129,24 +146,47 @@ typedef struct {
     int timePass;
     int tcount;
     PyObject *TIME;
-    
+
+    /* 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.*/
-    int globalSeed; /* initial seed for random objects. If -1, objects are seeded with the clock. */
+    int globalSeed; /* initial seed for random objects. If <= 0, objects are seeded with the clock. */
 } Server;
 
 PyObject * PyServer_get_server();
+extern unsigned int pyorand();
 extern PyObject * Server_removeStream(Server *self, int sid);
-extern MYFLT * Server_getInputBuffer(Server *self);    
-extern PmEvent * Server_getMidiEventBuffer(Server *self);    
-extern int Server_getMidiEventCount(Server *self);  
+extern MYFLT * Server_getInputBuffer(Server *self);
+extern PyoMidiEvent * Server_getMidiEventBuffer(Server *self);
+extern int Server_getMidiEventCount(Server *self);
+extern long Server_getMidiTimeOffset(Server *self);
+extern unsigned long Server_getElapsedTime(Server *self);
+extern int Server_getCurrentResamplingFactor(Server *self);
+extern int Server_getLastResamplingFactor(Server *self);
 extern int Server_generateSeed(Server *self, int oid);
-extern PyTypeObject ServerType;    
+extern PyTypeObject ServerType;
+void pyoGetMidiEvents(Server *self);
+void Server_process_buffers(Server *server);
+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_shutdown(Server *self);
+PyObject * Server_stop(Server *self);
+PyObject * Server_start(Server *self);
+PyObject * Server_boot(Server *self, PyObject *arg);
+void Server_process_gui(Server *server);
+void Server_process_time(Server *server);
+int Server_start_rec_internal(Server *self, char *filename);
 
 #ifdef __cplusplus
 }
-#endif
-
-#endif /* !defined(Py_SERVERMODULE_H) */
-
+#endif /* __cplusplus */
+#endif /* Py_SERVERMODULE_H */
diff --git a/include/streammodule.h b/include/streammodule.h
index 4febd94..b19b0ce 100644
--- a/include/streammodule.h
+++ b/include/streammodule.h
@@ -1,21 +1,21 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.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
@@ -87,6 +86,6 @@ extern PyTypeObject TriggerStreamType;
 #define Stream_setBufferCountWait(op, v) (((Stream *)(op))->bufferCountWait = (v))
 #define Stream_setDuration(op, v) (((Stream *)(op))->duration = (v))
 #define Stream_setBufferSize(op, v) (((Stream *)(op))->bufsize = (v))
- 
+
 #endif
-/* __STREAMMODULE */
+/* __STREAMMODULE */
\ No newline at end of file
diff --git a/include/tablemodule.h b/include/tablemodule.h
index 8b2dccf..e07857c 100644
--- a/include/tablemodule.h
+++ b/include/tablemodule.h
@@ -1,21 +1,21 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include "Python.h"
@@ -28,6 +28,7 @@ typedef struct {
     int size;
     double samplingRate;
     MYFLT *data;
+    Py_ssize_t shape[1]; /* 1-dimension array (must be set to table size) needed by the buffer protocol. */
 } TableStream;
 
 
@@ -44,4 +45,4 @@ double TableStream_getSamplingRate(PyObject *self);
 MYFLT * TableStream_getData(PyObject *self);
 extern PyTypeObject TableStreamType;
 
-#endif
+#endif
\ No newline at end of file
diff --git a/include/wind.h b/include/wind.h
index c7c939b..bc3658d 100644
--- a/include/wind.h
+++ b/include/wind.h
@@ -1,21 +1,21 @@
-/*************************************************************************
- * Copyright 2011 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *                                                                        *
  * Envelope window generator :                                            *
  *      0 : Rectangular (no window)                                       *
@@ -28,10 +28,10 @@
  *      7 : Tuckey (alpha = 0.66)                                         *
  *      8 : Sine (half-sine window)                                       *
  *************************************************************************/
+
 #include "pyomodule.h"
- 
+
 #ifndef _WIND_
 #define _WIND_
 void gen_window(MYFLT *window, int size, int wintype);
 #endif
-
diff --git a/installers/osx/PkgResources_i386/License.rtf b/installers/osx/PkgResources_i386/License.rtf
deleted file mode 100755
index 66b2d2a..0000000
--- a/installers/osx/PkgResources_i386/License.rtf
+++ /dev/null
@@ -1,681 +0,0 @@
-{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360
-{\fonttbl\f0\fnil\fcharset0 LucidaGrande;}
-{\colortbl;\red255\green255\blue255;}
-\margl1440\margr1440\vieww10100\viewh11340\viewkind0
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
-
-\f0\fs26 \cf0                     GNU GENERAL PUBLIC LICENSE\
-                       Version 3, 29 June 2007\
-\
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\
- Everyone is permitted to copy and distribute verbatim copies\
- of this license document, but changing it is not allowed.\
-\
-                            Preamble\
-\
-  The GNU General Public License is a free, copyleft license for\
-software and other kinds of works.\
-\
-  The licenses for most software and other practical works are designed\
-to take away your freedom to share and change the works.  By contrast,\
-the GNU General Public License is intended to guarantee your freedom to\
-share and change all versions of a program--to make sure it remains free\
-software for all its users.  We, the Free Software Foundation, use the\
-GNU General Public License for most of our software; it applies also to\
-any other work released this way by its authors.  You can apply it to\
-your programs, too.\
-\
-  When we speak of free software, we are referring to freedom, not\
-price.  Our General Public Licenses are designed to make sure that you\
-have the freedom to distribute copies of free software (and charge for\
-them if you wish), that you receive source code or can get it if you\
-want it, that you can change the software or use pieces of it in new\
-free programs, and that you know you can do these things.\
-\
-  To protect your rights, we need to prevent others from denying you\
-these rights or asking you to surrender the rights.  Therefore, you have\
-certain responsibilities if you distribute copies of the software, or if\
-you modify it: responsibilities to respect the freedom of others.\
-\
-  For example, if you distribute copies of such a program, whether\
-gratis or for a fee, you must pass on to the recipients the same\
-freedoms that you received.  You must make sure that they, too, receive\
-or can get the source code.  And you must show them these terms so they\
-know their rights.\
-\
-  Developers that use the GNU GPL protect your rights with two steps:\
-(1) assert copyright on the software, and (2) offer you this License\
-giving you legal permission to copy, distribute and/or modify it.\
-\
-  For the developers' and authors' protection, the GPL clearly explains\
-that there is no warranty for this free software.  For both users' and\
-authors' sake, the GPL requires that modified versions be marked as\
-changed, so that their problems will not be attributed erroneously to\
-authors of previous versions.\
-\
-  Some devices are designed to deny users access to install or run\
-modified versions of the software inside them, although the manufacturer\
-can do so.  This is fundamentally incompatible with the aim of\
-protecting users' freedom to change the software.  The systematic\
-pattern of such abuse occurs in the area of products for individuals to\
-use, which is precisely where it is most unacceptable.  Therefore, we\
-have designed this version of the GPL to prohibit the practice for those\
-products.  If such problems arise substantially in other domains, we\
-stand ready to extend this provision to those domains in future versions\
-of the GPL, as needed to protect the freedom of users.\
-\
-  Finally, every program is threatened constantly by software patents.\
-States should not allow patents to restrict development and use of\
-software on general-purpose computers, but in those that do, we wish to\
-avoid the special danger that patents applied to a free program could\
-make it effectively proprietary.  To prevent this, the GPL assures that\
-patents cannot be used to render the program non-free.\
-\
-  The precise terms and conditions for copying, distribution and\
-modification follow.\
-\
-                       TERMS AND CONDITIONS\
-\
-  0. Definitions.\
-\
-  "This License" refers to version 3 of the GNU General Public License.\
-\
-  "Copyright" also means copyright-like laws that apply to other kinds of\
-works, such as semiconductor masks.\
-\
-  "The Program" refers to any copyrightable work licensed under this\
-License.  Each licensee is addressed as "you".  "Licensees" and\
-"recipients" may be individuals or organizations.\
-\
-  To "modify" a work means to copy from or adapt all or part of the work\
-in a fashion requiring copyright permission, other than the making of an\
-exact copy.  The resulting work is called a "modified version" of the\
-earlier work or a work "based on" the earlier work.\
-\
-  A "covered work" means either the unmodified Program or a work based\
-on the Program.\
-\
-  To "propagate" a work means to do anything with it that, without\
-permission, would make you directly or secondarily liable for\
-infringement under applicable copyright law, except executing it on a\
-computer or modifying a private copy.  Propagation includes copying,\
-distribution (with or without modification), making available to the\
-public, and in some countries other activities as well.\
-\
-  To "convey" a work means any kind of propagation that enables other\
-parties to make or receive copies.  Mere interaction with a user through\
-a computer network, with no transfer of a copy, is not conveying.\
-\
-  An interactive user interface displays "Appropriate Legal Notices"\
-to the extent that it includes a convenient and prominently visible\
-feature that (1) displays an appropriate copyright notice, and (2)\
-tells the user that there is no warranty for the work (except to the\
-extent that warranties are provided), that licensees may convey the\
-work under this License, and how to view a copy of this License.  If\
-the interface presents a list of user commands or options, such as a\
-menu, a prominent item in the list meets this criterion.\
-\
-  1. Source Code.\
-\
-  The "source code" for a work means the preferred form of the work\
-for making modifications to it.  "Object code" means any non-source\
-form of a work.\
-\
-  A "Standard Interface" means an interface that either is an official\
-standard defined by a recognized standards body, or, in the case of\
-interfaces specified for a particular programming language, one that\
-is widely used among developers working in that language.\
-\
-  The "System Libraries" of an executable work include anything, other\
-than the work as a whole, that (a) is included in the normal form of\
-packaging a Major Component, but which is not part of that Major\
-Component, and (b) serves only to enable use of the work with that\
-Major Component, or to implement a Standard Interface for which an\
-implementation is available to the public in source code form.  A\
-"Major Component", in this context, means a major essential component\
-(kernel, window system, and so on) of the specific operating system\
-(if any) on which the executable work runs, or a compiler used to\
-produce the work, or an object code interpreter used to run it.\
-\
-  The "Corresponding Source" for a work in object code form means all\
-the source code needed to generate, install, and (for an executable\
-work) run the object code and to modify the work, including scripts to\
-control those activities.  However, it does not include the work's\
-System Libraries, or general-purpose tools or generally available free\
-programs which are used unmodified in performing those activities but\
-which are not part of the work.  For example, Corresponding Source\
-includes interface definition files associated with source files for\
-the work, and the source code for shared libraries and dynamically\
-linked subprograms that the work is specifically designed to require,\
-such as by intimate data communication or control flow between those\
-subprograms and other parts of the work.\
-\
-  The Corresponding Source need not include anything that users\
-can regenerate automatically from other parts of the Corresponding\
-Source.\
-\
-  The Corresponding Source for a work in source code form is that\
-same work.\
-\
-  2. Basic Permissions.\
-\
-  All rights granted under this License are granted for the term of\
-copyright on the Program, and are irrevocable provided the stated\
-conditions are met.  This License explicitly affirms your unlimited\
-permission to run the unmodified Program.  The output from running a\
-covered work is covered by this License only if the output, given its\
-content, constitutes a covered work.  This License acknowledges your\
-rights of fair use or other equivalent, as provided by copyright law.\
-\
-  You may make, run and propagate covered works that you do not\
-convey, without conditions so long as your license otherwise remains\
-in force.  You may convey covered works to others for the sole purpose\
-of having them make modifications exclusively for you, or provide you\
-with facilities for running those works, provided that you comply with\
-the terms of this License in conveying all material for which you do\
-not control copyright.  Those thus making or running the covered works\
-for you must do so exclusively on your behalf, under your direction\
-and control, on terms that prohibit them from making any copies of\
-your copyrighted material outside their relationship with you.\
-\
-  Conveying under any other circumstances is permitted solely under\
-the conditions stated below.  Sublicensing is not allowed; section 10\
-makes it unnecessary.\
-\
-  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\
-\
-  No covered work shall be deemed part of an effective technological\
-measure under any applicable law fulfilling obligations under article\
-11 of the WIPO copyright treaty adopted on 20 December 1996, or\
-similar laws prohibiting or restricting circumvention of such\
-measures.\
-\
-  When you convey a covered work, you waive any legal power to forbid\
-circumvention of technological measures to the extent such circumvention\
-is effected by exercising rights under this License with respect to\
-the covered work, and you disclaim any intention to limit operation or\
-modification of the work as a means of enforcing, against the work's\
-users, your or third parties' legal rights to forbid circumvention of\
-technological measures.\
-\
-  4. Conveying Verbatim Copies.\
-\
-  You may convey verbatim copies of the Program's source code as you\
-receive it, in any medium, provided that you conspicuously and\
-appropriately publish on each copy an appropriate copyright notice;\
-keep intact all notices stating that this License and any\
-non-permissive terms added in accord with section 7 apply to the code;\
-keep intact all notices of the absence of any warranty; and give all\
-recipients a copy of this License along with the Program.\
-\
-  You may charge any price or no price for each copy that you convey,\
-and you may offer support or warranty protection for a fee.\
-\
-  5. Conveying Modified Source Versions.\
-\
-  You may convey a work based on the Program, or the modifications to\
-produce it from the Program, in the form of source code under the\
-terms of section 4, provided that you also meet all of these conditions:\
-\
-    a) The work must carry prominent notices stating that you modified\
-    it, and giving a relevant date.\
-\
-    b) The work must carry prominent notices stating that it is\
-    released under this License and any conditions added under section\
-    7.  This requirement modifies the requirement in section 4 to\
-    "keep intact all notices".\
-\
-    c) You must license the entire work, as a whole, under this\
-    License to anyone who comes into possession of a copy.  This\
-    License will therefore apply, along with any applicable section 7\
-    additional terms, to the whole of the work, and all its parts,\
-    regardless of how they are packaged.  This License gives no\
-    permission to license the work in any other way, but it does not\
-    invalidate such permission if you have separately received it.\
-\
-    d) If the work has interactive user interfaces, each must display\
-    Appropriate Legal Notices; however, if the Program has interactive\
-    interfaces that do not display Appropriate Legal Notices, your\
-    work need not make them do so.\
-\
-  A compilation of a covered work with other separate and independent\
-works, which are not by their nature extensions of the covered work,\
-and which are not combined with it such as to form a larger program,\
-in or on a volume of a storage or distribution medium, is called an\
-"aggregate" if the compilation and its resulting copyright are not\
-used to limit the access or legal rights of the compilation's users\
-beyond what the individual works permit.  Inclusion of a covered work\
-in an aggregate does not cause this License to apply to the other\
-parts of the aggregate.\
-\
-  6. Conveying Non-Source Forms.\
-\
-  You may convey a covered work in object code form under the terms\
-of sections 4 and 5, provided that you also convey the\
-machine-readable Corresponding Source under the terms of this License,\
-in one of these ways:\
-\
-    a) Convey the object code in, or embodied in, a physical product\
-    (including a physical distribution medium), accompanied by the\
-    Corresponding Source fixed on a durable physical medium\
-    customarily used for software interchange.\
-\
-    b) Convey the object code in, or embodied in, a physical product\
-    (including a physical distribution medium), accompanied by a\
-    written offer, valid for at least three years and valid for as\
-    long as you offer spare parts or customer support for that product\
-    model, to give anyone who possesses the object code either (1) a\
-    copy of the Corresponding Source for all the software in the\
-    product that is covered by this License, on a durable physical\
-    medium customarily used for software interchange, for a price no\
-    more than your reasonable cost of physically performing this\
-    conveying of source, or (2) access to copy the\
-    Corresponding Source from a network server at no charge.\
-\
-    c) Convey individual copies of the object code with a copy of the\
-    written offer to provide the Corresponding Source.  This\
-    alternative is allowed only occasionally and noncommercially, and\
-    only if you received the object code with such an offer, in accord\
-    with subsection 6b.\
-\
-    d) Convey the object code by offering access from a designated\
-    place (gratis or for a charge), and offer equivalent access to the\
-    Corresponding Source in the same way through the same place at no\
-    further charge.  You need not require recipients to copy the\
-    Corresponding Source along with the object code.  If the place to\
-    copy the object code is a network server, the Corresponding Source\
-    may be on a different server (operated by you or a third party)\
-    that supports equivalent copying facilities, provided you maintain\
-    clear directions next to the object code saying where to find the\
-    Corresponding Source.  Regardless of what server hosts the\
-    Corresponding Source, you remain obligated to ensure that it is\
-    available for as long as needed to satisfy these requirements.\
-\
-    e) Convey the object code using peer-to-peer transmission, provided\
-    you inform other peers where the object code and Corresponding\
-    Source of the work are being offered to the general public at no\
-    charge under subsection 6d.\
-\
-  A separable portion of the object code, whose source code is excluded\
-from the Corresponding Source as a System Library, need not be\
-included in conveying the object code work.\
-\
-  A "User Product" is either (1) a "consumer product", which means any\
-tangible personal property which is normally used for personal, family,\
-or household purposes, or (2) anything designed or sold for incorporation\
-into a dwelling.  In determining whether a product is a consumer product,\
-doubtful cases shall be resolved in favor of coverage.  For a particular\
-product received by a particular user, "normally used" refers to a\
-typical or common use of that class of product, regardless of the status\
-of the particular user or of the way in which the particular user\
-actually uses, or expects or is expected to use, the product.  A product\
-is a consumer product regardless of whether the product has substantial\
-commercial, industrial or non-consumer uses, unless such uses represent\
-the only significant mode of use of the product.\
-\
-  "Installation Information" for a User Product means any methods,\
-procedures, authorization keys, or other information required to install\
-and execute modified versions of a covered work in that User Product from\
-a modified version of its Corresponding Source.  The information must\
-suffice to ensure that the continued functioning of the modified object\
-code is in no case prevented or interfered with solely because\
-modification has been made.\
-\
-  If you convey an object code work under this section in, or with, or\
-specifically for use in, a User Product, and the conveying occurs as\
-part of a transaction in which the right of possession and use of the\
-User Product is transferred to the recipient in perpetuity or for a\
-fixed term (regardless of how the transaction is characterized), the\
-Corresponding Source conveyed under this section must be accompanied\
-by the Installation Information.  But this requirement does not apply\
-if neither you nor any third party retains the ability to install\
-modified object code on the User Product (for example, the work has\
-been installed in ROM).\
-\
-  The requirement to provide Installation Information does not include a\
-requirement to continue to provide support service, warranty, or updates\
-for a work that has been modified or installed by the recipient, or for\
-the User Product in which it has been modified or installed.  Access to a\
-network may be denied when the modification itself materially and\
-adversely affects the operation of the network or violates the rules and\
-protocols for communication across the network.\
-\
-  Corresponding Source conveyed, and Installation Information provided,\
-in accord with this section must be in a format that is publicly\
-documented (and with an implementation available to the public in\
-source code form), and must require no special password or key for\
-unpacking, reading or copying.\
-\
-  7. Additional Terms.\
-\
-  "Additional permissions" are terms that supplement the terms of this\
-License by making exceptions from one or more of its conditions.\
-Additional permissions that are applicable to the entire Program shall\
-be treated as though they were included in this License, to the extent\
-that they are valid under applicable law.  If additional permissions\
-apply only to part of the Program, that part may be used separately\
-under those permissions, but the entire Program remains governed by\
-this License without regard to the additional permissions.\
-\
-  When you convey a copy of a covered work, you may at your option\
-remove any additional permissions from that copy, or from any part of\
-it.  (Additional permissions may be written to require their own\
-removal in certain cases when you modify the work.)  You may place\
-additional permissions on material, added by you to a covered work,\
-for which you have or can give appropriate copyright permission.\
-\
-  Notwithstanding any other provision of this License, for material you\
-add to a covered work, you may (if authorized by the copyright holders of\
-that material) supplement the terms of this License with terms:\
-\
-    a) Disclaiming warranty or limiting liability differently from the\
-    terms of sections 15 and 16 of this License; or\
-\
-    b) Requiring preservation of specified reasonable legal notices or\
-    author attributions in that material or in the Appropriate Legal\
-    Notices displayed by works containing it; or\
-\
-    c) Prohibiting misrepresentation of the origin of that material, or\
-    requiring that modified versions of such material be marked in\
-    reasonable ways as different from the original version; or\
-\
-    d) Limiting the use for publicity purposes of names of licensors or\
-    authors of the material; or\
-\
-    e) Declining to grant rights under trademark law for use of some\
-    trade names, trademarks, or service marks; or\
-\
-    f) Requiring indemnification of licensors and authors of that\
-    material by anyone who conveys the material (or modified versions of\
-    it) with contractual assumptions of liability to the recipient, for\
-    any liability that these contractual assumptions directly impose on\
-    those licensors and authors.\
-\
-  All other non-permissive additional terms are considered "further\
-restrictions" within the meaning of section 10.  If the Program as you\
-received it, or any part of it, contains a notice stating that it is\
-governed by this License along with a term that is a further\
-restriction, you may remove that term.  If a license document contains\
-a further restriction but permits relicensing or conveying under this\
-License, you may add to a covered work material governed by the terms\
-of that license document, provided that the further restriction does\
-not survive such relicensing or conveying.\
-\
-  If you add terms to a covered work in accord with this section, you\
-must place, in the relevant source files, a statement of the\
-additional terms that apply to those files, or a notice indicating\
-where to find the applicable terms.\
-\
-  Additional terms, permissive or non-permissive, may be stated in the\
-form of a separately written license, or stated as exceptions;\
-the above requirements apply either way.\
-\
-  8. Termination.\
-\
-  You may not propagate or modify a covered work except as expressly\
-provided under this License.  Any attempt otherwise to propagate or\
-modify it is void, and will automatically terminate your rights under\
-this License (including any patent licenses granted under the third\
-paragraph of section 11).\
-\
-  However, if you cease all violation of this License, then your\
-license from a particular copyright holder is reinstated (a)\
-provisionally, unless and until the copyright holder explicitly and\
-finally terminates your license, and (b) permanently, if the copyright\
-holder fails to notify you of the violation by some reasonable means\
-prior to 60 days after the cessation.\
-\
-  Moreover, your license from a particular copyright holder is\
-reinstated permanently if the copyright holder notifies you of the\
-violation by some reasonable means, this is the first time you have\
-received notice of violation of this License (for any work) from that\
-copyright holder, and you cure the violation prior to 30 days after\
-your receipt of the notice.\
-\
-  Termination of your rights under this section does not terminate the\
-licenses of parties who have received copies or rights from you under\
-this License.  If your rights have been terminated and not permanently\
-reinstated, you do not qualify to receive new licenses for the same\
-material under section 10.\
-\
-  9. Acceptance Not Required for Having Copies.\
-\
-  You are not required to accept this License in order to receive or\
-run a copy of the Program.  Ancillary propagation of a covered work\
-occurring solely as a consequence of using peer-to-peer transmission\
-to receive a copy likewise does not require acceptance.  However,\
-nothing other than this License grants you permission to propagate or\
-modify any covered work.  These actions infringe copyright if you do\
-not accept this License.  Therefore, by modifying or propagating a\
-covered work, you indicate your acceptance of this License to do so.\
-\
-  10. Automatic Licensing of Downstream Recipients.\
-\
-  Each time you convey a covered work, the recipient automatically\
-receives a license from the original licensors, to run, modify and\
-propagate that work, subject to this License.  You are not responsible\
-for enforcing compliance by third parties with this License.\
-\
-  An "entity transaction" is a transaction transferring control of an\
-organization, or substantially all assets of one, or subdividing an\
-organization, or merging organizations.  If propagation of a covered\
-work results from an entity transaction, each party to that\
-transaction who receives a copy of the work also receives whatever\
-licenses to the work the party's predecessor in interest had or could\
-give under the previous paragraph, plus a right to possession of the\
-Corresponding Source of the work from the predecessor in interest, if\
-the predecessor has it or can get it with reasonable efforts.\
-\
-  You may not impose any further restrictions on the exercise of the\
-rights granted or affirmed under this License.  For example, you may\
-not impose a license fee, royalty, or other charge for exercise of\
-rights granted under this License, and you may not initiate litigation\
-(including a cross-claim or counterclaim in a lawsuit) alleging that\
-any patent claim is infringed by making, using, selling, offering for\
-sale, or importing the Program or any portion of it.\
-\
-  11. Patents.\
-\
-  A "contributor" is a copyright holder who authorizes use under this\
-License of the Program or a work on which the Program is based.  The\
-work thus licensed is called the contributor's "contributor version".\
-\
-  A contributor's "essential patent claims" are all patent claims\
-owned or controlled by the contributor, whether already acquired or\
-hereafter acquired, that would be infringed by some manner, permitted\
-by this License, of making, using, or selling its contributor version,\
-but do not include claims that would be infringed only as a\
-consequence of further modification of the contributor version.  For\
-purposes of this definition, "control" includes the right to grant\
-patent sublicenses in a manner consistent with the requirements of\
-this License.\
-\
-  Each contributor grants you a non-exclusive, worldwide, royalty-free\
-patent license under the contributor's essential patent claims, to\
-make, use, sell, offer for sale, import and otherwise run, modify and\
-propagate the contents of its contributor version.\
-\
-  In the following three paragraphs, a "patent license" is any express\
-agreement or commitment, however denominated, not to enforce a patent\
-(such as an express permission to practice a patent or covenant not to\
-sue for patent infringement).  To "grant" such a patent license to a\
-party means to make such an agreement or commitment not to enforce a\
-patent against the party.\
-\
-  If you convey a covered work, knowingly relying on a patent license,\
-and the Corresponding Source of the work is not available for anyone\
-to copy, free of charge and under the terms of this License, through a\
-publicly available network server or other readily accessible means,\
-then you must either (1) cause the Corresponding Source to be so\
-available, or (2) arrange to deprive yourself of the benefit of the\
-patent license for this particular work, or (3) arrange, in a manner\
-consistent with the requirements of this License, to extend the patent\
-license to downstream recipients.  "Knowingly relying" means you have\
-actual knowledge that, but for the patent license, your conveying the\
-covered work in a country, or your recipient's use of the covered work\
-in a country, would infringe one or more identifiable patents in that\
-country that you have reason to believe are valid.\
-\
-  If, pursuant to or in connection with a single transaction or\
-arrangement, you convey, or propagate by procuring conveyance of, a\
-covered work, and grant a patent license to some of the parties\
-receiving the covered work authorizing them to use, propagate, modify\
-or convey a specific copy of the covered work, then the patent license\
-you grant is automatically extended to all recipients of the covered\
-work and works based on it.\
-\
-  A patent license is "discriminatory" if it does not include within\
-the scope of its coverage, prohibits the exercise of, or is\
-conditioned on the non-exercise of one or more of the rights that are\
-specifically granted under this License.  You may not convey a covered\
-work if you are a party to an arrangement with a third party that is\
-in the business of distributing software, under which you make payment\
-to the third party based on the extent of your activity of conveying\
-the work, and under which the third party grants, to any of the\
-parties who would receive the covered work from you, a discriminatory\
-patent license (a) in connection with copies of the covered work\
-conveyed by you (or copies made from those copies), or (b) primarily\
-for and in connection with specific products or compilations that\
-contain the covered work, unless you entered into that arrangement,\
-or that patent license was granted, prior to 28 March 2007.\
-\
-  Nothing in this License shall be construed as excluding or limiting\
-any implied license or other defenses to infringement that may\
-otherwise be available to you under applicable patent law.\
-\
-  12. No Surrender of Others' Freedom.\
-\
-  If conditions are imposed on you (whether by court order, agreement or\
-otherwise) that contradict the conditions of this License, they do not\
-excuse you from the conditions of this License.  If you cannot convey a\
-covered work so as to satisfy simultaneously your obligations under this\
-License and any other pertinent obligations, then as a consequence you may\
-not convey it at all.  For example, if you agree to terms that obligate you\
-to collect a royalty for further conveying from those to whom you convey\
-the Program, the only way you could satisfy both those terms and this\
-License would be to refrain entirely from conveying the Program.\
-\
-  13. Use with the GNU Affero General Public License.\
-\
-  Notwithstanding any other provision of this License, you have\
-permission to link or combine any covered work with a work licensed\
-under version 3 of the GNU Affero General Public License into a single\
-combined work, and to convey the resulting work.  The terms of this\
-License will continue to apply to the part which is the covered work,\
-but the special requirements of the GNU Affero General Public License,\
-section 13, concerning interaction through a network will apply to the\
-combination as such.\
-\
-  14. Revised Versions of this License.\
-\
-  The Free Software Foundation may publish revised and/or new versions of\
-the GNU General Public License from time to time.  Such new versions will\
-be similar in spirit to the present version, but may differ in detail to\
-address new problems or concerns.\
-\
-  Each version is given a distinguishing version number.  If the\
-Program specifies that a certain numbered version of the GNU General\
-Public License "or any later version" applies to it, you have the\
-option of following the terms and conditions either of that numbered\
-version or of any later version published by the Free Software\
-Foundation.  If the Program does not specify a version number of the\
-GNU General Public License, you may choose any version ever published\
-by the Free Software Foundation.\
-\
-  If the Program specifies that a proxy can decide which future\
-versions of the GNU General Public License can be used, that proxy's\
-public statement of acceptance of a version permanently authorizes you\
-to choose that version for the Program.\
-\
-  Later license versions may give you additional or different\
-permissions.  However, no additional obligations are imposed on any\
-author or copyright holder as a result of your choosing to follow a\
-later version.\
-\
-  15. Disclaimer of Warranty.\
-\
-  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\
-APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY\
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\
-IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\
-\
-  16. Limitation of Liability.\
-\
-  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\
-SUCH DAMAGES.\
-\
-  17. Interpretation of Sections 15 and 16.\
-\
-  If the disclaimer of warranty and limitation of liability provided\
-above cannot be given local legal effect according to their terms,\
-reviewing courts shall apply local law that most closely approximates\
-an absolute waiver of all civil liability in connection with the\
-Program, unless a warranty or assumption of liability accompanies a\
-copy of the Program in return for a fee.\
-\
-                     END OF TERMS AND CONDITIONS\
-\
-            How to Apply These Terms to Your New Programs\
-\
-  If you develop a new program, and you want it to be of the greatest\
-possible use to the public, the best way to achieve this is to make it\
-free software which everyone can redistribute and change under these terms.\
-\
-  To do so, attach the following notices to the program.  It is safest\
-to attach them to the start of each source file to most effectively\
-state the exclusion of warranty; and each file should have at least\
-the "copyright" line and a pointer to where the full notice is found.\
-\
-    <one line to give the program's name and a brief idea of what it does.>\
-    Copyright (C) <year>  <name of author>\
-\
-    This program is free software: you can redistribute it and/or modify\
-    it under the terms of the GNU General Public License as published by\
-    the Free Software Foundation, either version 3 of the License, or\
-    (at your option) any later version.\
-\
-    This program is distributed in the hope that it will be useful,\
-    but WITHOUT ANY WARRANTY; without even the implied warranty of\
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\
-    GNU General Public License for more details.\
-\
-    You should have received a copy of the GNU General Public License\
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.\
-\
-Also add information on how to contact you by electronic and paper mail.\
-\
-  If the program does terminal interaction, make it output a short\
-notice like this when it starts in an interactive mode:\
-\
-    <program>  Copyright (C) <year>  <name of author>\
-    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\
-    This is free software, and you are welcome to redistribute it\
-    under certain conditions; type `show c' for details.\
-\
-The hypothetical commands `show w' and `show c' should show the appropriate\
-parts of the General Public License.  Of course, your program's commands\
-might be different; for a GUI interface, you would use an "about box".\
-\
-  You should also get your employer (if you work as a programmer) or school,\
-if any, to sign a "copyright disclaimer" for the program, if necessary.\
-For more information on this, and how to apply and follow the GNU GPL, see\
-<http://www.gnu.org/licenses/>.\
-\
-  The GNU General Public License does not permit incorporating your program\
-into proprietary programs.  If your program is a subroutine library, you\
-may consider it more useful to permit linking proprietary applications with\
-the library.  If this is what you want to do, use the GNU Lesser General\
-Public License instead of this License.  But first, please read\
-<http://www.gnu.org/philosophy/why-not-lgpl.html>.\
-}
\ No newline at end of file
diff --git a/installers/osx/PkgResources_i386/ReadMe.rtf b/installers/osx/PkgResources_i386/ReadMe.rtf
deleted file mode 100755
index da986d8..0000000
--- a/installers/osx/PkgResources_i386/ReadMe.rtf
+++ /dev/null
@@ -1,71 +0,0 @@
-{\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\fcharset1 LucidaGrande;}{\f6\froman\fprq0\fcharset1 LucidaGrande;}{\f7\fnil\fprq2\fcharset0 DejaVu Sans;}{\f8\fnil\fprq2\fcharset0 Lohit Hindi;}{\f9\fnil\fprq0\fcharset1 Lohit Hindi;}}
-{\colortbl;\red0\green0\blue0;\red128\green128\blue128;}
-{\stylesheet{\s0\snext0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105 Normal;}
-{\s15\sbasedon0\snext16\sb240\sa120\keepn\dbch\af7\dbch\af8\afs28\loch\f4\fs28 Heading;}
-{\s16\sbasedon0\snext16\sb0\sa120 Text body;}
-{\s17\sbasedon16\snext17\sb0\sa120\dbch\af9 List;}
-{\s18\sbasedon0\snext18\sb120\sa120\noline\i\dbch\af9\afs24\ai\fs24 Caption;}
-{\s19\sbasedon0\snext19\noline\dbch\af9 Index;}
-}{\info{\creatim\yr0\mo0\dy0\hr0\min0}{\revtim\yr0\mo0\dy0\hr0\min0}{\printim\yr0\mo0\dy0\hr0\min0}{\comment LibreOffice}{\vern3600}}\deftab720
-\viewscale110
-{\*\pgdsctbl
-{\pgdsc0\pgdscuse195\pgwsxn12240\pghsxn15840\marglsxn1440\margrsxn1440\margtsxn1440\margbsxn1440\pgdscnxt0 Default;}}
-\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
-\pgndec\pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f6
-pyo (version 0.6.}{\cf1\rtlch \ltrch\loch\fs26\loch\f6
-6}{\cf1\rtlch \ltrch\loch\fs26\loch\f6
-)}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\rtlch \ltrch\loch\fs26\loch\f6
-
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f6
-This package installs all the required components to run pyo inside your current Python installation. Python 2.5, 2.6 (preferred) or 2.7 (32-bit Mac OS X Installer) must be already installed on your system.}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\rtlch \ltrch\loch\fs26\loch\f6
-
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f6
-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{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\rtlch \ltrch\loch\fs26\loch\f6
-
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b\rtlch \ltrch\loch\fs26\loch\f6
-1. pyo extension:}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-The following components will be installed in the site-packages folder of the current Python Framework:}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-_pyo.so}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-_pyo64.so}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-pyo.py}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-pyo64.py}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-pyolib (folder)}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b\rtlch \ltrch\loch\fs26\loch\f6
-2. Support libraries (i386):}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-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{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b\rtlch \ltrch\loch\fs26\loch\f6
-Warning:}{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
- 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{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-liblo.0.dylib}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-libportaudio.2.dylib}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-libportmidi.dylib}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-libsndfile.1.dylib}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-Olivier B\u233\'e9langer, 201}{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-3}
-\par }
\ No newline at end of file
diff --git a/installers/osx/PkgResources_i386/postinstall b/installers/osx/PkgResources_i386/postinstall
deleted file mode 100755
index 21e721a..0000000
--- a/installers/osx/PkgResources_i386/postinstall
+++ /dev/null
@@ -1,106 +0,0 @@
-#! /bin/sh
-
-VERSION=`sw_vers -productVersion | sed -e 's/\.//g'`
-
-if [ $VERSION -ge '1070' ]; then
-    echo "Install pyo on OSX 10.7";
-elif [ $VERSION -ge '1060' ]; then
-    echo "Install pyo on OSX 10.6";
-else
-    echo "Install pyo on OSX 10.5";
-fi
-
-# Removed older versions in the python site-packages builtin directories
-# Removed older versions in the python site-packages from python.org install directories
-PATHS=/Library/Python/2.5/site-packages/:/Library/Python/2.6/site-packages/:/Library/Python/2.7/site-packages/:/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/site-packages/:/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/:/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/
-for path in ${PATHS//:/ }; do
-    if cd $path; then
-        if [ -f pyo.py ]; then
-            sudo rm pyo.py;
-        fi    
-        if [ -f pyo64.py ]; then
-            sudo rm pyo64.py;
-        fi    
-        if [ -f pyo.pyc ]; then
-            sudo rm pyo.pyc;
-        fi    
-        if [ -f pyo64.pyc ]; then
-            sudo rm pyo64.pyc;
-        fi    
-        if [ -f _pyo.so ]; then
-            sudo rm _pyo.so;
-        fi    
-        if [ -f _pyo64.so ]; then
-            sudo rm _pyo64.so;
-        fi    
-        if [ -d pyolib ]; then
-            sudo rm -rf pyolib/;
-        fi    
-        ls -1 pyo*-info > /dev/null 2>&1
-        if [ "$?" = "0" ]; then
-            sudo rm pyo*-info;
-        fi    
-    fi
-done
-
-# Install pyo in the python site-packages builtin directories
-if [ $VERSION -ge '1070' ]; then
-    if cd /Library/Python/2.7/site-packages/; then
-        sudo cp -r /tmp/python27/* .
-    else
-        sudo mkdir -p /Library/Python/2.7/site-packages/
-        cd /Library/Python/2.7/site-packages/
-        sudo cp -r /tmp/python27/* .
-    fi
-else
-    if cd /Library/Python/2.6/site-packages/; then
-        sudo cp -r /tmp/python26/* .
-    else
-        sudo mkdir -p /Library/Python/2.6/site-packages/
-        cd /Library/Python/2.6/site-packages/
-        sudo cp -r /tmp/python26/* .
-    fi
-fi
-
-# Install pyo in the python site-packages from python.org install directories
-if cd /Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/; then
-    sudo cp -r /tmp/python26/* .
-else
-    sudo mkdir -p /Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/
-    cd /Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/
-    sudo cp -r /tmp/python26/* .
-fi
-
-if cd /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/; then  
-    sudo cp -r /tmp/python27/* .
-else
-    sudo mkdir -p /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/
-    cd /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/
-    sudo cp -r /tmp/python27/* .
-fi
-
-sudo rm -rf /tmp/python2*
-
-# Add /usr/local/lib in .bash_profile if not already done
-searchString="/usr/local/lib"
-
-if [ -f ~/.bash_profile ]; then
-    if `cat ~/.bash_profile | grep "${searchString}" 1>/dev/null 2>&1`; then
-        echo "path already in PATH variable";
-    else
-        echo "adding path to .bash_profile..."
-        echo "export PATH=/usr/local/lib:/usr/local/bin:\$PATH" >> ~/.bash_profile;
-    fi
-else
-    echo "creating .bash_profile and adding path to it..."
-	echo "export PATH=/usr/local/lib:/usr/local/bin:\$PATH" > ~/.bash_profile;
-fi	
-
-# Add VERSIONER_PYTHON_PREFER_32_BIT in .bash_profile if not already done
-searchString="VERSIONER_PYTHON_PREFER_32_BIT"
-
-if `cat ~/.bash_profile | grep "${searchString}" 1>/dev/null 2>&1`; then
-    echo "Variable VERSIONER_PYTHON_PREFER_32_BIT already set.";
-else
-    echo "export VERSIONER_PYTHON_PREFER_32_BIT=yes" >> ~/.bash_profile;
-fi
diff --git a/installers/osx/PkgResources_i386/postupgrade b/installers/osx/PkgResources_i386/postupgrade
deleted file mode 100755
index 21e721a..0000000
--- a/installers/osx/PkgResources_i386/postupgrade
+++ /dev/null
@@ -1,106 +0,0 @@
-#! /bin/sh
-
-VERSION=`sw_vers -productVersion | sed -e 's/\.//g'`
-
-if [ $VERSION -ge '1070' ]; then
-    echo "Install pyo on OSX 10.7";
-elif [ $VERSION -ge '1060' ]; then
-    echo "Install pyo on OSX 10.6";
-else
-    echo "Install pyo on OSX 10.5";
-fi
-
-# Removed older versions in the python site-packages builtin directories
-# Removed older versions in the python site-packages from python.org install directories
-PATHS=/Library/Python/2.5/site-packages/:/Library/Python/2.6/site-packages/:/Library/Python/2.7/site-packages/:/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/site-packages/:/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/:/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/
-for path in ${PATHS//:/ }; do
-    if cd $path; then
-        if [ -f pyo.py ]; then
-            sudo rm pyo.py;
-        fi    
-        if [ -f pyo64.py ]; then
-            sudo rm pyo64.py;
-        fi    
-        if [ -f pyo.pyc ]; then
-            sudo rm pyo.pyc;
-        fi    
-        if [ -f pyo64.pyc ]; then
-            sudo rm pyo64.pyc;
-        fi    
-        if [ -f _pyo.so ]; then
-            sudo rm _pyo.so;
-        fi    
-        if [ -f _pyo64.so ]; then
-            sudo rm _pyo64.so;
-        fi    
-        if [ -d pyolib ]; then
-            sudo rm -rf pyolib/;
-        fi    
-        ls -1 pyo*-info > /dev/null 2>&1
-        if [ "$?" = "0" ]; then
-            sudo rm pyo*-info;
-        fi    
-    fi
-done
-
-# Install pyo in the python site-packages builtin directories
-if [ $VERSION -ge '1070' ]; then
-    if cd /Library/Python/2.7/site-packages/; then
-        sudo cp -r /tmp/python27/* .
-    else
-        sudo mkdir -p /Library/Python/2.7/site-packages/
-        cd /Library/Python/2.7/site-packages/
-        sudo cp -r /tmp/python27/* .
-    fi
-else
-    if cd /Library/Python/2.6/site-packages/; then
-        sudo cp -r /tmp/python26/* .
-    else
-        sudo mkdir -p /Library/Python/2.6/site-packages/
-        cd /Library/Python/2.6/site-packages/
-        sudo cp -r /tmp/python26/* .
-    fi
-fi
-
-# Install pyo in the python site-packages from python.org install directories
-if cd /Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/; then
-    sudo cp -r /tmp/python26/* .
-else
-    sudo mkdir -p /Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/
-    cd /Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/
-    sudo cp -r /tmp/python26/* .
-fi
-
-if cd /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/; then  
-    sudo cp -r /tmp/python27/* .
-else
-    sudo mkdir -p /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/
-    cd /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/
-    sudo cp -r /tmp/python27/* .
-fi
-
-sudo rm -rf /tmp/python2*
-
-# Add /usr/local/lib in .bash_profile if not already done
-searchString="/usr/local/lib"
-
-if [ -f ~/.bash_profile ]; then
-    if `cat ~/.bash_profile | grep "${searchString}" 1>/dev/null 2>&1`; then
-        echo "path already in PATH variable";
-    else
-        echo "adding path to .bash_profile..."
-        echo "export PATH=/usr/local/lib:/usr/local/bin:\$PATH" >> ~/.bash_profile;
-    fi
-else
-    echo "creating .bash_profile and adding path to it..."
-	echo "export PATH=/usr/local/lib:/usr/local/bin:\$PATH" > ~/.bash_profile;
-fi	
-
-# Add VERSIONER_PYTHON_PREFER_32_BIT in .bash_profile if not already done
-searchString="VERSIONER_PYTHON_PREFER_32_BIT"
-
-if `cat ~/.bash_profile | grep "${searchString}" 1>/dev/null 2>&1`; then
-    echo "Variable VERSIONER_PYTHON_PREFER_32_BIT already set.";
-else
-    echo "export VERSIONER_PYTHON_PREFER_32_BIT=yes" >> ~/.bash_profile;
-fi
diff --git a/installers/osx/PkgResources_x86_64/License.rtf b/installers/osx/PkgResources_x86_64/License.rtf
deleted file mode 100755
index 66b2d2a..0000000
--- a/installers/osx/PkgResources_x86_64/License.rtf
+++ /dev/null
@@ -1,681 +0,0 @@
-{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360
-{\fonttbl\f0\fnil\fcharset0 LucidaGrande;}
-{\colortbl;\red255\green255\blue255;}
-\margl1440\margr1440\vieww10100\viewh11340\viewkind0
-\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
-
-\f0\fs26 \cf0                     GNU GENERAL PUBLIC LICENSE\
-                       Version 3, 29 June 2007\
-\
- Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\
- Everyone is permitted to copy and distribute verbatim copies\
- of this license document, but changing it is not allowed.\
-\
-                            Preamble\
-\
-  The GNU General Public License is a free, copyleft license for\
-software and other kinds of works.\
-\
-  The licenses for most software and other practical works are designed\
-to take away your freedom to share and change the works.  By contrast,\
-the GNU General Public License is intended to guarantee your freedom to\
-share and change all versions of a program--to make sure it remains free\
-software for all its users.  We, the Free Software Foundation, use the\
-GNU General Public License for most of our software; it applies also to\
-any other work released this way by its authors.  You can apply it to\
-your programs, too.\
-\
-  When we speak of free software, we are referring to freedom, not\
-price.  Our General Public Licenses are designed to make sure that you\
-have the freedom to distribute copies of free software (and charge for\
-them if you wish), that you receive source code or can get it if you\
-want it, that you can change the software or use pieces of it in new\
-free programs, and that you know you can do these things.\
-\
-  To protect your rights, we need to prevent others from denying you\
-these rights or asking you to surrender the rights.  Therefore, you have\
-certain responsibilities if you distribute copies of the software, or if\
-you modify it: responsibilities to respect the freedom of others.\
-\
-  For example, if you distribute copies of such a program, whether\
-gratis or for a fee, you must pass on to the recipients the same\
-freedoms that you received.  You must make sure that they, too, receive\
-or can get the source code.  And you must show them these terms so they\
-know their rights.\
-\
-  Developers that use the GNU GPL protect your rights with two steps:\
-(1) assert copyright on the software, and (2) offer you this License\
-giving you legal permission to copy, distribute and/or modify it.\
-\
-  For the developers' and authors' protection, the GPL clearly explains\
-that there is no warranty for this free software.  For both users' and\
-authors' sake, the GPL requires that modified versions be marked as\
-changed, so that their problems will not be attributed erroneously to\
-authors of previous versions.\
-\
-  Some devices are designed to deny users access to install or run\
-modified versions of the software inside them, although the manufacturer\
-can do so.  This is fundamentally incompatible with the aim of\
-protecting users' freedom to change the software.  The systematic\
-pattern of such abuse occurs in the area of products for individuals to\
-use, which is precisely where it is most unacceptable.  Therefore, we\
-have designed this version of the GPL to prohibit the practice for those\
-products.  If such problems arise substantially in other domains, we\
-stand ready to extend this provision to those domains in future versions\
-of the GPL, as needed to protect the freedom of users.\
-\
-  Finally, every program is threatened constantly by software patents.\
-States should not allow patents to restrict development and use of\
-software on general-purpose computers, but in those that do, we wish to\
-avoid the special danger that patents applied to a free program could\
-make it effectively proprietary.  To prevent this, the GPL assures that\
-patents cannot be used to render the program non-free.\
-\
-  The precise terms and conditions for copying, distribution and\
-modification follow.\
-\
-                       TERMS AND CONDITIONS\
-\
-  0. Definitions.\
-\
-  "This License" refers to version 3 of the GNU General Public License.\
-\
-  "Copyright" also means copyright-like laws that apply to other kinds of\
-works, such as semiconductor masks.\
-\
-  "The Program" refers to any copyrightable work licensed under this\
-License.  Each licensee is addressed as "you".  "Licensees" and\
-"recipients" may be individuals or organizations.\
-\
-  To "modify" a work means to copy from or adapt all or part of the work\
-in a fashion requiring copyright permission, other than the making of an\
-exact copy.  The resulting work is called a "modified version" of the\
-earlier work or a work "based on" the earlier work.\
-\
-  A "covered work" means either the unmodified Program or a work based\
-on the Program.\
-\
-  To "propagate" a work means to do anything with it that, without\
-permission, would make you directly or secondarily liable for\
-infringement under applicable copyright law, except executing it on a\
-computer or modifying a private copy.  Propagation includes copying,\
-distribution (with or without modification), making available to the\
-public, and in some countries other activities as well.\
-\
-  To "convey" a work means any kind of propagation that enables other\
-parties to make or receive copies.  Mere interaction with a user through\
-a computer network, with no transfer of a copy, is not conveying.\
-\
-  An interactive user interface displays "Appropriate Legal Notices"\
-to the extent that it includes a convenient and prominently visible\
-feature that (1) displays an appropriate copyright notice, and (2)\
-tells the user that there is no warranty for the work (except to the\
-extent that warranties are provided), that licensees may convey the\
-work under this License, and how to view a copy of this License.  If\
-the interface presents a list of user commands or options, such as a\
-menu, a prominent item in the list meets this criterion.\
-\
-  1. Source Code.\
-\
-  The "source code" for a work means the preferred form of the work\
-for making modifications to it.  "Object code" means any non-source\
-form of a work.\
-\
-  A "Standard Interface" means an interface that either is an official\
-standard defined by a recognized standards body, or, in the case of\
-interfaces specified for a particular programming language, one that\
-is widely used among developers working in that language.\
-\
-  The "System Libraries" of an executable work include anything, other\
-than the work as a whole, that (a) is included in the normal form of\
-packaging a Major Component, but which is not part of that Major\
-Component, and (b) serves only to enable use of the work with that\
-Major Component, or to implement a Standard Interface for which an\
-implementation is available to the public in source code form.  A\
-"Major Component", in this context, means a major essential component\
-(kernel, window system, and so on) of the specific operating system\
-(if any) on which the executable work runs, or a compiler used to\
-produce the work, or an object code interpreter used to run it.\
-\
-  The "Corresponding Source" for a work in object code form means all\
-the source code needed to generate, install, and (for an executable\
-work) run the object code and to modify the work, including scripts to\
-control those activities.  However, it does not include the work's\
-System Libraries, or general-purpose tools or generally available free\
-programs which are used unmodified in performing those activities but\
-which are not part of the work.  For example, Corresponding Source\
-includes interface definition files associated with source files for\
-the work, and the source code for shared libraries and dynamically\
-linked subprograms that the work is specifically designed to require,\
-such as by intimate data communication or control flow between those\
-subprograms and other parts of the work.\
-\
-  The Corresponding Source need not include anything that users\
-can regenerate automatically from other parts of the Corresponding\
-Source.\
-\
-  The Corresponding Source for a work in source code form is that\
-same work.\
-\
-  2. Basic Permissions.\
-\
-  All rights granted under this License are granted for the term of\
-copyright on the Program, and are irrevocable provided the stated\
-conditions are met.  This License explicitly affirms your unlimited\
-permission to run the unmodified Program.  The output from running a\
-covered work is covered by this License only if the output, given its\
-content, constitutes a covered work.  This License acknowledges your\
-rights of fair use or other equivalent, as provided by copyright law.\
-\
-  You may make, run and propagate covered works that you do not\
-convey, without conditions so long as your license otherwise remains\
-in force.  You may convey covered works to others for the sole purpose\
-of having them make modifications exclusively for you, or provide you\
-with facilities for running those works, provided that you comply with\
-the terms of this License in conveying all material for which you do\
-not control copyright.  Those thus making or running the covered works\
-for you must do so exclusively on your behalf, under your direction\
-and control, on terms that prohibit them from making any copies of\
-your copyrighted material outside their relationship with you.\
-\
-  Conveying under any other circumstances is permitted solely under\
-the conditions stated below.  Sublicensing is not allowed; section 10\
-makes it unnecessary.\
-\
-  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\
-\
-  No covered work shall be deemed part of an effective technological\
-measure under any applicable law fulfilling obligations under article\
-11 of the WIPO copyright treaty adopted on 20 December 1996, or\
-similar laws prohibiting or restricting circumvention of such\
-measures.\
-\
-  When you convey a covered work, you waive any legal power to forbid\
-circumvention of technological measures to the extent such circumvention\
-is effected by exercising rights under this License with respect to\
-the covered work, and you disclaim any intention to limit operation or\
-modification of the work as a means of enforcing, against the work's\
-users, your or third parties' legal rights to forbid circumvention of\
-technological measures.\
-\
-  4. Conveying Verbatim Copies.\
-\
-  You may convey verbatim copies of the Program's source code as you\
-receive it, in any medium, provided that you conspicuously and\
-appropriately publish on each copy an appropriate copyright notice;\
-keep intact all notices stating that this License and any\
-non-permissive terms added in accord with section 7 apply to the code;\
-keep intact all notices of the absence of any warranty; and give all\
-recipients a copy of this License along with the Program.\
-\
-  You may charge any price or no price for each copy that you convey,\
-and you may offer support or warranty protection for a fee.\
-\
-  5. Conveying Modified Source Versions.\
-\
-  You may convey a work based on the Program, or the modifications to\
-produce it from the Program, in the form of source code under the\
-terms of section 4, provided that you also meet all of these conditions:\
-\
-    a) The work must carry prominent notices stating that you modified\
-    it, and giving a relevant date.\
-\
-    b) The work must carry prominent notices stating that it is\
-    released under this License and any conditions added under section\
-    7.  This requirement modifies the requirement in section 4 to\
-    "keep intact all notices".\
-\
-    c) You must license the entire work, as a whole, under this\
-    License to anyone who comes into possession of a copy.  This\
-    License will therefore apply, along with any applicable section 7\
-    additional terms, to the whole of the work, and all its parts,\
-    regardless of how they are packaged.  This License gives no\
-    permission to license the work in any other way, but it does not\
-    invalidate such permission if you have separately received it.\
-\
-    d) If the work has interactive user interfaces, each must display\
-    Appropriate Legal Notices; however, if the Program has interactive\
-    interfaces that do not display Appropriate Legal Notices, your\
-    work need not make them do so.\
-\
-  A compilation of a covered work with other separate and independent\
-works, which are not by their nature extensions of the covered work,\
-and which are not combined with it such as to form a larger program,\
-in or on a volume of a storage or distribution medium, is called an\
-"aggregate" if the compilation and its resulting copyright are not\
-used to limit the access or legal rights of the compilation's users\
-beyond what the individual works permit.  Inclusion of a covered work\
-in an aggregate does not cause this License to apply to the other\
-parts of the aggregate.\
-\
-  6. Conveying Non-Source Forms.\
-\
-  You may convey a covered work in object code form under the terms\
-of sections 4 and 5, provided that you also convey the\
-machine-readable Corresponding Source under the terms of this License,\
-in one of these ways:\
-\
-    a) Convey the object code in, or embodied in, a physical product\
-    (including a physical distribution medium), accompanied by the\
-    Corresponding Source fixed on a durable physical medium\
-    customarily used for software interchange.\
-\
-    b) Convey the object code in, or embodied in, a physical product\
-    (including a physical distribution medium), accompanied by a\
-    written offer, valid for at least three years and valid for as\
-    long as you offer spare parts or customer support for that product\
-    model, to give anyone who possesses the object code either (1) a\
-    copy of the Corresponding Source for all the software in the\
-    product that is covered by this License, on a durable physical\
-    medium customarily used for software interchange, for a price no\
-    more than your reasonable cost of physically performing this\
-    conveying of source, or (2) access to copy the\
-    Corresponding Source from a network server at no charge.\
-\
-    c) Convey individual copies of the object code with a copy of the\
-    written offer to provide the Corresponding Source.  This\
-    alternative is allowed only occasionally and noncommercially, and\
-    only if you received the object code with such an offer, in accord\
-    with subsection 6b.\
-\
-    d) Convey the object code by offering access from a designated\
-    place (gratis or for a charge), and offer equivalent access to the\
-    Corresponding Source in the same way through the same place at no\
-    further charge.  You need not require recipients to copy the\
-    Corresponding Source along with the object code.  If the place to\
-    copy the object code is a network server, the Corresponding Source\
-    may be on a different server (operated by you or a third party)\
-    that supports equivalent copying facilities, provided you maintain\
-    clear directions next to the object code saying where to find the\
-    Corresponding Source.  Regardless of what server hosts the\
-    Corresponding Source, you remain obligated to ensure that it is\
-    available for as long as needed to satisfy these requirements.\
-\
-    e) Convey the object code using peer-to-peer transmission, provided\
-    you inform other peers where the object code and Corresponding\
-    Source of the work are being offered to the general public at no\
-    charge under subsection 6d.\
-\
-  A separable portion of the object code, whose source code is excluded\
-from the Corresponding Source as a System Library, need not be\
-included in conveying the object code work.\
-\
-  A "User Product" is either (1) a "consumer product", which means any\
-tangible personal property which is normally used for personal, family,\
-or household purposes, or (2) anything designed or sold for incorporation\
-into a dwelling.  In determining whether a product is a consumer product,\
-doubtful cases shall be resolved in favor of coverage.  For a particular\
-product received by a particular user, "normally used" refers to a\
-typical or common use of that class of product, regardless of the status\
-of the particular user or of the way in which the particular user\
-actually uses, or expects or is expected to use, the product.  A product\
-is a consumer product regardless of whether the product has substantial\
-commercial, industrial or non-consumer uses, unless such uses represent\
-the only significant mode of use of the product.\
-\
-  "Installation Information" for a User Product means any methods,\
-procedures, authorization keys, or other information required to install\
-and execute modified versions of a covered work in that User Product from\
-a modified version of its Corresponding Source.  The information must\
-suffice to ensure that the continued functioning of the modified object\
-code is in no case prevented or interfered with solely because\
-modification has been made.\
-\
-  If you convey an object code work under this section in, or with, or\
-specifically for use in, a User Product, and the conveying occurs as\
-part of a transaction in which the right of possession and use of the\
-User Product is transferred to the recipient in perpetuity or for a\
-fixed term (regardless of how the transaction is characterized), the\
-Corresponding Source conveyed under this section must be accompanied\
-by the Installation Information.  But this requirement does not apply\
-if neither you nor any third party retains the ability to install\
-modified object code on the User Product (for example, the work has\
-been installed in ROM).\
-\
-  The requirement to provide Installation Information does not include a\
-requirement to continue to provide support service, warranty, or updates\
-for a work that has been modified or installed by the recipient, or for\
-the User Product in which it has been modified or installed.  Access to a\
-network may be denied when the modification itself materially and\
-adversely affects the operation of the network or violates the rules and\
-protocols for communication across the network.\
-\
-  Corresponding Source conveyed, and Installation Information provided,\
-in accord with this section must be in a format that is publicly\
-documented (and with an implementation available to the public in\
-source code form), and must require no special password or key for\
-unpacking, reading or copying.\
-\
-  7. Additional Terms.\
-\
-  "Additional permissions" are terms that supplement the terms of this\
-License by making exceptions from one or more of its conditions.\
-Additional permissions that are applicable to the entire Program shall\
-be treated as though they were included in this License, to the extent\
-that they are valid under applicable law.  If additional permissions\
-apply only to part of the Program, that part may be used separately\
-under those permissions, but the entire Program remains governed by\
-this License without regard to the additional permissions.\
-\
-  When you convey a copy of a covered work, you may at your option\
-remove any additional permissions from that copy, or from any part of\
-it.  (Additional permissions may be written to require their own\
-removal in certain cases when you modify the work.)  You may place\
-additional permissions on material, added by you to a covered work,\
-for which you have or can give appropriate copyright permission.\
-\
-  Notwithstanding any other provision of this License, for material you\
-add to a covered work, you may (if authorized by the copyright holders of\
-that material) supplement the terms of this License with terms:\
-\
-    a) Disclaiming warranty or limiting liability differently from the\
-    terms of sections 15 and 16 of this License; or\
-\
-    b) Requiring preservation of specified reasonable legal notices or\
-    author attributions in that material or in the Appropriate Legal\
-    Notices displayed by works containing it; or\
-\
-    c) Prohibiting misrepresentation of the origin of that material, or\
-    requiring that modified versions of such material be marked in\
-    reasonable ways as different from the original version; or\
-\
-    d) Limiting the use for publicity purposes of names of licensors or\
-    authors of the material; or\
-\
-    e) Declining to grant rights under trademark law for use of some\
-    trade names, trademarks, or service marks; or\
-\
-    f) Requiring indemnification of licensors and authors of that\
-    material by anyone who conveys the material (or modified versions of\
-    it) with contractual assumptions of liability to the recipient, for\
-    any liability that these contractual assumptions directly impose on\
-    those licensors and authors.\
-\
-  All other non-permissive additional terms are considered "further\
-restrictions" within the meaning of section 10.  If the Program as you\
-received it, or any part of it, contains a notice stating that it is\
-governed by this License along with a term that is a further\
-restriction, you may remove that term.  If a license document contains\
-a further restriction but permits relicensing or conveying under this\
-License, you may add to a covered work material governed by the terms\
-of that license document, provided that the further restriction does\
-not survive such relicensing or conveying.\
-\
-  If you add terms to a covered work in accord with this section, you\
-must place, in the relevant source files, a statement of the\
-additional terms that apply to those files, or a notice indicating\
-where to find the applicable terms.\
-\
-  Additional terms, permissive or non-permissive, may be stated in the\
-form of a separately written license, or stated as exceptions;\
-the above requirements apply either way.\
-\
-  8. Termination.\
-\
-  You may not propagate or modify a covered work except as expressly\
-provided under this License.  Any attempt otherwise to propagate or\
-modify it is void, and will automatically terminate your rights under\
-this License (including any patent licenses granted under the third\
-paragraph of section 11).\
-\
-  However, if you cease all violation of this License, then your\
-license from a particular copyright holder is reinstated (a)\
-provisionally, unless and until the copyright holder explicitly and\
-finally terminates your license, and (b) permanently, if the copyright\
-holder fails to notify you of the violation by some reasonable means\
-prior to 60 days after the cessation.\
-\
-  Moreover, your license from a particular copyright holder is\
-reinstated permanently if the copyright holder notifies you of the\
-violation by some reasonable means, this is the first time you have\
-received notice of violation of this License (for any work) from that\
-copyright holder, and you cure the violation prior to 30 days after\
-your receipt of the notice.\
-\
-  Termination of your rights under this section does not terminate the\
-licenses of parties who have received copies or rights from you under\
-this License.  If your rights have been terminated and not permanently\
-reinstated, you do not qualify to receive new licenses for the same\
-material under section 10.\
-\
-  9. Acceptance Not Required for Having Copies.\
-\
-  You are not required to accept this License in order to receive or\
-run a copy of the Program.  Ancillary propagation of a covered work\
-occurring solely as a consequence of using peer-to-peer transmission\
-to receive a copy likewise does not require acceptance.  However,\
-nothing other than this License grants you permission to propagate or\
-modify any covered work.  These actions infringe copyright if you do\
-not accept this License.  Therefore, by modifying or propagating a\
-covered work, you indicate your acceptance of this License to do so.\
-\
-  10. Automatic Licensing of Downstream Recipients.\
-\
-  Each time you convey a covered work, the recipient automatically\
-receives a license from the original licensors, to run, modify and\
-propagate that work, subject to this License.  You are not responsible\
-for enforcing compliance by third parties with this License.\
-\
-  An "entity transaction" is a transaction transferring control of an\
-organization, or substantially all assets of one, or subdividing an\
-organization, or merging organizations.  If propagation of a covered\
-work results from an entity transaction, each party to that\
-transaction who receives a copy of the work also receives whatever\
-licenses to the work the party's predecessor in interest had or could\
-give under the previous paragraph, plus a right to possession of the\
-Corresponding Source of the work from the predecessor in interest, if\
-the predecessor has it or can get it with reasonable efforts.\
-\
-  You may not impose any further restrictions on the exercise of the\
-rights granted or affirmed under this License.  For example, you may\
-not impose a license fee, royalty, or other charge for exercise of\
-rights granted under this License, and you may not initiate litigation\
-(including a cross-claim or counterclaim in a lawsuit) alleging that\
-any patent claim is infringed by making, using, selling, offering for\
-sale, or importing the Program or any portion of it.\
-\
-  11. Patents.\
-\
-  A "contributor" is a copyright holder who authorizes use under this\
-License of the Program or a work on which the Program is based.  The\
-work thus licensed is called the contributor's "contributor version".\
-\
-  A contributor's "essential patent claims" are all patent claims\
-owned or controlled by the contributor, whether already acquired or\
-hereafter acquired, that would be infringed by some manner, permitted\
-by this License, of making, using, or selling its contributor version,\
-but do not include claims that would be infringed only as a\
-consequence of further modification of the contributor version.  For\
-purposes of this definition, "control" includes the right to grant\
-patent sublicenses in a manner consistent with the requirements of\
-this License.\
-\
-  Each contributor grants you a non-exclusive, worldwide, royalty-free\
-patent license under the contributor's essential patent claims, to\
-make, use, sell, offer for sale, import and otherwise run, modify and\
-propagate the contents of its contributor version.\
-\
-  In the following three paragraphs, a "patent license" is any express\
-agreement or commitment, however denominated, not to enforce a patent\
-(such as an express permission to practice a patent or covenant not to\
-sue for patent infringement).  To "grant" such a patent license to a\
-party means to make such an agreement or commitment not to enforce a\
-patent against the party.\
-\
-  If you convey a covered work, knowingly relying on a patent license,\
-and the Corresponding Source of the work is not available for anyone\
-to copy, free of charge and under the terms of this License, through a\
-publicly available network server or other readily accessible means,\
-then you must either (1) cause the Corresponding Source to be so\
-available, or (2) arrange to deprive yourself of the benefit of the\
-patent license for this particular work, or (3) arrange, in a manner\
-consistent with the requirements of this License, to extend the patent\
-license to downstream recipients.  "Knowingly relying" means you have\
-actual knowledge that, but for the patent license, your conveying the\
-covered work in a country, or your recipient's use of the covered work\
-in a country, would infringe one or more identifiable patents in that\
-country that you have reason to believe are valid.\
-\
-  If, pursuant to or in connection with a single transaction or\
-arrangement, you convey, or propagate by procuring conveyance of, a\
-covered work, and grant a patent license to some of the parties\
-receiving the covered work authorizing them to use, propagate, modify\
-or convey a specific copy of the covered work, then the patent license\
-you grant is automatically extended to all recipients of the covered\
-work and works based on it.\
-\
-  A patent license is "discriminatory" if it does not include within\
-the scope of its coverage, prohibits the exercise of, or is\
-conditioned on the non-exercise of one or more of the rights that are\
-specifically granted under this License.  You may not convey a covered\
-work if you are a party to an arrangement with a third party that is\
-in the business of distributing software, under which you make payment\
-to the third party based on the extent of your activity of conveying\
-the work, and under which the third party grants, to any of the\
-parties who would receive the covered work from you, a discriminatory\
-patent license (a) in connection with copies of the covered work\
-conveyed by you (or copies made from those copies), or (b) primarily\
-for and in connection with specific products or compilations that\
-contain the covered work, unless you entered into that arrangement,\
-or that patent license was granted, prior to 28 March 2007.\
-\
-  Nothing in this License shall be construed as excluding or limiting\
-any implied license or other defenses to infringement that may\
-otherwise be available to you under applicable patent law.\
-\
-  12. No Surrender of Others' Freedom.\
-\
-  If conditions are imposed on you (whether by court order, agreement or\
-otherwise) that contradict the conditions of this License, they do not\
-excuse you from the conditions of this License.  If you cannot convey a\
-covered work so as to satisfy simultaneously your obligations under this\
-License and any other pertinent obligations, then as a consequence you may\
-not convey it at all.  For example, if you agree to terms that obligate you\
-to collect a royalty for further conveying from those to whom you convey\
-the Program, the only way you could satisfy both those terms and this\
-License would be to refrain entirely from conveying the Program.\
-\
-  13. Use with the GNU Affero General Public License.\
-\
-  Notwithstanding any other provision of this License, you have\
-permission to link or combine any covered work with a work licensed\
-under version 3 of the GNU Affero General Public License into a single\
-combined work, and to convey the resulting work.  The terms of this\
-License will continue to apply to the part which is the covered work,\
-but the special requirements of the GNU Affero General Public License,\
-section 13, concerning interaction through a network will apply to the\
-combination as such.\
-\
-  14. Revised Versions of this License.\
-\
-  The Free Software Foundation may publish revised and/or new versions of\
-the GNU General Public License from time to time.  Such new versions will\
-be similar in spirit to the present version, but may differ in detail to\
-address new problems or concerns.\
-\
-  Each version is given a distinguishing version number.  If the\
-Program specifies that a certain numbered version of the GNU General\
-Public License "or any later version" applies to it, you have the\
-option of following the terms and conditions either of that numbered\
-version or of any later version published by the Free Software\
-Foundation.  If the Program does not specify a version number of the\
-GNU General Public License, you may choose any version ever published\
-by the Free Software Foundation.\
-\
-  If the Program specifies that a proxy can decide which future\
-versions of the GNU General Public License can be used, that proxy's\
-public statement of acceptance of a version permanently authorizes you\
-to choose that version for the Program.\
-\
-  Later license versions may give you additional or different\
-permissions.  However, no additional obligations are imposed on any\
-author or copyright holder as a result of your choosing to follow a\
-later version.\
-\
-  15. Disclaimer of Warranty.\
-\
-  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\
-APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY\
-OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\
-IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\
-ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\
-\
-  16. Limitation of Liability.\
-\
-  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\
-THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\
-GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\
-USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\
-DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\
-PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\
-EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\
-SUCH DAMAGES.\
-\
-  17. Interpretation of Sections 15 and 16.\
-\
-  If the disclaimer of warranty and limitation of liability provided\
-above cannot be given local legal effect according to their terms,\
-reviewing courts shall apply local law that most closely approximates\
-an absolute waiver of all civil liability in connection with the\
-Program, unless a warranty or assumption of liability accompanies a\
-copy of the Program in return for a fee.\
-\
-                     END OF TERMS AND CONDITIONS\
-\
-            How to Apply These Terms to Your New Programs\
-\
-  If you develop a new program, and you want it to be of the greatest\
-possible use to the public, the best way to achieve this is to make it\
-free software which everyone can redistribute and change under these terms.\
-\
-  To do so, attach the following notices to the program.  It is safest\
-to attach them to the start of each source file to most effectively\
-state the exclusion of warranty; and each file should have at least\
-the "copyright" line and a pointer to where the full notice is found.\
-\
-    <one line to give the program's name and a brief idea of what it does.>\
-    Copyright (C) <year>  <name of author>\
-\
-    This program is free software: you can redistribute it and/or modify\
-    it under the terms of the GNU General Public License as published by\
-    the Free Software Foundation, either version 3 of the License, or\
-    (at your option) any later version.\
-\
-    This program is distributed in the hope that it will be useful,\
-    but WITHOUT ANY WARRANTY; without even the implied warranty of\
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\
-    GNU General Public License for more details.\
-\
-    You should have received a copy of the GNU General Public License\
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.\
-\
-Also add information on how to contact you by electronic and paper mail.\
-\
-  If the program does terminal interaction, make it output a short\
-notice like this when it starts in an interactive mode:\
-\
-    <program>  Copyright (C) <year>  <name of author>\
-    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\
-    This is free software, and you are welcome to redistribute it\
-    under certain conditions; type `show c' for details.\
-\
-The hypothetical commands `show w' and `show c' should show the appropriate\
-parts of the General Public License.  Of course, your program's commands\
-might be different; for a GUI interface, you would use an "about box".\
-\
-  You should also get your employer (if you work as a programmer) or school,\
-if any, to sign a "copyright disclaimer" for the program, if necessary.\
-For more information on this, and how to apply and follow the GNU GPL, see\
-<http://www.gnu.org/licenses/>.\
-\
-  The GNU General Public License does not permit incorporating your program\
-into proprietary programs.  If your program is a subroutine library, you\
-may consider it more useful to permit linking proprietary applications with\
-the library.  If this is what you want to do, use the GNU Lesser General\
-Public License instead of this License.  But first, please read\
-<http://www.gnu.org/philosophy/why-not-lgpl.html>.\
-}
\ No newline at end of file
diff --git a/installers/osx/PkgResources_x86_64/ReadMe.rtf b/installers/osx/PkgResources_x86_64/ReadMe.rtf
deleted file mode 100755
index d6db53b..0000000
--- a/installers/osx/PkgResources_x86_64/ReadMe.rtf
+++ /dev/null
@@ -1,75 +0,0 @@
-{\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\fcharset1 LucidaGrande;}{\f6\froman\fprq0\fcharset1 LucidaGrande;}{\f7\fnil\fprq2\fcharset0 DejaVu Sans;}{\f8\fnil\fprq2\fcharset0 Lohit Hindi;}{\f9\fnil\fprq0\fcharset1 Lohit Hindi;}}
-{\colortbl;\red0\green0\blue0;\red128\green128\blue128;}
-{\stylesheet{\s0\snext0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105 Normal;}
-{\s15\sbasedon0\snext16\sb240\sa120\keepn\dbch\af7\dbch\af8\afs28\loch\f4\fs28 Heading;}
-{\s16\sbasedon0\snext16\sb0\sa120 Text body;}
-{\s17\sbasedon16\snext17\sb0\sa120\dbch\af9 List;}
-{\s18\sbasedon0\snext18\sb120\sa120\noline\i\dbch\af9\afs24\ai\fs24 Caption;}
-{\s19\sbasedon0\snext19\noline\dbch\af9 Index;}
-}{\info{\creatim\yr0\mo0\dy0\hr0\min0}{\revtim\yr0\mo0\dy0\hr0\min0}{\printim\yr0\mo0\dy0\hr0\min0}{\comment LibreOffice}{\vern3600}}\deftab720
-\viewscale110
-{\*\pgdsctbl
-{\pgdsc0\pgdscuse195\pgwsxn12240\pghsxn15840\marglsxn1440\margrsxn1440\margtsxn1440\margbsxn1440\pgdscnxt0 Default;}}
-\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
-\pgndec\pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f6
-pyo (version 0.6.}{\cf1\rtlch \ltrch\loch\fs26\loch\f6
-6}{\cf1\rtlch \ltrch\loch\fs26\loch\f6
-)}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\rtlch \ltrch\loch\fs26\loch\f6
-
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f6
-System requirements : OS X 10.6 or 10.7}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\rtlch \ltrch\loch\fs26\loch\f6
-
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f6
-This package installs all the required components to run pyo inside your current Python installation. Python 2.6 or 2.7 (64-bit) must be already installed on your system.}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\rtlch \ltrch\loch\fs26\loch\f6
-
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f6
-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{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\rtlch \ltrch\loch\fs26\loch\f6
-
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b\rtlch \ltrch\loch\fs26\loch\f6
-1. pyo extension:}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-The following components will be installed in the site-packages folder of the current Python Framework:}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-_pyo.so}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-_pyo64.so}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-pyo.py}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-pyo64.py}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-pyolib (folder)}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b\rtlch \ltrch\loch\fs26\loch\f6
-2. Support libraries (i386 and x86_64):}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-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{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b\rtlch \ltrch\loch\fs26\loch\f6
-Warning:}{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
- 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{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-liblo.7.dylib}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-libportaudio.2.dylib}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-libportmidi.dylib}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-libsndfile.1.dylib}
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-
-\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af7\langfe2052\dbch\af8\afs24\alang1081\loch\f3\fs24\lang4105{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-Olivier B\u233\'e9langer, 201}{\cf1\b0\rtlch \ltrch\loch\fs26\loch\f6
-3}
-\par }
\ No newline at end of file
diff --git a/installers/osx/PkgResources_x86_64_py2/License.rtf b/installers/osx/PkgResources_x86_64_py2/License.rtf
new file mode 100755
index 0000000..50a49ab
--- /dev/null
+++ b/installers/osx/PkgResources_x86_64_py2/License.rtf
@@ -0,0 +1,423 @@
+{\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 Droid Sans Fallback;}{\f7\fnil\fprq2\fcharset0 FreeSans;}{\f8\fswiss\fprq0\fcharset128 FreeSans;}}
+{\colortbl;\red0\green0\blue0;\red128\green128\blue128;}
+{\stylesheet{\s0\snext0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084 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;}
+}{\info{\creatim\yr0\mo0\dy0\hr0\min0}{\author olivier }{\revtim\yr2015\mo3\dy5\hr14\min36}{\printim\yr0\mo0\dy0\hr0\min0}{\comment LibreOffice}{\vern67306242}}\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{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+                }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+GNU LESSER GENERAL PUBLIC LICENSE}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+                       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Version 3, 29 June 2007}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+ }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+ }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Everyone is permitted to copy and distribute verbatim copies}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+ }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+of this license document, but changing it is not allowed.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+This version of the GNU Lesser General Public License incorporates}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+the terms and conditions of version 3 of the GNU General Public}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+License, supplemented by the additional permissions listed below.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+0. Additional Definitions.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+As used herein, "this License" refers to version 3 of the GNU Lesser}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+General Public License, and the "GNU GPL" refers to version 3 of the GNU}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+General Public License.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+"The Library" refers to a covered work governed by this License,}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+other than an Application or a Combined Work as defined below.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+An "Application" is any work that makes use of an interface provided}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+by the Library, but which is not otherwise based on the Library.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Defining a subclass of a class defined by the Library is deemed a mode}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+of using an interface provided by the Library.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+A "Combined Work" is a work produced by combining or linking an}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Application with the Library.  The particular version of the Library}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+with which the Combined Work was made is also called the "Linked}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Version".}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+The "Minimal Corresponding Source" for a Combined Work means the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Corresponding Source for the Combined Work, excluding any source code}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+for portions of the Combined Work that, considered in isolation, are}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+based on the Application, and not on the Linked Version.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+The "Corresponding Application Code" for a Combined Work means the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+object code and/or source code for the Application, including any data}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+and utility programs needed for reproducing the Combined Work from the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Application, but excluding the System Libraries of the Combined Work.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+1. Exception to Section 3 of the GNU GPL.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+You may convey a covered work under sections 3 and 4 of this License}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+without being bound by section 3 of the GNU GPL.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+2. Conveying Modified Versions.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+If you modify a copy of the Library, and, in your modifications, a}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+facility refers to a function or data to be supplied by an Application}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+that uses the facility (other than as an argument passed when the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+facility is invoked), then you may convey a copy of the modified}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+version:}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+a) under this License, provided that you make a good faith effort to}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+ensure that, in the event an Application does not supply the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+function or data, the facility still operates, and performs}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+whatever part of its purpose remains meaningful, or}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+b) under the GNU GPL, with none of the additional permissions of}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+this License applicable to that copy.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+3. Object Code Incorporating Material from Library Header Files.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+The object code form of an Application may incorporate material from}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+a header file that is part of the Library.  You may convey such object}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+code under terms of your choice, provided that, if the incorporated}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+material is not limited to numerical parameters, data structure}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+layouts and accessors, or small macros, inline functions and templates}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+(ten or fewer lines in length), you do both of the following:}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+a) Give prominent notice with each copy of the object code that the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Library is used in it and that the Library and its use are}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+covered by this License.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+b) Accompany the object code with a copy of the GNU GPL and this license}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+document.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+4. Combined Works.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+You may convey a Combined Work under terms of your choice that,}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+taken together, effectively do not restrict modification of the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+portions of the Library contained in the Combined Work and reverse}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+engineering for debugging such modifications, if you also do each of}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+the following:}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+a) Give prominent notice with each copy of the Combined Work that}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+the Library is used in it and that the Library and its use are}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+covered by this License.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+b) Accompany the Combined Work with a copy of the GNU GPL and this license}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+document.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+c) For a Combined Work that displays copyright notices during}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+execution, include the copyright notice for the Library among}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+these notices, as well as a reference directing the user to the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+copies of the GNU GPL and this license document.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+d) Do one of the following:}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+0) Convey the Minimal Corresponding Source under the terms of this}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+License, and the Corresponding Application Code in a form}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+suitable for, and under terms that permit, the user to}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+recombine or relink the Application with a modified version of}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+the Linked Version to produce a modified Combined Work, in the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+manner specified by section 6 of the GNU GPL for conveying}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Corresponding Source.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+1) Use a suitable shared library mechanism for linking with the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Library.  A suitable mechanism is one that (a) uses at run time}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+a copy of the Library already present on the user's computer}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+system, and (b) will operate properly with a modified version}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+of the Library that is interface-compatible with the Linked}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Version.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+e) Provide Installation Information, but only if you would otherwise}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+be required to provide such information under section 6 of the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+GNU GPL, and only to the extent that such information is}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+necessary to install and execute a modified version of the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Combined Work produced by recombining or relinking the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Application with a modified version of the Linked Version. (If}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+you use option 4d0, the Installation Information must accompany}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+the Minimal Corresponding Source and Corresponding Application}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Code. If you use option 4d1, you must provide the Installation}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Information in the manner specified by section 6 of the GNU GPL}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+for conveying Corresponding Source.)}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+5. Combined Libraries.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+You may place library facilities that are a work based on the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Library side by side in a single library together with other library}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+facilities that are not Applications and are not covered by this}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+License, and convey such a combined library under terms of your}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+choice, if you do both of the following:}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+a) Accompany the combined library with a copy of the same work based}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+on the Library, uncombined with any other library facilities,}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+conveyed under the terms of this License.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+b) Give prominent notice with the combined library that part of it}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+is a work based on the Library, and explaining where to find the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+accompanying uncombined form of the same work.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+6. Revised Versions of the GNU Lesser General Public License.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+The Free Software Foundation may publish revised and/or new versions}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+of the GNU Lesser General Public License from time to time. Such new}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+versions will be similar in spirit to the present version, but may}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+differ in detail to address new problems or concerns.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Each version is given a distinguishing version number. If the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Library as you received it specifies that a certain numbered version}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+of the GNU Lesser General Public License "or any later version"}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+applies to it, you have the option of following the terms and}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+conditions either of that published version or of any later version}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+published by the Free Software Foundation. If the Library as you}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+received it does not specify a version number of the GNU Lesser}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+General Public License, you may choose any version of the GNU Lesser}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+General Public License ever published by the Free Software Foundation.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+If the Library as you received it specifies that a proxy can decide}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+whether future versions of the GNU Lesser General Public License shall}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+apply, that proxy's public statement of acceptance of any version is}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+permanent authorization for you to choose that version for the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Library.}
+\par }
\ No newline at end of file
diff --git a/installers/osx/PkgResources_x86_64_py2/ReadMe.rtf b/installers/osx/PkgResources_x86_64_py2/ReadMe.rtf
new file mode 100755
index 0000000..70bea13
--- /dev/null
+++ b/installers/osx/PkgResources_x86_64_py2/ReadMe.rtf
@@ -0,0 +1,97 @@
+{\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.7) 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, 2017
+\f1\fs24 \
+}
\ No newline at end of file
diff --git a/installers/osx/PkgResources_i386/Welcome.rtf b/installers/osx/PkgResources_x86_64_py2/Welcome.rtf
similarity index 100%
copy from installers/osx/PkgResources_i386/Welcome.rtf
copy to installers/osx/PkgResources_x86_64_py2/Welcome.rtf
diff --git a/installers/osx/PkgResources_x86_64/postinstall b/installers/osx/PkgResources_x86_64_py2/postinstall
similarity index 61%
rename from installers/osx/PkgResources_x86_64/postinstall
rename to installers/osx/PkgResources_x86_64_py2/postinstall
index ade04c8..8a86d60 100755
--- a/installers/osx/PkgResources_x86_64/postinstall
+++ b/installers/osx/PkgResources_x86_64_py2/postinstall
@@ -1,15 +1,6 @@
 #! /bin/sh
 
-VERSION=`sw_vers -productVersion | sed -e 's/\.//g'`
-
-if [ $VERSION -ge '1070' ]; then
-    echo "Install pyo on OSX 10.7";
-else
-    echo "Install pyo on OSX 10.6";
-fi
-
-# Removed older versions in the python site-packages builtin directories
-# Removed older versions in the python site-packages from python.org install directories
+# Removed older versions in the python site-packages builtin and in the python site-packages from python.org directories
 PATHS=/Library/Python/2.6/site-packages/:/Library/Python/2.7/site-packages/:/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/:/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/
 for path in ${PATHS//:/ }; do
     if cd $path; then
@@ -42,33 +33,15 @@ for path in ${PATHS//:/ }; do
 done
 
 # Install pyo in the python site-packages builtin directories
-if [ $VERSION -ge '1070' ]; then
-    if cd /Library/Python/2.7/site-packages/; then
-        sudo cp -r /tmp/python27/* .
-    else
-        sudo mkdir -p /Library/Python/2.7/site-packages/
-        cd /Library/Python/2.7/site-packages/
-        sudo cp -r /tmp/python27/* .
-    fi
+if cd /Library/Python/2.7/site-packages/; then
+    sudo cp -r /tmp/python27/* .
 else
-    if cd /Library/Python/2.6/site-packages/; then
-        sudo cp -r /tmp/python26/* .
-    else
-        sudo mkdir -p /Library/Python/2.6/site-packages/
-        cd /Library/Python/2.6/site-packages/
-        sudo cp -r /tmp/python26/* .
-    fi
+    sudo mkdir -p /Library/Python/2.7/site-packages/
+    cd /Library/Python/2.7/site-packages/
+    sudo cp -r /tmp/python27/* .
 fi
 
 # Install pyo in the python.org site-packages directories
-if cd /Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/; then  
-    sudo cp -r /tmp/python26/* .
-else
-    sudo mkdir -p /Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/
-    cd /Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/
-    sudo cp -r /tmp/python26/* .
-fi
-
 if cd /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/; then  
     sudo cp -r /tmp/python27/* .
 else
@@ -77,7 +50,13 @@ else
     sudo cp -r /tmp/python27/* .
 fi
 
-sudo rm -rf /tmp/python2*
+# Check if anaconda is already installed and copy files to site-packages directory
+if cd ~/anaconda/lib/python2.7/site-packages/; then  
+    sudo cp -r /tmp/python27/* .
+fi
+
+# Clean up.
+sudo rm -rf /tmp/python27
 
 # Add /usr/local/lib in .bash_profile if not already done
 searchString="/usr/local/lib"
diff --git a/installers/osx/PkgResources_x86_64/postupgrade b/installers/osx/PkgResources_x86_64_py2/postupgrade
similarity index 61%
rename from installers/osx/PkgResources_x86_64/postupgrade
rename to installers/osx/PkgResources_x86_64_py2/postupgrade
index ade04c8..8a86d60 100755
--- a/installers/osx/PkgResources_x86_64/postupgrade
+++ b/installers/osx/PkgResources_x86_64_py2/postupgrade
@@ -1,15 +1,6 @@
 #! /bin/sh
 
-VERSION=`sw_vers -productVersion | sed -e 's/\.//g'`
-
-if [ $VERSION -ge '1070' ]; then
-    echo "Install pyo on OSX 10.7";
-else
-    echo "Install pyo on OSX 10.6";
-fi
-
-# Removed older versions in the python site-packages builtin directories
-# Removed older versions in the python site-packages from python.org install directories
+# Removed older versions in the python site-packages builtin and in the python site-packages from python.org directories
 PATHS=/Library/Python/2.6/site-packages/:/Library/Python/2.7/site-packages/:/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/:/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/
 for path in ${PATHS//:/ }; do
     if cd $path; then
@@ -42,33 +33,15 @@ for path in ${PATHS//:/ }; do
 done
 
 # Install pyo in the python site-packages builtin directories
-if [ $VERSION -ge '1070' ]; then
-    if cd /Library/Python/2.7/site-packages/; then
-        sudo cp -r /tmp/python27/* .
-    else
-        sudo mkdir -p /Library/Python/2.7/site-packages/
-        cd /Library/Python/2.7/site-packages/
-        sudo cp -r /tmp/python27/* .
-    fi
+if cd /Library/Python/2.7/site-packages/; then
+    sudo cp -r /tmp/python27/* .
 else
-    if cd /Library/Python/2.6/site-packages/; then
-        sudo cp -r /tmp/python26/* .
-    else
-        sudo mkdir -p /Library/Python/2.6/site-packages/
-        cd /Library/Python/2.6/site-packages/
-        sudo cp -r /tmp/python26/* .
-    fi
+    sudo mkdir -p /Library/Python/2.7/site-packages/
+    cd /Library/Python/2.7/site-packages/
+    sudo cp -r /tmp/python27/* .
 fi
 
 # Install pyo in the python.org site-packages directories
-if cd /Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/; then  
-    sudo cp -r /tmp/python26/* .
-else
-    sudo mkdir -p /Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/
-    cd /Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/site-packages/
-    sudo cp -r /tmp/python26/* .
-fi
-
 if cd /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/; then  
     sudo cp -r /tmp/python27/* .
 else
@@ -77,7 +50,13 @@ else
     sudo cp -r /tmp/python27/* .
 fi
 
-sudo rm -rf /tmp/python2*
+# Check if anaconda is already installed and copy files to site-packages directory
+if cd ~/anaconda/lib/python2.7/site-packages/; then  
+    sudo cp -r /tmp/python27/* .
+fi
+
+# Clean up.
+sudo rm -rf /tmp/python27
 
 # Add /usr/local/lib in .bash_profile if not already done
 searchString="/usr/local/lib"
diff --git a/installers/osx/PkgResources_x86_64_py35/License.rtf b/installers/osx/PkgResources_x86_64_py35/License.rtf
new file mode 100755
index 0000000..50a49ab
--- /dev/null
+++ b/installers/osx/PkgResources_x86_64_py35/License.rtf
@@ -0,0 +1,423 @@
+{\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 Droid Sans Fallback;}{\f7\fnil\fprq2\fcharset0 FreeSans;}{\f8\fswiss\fprq0\fcharset128 FreeSans;}}
+{\colortbl;\red0\green0\blue0;\red128\green128\blue128;}
+{\stylesheet{\s0\snext0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084 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;}
+}{\info{\creatim\yr0\mo0\dy0\hr0\min0}{\author olivier }{\revtim\yr2015\mo3\dy5\hr14\min36}{\printim\yr0\mo0\dy0\hr0\min0}{\comment LibreOffice}{\vern67306242}}\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{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+                }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+GNU LESSER GENERAL PUBLIC LICENSE}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+                       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Version 3, 29 June 2007}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+ }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+ }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Everyone is permitted to copy and distribute verbatim copies}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+ }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+of this license document, but changing it is not allowed.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+This version of the GNU Lesser General Public License incorporates}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+the terms and conditions of version 3 of the GNU General Public}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+License, supplemented by the additional permissions listed below.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+0. Additional Definitions.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+As used herein, "this License" refers to version 3 of the GNU Lesser}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+General Public License, and the "GNU GPL" refers to version 3 of the GNU}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+General Public License.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+"The Library" refers to a covered work governed by this License,}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+other than an Application or a Combined Work as defined below.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+An "Application" is any work that makes use of an interface provided}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+by the Library, but which is not otherwise based on the Library.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Defining a subclass of a class defined by the Library is deemed a mode}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+of using an interface provided by the Library.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+A "Combined Work" is a work produced by combining or linking an}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Application with the Library.  The particular version of the Library}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+with which the Combined Work was made is also called the "Linked}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Version".}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+The "Minimal Corresponding Source" for a Combined Work means the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Corresponding Source for the Combined Work, excluding any source code}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+for portions of the Combined Work that, considered in isolation, are}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+based on the Application, and not on the Linked Version.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+The "Corresponding Application Code" for a Combined Work means the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+object code and/or source code for the Application, including any data}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+and utility programs needed for reproducing the Combined Work from the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Application, but excluding the System Libraries of the Combined Work.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+1. Exception to Section 3 of the GNU GPL.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+You may convey a covered work under sections 3 and 4 of this License}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+without being bound by section 3 of the GNU GPL.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+2. Conveying Modified Versions.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+If you modify a copy of the Library, and, in your modifications, a}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+facility refers to a function or data to be supplied by an Application}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+that uses the facility (other than as an argument passed when the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+facility is invoked), then you may convey a copy of the modified}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+version:}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+a) under this License, provided that you make a good faith effort to}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+ensure that, in the event an Application does not supply the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+function or data, the facility still operates, and performs}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+whatever part of its purpose remains meaningful, or}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+b) under the GNU GPL, with none of the additional permissions of}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+this License applicable to that copy.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+3. Object Code Incorporating Material from Library Header Files.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+The object code form of an Application may incorporate material from}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+a header file that is part of the Library.  You may convey such object}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+code under terms of your choice, provided that, if the incorporated}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+material is not limited to numerical parameters, data structure}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+layouts and accessors, or small macros, inline functions and templates}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+(ten or fewer lines in length), you do both of the following:}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+a) Give prominent notice with each copy of the object code that the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Library is used in it and that the Library and its use are}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+covered by this License.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+b) Accompany the object code with a copy of the GNU GPL and this license}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+document.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+4. Combined Works.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+You may convey a Combined Work under terms of your choice that,}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+taken together, effectively do not restrict modification of the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+portions of the Library contained in the Combined Work and reverse}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+engineering for debugging such modifications, if you also do each of}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+the following:}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+a) Give prominent notice with each copy of the Combined Work that}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+the Library is used in it and that the Library and its use are}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+covered by this License.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+b) Accompany the Combined Work with a copy of the GNU GPL and this license}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+document.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+c) For a Combined Work that displays copyright notices during}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+execution, include the copyright notice for the Library among}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+these notices, as well as a reference directing the user to the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+copies of the GNU GPL and this license document.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+d) Do one of the following:}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+0) Convey the Minimal Corresponding Source under the terms of this}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+License, and the Corresponding Application Code in a form}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+suitable for, and under terms that permit, the user to}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+recombine or relink the Application with a modified version of}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+the Linked Version to produce a modified Combined Work, in the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+manner specified by section 6 of the GNU GPL for conveying}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Corresponding Source.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+1) Use a suitable shared library mechanism for linking with the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Library.  A suitable mechanism is one that (a) uses at run time}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+a copy of the Library already present on the user's computer}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+system, and (b) will operate properly with a modified version}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+of the Library that is interface-compatible with the Linked}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Version.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+e) Provide Installation Information, but only if you would otherwise}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+be required to provide such information under section 6 of the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+GNU GPL, and only to the extent that such information is}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+necessary to install and execute a modified version of the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Combined Work produced by recombining or relinking the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Application with a modified version of the Linked Version. (If}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+you use option 4d0, the Installation Information must accompany}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+the Minimal Corresponding Source and Corresponding Application}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Code. If you use option 4d1, you must provide the Installation}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Information in the manner specified by section 6 of the GNU GPL}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+for conveying Corresponding Source.)}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+5. Combined Libraries.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+You may place library facilities that are a work based on the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Library side by side in a single library together with other library}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+facilities that are not Applications and are not covered by this}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+License, and convey such a combined library under terms of your}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+choice, if you do both of the following:}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+a) Accompany the combined library with a copy of the same work based}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+on the Library, uncombined with any other library facilities,}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+conveyed under the terms of this License.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+b) Give prominent notice with the combined library that part of it}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+is a work based on the Library, and explaining where to find the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+accompanying uncombined form of the same work.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+6. Revised Versions of the GNU Lesser General Public License.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+The Free Software Foundation may publish revised and/or new versions}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+of the GNU Lesser General Public License from time to time. Such new}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+versions will be similar in spirit to the present version, but may}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+differ in detail to address new problems or concerns.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Each version is given a distinguishing version number. If the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Library as you received it specifies that a certain numbered version}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+of the GNU Lesser General Public License "or any later version"}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+applies to it, you have the option of following the terms and}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+conditions either of that published version or of any later version}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+published by the Free Software Foundation. If the Library as you}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+received it does not specify a version number of the GNU Lesser}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+General Public License, you may choose any version of the GNU Lesser}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+General Public License ever published by the Free Software Foundation.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+If the Library as you received it specifies that a proxy can decide}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+whether future versions of the GNU Lesser General Public License shall}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+apply, that proxy's public statement of acceptance of any version is}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+permanent authorization for you to choose that version for the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Library.}
+\par }
\ No newline at end of file
diff --git a/installers/osx/PkgResources_x86_64_py35/ReadMe.rtf b/installers/osx/PkgResources_x86_64_py35/ReadMe.rtf
new file mode 100755
index 0000000..d763b09
--- /dev/null
+++ b/installers/osx/PkgResources_x86_64_py35/ReadMe.rtf
@@ -0,0 +1,97 @@
+{\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.7) 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, 2017
+\f1\fs24 \
+}
\ No newline at end of file
diff --git a/installers/osx/PkgResources_x86_64/Welcome.rtf b/installers/osx/PkgResources_x86_64_py35/Welcome.rtf
similarity index 100%
rename from installers/osx/PkgResources_x86_64/Welcome.rtf
rename to installers/osx/PkgResources_x86_64_py35/Welcome.rtf
diff --git a/installers/osx/PkgResources_x86_64_py35/postinstall b/installers/osx/PkgResources_x86_64_py35/postinstall
new file mode 100755
index 0000000..d3b0e5a
--- /dev/null
+++ b/installers/osx/PkgResources_x86_64_py35/postinstall
@@ -0,0 +1,74 @@
+#! /bin/sh
+
+# Removed older versions in the python site-packages builtin and in the python site-packages from python.org directories
+PATHS=/Library/Python/3.5/site-packages/:/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/
+for path in ${PATHS//:/ }; do
+    if cd $path; then
+        if [ -f pyo.py ]; then
+            sudo rm pyo.py;
+        fi    
+        if [ -f pyo64.py ]; then
+            sudo rm pyo64.py;
+        fi    
+        if [ -f pyo.pyc ]; then
+            sudo rm pyo.pyc;
+        fi    
+        if [ -f pyo64.pyc ]; then
+            sudo rm pyo64.pyc;
+        fi    
+        if [ -f _pyo.cpython-35m-darwin.so ]; then
+            sudo rm _pyo.so;
+        fi    
+        if [ -f _pyo64.cpython-35m-darwin.so ]; then
+            sudo rm _pyo64.so;
+        fi    
+        if [ -d pyolib ]; then
+            sudo rm -rf pyolib/;
+        fi    
+        ls -1 pyo*-info > /dev/null 2>&1
+        if [ "$?" = "0" ]; then
+            sudo rm pyo*-info;
+        fi    
+    fi
+done
+
+# Install pyo in the python site-packages builtin directories
+if cd /Library/Python/3.5/site-packages/; then
+    sudo cp -r /tmp/python35/* .
+else
+    sudo mkdir -p /Library/Python/3.5/site-packages/
+    cd /Library/Python/3.5/site-packages/
+    sudo cp -r /tmp/python35/* .
+fi
+
+# Install pyo in the python.org site-packages directories
+if cd /Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/; then  
+    sudo cp -r /tmp/python35/* .
+else
+    sudo mkdir -p /Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/
+    cd /Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/
+    sudo cp -r /tmp/python35/* .
+fi
+
+# Check if anaconda is already installed and copy files to site-packages directory
+if cd ~/anaconda/lib/python3.5/site-packages/; then  
+    sudo cp -r /tmp/python35/* .
+fi
+
+# Clean up.
+sudo rm -rf /tmp/python35
+
+# Add /usr/local/lib in .bash_profile if not already done
+searchString="/usr/local/lib"
+
+if [ -f ~/.bash_profile ]; then
+    if `cat ~/.bash_profile | grep "${searchString}" 1>/dev/null 2>&1`; then
+        echo "path already in PATH variable";
+    else
+        echo "adding path to .bash_profile..."
+        echo "export PATH=/usr/local/lib:/usr/local/bin:\$PATH" >> ~/.bash_profile;
+    fi
+else
+    echo "creating .bash_profile and adding path to it..."
+    echo "export PATH=/usr/local/lib:/usr/local/bin:\$PATH" > ~/.bash_profile;
+fi
diff --git a/installers/osx/PkgResources_x86_64_py35/postupgrade b/installers/osx/PkgResources_x86_64_py35/postupgrade
new file mode 100755
index 0000000..d3b0e5a
--- /dev/null
+++ b/installers/osx/PkgResources_x86_64_py35/postupgrade
@@ -0,0 +1,74 @@
+#! /bin/sh
+
+# Removed older versions in the python site-packages builtin and in the python site-packages from python.org directories
+PATHS=/Library/Python/3.5/site-packages/:/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/
+for path in ${PATHS//:/ }; do
+    if cd $path; then
+        if [ -f pyo.py ]; then
+            sudo rm pyo.py;
+        fi    
+        if [ -f pyo64.py ]; then
+            sudo rm pyo64.py;
+        fi    
+        if [ -f pyo.pyc ]; then
+            sudo rm pyo.pyc;
+        fi    
+        if [ -f pyo64.pyc ]; then
+            sudo rm pyo64.pyc;
+        fi    
+        if [ -f _pyo.cpython-35m-darwin.so ]; then
+            sudo rm _pyo.so;
+        fi    
+        if [ -f _pyo64.cpython-35m-darwin.so ]; then
+            sudo rm _pyo64.so;
+        fi    
+        if [ -d pyolib ]; then
+            sudo rm -rf pyolib/;
+        fi    
+        ls -1 pyo*-info > /dev/null 2>&1
+        if [ "$?" = "0" ]; then
+            sudo rm pyo*-info;
+        fi    
+    fi
+done
+
+# Install pyo in the python site-packages builtin directories
+if cd /Library/Python/3.5/site-packages/; then
+    sudo cp -r /tmp/python35/* .
+else
+    sudo mkdir -p /Library/Python/3.5/site-packages/
+    cd /Library/Python/3.5/site-packages/
+    sudo cp -r /tmp/python35/* .
+fi
+
+# Install pyo in the python.org site-packages directories
+if cd /Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/; then  
+    sudo cp -r /tmp/python35/* .
+else
+    sudo mkdir -p /Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/
+    cd /Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/
+    sudo cp -r /tmp/python35/* .
+fi
+
+# Check if anaconda is already installed and copy files to site-packages directory
+if cd ~/anaconda/lib/python3.5/site-packages/; then  
+    sudo cp -r /tmp/python35/* .
+fi
+
+# Clean up.
+sudo rm -rf /tmp/python35
+
+# Add /usr/local/lib in .bash_profile if not already done
+searchString="/usr/local/lib"
+
+if [ -f ~/.bash_profile ]; then
+    if `cat ~/.bash_profile | grep "${searchString}" 1>/dev/null 2>&1`; then
+        echo "path already in PATH variable";
+    else
+        echo "adding path to .bash_profile..."
+        echo "export PATH=/usr/local/lib:/usr/local/bin:\$PATH" >> ~/.bash_profile;
+    fi
+else
+    echo "creating .bash_profile and adding path to it..."
+    echo "export PATH=/usr/local/lib:/usr/local/bin:\$PATH" > ~/.bash_profile;
+fi
diff --git a/installers/osx/PkgResources_x86_64_py36/License.rtf b/installers/osx/PkgResources_x86_64_py36/License.rtf
new file mode 100755
index 0000000..50a49ab
--- /dev/null
+++ b/installers/osx/PkgResources_x86_64_py36/License.rtf
@@ -0,0 +1,423 @@
+{\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 Droid Sans Fallback;}{\f7\fnil\fprq2\fcharset0 FreeSans;}{\f8\fswiss\fprq0\fcharset128 FreeSans;}}
+{\colortbl;\red0\green0\blue0;\red128\green128\blue128;}
+{\stylesheet{\s0\snext0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084 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;}
+}{\info{\creatim\yr0\mo0\dy0\hr0\min0}{\author olivier }{\revtim\yr2015\mo3\dy5\hr14\min36}{\printim\yr0\mo0\dy0\hr0\min0}{\comment LibreOffice}{\vern67306242}}\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{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+                }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+GNU LESSER GENERAL PUBLIC LICENSE}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+                       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Version 3, 29 June 2007}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+ }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+ }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Everyone is permitted to copy and distribute verbatim copies}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+ }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+of this license document, but changing it is not allowed.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+This version of the GNU Lesser General Public License incorporates}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+the terms and conditions of version 3 of the GNU General Public}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+License, supplemented by the additional permissions listed below.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+0. Additional Definitions.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+As used herein, "this License" refers to version 3 of the GNU Lesser}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+General Public License, and the "GNU GPL" refers to version 3 of the GNU}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+General Public License.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+"The Library" refers to a covered work governed by this License,}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+other than an Application or a Combined Work as defined below.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+An "Application" is any work that makes use of an interface provided}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+by the Library, but which is not otherwise based on the Library.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Defining a subclass of a class defined by the Library is deemed a mode}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+of using an interface provided by the Library.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+A "Combined Work" is a work produced by combining or linking an}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Application with the Library.  The particular version of the Library}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+with which the Combined Work was made is also called the "Linked}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Version".}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+The "Minimal Corresponding Source" for a Combined Work means the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Corresponding Source for the Combined Work, excluding any source code}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+for portions of the Combined Work that, considered in isolation, are}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+based on the Application, and not on the Linked Version.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+The "Corresponding Application Code" for a Combined Work means the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+object code and/or source code for the Application, including any data}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+and utility programs needed for reproducing the Combined Work from the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Application, but excluding the System Libraries of the Combined Work.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+1. Exception to Section 3 of the GNU GPL.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+You may convey a covered work under sections 3 and 4 of this License}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+without being bound by section 3 of the GNU GPL.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+2. Conveying Modified Versions.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+If you modify a copy of the Library, and, in your modifications, a}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+facility refers to a function or data to be supplied by an Application}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+that uses the facility (other than as an argument passed when the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+facility is invoked), then you may convey a copy of the modified}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+version:}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+a) under this License, provided that you make a good faith effort to}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+ensure that, in the event an Application does not supply the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+function or data, the facility still operates, and performs}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+whatever part of its purpose remains meaningful, or}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+b) under the GNU GPL, with none of the additional permissions of}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+this License applicable to that copy.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+3. Object Code Incorporating Material from Library Header Files.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+The object code form of an Application may incorporate material from}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+a header file that is part of the Library.  You may convey such object}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+code under terms of your choice, provided that, if the incorporated}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+material is not limited to numerical parameters, data structure}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+layouts and accessors, or small macros, inline functions and templates}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+(ten or fewer lines in length), you do both of the following:}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+a) Give prominent notice with each copy of the object code that the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Library is used in it and that the Library and its use are}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+covered by this License.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+b) Accompany the object code with a copy of the GNU GPL and this license}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+document.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+4. Combined Works.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+You may convey a Combined Work under terms of your choice that,}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+taken together, effectively do not restrict modification of the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+portions of the Library contained in the Combined Work and reverse}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+engineering for debugging such modifications, if you also do each of}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+the following:}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+a) Give prominent notice with each copy of the Combined Work that}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+the Library is used in it and that the Library and its use are}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+covered by this License.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+b) Accompany the Combined Work with a copy of the GNU GPL and this license}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+document.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+c) For a Combined Work that displays copyright notices during}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+execution, include the copyright notice for the Library among}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+these notices, as well as a reference directing the user to the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+copies of the GNU GPL and this license document.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+d) Do one of the following:}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+0) Convey the Minimal Corresponding Source under the terms of this}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+License, and the Corresponding Application Code in a form}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+suitable for, and under terms that permit, the user to}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+recombine or relink the Application with a modified version of}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+the Linked Version to produce a modified Combined Work, in the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+manner specified by section 6 of the GNU GPL for conveying}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Corresponding Source.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+1) Use a suitable shared library mechanism for linking with the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Library.  A suitable mechanism is one that (a) uses at run time}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+a copy of the Library already present on the user's computer}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+system, and (b) will operate properly with a modified version}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+of the Library that is interface-compatible with the Linked}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+       }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Version.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+e) Provide Installation Information, but only if you would otherwise}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+be required to provide such information under section 6 of the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+GNU GPL, and only to the extent that such information is}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+necessary to install and execute a modified version of the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Combined Work produced by recombining or relinking the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Application with a modified version of the Linked Version. (If}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+you use option 4d0, the Installation Information must accompany}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+the Minimal Corresponding Source and Corresponding Application}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Code. If you use option 4d1, you must provide the Installation}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Information in the manner specified by section 6 of the GNU GPL}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+for conveying Corresponding Source.)}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+5. Combined Libraries.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+You may place library facilities that are a work based on the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Library side by side in a single library together with other library}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+facilities that are not Applications and are not covered by this}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+License, and convey such a combined library under terms of your}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+choice, if you do both of the following:}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+a) Accompany the combined library with a copy of the same work based}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+on the Library, uncombined with any other library facilities,}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+conveyed under the terms of this License.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+b) Give prominent notice with the combined library that part of it}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+is a work based on the Library, and explaining where to find the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+   }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+accompanying uncombined form of the same work.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+6. Revised Versions of the GNU Lesser General Public License.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+The Free Software Foundation may publish revised and/or new versions}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+of the GNU Lesser General Public License from time to time. Such new}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+versions will be similar in spirit to the present version, but may}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+differ in detail to address new problems or concerns.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Each version is given a distinguishing version number. If the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Library as you received it specifies that a certain numbered version}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+of the GNU Lesser General Public License "or any later version"}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+applies to it, you have the option of following the terms and}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+conditions either of that published version or of any later version}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+published by the Free Software Foundation. If the Library as you}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+received it does not specify a version number of the GNU Lesser}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+General Public License, you may choose any version of the GNU Lesser}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+General Public License ever published by the Free Software Foundation.}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\rtlch \ltrch\loch
+
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\fs26\loch\f5
+  }{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+If the Library as you received it specifies that a proxy can decide}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+whether future versions of the GNU Lesser General Public License shall}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+apply, that proxy's public statement of acceptance of any version is}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+permanent authorization for you to choose that version for the}
+\par \pard\plain \s0\nowidctlpar{\*\hyphen2\hyphlead2\hyphtrail2\hyphmax0}\cf0\kerning1\dbch\af6\langfe2052\dbch\af7\afs24\alang1081\loch\f3\fs24\lang3084\ql\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720{\cf1\rtlch \ltrch\loch\fs26\loch\f5
+Library.}
+\par }
\ No newline at end of file
diff --git a/installers/osx/PkgResources_x86_64_py36/ReadMe.rtf b/installers/osx/PkgResources_x86_64_py36/ReadMe.rtf
new file mode 100755
index 0000000..d2bd3cd
--- /dev/null
+++ b/installers/osx/PkgResources_x86_64_py36/ReadMe.rtf
@@ -0,0 +1,97 @@
+{\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.7) for python 3.6
+\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.6 (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-36m-darwin.so
+\f1\fs24 \
+
+\f0\fs26 _pyo64.cpython-36m-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, 2017
+\f1\fs24 \
+}
\ No newline at end of file
diff --git a/installers/osx/PkgResources_i386/Welcome.rtf b/installers/osx/PkgResources_x86_64_py36/Welcome.rtf
similarity index 100%
rename from installers/osx/PkgResources_i386/Welcome.rtf
rename to installers/osx/PkgResources_x86_64_py36/Welcome.rtf
diff --git a/installers/osx/PkgResources_x86_64_py36/postinstall b/installers/osx/PkgResources_x86_64_py36/postinstall
new file mode 100755
index 0000000..0e9e5b6
--- /dev/null
+++ b/installers/osx/PkgResources_x86_64_py36/postinstall
@@ -0,0 +1,74 @@
+#! /bin/sh
+
+# Removed older versions in the python site-packages builtin and in the python site-packages from python.org directories
+PATHS=/Library/Python/3.6/site-packages/:/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/
+for path in ${PATHS//:/ }; do
+    if cd $path; then
+        if [ -f pyo.py ]; then
+            sudo rm pyo.py;
+        fi    
+        if [ -f pyo64.py ]; then
+            sudo rm pyo64.py;
+        fi    
+        if [ -f pyo.pyc ]; then
+            sudo rm pyo.pyc;
+        fi    
+        if [ -f pyo64.pyc ]; then
+            sudo rm pyo64.pyc;
+        fi    
+        if [ -f _pyo.cpython-36m-darwin.so ]; then
+            sudo rm _pyo.so;
+        fi    
+        if [ -f _pyo64.cpython-36m-darwin.so ]; then
+            sudo rm _pyo64.so;
+        fi    
+        if [ -d pyolib ]; then
+            sudo rm -rf pyolib/;
+        fi    
+        ls -1 pyo*-info > /dev/null 2>&1
+        if [ "$?" = "0" ]; then
+            sudo rm pyo*-info;
+        fi    
+    fi
+done
+
+# Install pyo in the python site-packages builtin directories
+if cd /Library/Python/3.6/site-packages/; then
+    sudo cp -r /tmp/python36/* .
+else
+    sudo mkdir -p /Library/Python/3.6/site-packages/
+    cd /Library/Python/3.6/site-packages/
+    sudo cp -r /tmp/python36/* .
+fi
+
+# Install pyo in the python.org site-packages directories
+if cd /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/; then  
+    sudo cp -r /tmp/python36/* .
+else
+    sudo mkdir -p /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/
+    cd /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/
+    sudo cp -r /tmp/python36/* .
+fi
+
+# Check if anaconda is already installed and copy files to site-packages directory
+if cd ~/anaconda/lib/python3.6/site-packages/; then  
+    sudo cp -r /tmp/python36/* .
+fi
+
+# Clean up.
+sudo rm -rf /tmp/python36
+
+# Add /usr/local/lib in .bash_profile if not already done
+searchString="/usr/local/lib"
+
+if [ -f ~/.bash_profile ]; then
+    if `cat ~/.bash_profile | grep "${searchString}" 1>/dev/null 2>&1`; then
+        echo "path already in PATH variable";
+    else
+        echo "adding path to .bash_profile..."
+        echo "export PATH=/usr/local/lib:/usr/local/bin:\$PATH" >> ~/.bash_profile;
+    fi
+else
+    echo "creating .bash_profile and adding path to it..."
+    echo "export PATH=/usr/local/lib:/usr/local/bin:\$PATH" > ~/.bash_profile;
+fi
diff --git a/installers/osx/PkgResources_x86_64_py36/postupgrade b/installers/osx/PkgResources_x86_64_py36/postupgrade
new file mode 100755
index 0000000..0e9e5b6
--- /dev/null
+++ b/installers/osx/PkgResources_x86_64_py36/postupgrade
@@ -0,0 +1,74 @@
+#! /bin/sh
+
+# Removed older versions in the python site-packages builtin and in the python site-packages from python.org directories
+PATHS=/Library/Python/3.6/site-packages/:/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/
+for path in ${PATHS//:/ }; do
+    if cd $path; then
+        if [ -f pyo.py ]; then
+            sudo rm pyo.py;
+        fi    
+        if [ -f pyo64.py ]; then
+            sudo rm pyo64.py;
+        fi    
+        if [ -f pyo.pyc ]; then
+            sudo rm pyo.pyc;
+        fi    
+        if [ -f pyo64.pyc ]; then
+            sudo rm pyo64.pyc;
+        fi    
+        if [ -f _pyo.cpython-36m-darwin.so ]; then
+            sudo rm _pyo.so;
+        fi    
+        if [ -f _pyo64.cpython-36m-darwin.so ]; then
+            sudo rm _pyo64.so;
+        fi    
+        if [ -d pyolib ]; then
+            sudo rm -rf pyolib/;
+        fi    
+        ls -1 pyo*-info > /dev/null 2>&1
+        if [ "$?" = "0" ]; then
+            sudo rm pyo*-info;
+        fi    
+    fi
+done
+
+# Install pyo in the python site-packages builtin directories
+if cd /Library/Python/3.6/site-packages/; then
+    sudo cp -r /tmp/python36/* .
+else
+    sudo mkdir -p /Library/Python/3.6/site-packages/
+    cd /Library/Python/3.6/site-packages/
+    sudo cp -r /tmp/python36/* .
+fi
+
+# Install pyo in the python.org site-packages directories
+if cd /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/; then  
+    sudo cp -r /tmp/python36/* .
+else
+    sudo mkdir -p /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/
+    cd /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/
+    sudo cp -r /tmp/python36/* .
+fi
+
+# Check if anaconda is already installed and copy files to site-packages directory
+if cd ~/anaconda/lib/python3.6/site-packages/; then  
+    sudo cp -r /tmp/python36/* .
+fi
+
+# Clean up.
+sudo rm -rf /tmp/python36
+
+# Add /usr/local/lib in .bash_profile if not already done
+searchString="/usr/local/lib"
+
+if [ -f ~/.bash_profile ]; then
+    if `cat ~/.bash_profile | grep "${searchString}" 1>/dev/null 2>&1`; then
+        echo "path already in PATH variable";
+    else
+        echo "adding path to .bash_profile..."
+        echo "export PATH=/usr/local/lib:/usr/local/bin:\$PATH" >> ~/.bash_profile;
+    fi
+else
+    echo "creating .bash_profile and adding path to it..."
+    echo "export PATH=/usr/local/lib:/usr/local/bin:\$PATH" > ~/.bash_profile;
+fi
diff --git a/installers/osx/release_i386.sh b/installers/osx/release_i386.sh
deleted file mode 100644
index 7fc5e31..0000000
--- a/installers/osx/release_i386.sh
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/bin/sh
-
-# Need Xcode 3.2.6 or later (pkgbuild and productbuild)
-# 1. install python (and wxpython) 2.6 and 2.7 (32-bit)
-# 2. update pyo sources
-# 3. compile and install pyo float and double
-# 4. cd utils and build E-Pyo
-# 5. cd installer/osx and build the realease
-
-export PACKAGE_NAME=pyo_0.6.8_i386.pkg
-export DMG_DIR="pyo 0.6.8 Intel"
-export DMG_NAME="pyo_0.6.8_OSX-Intel.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
-export BUILD_RESOURCES=$INSTALLER_DIR/PkgResources/English.lproj
-export PKG_RESOURCES=$INSTALLER_DIR/../PkgResources_i386
-
-mkdir -p $PYO_MODULE_DIR
-mkdir -p $SUPPORT_LIBS_DIR
-mkdir -p $BUILD_RESOURCES
-
-cp $PKG_RESOURCES/License.rtf $BUILD_RESOURCES/License.rtf
-cp $PKG_RESOURCES/Welcome.rtf $BUILD_RESOURCES/Welcome.rtf
-cp $PKG_RESOURCES/ReadMe.rtf $BUILD_RESOURCES/ReadMe.rtf
-
-svn export ../.. installer/pyo-build
-cd installer/pyo-build
-
-echo "building pyo for python 2.6 (32-bit)..."
-sudo /usr/local/bin/python2.6 setup.py install --use-coreaudio --use-double
-
-sudo cp -R build/lib.macosx-10.3-fat-2.6 $PYO_MODULE_DIR/python26
-
-echo "building pyo for python 2.7 (32-bit)..."
-sudo /usr/local/bin/python2.7 setup.py install --use-coreaudio --use-double
-
-sudo cp -R build/lib.macosx-10.3-fat-2.7 $PYO_MODULE_DIR/python27
-
-cd ..
-
-echo "copying support libs..."
-sudo cp /usr/local/lib/liblo.7.dylib $SUPPORT_LIBS_DIR/liblo.7.dylib
-sudo cp /usr/local/lib/libportaudio.2.dylib $SUPPORT_LIBS_DIR/libportaudio.2.dylib
-sudo cp /usr/local/lib/libportmidi.dylib $SUPPORT_LIBS_DIR/libportmidi.dylib
-sudo cp /usr/local/lib/libsndfile.1.dylib $SUPPORT_LIBS_DIR/libsndfile.1.dylib
-sudo cp /usr/local/lib/libFLAC.8.dylib $SUPPORT_LIBS_DIR/libFLAC.8.dylib
-sudo cp /usr/local/lib/libogg.0.dylib $SUPPORT_LIBS_DIR/libogg.0.dylib
-sudo cp /usr/local/lib/libvorbis.0.dylib $SUPPORT_LIBS_DIR/libvorbis.0.dylib
-sudo cp /usr/local/lib/libvorbisenc.2.dylib $SUPPORT_LIBS_DIR/libvorbisenc.2.dylib
-
-echo "setting permissions..."
-
-sudo chgrp -R admin PyoModule/Package_Contents/tmp
-sudo chown -R root PyoModule/Package_Contents/tmp
-sudo chmod -R 755 PyoModule/Package_Contents/tmp
-
-sudo chgrp -R wheel SupportLibs/Package_Contents/usr
-sudo chown -R root SupportLibs/Package_Contents/usr
-sudo chmod -R 755 SupportLibs/Package_Contents/usr
-
-echo "building packages..."
-
-pkgbuild    --identifier com.iact.umontreal.ca.pyo.tmp.pkg \
-            --root PyoModule/Package_Contents/ \
-            --version 1.0 \
-            --scripts $PKG_RESOURCES \
-            PyoModule.pkg
-
-pkgbuild    --identifier com.iact.umontreal.ca.pyo.usr.pkg \
-            --root SupportLibs/Package_Contents/ \
-            --version 1.0 \
-            SupportLibs.pkg
-
-echo "building product..."
-productbuild --distribution ../Distribution.dist --resources $BUILD_RESOURCES $PACKAGE_NAME
-
-echo "assembling DMG..."
-mkdir "$DMG_DIR"
-cd "$DMG_DIR"
-cp ../$PACKAGE_NAME .
-cp -R ../../../../utils/E-Pyo.app .
-ln -s /Applications .
-cd ..
-
-hdiutil create "$DMG_NAME" -srcfolder "$DMG_DIR"
-
-cd ..
-mv installer/$DMG_NAME .
-
-echo "clean up resources..."
-sudo rm -rf installer
-
-
diff --git a/installers/osx/release_x86_64.sh b/installers/osx/release_x86_64.sh
deleted file mode 100644
index 4c21d67..0000000
--- a/installers/osx/release_x86_64.sh
+++ /dev/null
@@ -1,90 +0,0 @@
-#!/bin/sh
-
-export PACKAGE_NAME=pyo_0.6.8_x86_64.pkg
-export DMG_DIR="pyo 0.6.8 Universal"
-export DMG_NAME="pyo_0.6.8_OSX-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
-export BUILD_RESOURCES=$INSTALLER_DIR/PkgResources/English.lproj
-export PKG_RESOURCES=$INSTALLER_DIR/../PkgResources_x86_64
-
-mkdir -p $PYO_MODULE_DIR
-mkdir -p $SUPPORT_LIBS_DIR
-mkdir -p $BUILD_RESOURCES
-
-cp $PKG_RESOURCES/License.rtf $BUILD_RESOURCES/License.rtf
-cp $PKG_RESOURCES/Welcome.rtf $BUILD_RESOURCES/Welcome.rtf
-cp $PKG_RESOURCES/ReadMe.rtf $BUILD_RESOURCES/ReadMe.rtf
-
-svn export ../.. installer/pyo-build
-cd installer/pyo-build
-
-echo "building pyo for python 2.6 (64-bit)..."
-sudo /usr/bin/python setup.py install --use-coreaudio
-
-sudo rm -rf build/temp.macosx-10.6-universal-2.6
-sudo /usr/bin/python setup.py install --use-coreaudio --only-double
-
-sudo cp -R build/lib.macosx-10.6-universal-2.6 $PYO_MODULE_DIR/python26
-
-echo "building pyo for python 2.7 (64-bit)..."
-sudo /usr/local/bin/python2.7 setup.py install --use-coreaudio --use-double
-
-sudo cp -R build/lib.macosx-10.6-intel-2.7 $PYO_MODULE_DIR/python27
-
-cd ..
-
-echo "copying support libs..."
-sudo cp /usr/local/lib/liblo.7.dylib $SUPPORT_LIBS_DIR/liblo.7.dylib
-sudo cp /usr/local/lib/libportaudio.2.dylib $SUPPORT_LIBS_DIR/libportaudio.2.dylib
-sudo cp /usr/local/lib/libportmidi.dylib $SUPPORT_LIBS_DIR/libportmidi.dylib
-sudo cp /usr/local/lib/libsndfile.1.dylib $SUPPORT_LIBS_DIR/libsndfile.1.dylib
-sudo cp /usr/local/lib/libFLAC.8.dylib $SUPPORT_LIBS_DIR/libFLAC.8.dylib
-sudo cp /usr/local/lib/libogg.0.dylib $SUPPORT_LIBS_DIR/libogg.0.dylib
-sudo cp /usr/local/lib/libvorbis.0.dylib $SUPPORT_LIBS_DIR/libvorbis.0.dylib
-sudo cp /usr/local/lib/libvorbisenc.2.dylib $SUPPORT_LIBS_DIR/libvorbisenc.2.dylib
-
-echo "setting permissions..."
-
-sudo chgrp -R admin PyoModule/Package_Contents/tmp
-sudo chown -R root PyoModule/Package_Contents/tmp
-sudo chmod -R 755 PyoModule/Package_Contents/tmp
-
-sudo chgrp -R wheel SupportLibs/Package_Contents/usr
-sudo chown -R root SupportLibs/Package_Contents/usr
-sudo chmod -R 755 SupportLibs/Package_Contents/usr
-
-echo "building packages..."
-
-pkgbuild    --identifier com.iact.umontreal.ca.pyo.tmp.pkg \
-            --root PyoModule/Package_Contents/ \
-            --version 1.0 \
-            --scripts $PKG_RESOURCES \
-            PyoModule.pkg
-
-pkgbuild    --identifier com.iact.umontreal.ca.pyo.usr.pkg \
-            --root SupportLibs/Package_Contents/ \
-            --version 1.0 \
-            SupportLibs.pkg
-
-echo "building product..."
-productbuild --distribution ../Distribution.dist --resources $BUILD_RESOURCES $PACKAGE_NAME
-
-echo "assembling DMG..."
-mkdir "$DMG_DIR"
-cd "$DMG_DIR"
-cp ../$PACKAGE_NAME .
-cp -R ../../../../utils/E-Pyo.app .
-ln -s /Applications .
-cd ..
-
-hdiutil create "$DMG_NAME" -srcfolder "$DMG_DIR"
-
-cd ..
-mv installer/$DMG_NAME .
-
-echo "clean up resources..."
-sudo rm -rf installer
-
-
diff --git a/installers/osx/release_x86_64_py2.sh b/installers/osx/release_x86_64_py2.sh
new file mode 100755
index 0000000..2db031e
--- /dev/null
+++ b/installers/osx/release_x86_64_py2.sh
@@ -0,0 +1,105 @@
+#!/bin/sh
+
+# Need Xcode 3.2.6 or later (pkgbuild and productbuild)
+# with python 2.7.13 (32/64-bit) and wxpython 3.0.2.0 (classic) installed
+
+# 1. update pyo sources
+# 2. compile and install pyo float and double for python2
+# 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.7_x86_64_py2.pkg
+export DMG_DIR="pyo 0.8.7 py2 Universal"
+export DMG_NAME="pyo_0.8.7_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
+export BUILD_RESOURCES=$INSTALLER_DIR/PkgResources/English.lproj
+export PKG_RESOURCES=$INSTALLER_DIR/../PkgResources_x86_64_py2
+
+mkdir -p $PYO_MODULE_DIR
+mkdir -p $SUPPORT_LIBS_DIR
+mkdir -p $BUILD_RESOURCES
+
+cp $PKG_RESOURCES/License.rtf $BUILD_RESOURCES/License.rtf
+cp $PKG_RESOURCES/Welcome.rtf $BUILD_RESOURCES/Welcome.rtf
+cp $PKG_RESOURCES/ReadMe.rtf $BUILD_RESOURCES/ReadMe.rtf
+
+cd ../..
+git checkout-index -a -f --prefix=installers/osx/installer/pyo-build/
+cd installers/osx/installer/pyo-build
+
+echo "building pyo for python 2.7 (64-bit)..."
+sudo /usr/local/bin/python2.7 setup.py install --use-coreaudio --use-double
+
+sudo cp -R build/lib.macosx-10.6-intel-2.7 $PYO_MODULE_DIR/python27
+
+sudo install_name_tool -change /usr/local/opt/portmidi/lib/libportmidi.dylib /usr/local/lib/libportmidi.dylib $PYO_MODULE_DIR/python27/_pyo.so
+sudo install_name_tool -change /usr/local/opt/portmidi/lib/libportmidi.dylib /usr/local/lib/libportmidi.dylib $PYO_MODULE_DIR/python27/_pyo64.so
+sudo install_name_tool -change /usr/local/opt/portaudio/lib/libportaudio.2.dylib /usr/local/lib/libportaudio.2.dylib $PYO_MODULE_DIR/python27/_pyo.so
+sudo install_name_tool -change /usr/local/opt/portaudio/lib/libportaudio.2.dylib /usr/local/lib/libportaudio.2.dylib $PYO_MODULE_DIR/python27/_pyo64.so
+sudo install_name_tool -change /usr/local/opt/liblo/lib/liblo.7.dylib /usr/local/lib/liblo.7.dylib $PYO_MODULE_DIR/python27/_pyo.so
+sudo install_name_tool -change /usr/local/opt/liblo/lib/liblo.7.dylib /usr/local/lib/liblo.7.dylib $PYO_MODULE_DIR/python27/_pyo64.so
+sudo install_name_tool -change /usr/local/opt/libsndfile/lib/libsndfile.1.dylib /usr/local/lib/libsndfile.1.dylib $PYO_MODULE_DIR/python27/_pyo.so
+sudo install_name_tool -change /usr/local/opt/libsndfile/lib/libsndfile.1.dylib /usr/local/lib/libsndfile.1.dylib $PYO_MODULE_DIR/python27/_pyo64.so
+
+cd ..
+
+echo "copying support libs..."
+sudo cp /usr/local/lib/liblo.7.dylib $SUPPORT_LIBS_DIR/liblo.7.dylib
+sudo cp /usr/local/lib/libportaudio.2.dylib $SUPPORT_LIBS_DIR/libportaudio.2.dylib
+sudo cp /usr/local/lib/libportmidi.dylib $SUPPORT_LIBS_DIR/libportmidi.dylib
+sudo cp /usr/local/lib/libsndfile.1.dylib $SUPPORT_LIBS_DIR/libsndfile.1.dylib
+sudo cp /usr/local/lib/libFLAC.8.dylib $SUPPORT_LIBS_DIR/libFLAC.8.dylib
+sudo cp /usr/local/lib/libvorbisenc.2.dylib $SUPPORT_LIBS_DIR/libvorbisenc.2.dylib
+sudo cp /usr/local/lib/libvorbis.0.dylib $SUPPORT_LIBS_DIR/libvorbis.0.dylib
+sudo cp /usr/local/lib/libogg.0.dylib $SUPPORT_LIBS_DIR/libogg.0.dylib
+
+sudo install_name_tool -change /usr/local/opt/flac/lib/libFLAC.8.dylib /usr/local/lib/libFLAC.8.dylib $SUPPORT_LIBS_DIR/libsndfile.1.dylib
+sudo install_name_tool -change /usr/local/opt/libogg/lib/libogg.0.dylib /usr/local/lib/libogg.0.dylib $SUPPORT_LIBS_DIR/libsndfile.1.dylib
+sudo install_name_tool -change /usr/local/opt/libvorbis/lib/libvorbis.0.dylib /usr/local/lib/libvorbis.0.dylib $SUPPORT_LIBS_DIR/libsndfile.1.dylib
+sudo install_name_tool -change /usr/local/opt/libvorbis/lib/libvorbisenc.2.dylib /usr/local/lib/libvorbisenc.2.dylib $SUPPORT_LIBS_DIR/libsndfile.1.dylib
+sudo install_name_tool -change /usr/local/opt/libogg/lib/libogg.0.dylib /usr/local/lib/libogg.0.dylib $SUPPORT_LIBS_DIR/libvorbis.0.dylib
+sudo install_name_tool -change /usr/local/opt/libogg/lib/libogg.0.dylib /usr/local/lib/libogg.0.dylib $SUPPORT_LIBS_DIR/libvorbisenc.2.dylib
+sudo install_name_tool -change /usr/local/Cellar/libvorbis/1.3.5/lib/libvorbis.0.dylib /usr/local/lib/libvorbis.0.dylib $SUPPORT_LIBS_DIR/libvorbisenc.2.dylib
+
+echo "setting permissions..."
+sudo chgrp -R admin PyoModule/Package_Contents/tmp
+sudo chown -R root PyoModule/Package_Contents/tmp
+sudo chmod -R 755 PyoModule/Package_Contents/tmp
+
+sudo chgrp -R wheel SupportLibs/Package_Contents/usr
+sudo chown -R root SupportLibs/Package_Contents/usr
+sudo chmod -R 755 SupportLibs/Package_Contents/usr
+
+echo "building packages..."
+
+pkgbuild    --identifier com.iact.umontreal.ca.pyo.py2.tmp.pkg \
+            --root PyoModule/Package_Contents/ \
+            --version 1.0 \
+            --scripts $PKG_RESOURCES \
+            PyoModule.pkg
+
+pkgbuild    --identifier com.iact.umontreal.ca.pyo.py2.usr.pkg \
+            --root SupportLibs/Package_Contents/ \
+            --version 1.0 \
+            SupportLibs.pkg
+
+echo "building product..."
+productbuild --distribution ../Distribution.dist --resources $BUILD_RESOURCES $PACKAGE_NAME
+
+echo "assembling DMG..."
+mkdir "$DMG_DIR"
+cd "$DMG_DIR"
+cp ../$PACKAGE_NAME .
+cp -R ../../../../utils/E-Pyo_OSX_py2/E-Pyo.app .
+ln -s /Applications .
+cd ..
+
+hdiutil create "$DMG_NAME" -srcfolder "$DMG_DIR"
+
+cd ..
+mv installer/$DMG_NAME .
+
+echo "clean up resources..."
+sudo rm -rf installer
diff --git a/installers/osx/release_x86_64_py3.5.sh b/installers/osx/release_x86_64_py3.5.sh
new file mode 100755
index 0000000..0cee288
--- /dev/null
+++ b/installers/osx/release_x86_64_py3.5.sh
@@ -0,0 +1,107 @@
+#!/bin/sh
+
+# Need Xcode 3.2.6 or later (pkgbuild and productbuild)
+# with python 3.5.4 (32/64-bit) and wxpython 4.0.0b1 (phoenix) installed
+
+# 1. update pyo sources
+# 2. compile and install pyo float and double for python3.5
+# 3. cd utils and build E-Pyo for python3.5
+# 4. cd installers/osx and build the release for python3.5
+
+export PACKAGE_NAME=pyo_0.8.7_x86_64_py35.pkg
+export DMG_DIR="pyo 0.8.7 py35 Universal"
+export DMG_NAME="pyo_0.8.7_OSX_py35-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
+export BUILD_RESOURCES=$INSTALLER_DIR/PkgResources/English.lproj
+export PKG_RESOURCES=$INSTALLER_DIR/../PkgResources_x86_64_py35
+
+mkdir -p $PYO_MODULE_DIR
+mkdir -p $SUPPORT_LIBS_DIR
+mkdir -p $BUILD_RESOURCES
+
+cp $PKG_RESOURCES/License.rtf $BUILD_RESOURCES/License.rtf
+cp $PKG_RESOURCES/Welcome.rtf $BUILD_RESOURCES/Welcome.rtf
+cp $PKG_RESOURCES/ReadMe.rtf $BUILD_RESOURCES/ReadMe.rtf
+
+cd ../..
+git checkout-index -a -f --prefix=installers/osx/installer/pyo-build/
+cd installers/osx/installer/pyo-build
+
+echo "building pyo for python 3.5 (64-bit)..."
+sudo /usr/local/bin/python3.5 setup.py install --use-coreaudio --use-double
+
+sudo cp -R build/lib.macosx-10.6-intel-3.5 $PYO_MODULE_DIR/python35
+
+sudo install_name_tool -change /usr/local/opt/portmidi/lib/libportmidi.dylib /usr/local/lib/libportmidi.dylib $PYO_MODULE_DIR/python35/_pyo.cpython-35m-darwin.so
+sudo install_name_tool -change /usr/local/opt/portmidi/lib/libportmidi.dylib /usr/local/lib/libportmidi.dylib $PYO_MODULE_DIR/python35/_pyo64.cpython-35m-darwin.so
+sudo install_name_tool -change /usr/local/opt/portaudio/lib/libportaudio.2.dylib /usr/local/lib/libportaudio.2.dylib $PYO_MODULE_DIR/python35/_pyo.cpython-35m-darwin.so
+sudo install_name_tool -change /usr/local/opt/portaudio/lib/libportaudio.2.dylib /usr/local/lib/libportaudio.2.dylib $PYO_MODULE_DIR/python35/_pyo64.cpython-35m-darwin.so
+sudo install_name_tool -change /usr/local/opt/liblo/lib/liblo.7.dylib /usr/local/lib/liblo.7.dylib $PYO_MODULE_DIR/python35/_pyo.cpython-35m-darwin.so
+sudo install_name_tool -change /usr/local/opt/liblo/lib/liblo.7.dylib /usr/local/lib/liblo.7.dylib $PYO_MODULE_DIR/python35/_pyo64.cpython-35m-darwin.so
+sudo install_name_tool -change /usr/local/opt/libsndfile/lib/libsndfile.1.dylib /usr/local/lib/libsndfile.1.dylib $PYO_MODULE_DIR/python35/_pyo.cpython-35m-darwin.so
+sudo install_name_tool -change /usr/local/opt/libsndfile/lib/libsndfile.1.dylib /usr/local/lib/libsndfile.1.dylib $PYO_MODULE_DIR/python35/_pyo64.cpython-35m-darwin.so
+
+cd ..
+
+echo "copying support libs..."
+sudo cp /usr/local/lib/liblo.7.dylib $SUPPORT_LIBS_DIR/liblo.7.dylib
+sudo cp /usr/local/lib/libportaudio.2.dylib $SUPPORT_LIBS_DIR/libportaudio.2.dylib
+sudo cp /usr/local/lib/libportmidi.dylib $SUPPORT_LIBS_DIR/libportmidi.dylib
+sudo cp /usr/local/lib/libsndfile.1.dylib $SUPPORT_LIBS_DIR/libsndfile.1.dylib
+sudo cp /usr/local/lib/libFLAC.8.dylib $SUPPORT_LIBS_DIR/libFLAC.8.dylib
+sudo cp /usr/local/lib/libvorbisenc.2.dylib $SUPPORT_LIBS_DIR/libvorbisenc.2.dylib
+sudo cp /usr/local/lib/libvorbis.0.dylib $SUPPORT_LIBS_DIR/libvorbis.0.dylib
+sudo cp /usr/local/lib/libogg.0.dylib $SUPPORT_LIBS_DIR/libogg.0.dylib
+
+sudo install_name_tool -change /usr/local/opt/flac/lib/libFLAC.8.dylib /usr/local/lib/libFLAC.8.dylib $SUPPORT_LIBS_DIR/libsndfile.1.dylib
+sudo install_name_tool -change /usr/local/opt/libogg/lib/libogg.0.dylib /usr/local/lib/libogg.0.dylib $SUPPORT_LIBS_DIR/libsndfile.1.dylib
+sudo install_name_tool -change /usr/local/opt/libvorbis/lib/libvorbis.0.dylib /usr/local/lib/libvorbis.0.dylib $SUPPORT_LIBS_DIR/libsndfile.1.dylib
+sudo install_name_tool -change /usr/local/opt/libvorbis/lib/libvorbisenc.2.dylib /usr/local/lib/libvorbisenc.2.dylib $SUPPORT_LIBS_DIR/libsndfile.1.dylib
+sudo install_name_tool -change /usr/local/opt/libogg/lib/libogg.0.dylib /usr/local/lib/libogg.0.dylib $SUPPORT_LIBS_DIR/libvorbis.0.dylib
+sudo install_name_tool -change /usr/local/opt/libogg/lib/libogg.0.dylib /usr/local/lib/libogg.0.dylib $SUPPORT_LIBS_DIR/libvorbisenc.2.dylib
+sudo install_name_tool -change /usr/local/Cellar/libvorbis/1.3.5/lib/libvorbis.0.dylib /usr/local/lib/libvorbis.0.dylib $SUPPORT_LIBS_DIR/libvorbisenc.2.dylib
+
+echo "setting permissions..."
+sudo chgrp -R admin PyoModule/Package_Contents/tmp
+sudo chown -R root PyoModule/Package_Contents/tmp
+sudo chmod -R 755 PyoModule/Package_Contents/tmp
+
+sudo chgrp -R wheel SupportLibs/Package_Contents/usr
+sudo chown -R root SupportLibs/Package_Contents/usr
+sudo chmod -R 755 SupportLibs/Package_Contents/usr
+
+echo "building packages..."
+
+pkgbuild    --identifier com.iact.umontreal.ca.pyo.py35.tmp.pkg \
+            --root PyoModule/Package_Contents/ \
+            --version 1.0 \
+            --scripts $PKG_RESOURCES \
+            PyoModule.pkg
+
+pkgbuild    --identifier com.iact.umontreal.ca.pyo.py35.usr.pkg \
+            --root SupportLibs/Package_Contents/ \
+            --version 1.0 \
+            SupportLibs.pkg
+
+echo "building product..."
+productbuild --distribution ../Distribution.dist --resources $BUILD_RESOURCES $PACKAGE_NAME
+
+echo "assembling DMG..."
+mkdir "$DMG_DIR"
+cd "$DMG_DIR"
+cp ../$PACKAGE_NAME .
+cp -R ../../../../utils/E-Pyo_OSX_py35/E-Pyo.app .
+ln -s /Applications .
+cd ..
+
+hdiutil create "$DMG_NAME" -srcfolder "$DMG_DIR"
+
+cd ..
+mv installer/$DMG_NAME .
+
+echo "clean up resources..."
+sudo rm -rf installer
+
+
diff --git a/installers/osx/release_x86_64_py3.6.sh b/installers/osx/release_x86_64_py3.6.sh
new file mode 100755
index 0000000..367a5d0
--- /dev/null
+++ b/installers/osx/release_x86_64_py3.6.sh
@@ -0,0 +1,107 @@
+#!/bin/sh
+
+# Need Xcode 3.2.6 or later (pkgbuild and productbuild)
+# with python 3.6.2 (32/64-bit) and wxpython 4.0.0b1 (phoenix) installed
+
+# 1. update pyo sources
+# 2. compile and install pyo float and double for python3.6
+# 3. cd utils and build E-Pyo for python3.6
+# 4. cd installers/osx and build the release for python3.6
+
+export PACKAGE_NAME=pyo_0.8.7_x86_64_py36.pkg
+export DMG_DIR="pyo 0.8.7 py36 Universal"
+export DMG_NAME="pyo_0.8.7_OSX_py36-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
+export BUILD_RESOURCES=$INSTALLER_DIR/PkgResources/English.lproj
+export PKG_RESOURCES=$INSTALLER_DIR/../PkgResources_x86_64_py36
+
+mkdir -p $PYO_MODULE_DIR
+mkdir -p $SUPPORT_LIBS_DIR
+mkdir -p $BUILD_RESOURCES
+
+cp $PKG_RESOURCES/License.rtf $BUILD_RESOURCES/License.rtf
+cp $PKG_RESOURCES/Welcome.rtf $BUILD_RESOURCES/Welcome.rtf
+cp $PKG_RESOURCES/ReadMe.rtf $BUILD_RESOURCES/ReadMe.rtf
+
+cd ../..
+git checkout-index -a -f --prefix=installers/osx/installer/pyo-build/
+cd installers/osx/installer/pyo-build
+
+echo "building pyo for python 3.6 (64-bit)..."
+sudo /usr/local/bin/python3.6 setup.py install --use-coreaudio --use-double
+
+sudo cp -R build/lib.macosx-10.6-intel-3.6 $PYO_MODULE_DIR/python36
+
+sudo install_name_tool -change /usr/local/opt/portmidi/lib/libportmidi.dylib /usr/local/lib/libportmidi.dylib $PYO_MODULE_DIR/python36/_pyo.cpython-36m-darwin.so
+sudo install_name_tool -change /usr/local/opt/portmidi/lib/libportmidi.dylib /usr/local/lib/libportmidi.dylib $PYO_MODULE_DIR/python36/_pyo64.cpython-36m-darwin.so
+sudo install_name_tool -change /usr/local/opt/portaudio/lib/libportaudio.2.dylib /usr/local/lib/libportaudio.2.dylib $PYO_MODULE_DIR/python36/_pyo.cpython-36m-darwin.so
+sudo install_name_tool -change /usr/local/opt/portaudio/lib/libportaudio.2.dylib /usr/local/lib/libportaudio.2.dylib $PYO_MODULE_DIR/python36/_pyo64.cpython-36m-darwin.so
+sudo install_name_tool -change /usr/local/opt/liblo/lib/liblo.7.dylib /usr/local/lib/liblo.7.dylib $PYO_MODULE_DIR/python36/_pyo.cpython-36m-darwin.so
+sudo install_name_tool -change /usr/local/opt/liblo/lib/liblo.7.dylib /usr/local/lib/liblo.7.dylib $PYO_MODULE_DIR/python36/_pyo64.cpython-36m-darwin.so
+sudo install_name_tool -change /usr/local/opt/libsndfile/lib/libsndfile.1.dylib /usr/local/lib/libsndfile.1.dylib $PYO_MODULE_DIR/python36/_pyo.cpython-36m-darwin.so
+sudo install_name_tool -change /usr/local/opt/libsndfile/lib/libsndfile.1.dylib /usr/local/lib/libsndfile.1.dylib $PYO_MODULE_DIR/python36/_pyo64.cpython-36m-darwin.so
+
+cd ..
+
+echo "copying support libs..."
+sudo cp /usr/local/lib/liblo.7.dylib $SUPPORT_LIBS_DIR/liblo.7.dylib
+sudo cp /usr/local/lib/libportaudio.2.dylib $SUPPORT_LIBS_DIR/libportaudio.2.dylib
+sudo cp /usr/local/lib/libportmidi.dylib $SUPPORT_LIBS_DIR/libportmidi.dylib
+sudo cp /usr/local/lib/libsndfile.1.dylib $SUPPORT_LIBS_DIR/libsndfile.1.dylib
+sudo cp /usr/local/lib/libFLAC.8.dylib $SUPPORT_LIBS_DIR/libFLAC.8.dylib
+sudo cp /usr/local/lib/libvorbisenc.2.dylib $SUPPORT_LIBS_DIR/libvorbisenc.2.dylib
+sudo cp /usr/local/lib/libvorbis.0.dylib $SUPPORT_LIBS_DIR/libvorbis.0.dylib
+sudo cp /usr/local/lib/libogg.0.dylib $SUPPORT_LIBS_DIR/libogg.0.dylib
+
+sudo install_name_tool -change /usr/local/opt/flac/lib/libFLAC.8.dylib /usr/local/lib/libFLAC.8.dylib $SUPPORT_LIBS_DIR/libsndfile.1.dylib
+sudo install_name_tool -change /usr/local/opt/libogg/lib/libogg.0.dylib /usr/local/lib/libogg.0.dylib $SUPPORT_LIBS_DIR/libsndfile.1.dylib
+sudo install_name_tool -change /usr/local/opt/libvorbis/lib/libvorbis.0.dylib /usr/local/lib/libvorbis.0.dylib $SUPPORT_LIBS_DIR/libsndfile.1.dylib
+sudo install_name_tool -change /usr/local/opt/libvorbis/lib/libvorbisenc.2.dylib /usr/local/lib/libvorbisenc.2.dylib $SUPPORT_LIBS_DIR/libsndfile.1.dylib
+sudo install_name_tool -change /usr/local/opt/libogg/lib/libogg.0.dylib /usr/local/lib/libogg.0.dylib $SUPPORT_LIBS_DIR/libvorbis.0.dylib
+sudo install_name_tool -change /usr/local/opt/libogg/lib/libogg.0.dylib /usr/local/lib/libogg.0.dylib $SUPPORT_LIBS_DIR/libvorbisenc.2.dylib
+sudo install_name_tool -change /usr/local/Cellar/libvorbis/1.3.5/lib/libvorbis.0.dylib /usr/local/lib/libvorbis.0.dylib $SUPPORT_LIBS_DIR/libvorbisenc.2.dylib
+
+echo "setting permissions..."
+sudo chgrp -R admin PyoModule/Package_Contents/tmp
+sudo chown -R root PyoModule/Package_Contents/tmp
+sudo chmod -R 755 PyoModule/Package_Contents/tmp
+
+sudo chgrp -R wheel SupportLibs/Package_Contents/usr
+sudo chown -R root SupportLibs/Package_Contents/usr
+sudo chmod -R 755 SupportLibs/Package_Contents/usr
+
+echo "building packages..."
+
+pkgbuild    --identifier com.iact.umontreal.ca.pyo.py36.tmp.pkg \
+            --root PyoModule/Package_Contents/ \
+            --version 1.0 \
+            --scripts $PKG_RESOURCES \
+            PyoModule.pkg
+
+pkgbuild    --identifier com.iact.umontreal.ca.pyo.py36.usr.pkg \
+            --root SupportLibs/Package_Contents/ \
+            --version 1.0 \
+            SupportLibs.pkg
+
+echo "building product..."
+productbuild --distribution ../Distribution.dist --resources $BUILD_RESOURCES $PACKAGE_NAME
+
+echo "assembling DMG..."
+mkdir "$DMG_DIR"
+cd "$DMG_DIR"
+cp ../$PACKAGE_NAME .
+cp -R ../../../../utils/E-Pyo_OSX_py36/E-Pyo.app .
+ln -s /Applications .
+cd ..
+
+hdiutil create "$DMG_NAME" -srcfolder "$DMG_DIR"
+
+cd ..
+mv installer/$DMG_NAME .
+
+echo "clean up resources..."
+sudo rm -rf installer
+
+
diff --git a/installers/win/README-win32-py26.txt b/installers/win/README-win32-py26.txt
index bbe9866..e482de4 100644
--- a/installers/win/README-win32-py26.txt
+++ b/installers/win/README-win32-py26.txt
@@ -4,7 +4,7 @@ Pyo is a Python module written in C to help digital signal processing script cre
 
 http://www.python.org/download/releases/2.6.6/
 
-To use the WxPython toolkit for widgets, you need to install wxPython2.8-win32-unicode-py26:
+To use the WxPython toolkit for widgets, you need to install wxPython 3.0 for python 2.6:
 
 http://www.wxpython.org/download.php#stable
 
@@ -13,8 +13,8 @@ it's a good starting point to explore the library!
 
 In a Command Prompt:
 
-cd Desktop\pyo_examples
-python xnoise_example.py
+cd Desktop\pyo_examples\algorithmic
+python 01_music_box.py
 
 Please, send comments and bugs to:
 
diff --git a/installers/win/README-win32-py27.txt b/installers/win/README-win32-py27.txt
index 872130e..eddb84d 100644
--- a/installers/win/README-win32-py27.txt
+++ b/installers/win/README-win32-py27.txt
@@ -4,7 +4,7 @@ Pyo is a Python module written in C to help digital signal processing script cre
 
 http://www.python.org/download/
 
-To use the WxPython toolkit for widgets, you need to install wxPython2.8-win32-unicode-py27:
+To use the WxPython toolkit for widgets, you need to install wxPython 3.0 for python 2.7:
 
 http://www.wxpython.org/download.php#stable
 
@@ -13,8 +13,8 @@ it's a good starting point to explore the library!
 
 In a Command Prompt:
 
-cd Desktop\pyo_examples
-python xnoise_example.py
+cd Desktop\pyo_examples\algorithmic
+python 01_music_box.py
 
 Please, send comments and bugs to:
 
diff --git a/installers/win/README-win32-py27.txt b/installers/win/README-win32-py35.txt
similarity index 73%
copy from installers/win/README-win32-py27.txt
copy to installers/win/README-win32-py35.txt
index 872130e..a1cd9e3 100644
--- a/installers/win/README-win32-py27.txt
+++ b/installers/win/README-win32-py35.txt
@@ -1,21 +1,21 @@
-Pyo is a Python module written in C to help digital signal processing script creation.
-
-* Python 2.7 must be installed on your system before running this installer. *
-
-http://www.python.org/download/
-
-To use the WxPython toolkit for widgets, you need to install wxPython2.8-win32-unicode-py27:
-
-http://www.wxpython.org/download.php#stable
-
-This installer will leave a folder called pyo_examples on the Desktop, 
-it's a good starting point to explore the library!
-
-In a Command Prompt:
-
-cd Desktop\pyo_examples
-python xnoise_example.py
-
-Please, send comments and bugs to:
-
-belangeo at gmail.com
+Pyo is a Python module written in C to help digital signal processing script creation.
+
+* Python 3.5 must be installed on your system before running this installer. *
+
+http://www.python.org/download/
+
+To use the WxPython toolkit for widgets, you need to install wxPython Phoenix (3.0.3+) for python 3.5:
+
+http://www.wxpython.org/download.php#stable
+
+This installer will leave a folder called pyo_examples on the Desktop, 
+it's a good starting point to explore the library!
+
+In a Command Prompt:
+
+cd Desktop\pyo_examples\algorithmic
+python 01_music_box.py
+
+Please, send comments and bugs to:
+
+belangeo at gmail.com
diff --git a/installers/win/README-win32-py27.txt b/installers/win/README-win32-py36.txt
similarity index 73%
copy from installers/win/README-win32-py27.txt
copy to installers/win/README-win32-py36.txt
index 872130e..4b83913 100644
--- a/installers/win/README-win32-py27.txt
+++ b/installers/win/README-win32-py36.txt
@@ -1,21 +1,21 @@
-Pyo is a Python module written in C to help digital signal processing script creation.
-
-* Python 2.7 must be installed on your system before running this installer. *
-
-http://www.python.org/download/
-
-To use the WxPython toolkit for widgets, you need to install wxPython2.8-win32-unicode-py27:
-
-http://www.wxpython.org/download.php#stable
-
-This installer will leave a folder called pyo_examples on the Desktop, 
-it's a good starting point to explore the library!
-
-In a Command Prompt:
-
-cd Desktop\pyo_examples
-python xnoise_example.py
-
-Please, send comments and bugs to:
-
-belangeo at gmail.com
+Pyo is a Python module written in C to help digital signal processing script creation.
+
+* Python 3.6 must be installed on your system before running this installer. *
+
+http://www.python.org/download/
+
+To use the WxPython toolkit for widgets, you need to install wxPython Phoenix (4.0.0b1+) for python 3.6:
+
+http://www.wxpython.org/download.php#stable
+
+This installer will leave a folder called pyo_examples on the Desktop, 
+it's a good starting point to explore the library!
+
+In a Command Prompt:
+
+cd Desktop\pyo_examples\algorithmic
+python 01_music_box.py
+
+Please, send comments and bugs to:
+
+belangeo at gmail.com
diff --git a/installers/win/build_installers_win.bat b/installers/win/build_installers_win.bat
index 0861ba3..cc6c15f 100644
--- a/installers/win/build_installers_win.bat
+++ b/installers/win/build_installers_win.bat
@@ -1,7 +1,10 @@
 echo off
 
-echo *** Build installer for python2.6 ***
-Compil32 /cc "win_installer_py26.iss"
-
 echo *** Build installer for python2.7 ***
 Compil32 /cc "win_installer_py27.iss"
+
+echo *** Build installer for python3.5 ***
+Compil32 /cc "win_installer_py35.iss"
+
+echo *** Build installer for python3.6 ***
+Compil32 /cc "win_installer_py36.iss"
diff --git a/installers/win/win_installer_py26.iss b/installers/win/win_installer_py26.iss
index 1d24ca6..1ac3b9d 100644
--- a/installers/win/win_installer_py26.iss
+++ b/installers/win/win_installer_py26.iss
@@ -1,55 +1,62 @@
 ; Script generated by the Inno Setup Script Wizard.
 ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
+
+#define appName "pyo"
+#define pyVer "2.6"
+#define appVer "0.8.0"
 
 [Setup]
 ; NOTE: The value of AppId uniquely identifies this application.
 ; Do not use the same AppId value in installers for other applications.
 ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
-AppId={{4F72B6EF-CFA0-434F-A2B4-B130F94F54EB}
-AppName=Pyo
-AppVersion=0.6.8
-AppPublisher=iACT.umontreal.ca
-AppPublisherURL=http://code.google.com/p/pyo
-AppSupportURL=http://code.google.com/p/pyo
-AppUpdatesURL=http://code.google.com/p/pyo
-DefaultDirName={sd}\Python26
-DisableDirPage=yes
-DefaultGroupName=pyo
-AllowNoIcons=yes
-InfoBeforeFile=C:\Documents and Settings\user\svn\pyo\installers\win\\README-win32-py26.txt
-OutputBaseFilename=pyo_0.6.8_py2.6_setup
+AppId={{AC79C5C4-BE36-419E-B94A-98C6D0DCF4B9}
+AppName={#appName}
+AppVersion={#appVer}
+AppPublisher=ajaxsoundstudio.com
+AppPublisherURL=https://github.com/belangeo/pyo
+AppSupportURL=https://github.com/belangeo/pyo
+AppUpdatesURL=https://github.com/belangeo/pyo
+DefaultDirName={code:GetDirName}
+DisableDirPage=no
+AlwaysShowDirOnReadyPage=yes
+DefaultGroupName={#appName}
+AllowNoIcons=yes
+InfoBeforeFile=C:\Users\olivier\git\pyo\installers\win\\README-win32-py26.txt
+LicenseFile=C:\Users\olivier\git\pyo\COPYING.txt
+OutputBaseFilename={#appName}_{#appVer}_py{#pyVer}_setup
 Compression=lzma
 SolidCompression=yes
 ChangesAssociations=yes
 ChangesEnvironment=yes
+DirExistsWarning=no
+SetupIconFile=C:\Users\olivier\git\pyo\utils\E-PyoIcon.ico
 
 [Languages]
 Name: "english"; MessagesFile: "compiler:Default.isl"
 
 ; should use PYTHONPATH variable
 [Files]
-Source: "C:\Python26\Lib\site-packages\pyo.py"; DestDir: "{sd}\Python26\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\Python26\Lib\site-packages\pyo64.py"; DestDir: "{sd}\Python26\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\Python26\Lib\site-packages\pyolib\*"; DestDir: "{sd}\Python26\Lib\site-packages\pyolib"; Flags: ignoreversion recursesubdirs createallsubdirs
-Source: "C:\Python26\Lib\site-packages\_pyo.pyd"; DestDir: "{sd}\Python26\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\Python26\Lib\site-packages\_pyo64.pyd"; DestDir: "{sd}\Python26\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\Python26\Lib\site-packages\libsndfile-1.dll"; DestDir: "{sd}\Python26\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\Python26\Lib\site-packages\lo.dll"; DestDir: "{sd}\Python26\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\Python26\Lib\site-packages\portaudio.dll"; DestDir: "{sd}\Python26\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\Python26\Lib\site-packages\portmidi.dll"; DestDir: "{sd}\Python26\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\Python26\Lib\site-packages\porttime.dll"; DestDir: "{sd}\Python26\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\Python26\Lib\site-packages\pthreadVC2.dll"; DestDir: "{sd}\Python26\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\Python26\Lib\site-packages\msvcr90.dll"; DestDir: "{sd}\Python26\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\MinGW\bin\libgcc_s_dw2-1.dll"; DestDir: "{sd}\Python26\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\MinGW\bin\libstdc++-6.dll"; DestDir: "{sd}\Python26\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\Python26\Lib\site-packages\pyo-0.6.8-py2.6.egg-info"; DestDir: "{sd}\Python26\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\Documents and Settings\user\svn\pyo\examples\*"; DestDir: "{userdesktop}\pyo_examples\"; Flags: ignoreversion recursesubdirs createallsubdirs
-Source: "C:\Documents and Settings\user\svn\pyo\installers\win\README-win32-py26.txt"; DestDir: "{userdesktop}"; Flags: ignoreversion
+Source: "C:\Python26\Lib\site-packages\pyo.py"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Python26\Lib\site-packages\pyo64.py"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Python26\Lib\site-packages\pyolib\*"; DestDir: "{app}\Lib\site-packages\pyolib"; Flags: ignoreversion recursesubdirs createallsubdirs
+Source: "C:\Python26\Lib\site-packages\_pyo.pyd"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Python26\Lib\site-packages\_pyo64.pyd"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Python26\Lib\site-packages\libsndfile-1.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Python26\Lib\site-packages\lo.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Python26\Lib\site-packages\portaudio.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Python26\Lib\site-packages\portmidi.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Python26\Lib\site-packages\porttime.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Python26\Lib\site-packages\pthreadVC2.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Python26\Lib\site-packages\msvcr90.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\MinGW\bin\libgcc_s_dw2-1.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\MinGW\bin\libstdc++-6.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Python26\Lib\site-packages\pyo-{#appVer}-py{#pyVer}.egg-info"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\git\pyo\examples\*"; DestDir: "{userdesktop}\pyo_examples\"; Flags: ignoreversion recursesubdirs createallsubdirs
 ; NOTE: Don't use "Flags: ignoreversion" on any shared system files
 
 ; E-Pyo stuff
-Source: "C:\Documents and Settings\user\svn\pyo\utils\E-Pyo_py26\E-Pyo.exe"; DestDir: "{pf}\E-Pyo"; Flags: ignoreversion
-Source: "C:\Documents and Settings\user\svn\pyo\utils\E-Pyo_py26\Resources\*"; DestDir: "{pf}\E-Pyo\Resources"; Flags: ignoreversion recursesubdirs createallsubdirs
+Source: "C:\Users\olivier\git\pyo\utils\E-Pyo_py26\E-Pyo.exe"; DestDir: "{pf}\E-Pyo"; Flags: ignoreversion
+Source: "C:\Users\olivier\git\pyo\utils\E-Pyo_py26\Resources\*"; DestDir: "{pf}\E-Pyo\Resources"; Flags: ignoreversion recursesubdirs createallsubdirs
 
 [Tasks]
 Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"
@@ -67,9 +74,12 @@ Type: filesandordirs; Name: "{userdocs}\.epyo";
 ;;;;;;;;;;;;;
 
 [Registry]
-Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; ValueName: "Path"; ValueData: "C:\Python26;{olddata}"; Check: NeedsAddPath('C:\Python26')
+Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; ValueName: "Path"; ValueData: "C:\Python26;{olddata}"; Check: NeedsAddPath('{app}')
 
 [Code]
+procedure ExitProcess(exitCode:integer);
+  external 'ExitProcess at kernel32.dll stdcall';
+
 function NeedsAddPath(Param: string): boolean;
 var
   OrigPath: string;
@@ -86,6 +96,37 @@ begin
   Result := Pos(';' + Param + ';', ';' + OrigPath + ';') = 0;
 end;
 
-
+function GetDirName(Value: string): string;
+var          
+  InstallPath: string;
+  reg1 : string;
+  reg2 : string;
+  reg3 : string;
+  reg4 : string;
+begin
+  reg1 := 'SOFTWARE\Python\PythonCore\' + '{#PyVer}' + '\InstallPath';
+  reg2 := 'SOFTWARE\Wow6432Node\Python\PythonCore\' + '{#PyVer}' + '\InstallPath';
+  reg3 := 'Software\Python\PythonCore\' + '{#PyVer}' + '\InstallPath';
+  reg4 := 'Software\Wow6432Node\Python\PythonCore\' + '{#PyVer}' + '\InstallPath';
+  if RegQueryStringValue(HKLM, reg1, '', InstallPath) then
+    BEGIN
+    Result := InstallPath;
+  END else
+  if RegQueryStringValue(HKCU, reg3, '', InstallPath) then
+    BEGIN
+    Result := InstallPath;
+  END else
+  if RegQueryStringValue(HKLM, reg2, '', InstallPath) then
+    BEGIN
+    Result := InstallPath;
+  END else
+  if RegQueryStringValue(HKCU, reg4, '', InstallPath) then
+    BEGIN
+    Result := InstallPath;
+  END else
+    BEGIN
+    Result := 'C:\Python26';
+   END
+end;
 
 
diff --git a/installers/win/win_installer_py27.iss b/installers/win/win_installer_py27.iss
index 6b0cf86..20209f8 100644
--- a/installers/win/win_installer_py27.iss
+++ b/installers/win/win_installer_py27.iss
@@ -1,54 +1,63 @@
 ; Script generated by the Inno Setup Script Wizard.
 ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
+
+#define appName "pyo"
+#define pyVer "2.7"
+#define appVer "0.8.7"
 
 [Setup]
 ; NOTE: The value of AppId uniquely identifies this application.
 ; Do not use the same AppId value in installers for other applications.
 ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
-AppId={{244D309A-C251-481A-AD24-0602D392A634}
-AppName=Pyo
-AppVersion=0.6.8
-AppPublisher=iACT.umontreal.ca
-AppPublisherURL=http://code.google.com/p/pyo
-AppSupportURL=http://code.google.com/p/pyo
-AppUpdatesURL=http://code.google.com/p/pyo
-DefaultDirName={sd}\Python27
-DisableDirPage=yes
-DefaultGroupName=pyo
+AppId={{59447873-F994-4BC7-8B1D-0DDCA5B6AFFD}
+AppName={#appName}
+AppVersion={#appVer}
+AppPublisher=ajaxsoundstudio.com
+AppPublisherURL=https://github.com/belangeo/pyo
+AppSupportURL=https://github.com/belangeo/pyo
+AppUpdatesURL=https://github.com/belangeo/pyo
+DefaultDirName={code:GetDirName}
+DisableDirPage=no
+AlwaysShowDirOnReadyPage=yes
+DefaultGroupName={#appName}
 AllowNoIcons=yes
-InfoBeforeFile=C:\Documents and Settings\user\svn\pyo\installers\win\\README-win32-py27.txt
-OutputBaseFilename=pyo_0.6.8_py2.7_setup
+InfoBeforeFile=C:\Users\olivier\git\pyo\installers\win\\README-win32-py27.txt
+LicenseFile=C:\Users\olivier\git\pyo\COPYING.txt
+OutputBaseFilename={#appName}_{#appVer}_py{#pyVer}_setup
 Compression=lzma
 SolidCompression=yes
 ChangesAssociations=yes
-ChangesEnvironment=yes
+ChangesEnvironment=yes
+DirExistsWarning=no
+SetupIconFile=C:\Users\olivier\git\pyo\utils\E-PyoIcon.ico
 
 [Languages]
 Name: "english"; MessagesFile: "compiler:Default.isl"
 
 [Files]
-Source: "C:\Python27\Lib\site-packages\pyo.py"; DestDir: "{sd}\Python27\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\Python27\Lib\site-packages\pyo64.py"; DestDir: "{sd}\Python27\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\Python27\Lib\site-packages\pyolib\*"; DestDir: "{sd}\Python27\Lib\site-packages\pyolib"; Flags: ignoreversion recursesubdirs createallsubdirs
-Source: "C:\Python27\Lib\site-packages\_pyo.pyd"; DestDir: "{sd}\Python27\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\Python27\Lib\site-packages\_pyo64.pyd"; DestDir: "{sd}\Python27\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\Python27\Lib\site-packages\libsndfile-1.dll"; DestDir: "{sd}\Python27\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\Python27\Lib\site-packages\lo.dll"; DestDir: "{sd}\Python27\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\Python27\Lib\site-packages\portaudio.dll"; DestDir: "{sd}\Python27\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\Python27\Lib\site-packages\portmidi.dll"; DestDir: "{sd}\Python27\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\Python27\Lib\site-packages\porttime.dll"; DestDir: "{sd}\Python27\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\Python27\Lib\site-packages\pthreadVC2.dll"; DestDir: "{sd}\Python27\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\Python27\Lib\site-packages\msvcr90.dll"; DestDir: "{sd}\Python27\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\MinGW\bin\libgcc_s_dw2-1.dll"; DestDir: "{sd}\Python27\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\MinGW\bin\libstdc++-6.dll"; DestDir: "{sd}\Python27\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\Python27\Lib\site-packages\pyo-0.6.8-py2.7.egg-info"; DestDir: "{sd}\Python27\Lib\site-packages"; Flags: ignoreversion
-Source: "C:\Documents and Settings\user\svn\pyo\examples\*"; DestDir: "{userdesktop}\pyo_examples\"; Flags: ignoreversion recursesubdirs createallsubdirs
-Source: "C:\Documents and Settings\user\svn\pyo\installers\win\README-win32-py27.txt"; DestDir: "{userdesktop}"; Flags: ignoreversion
+Source: "C:\Python27\Lib\site-packages\pyo.py"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion 
+Source: "C:\Python27\Lib\site-packages\pyo64.py"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Python27\Lib\site-packages\pyolib\*"; DestDir: "{app}\Lib\site-packages\pyolib"; Flags: ignoreversion recursesubdirs createallsubdirs
+Source: "C:\Python27\Lib\site-packages\_pyo.pyd"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Python27\Lib\site-packages\_pyo64.pyd"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Python27\Lib\site-packages\libsndfile-1.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Python27\Lib\site-packages\liblo-7.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Python27\Lib\site-packages\portaudio.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Python27\Lib\site-packages\portmidi.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Python27\Lib\site-packages\porttime.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Python27\Lib\site-packages\pthreadGC2.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Python27\Lib\site-packages\pthreadVC2.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Python27\Lib\site-packages\msvcr90.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Python27\Lib\site-packages\msvcr100.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\MinGW\bin\libgcc_s_dw2-1.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\MinGW\bin\libstdc++-6.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Python27\Lib\site-packages\pyo-{#appVer}-py{#pyVer}.egg-info"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\git\pyo\examples\*"; DestDir: "{userdesktop}\pyo_examples\"; Flags: ignoreversion recursesubdirs createallsubdirs
 ; NOTE: Don't use "Flags: ignoreversion" on any shared system files
 
 ; E-Pyo stuff
-Source: "C:\Documents and Settings\user\svn\pyo\utils\E-Pyo_py27\E-Pyo.exe"; DestDir: "{pf}\E-Pyo"; Flags: ignoreversion
-Source: "C:\Documents and Settings\user\svn\pyo\utils\E-Pyo_py27\Resources\*"; DestDir: "{pf}\E-Pyo\Resources"; Flags: ignoreversion recursesubdirs createallsubdirs
+Source: "C:\Users\olivier\git\pyo\utils\E-Pyo_py27\E-Pyo.exe"; DestDir: "{pf}\E-Pyo"; Flags: ignoreversion
+Source: "C:\Users\olivier\git\pyo\utils\E-Pyo_py27\Resources\*"; DestDir: "{pf}\E-Pyo\Resources"; Flags: ignoreversion recursesubdirs createallsubdirs
 
 [Tasks]
 Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"
@@ -66,9 +75,12 @@ Type: filesandordirs; Name: "{userdocs}\.epyo";
 ;;;;;;;;;;;;;
 
 [Registry]
-Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; ValueName: "Path"; ValueData: "C:\Python27;{olddata}"; Check: NeedsAddPath('C:\Python27')
+Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; ValueName: "Path"; ValueData: "{app};{olddata}"; Check: NeedsAddPath('{app}')
 
 [Code]
+procedure ExitProcess(exitCode:integer);
+  external 'ExitProcess at kernel32.dll stdcall';
+
 function NeedsAddPath(Param: string): boolean;
 var
   OrigPath: string;
@@ -84,3 +96,36 @@ begin
   // Pos() returns 0 if not found
   Result := Pos(';' + Param + ';', ';' + OrigPath + ';') = 0;
 end;
+
+function GetDirName(Value: string): string;
+var          
+  InstallPath: string;
+  reg1 : string;
+  reg2 : string;
+  reg3 : string;
+  reg4 : string;
+begin
+  reg1 := 'SOFTWARE\Python\PythonCore\' + '{#PyVer}' + '\InstallPath';
+  reg2 := 'SOFTWARE\Wow6432Node\Python\PythonCore\' + '{#PyVer}' + '\InstallPath';
+  reg3 := 'Software\Python\PythonCore\' + '{#PyVer}' + '\InstallPath';
+  reg4 := 'Software\Wow6432Node\Python\PythonCore\' + '{#PyVer}' + '\InstallPath';
+  if RegQueryStringValue(HKLM, reg1, '', InstallPath) then
+    BEGIN
+    Result := InstallPath;
+  END else
+  if RegQueryStringValue(HKCU, reg3, '', InstallPath) then
+    BEGIN
+    Result := InstallPath;
+  END else
+  if RegQueryStringValue(HKLM, reg2, '', InstallPath) then
+    BEGIN
+    Result := InstallPath;
+  END else
+  if RegQueryStringValue(HKCU, reg4, '', InstallPath) then
+    BEGIN
+    Result := InstallPath;
+  END else
+    BEGIN
+    Result := 'C:\Python27';
+   END
+end;
\ No newline at end of file
diff --git a/installers/win/win_installer_py35.iss b/installers/win/win_installer_py35.iss
new file mode 100644
index 0000000..92468e2
--- /dev/null
+++ b/installers/win/win_installer_py35.iss
@@ -0,0 +1,133 @@
+; Script generated by the Inno Setup Script Wizard.
+; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
+
+#define appName "pyo"
+#define pyVer "3.5"
+#define appVer "0.8.7"
+
+[Setup]
+; NOTE: The value of AppId uniquely identifies this application.
+; Do not use the same AppId value in installers for other applications.
+; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
+AppId={{D9B062A3-AFAE-4FC0-9603-CE4FCA106382}
+AppName={#appName}
+AppVersion={#appVer}
+AppPublisher=ajaxsoundstudio.com
+AppPublisherURL=https://github.com/belangeo/pyo
+AppSupportURL=https://github.com/belangeo/pyo
+AppUpdatesURL=https://github.com/belangeo/pyo
+DefaultDirName={code:GetDirName}
+DisableDirPage=no
+AlwaysShowDirOnReadyPage=yes
+DefaultGroupName={#appName}
+AllowNoIcons=yes
+InfoBeforeFile=C:\Users\olivier\git\pyo\installers\win\\README-win32-py35.txt
+LicenseFile=C:\Users\olivier\git\pyo\COPYING.txt
+OutputBaseFilename={#appName}_{#appVer}_py{#pyVer}_setup
+Compression=lzma
+SolidCompression=yes
+ChangesAssociations=yes
+ChangesEnvironment=yes
+DirExistsWarning=no
+SetupIconFile=C:\Users\olivier\git\pyo\utils\E-PyoIcon.ico
+
+[Languages]
+Name: "english"; MessagesFile: "compiler:Default.isl"
+
+[Files]
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python35-32\Lib\site-packages\pyo.py"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion 
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python35-32\Lib\site-packages\pyo64.py"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python35-32\Lib\site-packages\pyolib\*"; DestDir: "{app}\Lib\site-packages\pyolib"; Flags: ignoreversion recursesubdirs createallsubdirs
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python35-32\Lib\site-packages\_pyo.cp35-win32.pyd"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python35-32\Lib\site-packages\_pyo64.cp35-win32.pyd"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python35-32\Lib\site-packages\libsndfile-1.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python35-32\Lib\site-packages\liblo-7.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python35-32\Lib\site-packages\portaudio.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python35-32\Lib\site-packages\portmidi.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python35-32\Lib\site-packages\porttime.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python35-32\Lib\site-packages\pthreadVC2.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python35-32\Lib\site-packages\pthreadGC2.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python35-32\Lib\site-packages\dcomp.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python35-32\Lib\site-packages\gpsvc.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python35-32\Lib\site-packages\sysntfy.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python35-32\Lib\site-packages\msvcr100.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\MinGW\bin\libgcc_s_dw2-1.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\MinGW\bin\libstdc++-6.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python35-32\Lib\site-packages\pyo-{#appVer}-py{#pyVer}.egg-info"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\git\pyo\examples\*"; DestDir: "{userdesktop}\pyo_examples\"; Flags: ignoreversion recursesubdirs createallsubdirs
+; NOTE: Don't use "Flags: ignoreversion" on any shared system files
+
+; E-Pyo stuff
+Source: "C:\Users\olivier\git\pyo\utils\E-Pyo_py35\E-Pyo.exe"; DestDir: "{pf}\E-Pyo"; Flags: ignoreversion
+Source: "C:\Users\olivier\git\pyo\utils\E-Pyo_py35\Resources\*"; DestDir: "{pf}\E-Pyo\Resources"; Flags: ignoreversion recursesubdirs createallsubdirs
+
+[Tasks]
+Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"
+
+[Icons]
+Name: "{group}\E-Pyo"; Filename: "{pf}\E-Pyo\E-Pyo.exe"; WorkingDir: "{pf}\E-Pyo"
+Name: "{commondesktop}\E-Pyo"; Filename: "{pf}\E-Pyo\E-Pyo.exe"; Tasks: desktopicon
+
+[Run]
+Filename: "{pf}\E-Pyo\E-Pyo.exe"; Description: "{cm:LaunchProgram,E-Pyo}"; Flags: nowait postinstall skipifsilent
+
+[InstallDelete]
+Type: filesandordirs; Name: "{userdesktop}\pyo_examples";
+Type: filesandordirs; Name: "{userdocs}\.epyo";
+;;;;;;;;;;;;;
+
+[Registry]
+Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; ValueName: "Path"; ValueData: "{app};{olddata}"; Check: NeedsAddPath('{app}')
+
+[Code]
+procedure ExitProcess(exitCode:integer);
+  external 'ExitProcess at kernel32.dll stdcall';
+
+function NeedsAddPath(Param: string): boolean;
+var
+  OrigPath: string;
+begin
+  if not RegQueryStringValue(HKEY_LOCAL_MACHINE,
+    'SYSTEM\CurrentControlSet\Control\Session Manager\Environment',
+    'Path', OrigPath)
+  then begin
+    Result := True;
+    exit;
+  end;
+  // look for the path with leading and trailing semicolon
+  // Pos() returns 0 if not found
+  Result := Pos(';' + Param + ';', ';' + OrigPath + ';') = 0;
+end;
+
+function GetDirName(Value: string): string;
+var          
+  InstallPath: string;
+  reg1 : string;
+  reg2 : string;
+  reg3 : string;
+  reg4 : string;
+begin
+  reg1 := 'SOFTWARE\Python\PythonCore\' + '{#PyVer}' + '-32\InstallPath';
+  reg2 := 'SOFTWARE\Wow6432Node\Python\PythonCore\' + '{#PyVer}' + '-32\InstallPath';
+  reg3 := 'Software\Python\PythonCore\' + '{#PyVer}' + '-32\InstallPath';
+  reg4 := 'Software\Wow6432Node\Python\PythonCore\' + '{#PyVer}' + '-32\InstallPath';
+  if RegQueryStringValue(HKLM, reg1, '', InstallPath) then
+    BEGIN
+    Result := InstallPath;
+  END else
+  if RegQueryStringValue(HKCU, reg3, '', InstallPath) then
+    BEGIN
+    Result := InstallPath;
+  END else
+  if RegQueryStringValue(HKLM, reg2, '', InstallPath) then
+    BEGIN
+    Result := InstallPath;
+  END else
+  if RegQueryStringValue(HKCU, reg4, '', InstallPath) then
+    BEGIN
+    Result := InstallPath;
+  END else
+    BEGIN
+    Result := 'C:\Python35-32';
+   END
+end;
\ No newline at end of file
diff --git a/installers/win/win_installer_py36.iss b/installers/win/win_installer_py36.iss
new file mode 100644
index 0000000..920f1a8
--- /dev/null
+++ b/installers/win/win_installer_py36.iss
@@ -0,0 +1,133 @@
+; Script generated by the Inno Setup Script Wizard.
+; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
+
+#define appName "pyo"
+#define pyVer "3.6"
+#define appVer "0.8.7"
+
+[Setup]
+; NOTE: The value of AppId uniquely identifies this application.
+; Do not use the same AppId value in installers for other applications.
+; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
+AppId={{C33D5687-694D-4000-AF85-191E2DC66F64}
+AppName={#appName}
+AppVersion={#appVer}
+AppPublisher=ajaxsoundstudio.com
+AppPublisherURL=https://github.com/belangeo/pyo
+AppSupportURL=https://github.com/belangeo/pyo
+AppUpdatesURL=https://github.com/belangeo/pyo
+DefaultDirName={code:GetDirName}
+DisableDirPage=no
+AlwaysShowDirOnReadyPage=yes
+DefaultGroupName={#appName}
+AllowNoIcons=yes
+InfoBeforeFile=C:\Users\olivier\git\pyo\installers\win\\README-win32-py36.txt
+LicenseFile=C:\Users\olivier\git\pyo\COPYING.txt
+OutputBaseFilename={#appName}_{#appVer}_py{#pyVer}_setup
+Compression=lzma
+SolidCompression=yes
+ChangesAssociations=yes
+ChangesEnvironment=yes
+DirExistsWarning=no
+SetupIconFile=C:\Users\olivier\git\pyo\utils\E-PyoIcon.ico
+
+[Languages]
+Name: "english"; MessagesFile: "compiler:Default.isl"
+
+[Files]
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python36-32\Lib\site-packages\pyo.py"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion 
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python36-32\Lib\site-packages\pyo64.py"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python36-32\Lib\site-packages\pyolib\*"; DestDir: "{app}\Lib\site-packages\pyolib"; Flags: ignoreversion recursesubdirs createallsubdirs
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python36-32\Lib\site-packages\_pyo.cp36-win32.pyd"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python36-32\Lib\site-packages\_pyo64.cp36-win32.pyd"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python36-32\Lib\site-packages\libsndfile-1.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python36-32\Lib\site-packages\liblo-7.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python36-32\Lib\site-packages\portaudio.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python36-32\Lib\site-packages\portmidi.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python36-32\Lib\site-packages\porttime.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python36-32\Lib\site-packages\pthreadVC2.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python36-32\Lib\site-packages\pthreadGC2.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python36-32\Lib\site-packages\dcomp.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python36-32\Lib\site-packages\gpsvc.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python36-32\Lib\site-packages\sysntfy.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python36-32\Lib\site-packages\msvcr100.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\MinGW\bin\libgcc_s_dw2-1.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\MinGW\bin\libstdc++-6.dll"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\AppData\Local\Programs\Python\Python36-32\Lib\site-packages\pyo-{#appVer}-py{#pyVer}.egg-info"; DestDir: "{app}\Lib\site-packages"; Flags: ignoreversion
+Source: "C:\Users\olivier\git\pyo\examples\*"; DestDir: "{userdesktop}\pyo_examples\"; Flags: ignoreversion recursesubdirs createallsubdirs
+; NOTE: Don't use "Flags: ignoreversion" on any shared system files
+
+; E-Pyo stuff
+Source: "C:\Users\olivier\git\pyo\utils\E-Pyo_py36\E-Pyo.exe"; DestDir: "{pf}\E-Pyo"; Flags: ignoreversion
+Source: "C:\Users\olivier\git\pyo\utils\E-Pyo_py36\Resources\*"; DestDir: "{pf}\E-Pyo\Resources"; Flags: ignoreversion recursesubdirs createallsubdirs
+
+[Tasks]
+Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"
+
+[Icons]
+Name: "{group}\E-Pyo"; Filename: "{pf}\E-Pyo\E-Pyo.exe"; WorkingDir: "{pf}\E-Pyo"
+Name: "{commondesktop}\E-Pyo"; Filename: "{pf}\E-Pyo\E-Pyo.exe"; Tasks: desktopicon
+
+[Run]
+Filename: "{pf}\E-Pyo\E-Pyo.exe"; Description: "{cm:LaunchProgram,E-Pyo}"; Flags: nowait postinstall skipifsilent
+
+[InstallDelete]
+Type: filesandordirs; Name: "{userdesktop}\pyo_examples";
+Type: filesandordirs; Name: "{userdocs}\.epyo";
+;;;;;;;;;;;;;
+
+[Registry]
+Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; ValueName: "Path"; ValueData: "{app};{olddata}"; Check: NeedsAddPath('{app}')
+
+[Code]
+procedure ExitProcess(exitCode:integer);
+  external 'ExitProcess at kernel32.dll stdcall';
+
+function NeedsAddPath(Param: string): boolean;
+var
+  OrigPath: string;
+begin
+  if not RegQueryStringValue(HKEY_LOCAL_MACHINE,
+    'SYSTEM\CurrentControlSet\Control\Session Manager\Environment',
+    'Path', OrigPath)
+  then begin
+    Result := True;
+    exit;
+  end;
+  // look for the path with leading and trailing semicolon
+  // Pos() returns 0 if not found
+  Result := Pos(';' + Param + ';', ';' + OrigPath + ';') = 0;
+end;
+
+function GetDirName(Value: string): string;
+var          
+  InstallPath: string;
+  reg1 : string;
+  reg2 : string;
+  reg3 : string;
+  reg4 : string;
+begin
+  reg1 := 'SOFTWARE\Python\PythonCore\' + '{#PyVer}' + '-32\InstallPath';
+  reg2 := 'SOFTWARE\Wow6432Node\Python\PythonCore\' + '{#PyVer}' + '-32\InstallPath';
+  reg3 := 'Software\Python\PythonCore\' + '{#PyVer}' + '-32\InstallPath';
+  reg4 := 'Software\Wow6432Node\Python\PythonCore\' + '{#PyVer}' + '-32\InstallPath';
+  if RegQueryStringValue(HKLM, reg1, '', InstallPath) then
+    BEGIN
+    Result := InstallPath;
+  END else
+  if RegQueryStringValue(HKCU, reg3, '', InstallPath) then
+    BEGIN
+    Result := InstallPath;
+  END else
+  if RegQueryStringValue(HKLM, reg2, '', InstallPath) then
+    BEGIN
+    Result := InstallPath;
+  END else
+  if RegQueryStringValue(HKCU, reg4, '', InstallPath) then
+    BEGIN
+    Result := InstallPath;
+  END else
+    BEGIN
+    Result := 'C:\Python36-32';
+   END
+end;
\ No newline at end of file
diff --git a/pyo.py b/pyo.py
index f7a865f..b8f5e25 100644
--- a/pyo.py
+++ b/pyo.py
@@ -1,57 +1,22 @@
 """
-Copyright 2010 Olivier Belanger
+Copyright 2009-2016 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+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 os
-
-import sys
-import __builtin__
-from types import IntType, FloatType
-
-# For Python 2.5-, this will enable the simliar property mechanism as in
-# Python 2.6+/3.0+. The code is based on
-# http://bruynooghe.blogspot.com/2008/04/xsetter-syntax-in-python-25.html
-if sys.version_info[:2] <= (2, 5):
-    class property(property):
-        def __init__(self, fget, *args, **kwargs):
-            self.__doc__ = fget.__doc__
-            super(property, self).__init__(fget, *args, **kwargs)
-
-        def setter(self, fset):
-            cls_ns = sys._getframe(1).f_locals
-            for k, v in cls_ns.iteritems():
-                if v == self:
-                    propname = k
-                    break
-            cls_ns[propname] = property(self.fget, fset, self.fdel, self.__doc__)
-            return cls_ns[propname]
-
-        def deleter(self, fdel):
-            cls_ns = sys._getframe(1).f_locals
-            for k, v in cls_ns.iteritems():
-                if v == self:
-                    propname = k
-                    break
-            cls_ns[propname] = property(self.fget, self.fset, fdel, self.__doc__)
-            return cls_ns[propname]
-
-    __builtin__.property = property
-
 from pyolib._maps import *
 import pyolib.analysis as analysis
 from pyolib.analysis import *
@@ -78,6 +43,7 @@ from pyolib.pattern import *
 import pyolib.randoms as randoms
 from pyolib.randoms import *
 from pyolib.server import *
+from pyolib.listener import *
 import pyolib.players as players
 from pyolib.players import *
 import pyolib.tableprocess as tableprocess
@@ -90,210 +56,157 @@ import pyolib.triggers as triggers
 from pyolib.triggers import *
 import pyolib.utils as utils
 from pyolib.utils import *
+import pyolib.expression as expression
+from pyolib.expression import *
 import pyolib.fourier as fourier
 from pyolib.fourier import *
 import pyolib.phasevoc as phasevoc
 from pyolib.phasevoc import *
 from pyolib._core import *
+from pyolib.wxgui import *
+import pyolib.wxgui as wxgui
 if WITH_EXTERNALS:
     import pyolib.external as external
     from pyolib.external import *
 
-# Temporary objects, need to be coded in C
-class FreqShift(PyoObject):
+OBJECTS_TREE = {
+    'functions': sorted(['pa_count_devices', 'pa_get_default_input', 
+                         'pa_get_default_output', 'pm_get_input_devices',
+                         'pa_list_devices', 'pa_count_host_apis', 
+                         'pa_list_host_apis', 'pa_get_default_host_api',
+                         'pa_get_default_devices_from_host',
+                         'pm_count_devices', 'pm_list_devices', 'sndinfo', 
+                         'savefile', 'pa_get_output_devices',
+                         'pa_get_input_devices', 'midiToHz', 'hzToMidi', 
+                         'sampsToSec', 'secToSamps', 'example', 'class_args',
+                         'pm_get_default_input', 'pm_get_output_devices', 
+                         'pm_get_default_output', 'midiToTranspo','getVersion', 
+                         'reducePoints', 'serverCreated', 'serverBooted', 
+                         'distanceToSegment', 'rescale', 'upsamp', 'downsamp', 
+                         'linToCosCurve', 'convertStringToSysEncoding', 
+                         'savefileFromTable', 'pa_get_input_max_channels', 
+                         'pa_get_output_max_channels', 'pa_get_devices_infos', 
+                         'pa_get_version', 'pa_get_version_text', 'floatmap']),
+    'PyoObjectBase': {
+        'PyoMatrixObject': sorted(['NewMatrix']),
+        'PyoTableObject': sorted(['LinTable', 'NewTable', 'SndTable', 
+                                  'HannTable', 'HarmTable', 'SawTable', 
+                                  'ParaTable', 'LogTable', 'CosLogTable', 
+                                  'SquareTable', 'ChebyTable', 'CosTable', 
+                                  'CurveTable', 'ExpTable', 'DataTable', 
+                                  'WinTable', 'SincTable', 'PartialTable', 
+                                  'AtanTable', 'PadSynthTable', 'SharedTable']),
+        'PyoPVObject' : sorted(['PVAnal', 'PVSynth', 'PVTranspose', 'PVVerb', 
+                                'PVGate', 'PVAddSynth', 'PVCross', 'PVMult',
+                                'PVMorph', 'PVFilter', 'PVDelay', 'PVBuffer', 
+                                'PVShift', 'PVAmpMod', 'PVFreqMod', 
+                                'PVBufLoops', 'PVBufTabLoops', 'PVMix']),
+        'PyoObject': {
+            'analysis': sorted(['Follower', 'Follower2', 'ZCross', 'Yin', 
+                                'Centroid', 'AttackDetector', 'Scope',
+                                'Spectrum', 'PeakAmp']),
+            'arithmetic': sorted(['Sin', 'Cos', 'Tan', 'Abs', 'Sqrt', 'Log', 
+                                  'Log2', 'Log10', 'Pow', 'Atan2', 'Floor',
+                                  'Round', 'Ceil', 'Tanh', 'Exp']),
+            'controls': sorted(['Fader', 'Sig', 'SigTo', 'Adsr', 'Linseg', 
+                                'Expseg']),
+            'dynamics': sorted(['Clip', 'Compress', 'Degrade', 'Mirror', 
+                                'Wrap', 'Gate', 'Balance', 'Min', 'Max']),
+            'effects': sorted(['Delay', 'SDelay', 'Disto', 'Freeverb', 
+                               'Waveguide', 'Convolve', 'WGVerb', 'SmoothDelay',
+                               'Harmonizer', 'Chorus', 'AllpassWG', 'FreqShift', 
+                               'Vocoder', 'Delay1', 'STRev']),
+            'filters': sorted(['Biquad', 'BandSplit', 'Port', 'Hilbert', 'Tone', 
+                               'DCBlock', 'EQ', 'Allpass', 'Allpass2', 'Phaser', 
+                               'Biquadx', 'IRWinSinc', 'IRAverage', 'IRPulse', 
+                               'IRFM', 'FourBand', 'Biquada', 'Atone', 'SVF', 
+                               'Average', 'Reson', 'Resonx', 'ButLP', 'ButHP', 
+                               'ButBP', 'ButBR', 'ComplexRes', 'MoogLP']),
+            'generators': sorted(['Noise', 'Phasor', 'Sine', 'Input', 'CrossFM', 
+                                  'SineLoop', 'Blit', 'PinkNoise', 'FM', 'LFO', 
+                                  'BrownNoise', 'Rossler', 'Lorenz', 'ChenLee', 
+                                  'SumOsc', 'SuperSaw', 'RCOsc', 'FastSine']),
+            'internals': sorted(['Dummy', 'InputFader', 'Mix', 'VarPort']),
+            'midi': sorted(['Midictl', 'CtlScan', 'CtlScan2', 'Notein', 
+                            'MidiAdsr', 'MidiDelAdsr', 'Bendin', 'Touchin', 
+                            'Programin', 'RawMidi']),
+            'opensndctrl': sorted(['OscReceive', 'OscSend', 'OscDataSend', 
+                                   'OscDataReceive', 'OscListReceive']),
+            'pan': sorted(['Pan', 'SPan', 'Switch', 'Selector', 'Mixer', 
+                           'VoiceManager']),
+            'pattern': sorted(['Pattern', 'Score', 'CallAfter']),
+            'randoms': sorted(['Randi', 'Randh', 'Choice', 'RandInt', 'Xnoise', 
+                               'XnoiseMidi', 'RandDur', 'XnoiseDur', 'Urn',
+                               'LogiMap']),
+            'players': sorted(['SfMarkerShuffler', 'SfPlayer', 'SfMarkerLooper']),
+            'tableprocess': sorted(['TableRec', 'Osc', 'Pointer', 'Pointer2', 
+                                    'Lookup', 'Granulator', 'Pulsar', 'OscLoop',
+                                    'Granule', 'TableRead', 'TableMorph', 
+                                    'Looper', 'TableIndex', 'OscBank', 'OscTrig',
+                                    'TablePut', 'TableScale', 'Particle', 
+                                     'Particle2', 'TableWrite', 'TableFill',
+                                     'TableScan']),
+            'matrixprocess': sorted(['MatrixRec', 'MatrixPointer', 'MatrixMorph', 
+                                     'MatrixRecLoop']),
+            'triggers': sorted(['Metro', 'Beat', 'TrigEnv', 'TrigRand', 'Trig', 
+                                'TrigRandInt', 'Select', 'Counter', 'TrigChoice',
+                                'TrigFunc', 'Thresh', 'Cloud', 'TrigXnoise', 
+                                'TrigXnoiseMidi', 'Timer', 'Count', 'Change', 
+                                'TrigLinseg', 'TrigExpseg', 'Percent', 'Seq', 
+                                'TrigTableRec', 'Iter', 'NextTrig', 'TrigVal', 
+                                'Euclide', 'TrigBurst']),
+            'utils': sorted(['Clean_objects', 'Print', 'Snap', 'Interp', 
+                             'SampHold', 'Compare', 'Record', 'DBToA', 'AToDB', 
+                             'Between', 'Denorm', 'ControlRec', 'ControlRead', 
+                             'NoteinRec', 'NoteinRead', 'Scale', 'TrackHold', 
+                             'CentsToTranspo', 'TranspoToCents', 'MToF', 'FToM', 
+                             'MToT', 'Resample', 'Expr']),
+            'expression': sorted(['Expr']),
+            'fourier': sorted(['FFT', 'IFFT', 'CarToPol', 'PolToCar', 
+                               'FrameDelta', 'FrameAccum', 'Vectral', 'CvlVerb'])
+            }
+        },
+        'Map': {'SLMap': sorted(['SLMapFreq', 'SLMapMul', 'SLMapPhase', 
+                                 'SLMapQ', 'SLMapDur', 'SLMapPan'])},
+        'Server': [],
+        'MidiListener': [],
+        'MidiDispatcher': [],
+        'OscListener': [],
+        'Stream': [],
+        'TableStream': [],
+        'PyoGui': ['PyoGuiControlSlider', 'PyoGuiVuMeter', 'PyoGuiGrapher', 
+                   'PyoGuiMultiSlider', 'PyoGuiSpectrum', 'PyoGuiScope',
+                   'PyoGuiSndView']}
+
+DOC_KEYWORDS = ['Attributes', 'Examples', 'Parameters', 'Methods', 'Notes', 
+                'Methods details', 'See also', 'Parentclass']
+
+def getPyoKeywords():
     """
-    Frequency shifting using single sideband amplitude modulation.
-
-    Shifting frequencies means that the input signal can be detuned, 
-    where the harmonic components of the signal are shifted out of 
-    harmonic alignment with each other, e.g. a signal with harmonics at 
-    100, 200, 300, 400 and 500 Hz, shifted up by 50 Hz, will have harmonics 
-    at 150, 250, 350, 450, and 550 Hz.
-
-    Parent class : PyoObject
-
-    Parameters:
+    Returns a list of every keywords (classes and functions) of pyo.
 
-    input : PyoObject
-        Input signal to process.
-    shift : float or PyoObject, optional
-        Amount of shifting in Hertz. Defaults to 100.
-
-    Methods:
-
-    setInput(x, fadetime) : Replace the `input` attribute.
-    setShift(x) : Replace the `shift` attribute.
-
-    Attributes:
-
-    input : PyoObject. Input signal to process.
-    shift : float or PyoObject. Amount of shifting in Hertz.
-
-    Examples:
-
-    >>> s = Server().boot()
-    >>> s.start()
-    >>> a = SineLoop(freq=300, feedback=.1, mul=.3)
-    >>> lf1 = Sine(freq=.04, mul=10)
-    >>> lf2 = Sine(freq=.05, mul=10)
-    >>> b = FreqShift(a, shift=lf1, mul=.5).out()
-    >>> c = FreqShift(a, shift=lf2, mul=.5).out(1)
+    >>> keywords = getPyoKeywords()
 
     """
-    def __init__(self, input, shift=100, mul=1, add=0):
-        PyoObject.__init__(self)
-        self._input = input
-        self._shift = shift
-        self._mul = mul
-        self._add = add
-        self._in_fader = InputFader(input)
-        in_fader, shift, mul, add, lmax = convertArgsToLists(self._in_fader, shift, mul, add)
-
-        self._hilb_objs = []
-        self._sin_objs = []
-        self._cos_objs = []
-        self._mod_objs = []
-        self._base_objs = []
-        for i in range(lmax):
-            self._hilb_objs.append(Hilbert(wrap(in_fader,i)))
-            self._sin_objs.append(Sine(freq=wrap(shift,i), mul=.707))
-            self._cos_objs.append(Sine(freq=wrap(shift,i), phase=0.25, mul=.707))
-            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())
-
-    def __dir__(self):
-        return ["input", "shift", "mul", "add"]
-
-    def play(self, dur=0, delay=0):
-        dur, delay, lmax = convertArgsToLists(dur, delay)
-        [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._hilb_objs)]
-        [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._sin_objs)]
-        [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._cos_objs)]
-        [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._mod_objs)]
-        self._base_objs = [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_objs)]
-        return self
-
-    def stop(self):
-        [obj.stop() for obj in self._hilb_objs]
-        [obj.stop() for obj in self._sin_objs]
-        [obj.stop() for obj in self._cos_objs]
-        [obj.stop() for obj in self._mod_objs]
-        [obj.stop() for obj in self._base_objs]
-        return self
-
-    def out(self, chnl=0, inc=1, dur=0, delay=0):
-        dur, delay, lmax = convertArgsToLists(dur, delay)
-        [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._hilb_objs)]
-        [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._sin_objs)]
-        [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._cos_objs)]
-        [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._mod_objs)]
-        if type(chnl) == ListType:
-            self._base_objs = [obj.out(wrap(chnl,i), wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_objs)]
+    tree = OBJECTS_TREE
+    _list = []
+    for k1 in tree.keys():
+        if type(tree[k1]) == type({}):
+            for k2 in tree[k1].keys():
+                if type(tree[k1][k2]) == type({}):
+                    for k3 in tree[k1][k2].keys():
+                        for val in tree[k1][k2][k3]:
+                            _list.append(val)
+                else:
+                    for val in tree[k1][k2]:
+                        _list.append(val)
         else:
-            if chnl < 0:    
-                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:
-                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 setInput(self, x, fadetime=0.05):
-        """
-        Replace the `input` attribute.
-
-        Parameters:
-
-        x : PyoObject
-            New signal to process.
-        fadetime : float, optional
-            Crossfade time between old and new input. Defaults to 0.05.
-
-        """
-        self._input = x
-        self._in_fader.setInput(x, fadetime)
-
-    def setShift(self, x):
-        """
-        Replace the `shift` attribute.
-
-        Parameters:
-
-        x : float or PyoObject
-            New `shift` attribute.
-
-        """
-        self._shift = x
-        x, lmax = convertArgsToLists(x)
-        [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._sin_objs)]
-        [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._cos_objs)]
-
-    def ctrl(self, map_list=None, title=None, wxnoserver=False):
-        self._map_list = [SLMap(-2000., 2000., "lin", "shift", self._shift), SLMapMul(self._mul)]
-        PyoObject.ctrl(self, map_list, title, wxnoserver)
-
-    @property
-    def input(self): 
-        """PyoObject. Input signal to pitch shift.""" 
-        return self._input
-    @input.setter
-    def input(self, x): self.setInput(x)
-
-    @property
-    def shift(self): 
-        """float or PyoObject. Amount of pitch shift in Hertz.""" 
-        return self._shift
-    @shift.setter
-    def shift(self, x): self.setShift(x)
-
-
-OBJECTS_TREE = {'functions': sorted(['pa_count_devices', 'pa_get_default_input', 'pa_get_default_output', 'pm_get_input_devices',
-                                    'pa_list_devices', 'pa_count_host_apis', 'pa_list_host_apis', 'pa_get_default_host_api', 
-                                    'pm_count_devices', 'pm_list_devices', 'sndinfo', 'savefile', 'pa_get_output_devices', 
-                                    'pa_get_input_devices', 'midiToHz', 'sampsToSec', 'secToSamps', 'example', 'class_args', 
-                                    'pm_get_default_input', 'pm_get_output_devices', 'pm_get_default_output', 'midiToTranspo',
-                                     'getVersion', 'reducePoints', 'serverCreated', 'serverBooted', 'distanceToSegment', 'rescale',
-                                     'upsamp', 'downsamp', 'linToCosCurve', 'convertStringToSysEncoding', 'savefileFromTable',
-                                    'pa_get_input_max_channels', 'pa_get_output_max_channels', 'pa_get_devices_infos']),
-                'PyoObjectBase': {
-                    'PyoMatrixObject': sorted(['NewMatrix']),                        
-                    'PyoTableObject': sorted(['LinTable', 'NewTable', 'SndTable', 'HannTable', 'HarmTable', 'SawTable', 'ParaTable', 'LogTable', 'CosLogTable',
-                                            'SquareTable', 'ChebyTable', 'CosTable', 'CurveTable', 'ExpTable', 'DataTable', 'WinTable', 'SincTable']),
-                    'PyoPVObject' : sorted(['PVAnal', 'PVSynth', 'PVTranspose', 'PVVerb', 'PVGate', 'PVAddSynth', 'PVCross', 'PVMult', 'PVMorph', 'PVFilter', 'PVDelay', 'PVBuffer', 'PVShift', 'PVAmpMod', 'PVFreqMod', 'PVBufLoops', 'PVBufTabLoops', 'PVMix']),
-                    'PyoObject': {'analysis': sorted(['Follower', 'Follower2', 'ZCross', 'Yin']),
-                                  'arithmetic': sorted(['Sin', 'Cos', 'Tan', 'Abs', 'Sqrt', 'Log', 'Log2', 'Log10', 'Pow', 'Atan2', 'Floor', 'Round',
-                                                        'Ceil']),
-                                  'controls': sorted(['Fader', 'Sig', 'SigTo', 'Adsr', 'Linseg', 'Expseg']),
-                                  'dynamics': sorted(['Clip', 'Compress', 'Degrade', 'Mirror', 'Wrap', 'Gate', 'Balance', 'Min', 'Max']),
-                                  'effects': sorted(['Delay', 'SDelay', 'Disto', 'Freeverb', 'Waveguide', 'Convolve', 'WGVerb', 
-                                                     'Harmonizer', 'Chorus', 'AllpassWG', 'FreqShift', 'Vocoder', 'Delay1']),
-                                  'filters': sorted(['Biquad', 'BandSplit', 'Port', 'Hilbert', 'Tone', 'DCBlock', 'EQ', 'Allpass',
-                                                     'Allpass2', 'Phaser', 'Biquadx', 'IRWinSinc', 'IRAverage', 'IRPulse', 'IRFM', 'FourBand',
-                                                     'Biquada', 'Atone', 'SVF', 'Average', 'Reson', 'Resonx', 'ButLP', 'ButHP', 'ButBP', 'ButBR']),
-                                  'generators': sorted(['Noise', 'Phasor', 'Sine', 'Input', 'FM', 'SineLoop', 'Blit', 'PinkNoise', 'CrossFM',
-                                                        'BrownNoise', 'Rossler', 'Lorenz', 'LFO', 'SumOsc', 'SuperSaw', 'RCOsc']),
-                                  'internals': sorted(['Dummy', 'InputFader', 'Mix', 'VarPort']),
-                                  'midi': sorted(['Midictl', 'CtlScan', 'CtlScan2', 'Notein', 'MidiAdsr', 'MidiDelAdsr', 'Bendin', 'Touchin', 'Programin']),
-                                  'opensndctrl': sorted(['OscReceive', 'OscSend', 'OscDataSend', 'OscDataReceive', 'OscListReceive']),
-                                  'pan': sorted(['Pan', 'SPan', 'Switch', 'Selector', 'Mixer', 'VoiceManager']),
-                                  'pattern': sorted(['Pattern', 'Score', 'CallAfter']),
-                                  'randoms': sorted(['Randi', 'Randh', 'Choice', 'RandInt', 'Xnoise', 'XnoiseMidi', 'RandDur', 'XnoiseDur', 'Urn']),
-                                  'players': sorted(['SfMarkerShuffler', 'SfPlayer', 'SfMarkerLooper']),
-                                  'tableprocess': sorted(['TableRec', 'Osc', 'Pointer', 'Lookup', 'Granulator', 'Pulsar', 'OscLoop', 'Granule',
-                                                        'TableRead', 'TableMorph', 'Looper', 'TableIndex', 'OscBank', 'OscTrig', 'TablePut', 'TableScale']),
-                                  'matrixprocess': sorted(['MatrixRec', 'MatrixPointer', 'MatrixMorph', 'MatrixRecLoop']), 
-                                  'triggers': sorted(['Metro', 'Beat', 'TrigEnv', 'TrigRand', 'TrigRandInt', 'Select', 'Counter', 'TrigChoice', 
-                                                    'TrigFunc', 'Thresh', 'Cloud', 'Trig', 'TrigXnoise', 'TrigXnoiseMidi', 'Timer', 'Count',
-                                                    'Change', 'TrigLinseg', 'TrigExpseg', 'Percent', 'Seq', 'TrigTableRec', 'Iter', 'NextTrig',
-                                                    'TrigVal']),
-                                  'utils': sorted(['Clean_objects', 'Print', 'Snap', 'Interp', 'SampHold', 'Compare', 'Record', 'Between', 'Denorm',
-                                                    'ControlRec', 'ControlRead', 'NoteinRec', 'NoteinRead', 'DBToA', 'AToDB', 'Scale', 'CentsToTranspo',
-                                                    'TranspoToCents', 'MToF', 'MToT']),
-                                  'fourier': sorted(['FFT', 'IFFT', 'CarToPol', 'PolToCar', 'FrameDelta', 'FrameAccum', 'Vectral', 'CvlVerb', 'Spectrum'])}},
-        'Map': {'SLMap': sorted(['SLMapFreq', 'SLMapMul', 'SLMapPhase', 'SLMapQ', 'SLMapDur', 'SLMapPan'])},
-        'Server': [], 
-        'Stream': [], 
-        'TableStream': []}
-
-DOC_KEYWORDS = ['Attributes', 'Examples', 'Parameters', 'Methods', 'Notes', 'Methods details', 'See also', 'Parentclass']
-
-DEMOS_PATH = SNDS_PATH
+            for val in tree[k1]:
+                _list.append(val)
+    _list.extend(["PyoObjectBase", "PyoObject", "PyoTableObject", 
+                  "PyoMatrixObject", "PyoPVObject"])
+    _list.extend(["Server", "Map", "SLMap", "MidiListener", "OscListener", 
+                  "Stream", "TableStream"])
+    return _list
+
+OBJECTS_TREE["functions"] = sorted(OBJECTS_TREE["functions"] + ["getPyoKeywords"])
diff --git a/pyo64.py b/pyo64.py
index dbd5b17..e2263ca 100644
--- a/pyo64.py
+++ b/pyo64.py
@@ -1,22 +1,29 @@
 """
-Copyright 2010 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+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 __builtin__
-__builtin__.pyo_use_double = True
-from pyo import *
+import sys
+if sys.version_info[0] < 3:
+    import __builtin__
+    builtins = __builtin__
+else:
+    import builtins
+
+builtins.pyo_use_double = True
+
+from pyo import *
\ No newline at end of file
diff --git a/pyolib/_core.py b/pyolib/_core.py
index 0a643c6..275f628 100644
--- a/pyolib/_core.py
+++ b/pyolib/_core.py
@@ -1,107 +1,517 @@
-# -*- coding: utf-8 -*-
+# encoding: utf-8
 """
-Copyright 2010 Olivier Belanger
+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-2016 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+You should have received a copy of the GNU Lesser General Public
+License along with pyo.  If not, see <http://www.gnu.org/licenses/>.
 
 """
-from types import ListType, SliceType, FloatType, StringType, UnicodeType
-import random, os, sys, inspect, tempfile
+import os
+import sys
+import random
+import inspect
+import tempfile
 from subprocess import call
-
-import __builtin__
-if hasattr(__builtin__, 'pyo_use_double'):
-    import pyo64 as current_pyo
+from weakref import proxy
+
+if sys.version_info[0] < 3:
+    import __builtin__
+    builtins = __builtin__
+    bytes_t = str
+    unicode_t = unicode
+    def tobytes(strng, encoding=None):
+        "Convert unicode string to bytes."
+        return bytes(strng)
+else:
+    import builtins
+    bytes_t = bytes
+    unicode_t = str
+    def tobytes(strng, encoding="utf-8"):
+        "Convert unicode string to bytes."
+        return bytes(strng, encoding=encoding)
+
+if hasattr(builtins, 'pyo_use_double'):
     from _pyo64 import *
-else:    
-    import pyo as current_pyo
+    import pyo64 as current_pyo
+else:
     from _pyo import *
-    
-from _maps import *
-from _widgets import createCtrlWindow, createViewTableWindow, createViewMatrixWindow
+    import pyo as current_pyo
+
+from ._maps import SLMap, SLMapMul
+from ._widgets import createCtrlWindow
+from ._widgets import createViewTableWindow
+from ._widgets import createViewMatrixWindow
 
 ######################################################################
 ### Utilities
 ######################################################################
-SNDS_PATH = os.path.join(os.path.dirname(current_pyo.__file__), "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, 
-                'loopseg': 12}
-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_list_host_apis": "pa_list_host_apis()",
-                        "pa_get_default_host_api": "pa_get_default_host_api()", "pa_count_devices": "pa_count_devices()",
-                        "pa_list_devices": "pa_list_devices()", "pa_get_devices_infos": "pa_get_devices_infos()",
-                        "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_output": "pa_get_default_output()",
-                        "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_input": "pm_get_default_input()",
-                        "pm_get_output_devices": "pm_get_output_devices()", "pm_get_input_devices": "pm_get_input_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)", "downsamp": "downsamp(path, outfile, down=4, order=128)",
-                        "midiToHz": "midiToHz(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()", "serverBooted": "serverBooted()",
-                        "example": "example(cls, dur=5, toprint=True, double=False)", "class_args": "class_args(cls)", "getVersion": "getVersion()",
-                        "convertStringToSysEncoding": "convertStringToSysEncoding(str)", "convertArgsToLists": "convertArgsToLists(*args)",
-                        "wrap": "wrap(arg, i)"
-                        }
-
-def convertStringToSysEncoding(str):
+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,
+               'loopseg': 12}
+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_list_host_apis": "pa_list_host_apis()",
+    "pa_get_default_host_api": "pa_get_default_host_api()",
+    "pa_get_default_devices_from_host": "pa_get_default_devices_from_host(host)",
+    "pa_count_devices": "pa_count_devices()",
+    "pa_list_devices": "pa_list_devices()",
+    "pa_get_devices_infos": "pa_get_devices_infos()",
+    "pa_get_version": "pa_get_version()",
+    "pa_get_version_text": "pa_get_version_text()",
+    "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_output": "pa_get_default_output()",
+    "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_input": "pm_get_default_input()",
+    "pm_get_output_devices": "pm_get_output_devices()",
+    "pm_get_input_devices": "pm_get_input_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, quality=0.4)",
+    "savefileFromTable": "savefileFromTable(table, path, fileformat=0, "
+                         "sampletype=0, quality=0.4)",
+    "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)",
+    "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()",
+    "serverBooted": "serverBooted()",
+    "example": "example(cls, dur=5, toprint=True, double=False)",
+    "class_args": "class_args(cls)",
+    "getVersion": "getVersion()",
+    "convertStringToSysEncoding": "convertStringToSysEncoding(str)",
+    "convertArgsToLists": "convertArgsToLists(*args)",
+    "wrap": "wrap(arg, i)",
+    "floatmap": "floatmap(x, min=0, max=1, exp=1)",
+    "getPyoKeywords": "getPyoKeywords()"
+}
+
+def stringencode(st):
+    if sys.version_info[0] >= 3:
+        if type(st) is str:
+            st = st.encode(sys.getfilesystemencoding())
+    return st
+
+def sndinfo(path, print=False):
+    """
+    Retrieve informations about a soundfile.
+
+    Prints the infos of the given soundfile to the console and returns a
+    tuple containing:
+
+    (number of frames, duration in seconds, sampling rate,
+     number of channels, file format, sample type)
+
+    :Args:
+
+        path: string
+            Path of a valid soundfile.
+        print: boolean, optional
+            If True, sndinfo will print sound infos to the console.
+            Defaults to False.
+
+    >>> path = SNDS_PATH + '/transparent.aif'
+    >>> print(path)
+    /usr/lib/python2.7/dist-packages/pyolib/snds/transparent.aif
+    >>> info = sndinfo(path)
+    >>> print(info)
+    (29877, 0.6774829931972789, 44100.0, 1, 'AIFF', '16 bit int')
+
+    """
+    path = stringencode(path)
+    return p_sndinfo(path, print)
+
+def savefile(samples, path, sr=44100, channels=1, fileformat=0, sampletype=0,
+             quality=0.4):
+    """
+    Creates an audio file from a list of floats.
+
+    :Args:
+
+        samples: list of floats
+            List of samples data, or list of list of samples data if more than 1 channels.
+        path: string
+            Full path (including extension) of the new file.
+        sr: int, optional
+            Sampling rate of the new file. Defaults to 44100.
+        channels: int, optional
+            Number of channels of the new file. Defaults to 1.
+        fileformat: int, optional
+            Format type of the new file. Defaults to 0. Supported formats are:
+                0. WAVE - Microsoft WAV format (little endian) {.wav, .wave}
+                1. AIFF - Apple/SGI AIFF format (big endian) {.aif, .aiff}
+                2. AU - Sun/NeXT AU format (big endian) {.au}
+                3. RAW - RAW PCM data {no extension}
+                4. SD2 - Sound Designer 2 {.sd2}
+                5. FLAC - FLAC lossless file format {.flac}
+                6. CAF - Core Audio File format {.caf}
+                7. OGG - Xiph OGG container {.ogg}
+        sampletype ; int, optional
+            Bit depth encoding of the audio file. Defaults to 0.
+            SD2 and FLAC only support 16 or 24 bit int. Supported types are:
+                0. 16 bit int
+                1. 24 bit int
+                2. 32 bit int
+                3. 32 bit float
+                4. 64 bit float
+                5. U-Law encoded
+                6. A-Law encoded
+        quality: float, optional
+            The encoding quality value, between 0.0 (lowest quality) and
+            1.0 (highest quality). This argument has an effect only with
+            FLAC and OGG compressed formats. Defaults to 0.4.
+
+    >>> from random import uniform
+    >>> import os
+    >>> home = os.path.expanduser('~')
+    >>> sr, dur, chnls, path = 44100, 5, 2, os.path.join(home, 'noise.aif')
+    >>> samples = [[uniform(-0.5,0.5) for i in range(sr*dur)] for i in range(chnls)]
+    >>> savefile(samples=samples, path=path, sr=sr, channels=chnls, fileformat=1, sampletype=1)
+
+    """
+    path = stringencode(path)
+    p_savefile(samples, path, sr, channels, fileformat, sampletype, quality)
+
+def savefileFromTable(table, path, fileformat=0, sampletype=0, quality=0.4):
+    """
+    Creates an audio file from the content of a table.
+
+    :Args:
+
+        table: PyoTableObject
+            Table from which to retrieve the samples to write.
+        path: string
+            Full path (including extension) of the new file.
+        fileformat: int, optional
+            Format type of the new file. Defaults to 0. Supported formats are:
+                0. WAVE - Microsoft WAV format (little endian) {.wav, .wave}
+                1. AIFF - Apple/SGI AIFF format (big endian) {.aif, .aiff}
+                2. AU - Sun/NeXT AU format (big endian) {.au}
+                3. RAW - RAW PCM data {no extension}
+                4. SD2 - Sound Designer 2 {.sd2}
+                5. FLAC - FLAC lossless file format {.flac}
+                6. CAF - Core Audio File format {.caf}
+                7. OGG - Xiph OGG container {.ogg}
+        sampletype ; int, optional
+            Bit depth encoding of the audio file. Defaults to 0.
+            SD2 and FLAC only support 16 or 24 bit int. Supported types are:
+                0. 16 bit int
+                1. 24 bit int
+                2. 32 bit int
+                3. 32 bit float
+                4. 64 bit float
+                5. U-Law encoded
+                6. A-Law encoded
+        quality: float, optional
+            The encoding quality value, between 0.0 (lowest quality) and
+            1.0 (highest quality). This argument has an effect only with
+            FLAC and OGG compressed formats. Defaults to 0.4.
+
+    >>> import os
+    >>> home = os.path.expanduser('~')
+    >>> path1 = SNDS_PATH + '/transparent.aif'
+    >>> path2 = os.path.join(home, '/transparent2.aif')
+    >>> t = SndTable(path1)
+    >>> savefileFromTable(table=t, path=path, fileformat=1, sampletype=1)
+
+    """
+    path = stringencode(path)
+    p_savefileFromTable(table, path, fileformat, sampletype, quality)
+
+def upsamp(path, outfile, up=4, order=128):
+    """
+    Increases the sampling rate of an audio file.
+
+    :Args:
+
+        path: string
+            Full path (including extension) of the audio file to convert.
+        outfile: string
+            Full path (including extension) of the new file.
+        up: int, optional
+            Upsampling factor. Defaults to 4.
+        order: int, optional
+            Length, in samples, of the anti-aliasing lowpass filter.
+            Defaults to 128.
+
+    >>> import os
+    >>> home = os.path.expanduser('~')
+    >>> f = SNDS_PATH+'/transparent.aif'
+    >>> # upsample a signal 3 times
+    >>> upfile = os.path.join(home, 'trans_upsamp_2.aif')
+    >>> upsamp(f, upfile, 2, 256)
+    >>> # downsample the upsampled signal 3 times
+    >>> downfile = os.path.join(home, 'trans_downsamp_3.aif')
+    >>> downsamp(upfile, downfile, 3, 256)
+
+    """
+    path = stringencode(path)
+    outfile = stringencode(outfile)
+    p_upsamp(path, outfile, up, order)
+
+def downsamp(path, outfile, down=4, order=128):
+    """
+    Decreases the sampling rate of an audio file.
+
+    :Args:
+
+        path: string
+            Full path (including extension) of the audio file to convert.
+        outfile: string
+            Full path (including extension) of the new file.
+        down: int, optional
+            Downsampling factor. Defaults to 4.
+        order: int, optional
+            Length, in samples, of the anti-aliasing lowpass filter.
+            Defaults to 128.
+
+    >>> import os
+    >>> home = os.path.expanduser('~')
+    >>> f = SNDS_PATH+'/transparent.aif'
+    >>> # upsample a signal 3 times
+    >>> upfile = os.path.join(home, 'trans_upsamp_2.aif')
+    >>> upsamp(f, upfile, 2, 256)
+    >>> # downsample the upsampled signal 3 times
+    >>> downfile = os.path.join(home, 'trans_downsamp_3.aif')
+    >>> downsamp(upfile, downfile, 3, 256)
+
+    """
+    path = stringencode(path)
+    outfile = stringencode(outfile)
+    p_downsamp(path, outfile, down, order)
+
+class PyoError(Exception):
+    """Base class for all pyo exceptions."""
+
+class PyoServerStateException(PyoError):
+    """Error raised when an operation requires the server to be booted."""
+
+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):
+    """
+    Raise an Exception if an object got an invalid argument.
+
+    :Args:
+
+        obj: Pyo object on which method is called.
+            Usually "self" in the function call.
+        format :
+            String of length equal to the number of arguments. Each character
+            indicating the expected argument type.
+
+            - O: float or PyoObject
+            - o: PyoObject
+            - T: float or PyoTableObject
+            - t: PyoTableObject
+            - m: PyoMatrixObject
+            - p: PyoPVObject
+            - n: any number (int or float)
+            - N: any number (no list-expansion)
+            - f: float
+            - F: float (no list-expansion)
+            - i: integer
+            - I: integer (no list-expansion)
+            - s: string or unicode
+            - S: string or unicode (no list-expansion)
+            - b: boolean
+            - B: boolean (no list-expansion)
+            - l: list
+            - L: list or None
+            - u: tuple
+            - x: sequence (list or tuple)
+            - c: callable
+            - C: callable (no list-expansion)
+            - z: anything
+        *args: any
+            Arguments passed to the object's method.
+
+    """
+    if sys.version_info[0] < 3:
+        # Python 2
+        longType = int
+    else:
+        # Python 3
+        # Not used in Python 3, ignore it
+        longType = None
+
+    i = 0
+    expected = ""
+    for i, arg in enumerate(args):
+        f = format[i]
+        argtype = type(arg)
+        if f == "O":
+            atypes = [list, int, longType, float]
+            if not isAudioObject(arg) and argtype not in atypes:
+                expected = "float or PyoObject"
+        elif f == "o":
+            if not isAudioObject(arg) and argtype not in [list]:
+                expected = "PyoObject"
+        elif f == "T":
+            if not isTableObject(arg) and argtype not in [float, list]:
+                expected = "float or PyoTableObject"
+        elif f == "t":
+            if not isTableObject(arg) and argtype not in [list]:
+                expected = "PyoTableObject"
+        elif f == "m":
+            if not isMatrixObject(arg) and argtype not in [list]:
+                expected = "PyoMatrixObject"
+        elif f == "p":
+            if not isPVObject(arg) and argtype not in [list]:
+                expected = "PyoPVObject"
+        elif f == "n":
+            if argtype not in [list, int, longType, float]:
+                expected = "any number"
+        elif f == "N":
+            if argtype not in [int, longType, float]:
+                expected = "any number - list not allowed"
+        elif f == "f":
+            if argtype not in [list, float]:
+                expected = "float"
+        elif f == "F":
+            if argtype not in [float]:
+                expected = "float - list not allowed"
+        elif f == "i":
+            if argtype not in [list, int, longType]:
+                expected = "integer"
+        elif f == "I":
+            if argtype not in [int, longType]:
+                expected = "integer - list not allowed"
+        elif f == "s":
+            if argtype not in [list, bytes_t, unicode_t]:
+                expected = "string"
+        elif f == "S":
+            if argtype not in [bytes_t, unicode_t]:
+                expected = "string - list not allowed"
+        elif f == "b":
+            if argtype not in [bool, list, int, longType]:
+                expected = "boolean"
+        elif f == "B":
+            if argtype not in [bool, int, longType]:
+                expected = "boolean - list not allowed"
+        elif f == "l":
+            if argtype not in [list]:
+                expected = "list"
+        elif f == "L":
+            if argtype not in [list, type(None)]:
+                expected = "list or None"
+        elif f == "u":
+            if argtype not in [tuple]:
+                expected = "tuple"
+        elif f == "x":
+            if argtype not in [list, tuple]:
+                expected = "list or tuple"
+        elif f == "c":
+            if not callable(arg) and argtype not in [list, tuple, type(None)]:
+                expected = "callable"
+        elif f == "C":
+            if not callable(arg) and argtype not in [type(None)]:
+                expected = "callable - list not allowed"
+        elif f == "z":
+            pass
+
+        if expected:
+            break
+
+    if expected:
+        name = obj.__class__.__name__
+        err = 'bad argument at position %d to "%s" (%s expected, got %s)'
+        raise PyoArgumentTypeError(err % (i, name, expected, argtype))
+
+def convertStringToSysEncoding(strng):
     """
     Convert a string to the current platform file system encoding.
-    
+
     Returns the new encoded string.
 
     :Args:
-    
-        str : string
+
+        strng: string
             String to convert.
 
     """
-    if type(str) != UnicodeType:
-        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):
     """
-    Convert all arguments to list if not already a list or a PyoObject. 
+    Convert all arguments to list if not already a list or a PyoObjectBase.
     Return new args and maximum list length.
-    
+
     """
     converted = []
     for i in args:
-        if isinstance(i, PyoObjectBase) or type(i) == ListType:
+        if isinstance(i, PyoObjectBase) or isinstance(i, list):
             converted.append(i)
         else:
             converted.append([i])
-            
+
     max_length = max(len(i) for i in converted)
     return tuple(converted + [max_length])
 
 def wrap(arg, i):
     """
     Return value at position `i` from `arg` with wrap around `arg` length.
-    
+
     """
     x = arg[i % len(arg)]
     if isinstance(x, PyoObjectBase):
@@ -111,18 +521,18 @@ 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:
 
-        cls : PyoObject class
+        cls: PyoObject class
             Class reference of the desired object example.
-        dur : float, optional
+        dur: float, optional
             Duration of the example.
-        toprint : boolean, optional
+        toprint: boolean, optional
             If True, the example script will be printed to the console.
             Defaults to True.
-        double : boolean, optional
+        double: boolean, optional
             If True, force the example to run in double precision (64-bit)
             Defaults to False.
 
@@ -132,7 +542,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
@@ -143,34 +553,37 @@ def example(cls, dur=5, toprint=True, double=False):
                 lines.append(line)
 
     if lines == []:
-        print "There is no manual example for %s object." % cls.__name__
+        print("There is no manual example for %s object." % cls.__name__)
         return
 
-    ex_lines = [line.lstrip("    ") for line in lines if ">>>" in line or "..." in line]
-    if hasattr(__builtin__, 'pyo_use_double') or double:
+    ex_lines = [l.lstrip("    ") for l in lines if ">>>" in l or "..." in l]
+    if hasattr(builtins, 'pyo_use_double') or double:
         ex = "import time\nfrom pyo64 import *\n"
     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
-    if sys.version_info[:2] <= (2, 5):
-        f = open('/tmp/pyo_example.py', 'w')
-    else:
-        f = tempfile.NamedTemporaryFile(delete=False)
+    f = tempfile.NamedTemporaryFile(delete=False)
     if toprint:
-        f.write('print """\n%s\n"""\n' % ex)
-    f.write(ex)
-    f.close()    
-    p = call(["python", f.name])
-      
+        f.write(tobytes('print("""\n%s\n""")\n' % ex))
+    f.write(tobytes(ex))
+    f.close()
+    executable = sys.executable
+    if not executable or executable is None:
+        executable = "python"
+    call([executable, f.name])
+
 def removeExtraDecimals(x):
-    if type(x) == FloatType:
+    "Return a floating-point value as a string with only two digits."
+    if isinstance(x, float):
         return "=%.2f" % x
-    elif type(x) == StringType:
+    elif type(x) in [bytes_t, unicode_t]:
         return '="%s"' % x
     else:
         return "=" + str(x)
@@ -179,23 +592,25 @@ def class_args(cls):
     """
     Returns the init line of a class reference.
 
-    This function takes a class reference (not an instance of that class) 
+    This function takes a class reference (not an instance of that class)
     as input and returns the init line of that class with the default values.
 
     :Args:
 
-        cls : PyoObject class
+        cls: PyoObject class
             Class reference of the desired object's init line.
 
-    >>> print class_args(Sine)
+    >>> print(class_args(Sine))
     >>> 'Sine(freq=1000, phase=0, mul=1, add=0)'
 
     """
     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, formatvalue=removeExtraDecimals)
+        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
     except TypeError:
@@ -204,30 +619,130 @@ def class_args(cls):
             if name in FUNCTIONS_INIT_LINES:
                 return FUNCTIONS_INIT_LINES[name]
         except:
-            print "class_args was unable to retrieve the init line of the object as an argument."
-            return ""
+            print("class_args was unable to retrieve the "
+                  "init line of the object as an argument.")
+        return ""
 
 def getVersion():
     """
     Returns the version number of the current pyo installation.
 
     This function returns the version number of the current pyo
-    installation as a 3-ints tuple (major, minor, rev). 
+    installation as a 3-ints tuple (major, minor, rev).
 
-    The returned tuple for version '0.4.1' will look like : (0, 4, 1)
+    The returned tuple for version '0.4.1' will look like: (0, 4, 1)
 
-    >>> print getVersion()
+    >>> print(getVersion())
     >>> (0, 5, 1)
 
     """
     major, minor, rev = PYO_VERSION.split('.')
     return (int(major), int(minor), int(rev))
 
-class PyoError(Exception):
-    """Base class for all pyo exceptions."""
+def pa_get_default_devices_from_host(host):
+    """
+    Returns the default input and output devices for a given audio host.
 
-class PyoServerStateException(PyoError):
-    """Error raised when an operation requires the server to be booted."""
+    This function can greatly help finding the device indexes (especially
+    on Windows) to give to the server in order to use to desired audio host.
+
+    :Args:
+
+        host: string
+            Name of the desired audio host. Possible hosts are:
+
+            - For Windows: mme, directsound, asio, wasapi or wdm-ks.
+            - For linux: alsa, oss, pulse or jack.
+            - For MacOS: core audio, jack or soundflower.
+
+    Return: (default_input_device, default_output_device)
+
+    """
+    host_default_in = pa_get_default_input()
+    host_default_out = pa_get_default_output()
+
+    # Retrieve host apis infos.
+    tempfile = os.path.join(os.path.expanduser("~"), "pa_retrieve_host_apis")
+    with open(tempfile, "w") as f:
+        with f as sys.stdout:
+            pa_list_host_apis()
+        sys.stdout = sys.__stdout__
+
+    with open(tempfile, "r") as f:
+        lines = f.readlines()
+
+    os.remove(tempfile)
+
+    # Build the list of currently available hosts.
+    host_names = []
+    for line in lines:
+        p1 = line.find("name: ") + 6
+        p2 = line.find(",", p1+1)
+        host_names.append(line[p1:p2])
+
+    # Search for the desired host.
+    found = False
+    for line in lines:
+        if host.lower() in line.lower():
+            splitted = line.replace("\n", "").split(", ")
+            attributes = [x.split(": ") for x in splitted]
+            found = True
+            break
+
+    # If not found, return portaudio default values.
+    if not found:
+        print("Pyo can't find audio host '%s'. Currently available hosts are:" % host)
+        for host in host_names:
+            print("    %s" % host.lower())
+        return host_default_in, host_default_out
+
+    # If found, search default device indexes.
+    for attribute in attributes:
+        if attribute[0] == "default in":
+            host_default_in = int(attribute[1])
+        elif attribute[0] == "default out":
+            host_default_out = int(attribute[1])
+
+    return host_default_in, host_default_out
+
+def getWeakMethodRef(x):
+    "Return a callable object as a weak method reference."
+    if type(x) in [list, tuple]:
+        tmp = []
+        for y in x:
+            if hasattr(y, "__self__"):
+                y = WeakMethod(y)
+            tmp.append(y)
+        x = tmp
+    else:
+        if hasattr(x, "__self__"):
+            x = WeakMethod(x)
+    return x
+
+class WeakMethod(object):
+    """A callable object. Takes one argument to init: 'object.method'.
+    Once created, call this object -- MyWeakMethod() --
+    and pass args/kwargs as you normally would.
+    """
+    def __new__(cls, callobj):
+        if callable(callobj):
+            return super(WeakMethod, cls).__new__(cls)
+
+    def __init__(self, callobj):
+        if hasattr(callobj, "__self__"):
+            self.target = proxy(callobj.__self__)
+            self.method = proxy(callobj.__func__)
+            self.isMethod = True
+        else:
+            self.method = callobj
+            self.isMethod = False
+
+    def __call__(self, *args, **kwargs):
+        """Call the method with args and kwargs as needed."""
+        if self.isMethod:
+            return self.method(self.target, *args, **kwargs)
+        else:
+            return self.method(*args, **kwargs)
 
 ######################################################################
 ### PyoObjectBase -> abstract class for pyo objects
@@ -244,33 +759,41 @@ class PyoObjectBase(object):
     .. note::
 
         **Operations allowed on all PyoObjectBase**
-            
-        >>> len(obj) # Return the number of streams managed by 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.
+
+        >>> len(obj)      # Return the number of streams managed by 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
+        >>>               # object's audio streams).
 
     """
 
     # Descriptive word for this kind of object, for use in printing
     # descriptions of the object. Subclasses need to set this.
     _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 before creating any audio object.")
+            raise PyoServerStateException("You must create and boot a Server "
+                                          "before creating any audio object.")
         if not serverBooted():
-            raise PyoServerStateException("The Server must be booted before creating any audio object.")
+            raise PyoServerStateException("The Server must be booted before "
+                                          "creating any audio object.")
 
     def dump(self):
         """
         Print infos about the current state of the object.
 
-        Print the number of Stream objects managed by the instance 
+        Print the number of Stream objects managed by the instance
         and the current status of the object's attributes.
 
         """
         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 ---'
@@ -286,16 +809,55 @@ class PyoObjectBase(object):
         """
         return self._base_objs
 
+    def getServer(self):
+        """
+        Return a reference to the current Server object.
+
+        """
+        return self._base_objs[0].getServer()
+
+    def getSamplingRate(self):
+        """
+        Return the current sampling rate (samples per second), as a float.
+
+        """
+        return self._base_objs[0].getServer().getSamplingRate()
+
+    def getBufferSize(self):
+        """
+        Return the current buffer size (samples per buffer), as an integer.
+
+        """
+        return self._base_objs[0].getServer().getBufferSize()
+
+    def __iter__(self):
+        self.__index = 0
+        return self
+
+    def __next__(self):
+        if self.__index >= len(self):
+            raise StopIteration
+        x = self[self.__index]
+        self.__index += 1
+        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':
             return self._trig_objs
-        if type(i) == SliceType or i < len(self._base_objs):
+        if type(i) == slice or i < len(self._base_objs):
             return self._base_objs[i]
         else:
-            if type(i) == StringType:
-                print "Object %s has no stream named '%s'!" % (self.__class__.__name__, i)
+            if type(i) in [bytes_t, unicode_t]:
+                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)
@@ -304,7 +866,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
 
@@ -314,96 +877,106 @@ class PyoObjectBase(object):
 class PyoObject(PyoObjectBase):
     """
     Base class for all pyo objects that manipulate vectors of samples.
-    
+
     The user should never instantiate an object of this class.
 
     :Parent: :py:class:`PyoObjectBase`
-    
+
     :Args:
 
-        mul : float or PyoObject, optional
+        mul: float or PyoObject, optional
             Multiplication factor. Defaults to 1.
-        add : float or PyoObject, optional
+        add: float or PyoObject, optional
             Addition factor. Defaults to 0.
 
     .. note::
-    
+
         **Arithmetics**
-    
-        Multiplication, addition, division and substraction can be applied 
-        between pyo objects or between pyo objects and numbers. Doing so 
+
+        Multiplication, addition, division and substraction can be applied
+        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 
-        applied between pyo objects or between pyo objects and numbers.         
-        These operations will replace the `mul` or `add` factor of the object. 
-        
+
+        Inplace multiplication, addition, division and substraction can be
+        applied between pyo objects or between pyo objects and numbers.
+        These operations will replace the `mul` or `add` factor of the object.
+
         >>> 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**
 
-        >>> a ** 10 # returns a Pow object created as : Pow(a, 10)
-        >>> 10 ** a # returns a Pow object created as : Pow(10, a)
-        >>> a % 4 # returns a Wrap object created as : Wrap(a, 0, 4)
-        >>> a % b # returns a Wrap object created as : Wrap(a, 0, b)
+        >>> a ** 10 # returns a Pow object created as: Pow(a, 10)
+        >>> 10 ** a # returns a Pow object created as: Pow(10, a)
+        >>> a % 4 # returns a Wrap object created as: Wrap(a, 0, 4)
+        >>> a % b # returns a Wrap object created as: Wrap(a, 0, b)
 
         **Unary negative** (**-**)
-    
+
         >>> -a # returns a Dummy object with negative values of streams in `a`.
-    
+
         **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=">=")
 
-        A special case concerns the comparison of a PyoObject with None. All operators
-        return False except `a != None`, which returns True.
+        >>> # 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.
 
     """
-    
+
     _STREAM_TYPE = 'audio'
 
     def __init__(self, mul=1.0, add=0.0):
         PyoObjectBase.__init__(self)
         self._target_dict = {}
         self._signal_dict = {}
+        self._callback_dict = {}
         self._keep_trace = []
         self._mul = mul
         self._add = add
         self._op_duplicate = 1
         self._map_list = []
         self._zeros = None
+        self._base_players = None
+        self._time_objs = 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
-            
+
     def __iadd__(self, x):
         self.setAdd(x)
         return self
@@ -411,12 +984,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
 
@@ -425,7 +1001,7 @@ class PyoObject(PyoObjectBase):
         if self.__len__() >= lmax:
             tmp = []
             for i, obj in enumerate(self._base_objs):
-                sub_upsamp = Sig(wrap(x, i/self._op_duplicate))
+                sub_upsamp = Sig(wrap(x, i//self._op_duplicate))
                 self._keep_trace.append(sub_upsamp)
                 tmp.append(sub_upsamp - obj)
             _add_dummy = Dummy(tmp)
@@ -434,7 +1010,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
@@ -442,41 +1018,57 @@ class PyoObject(PyoObjectBase):
     def __isub__(self, x):
         self.setSub(x)
         return self
- 
+
     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
-            
+
     def __imul__(self, x):
         self.setMul(x)
         return self
- 
+
+    def __truediv__(self, x):
+        return self.__div__(x)
+
+    def __rtruediv__(self, x):
+        return self.__rdiv__(x)
+
+    def __itruediv__(self, x):
+        return self.__idiv__(x)
+
     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
 
@@ -485,7 +1077,7 @@ class PyoObject(PyoObjectBase):
         if self.__len__() >= lmax:
             tmp = []
             for i, obj in enumerate(self._base_objs):
-                div_upsamp = Sig(wrap(x, i/self._op_duplicate))
+                div_upsamp = Sig(wrap(x, i//self._op_duplicate))
                 self._keep_trace.append(div_upsamp)
                 tmp.append(div_upsamp / obj)
             _mul_dummy = Dummy(tmp)
@@ -494,7 +1086,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
@@ -511,9 +1103,9 @@ class PyoObject(PyoObjectBase):
 
     def __mod__(self, x):
         return Wrap(self, 0, x)
-    
+
     def __neg__(self):
-        if self._zeros == None:
+        if self._zeros is None:
             self._zeros = Sig(0)
         return self._zeros - self
 
@@ -536,7 +1128,7 @@ class PyoObject(PyoObjectBase):
         return self.__do_comp__(comp=x, mode=">=")
 
     def __do_comp__(self, comp, mode, default=False):
-        if comp == None:
+        if comp is None:
             return default
         else:
             return Compare(self, comp=comp, mode=mode)
@@ -547,14 +1139,15 @@ class PyoObject(PyoObjectBase):
 
         :Args:
 
-            all : boolean, optional
+            all: boolean, optional
                 If True, the object returns a list with the state of all
                 streams managed by the object.
-                
-                If False, it return a boolean corresponding to the state 
+
+                If False, it return a boolean corresponding to the state
                 of the first stream.
 
         """
+        pyoArgsAssert(self, "B", all)
         if all:
             return [obj._getStream().isPlaying() for obj in self._base_objs]
         else:
@@ -562,44 +1155,49 @@ 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:
 
-            all : boolean, optional
+            all: boolean, optional
                 If True, the object returns a list with the state of all
-                streams managed by the object. 
-                
-                If False, it return a boolean corresponding to the state 
+                streams managed by the object.
+
+                If False, it return a boolean corresponding to the state
                 of the first stream.
 
         """
+        pyoArgsAssert(self, "B", all)
         if all:
             return [obj._getStream().isOutputting() for obj in self._base_objs]
         else:
             return self._base_objs[0]._getStream().isOutputting()
-            
+
     def get(self, all=False):
         """
         Return the first sample of the current buffer as a float.
-        
+
         Can be used to convert audio stream to usable Python data.
-        
-        Object that implements string identifier for specific audio 
+
+        Object that implements string identifier for specific audio
         streams must use the corresponding string to specify the stream
-        from which to get the value. See get() method definition in these 
+        from which to get the value. See get() method definition in these
         object's man pages.
-        
+
         :Args:
 
-            all : boolean, optional
+            all: boolean, optional
                 If True, the first value of each object's stream
-                will be returned as a list. 
-                
-                If False, only the value of the first object's stream 
+                will be returned as a list.
+
+                If False, only the value of the first object's stream
                 will be returned as a float.
 
         """
+        pyoArgsAssert(self, "B", all)
         if not all:
             return self._base_objs[0]._getStream().getValue()
         else:
@@ -607,27 +1205,40 @@ class PyoObject(PyoObjectBase):
 
     def play(self, dur=0, delay=0):
         """
-        Start processing without sending samples to output. 
+        Start processing without sending samples to output.
         This method is called automatically at the object creation.
 
         This method returns `self`, allowing it to be applied at the object
         creation.
-        
+
         :Args:
-        
-            dur : float, optional
-                Duration, in seconds, of the object's activation. The default is 0
-                and means infinite duration.
-            delay : float, optional
+
+            dur: float, optional
+                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"):
-            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._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))
+            else:
+                self._trig_objs.play(dur, delay)
+        if self._base_players is not None:
+            [obj.play(wrap(dur, i), wrap(delay, i)) \
+             for i, obj in enumerate(self._base_players)]
+        if self._time_objs is not None:
+            # We don't send 'dur' argument to time_stream to avoid a stop() call.
+            [obj.play(0, wrap(delay, i)) \
+             for i, obj in enumerate(self._time_objs)]
+
+        [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):
@@ -636,74 +1247,99 @@ class PyoObject(PyoObjectBase):
 
         This method returns `self`, allowing it to be applied at the object
         creation.
-        
+
         :Args:
 
-            chnl : int, optional
-                Physical output assigned to the first audio stream of the object. 
-                Defaults to 0.
-            inc : int, optional
+            chnl: int, optional
+                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.
-            delay : float, optional
-                Delay, in seconds, before the object's activation. Defaults to 0.
-            
-        If `chnl` >= 0, successive streams increment the output number by 
+            dur: float, optional
+                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.
+
+        If `chnl` >= 0, successive streams increment the output number by
         `inc` and wrap around the global number of channels.
-        
-        If `chnl` is negative, streams begin at 0, increment 
-        the output number by `inc` and wrap around the global number of 
+
+        If `chnl` is negative, streams begin at 0, increment
+        the output number by `inc` and wrap around the global number of
         channels. Then, the list of streams is scrambled.
-        
-        If `chnl` is a list, successive values in the list will be 
+
+        If `chnl` is a list, successive values in the list will be
         assigned to successive streams.
 
         """
+        pyoArgsAssert(self, "iInn", chnl, inc, dur, delay)
         dur, delay, lmax = convertArgsToLists(dur, delay)
-        if hasattr(self, "_trig_objs"):
-            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) == ListType:
-            [obj.out(wrap(chnl,i), wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_objs)]
+        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))
+            else:
+                self._trig_objs.play(dur, delay)
+        if self._base_players is not None:
+            [obj.play(wrap(dur, i), wrap(delay, i))
+             for i, obj in enumerate(self._base_players)]
+        if self._time_objs is not None:
+            # We don't send 'dur' argument to time_stream to avoid a stop() call.
+            [obj.play(0, wrap(delay, i))
+             for i, obj in enumerate(self._time_objs)]
+
+        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)))]
+            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)))]
             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):
         """
         Stop processing.
 
         This method returns `self`, allowing it to be applied at the object
         creation.
-        
+
         """
-        if hasattr(self, "_trig_objs"):
-            self._trig_objs.stop()
-        if hasattr(self, "_base_players"):
+        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 self._base_players is not None:
             [obj.stop() for obj in self._base_players]
+        # This is not good for TableRec objects, only for Looper.
+        # It's move locally to the Looper definition.
+        #if self._time_objs is not None:
+        #    [obj.stop() for obj in self._time_objs]
+
         [obj.stop() for obj in self._base_objs]
         return self
 
     def mix(self, voices=1):
         """
-        Mix the object's audio streams into `voices` streams and return 
+        Mix the object's audio streams into `voices` streams and return
         a Mix object.
-        
+
         :Args:
 
-            voices : int, optional
-                Number of audio streams of the Mix object created by this method. 
-                Defaults to 1.
+            voices: int, optional
+                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 
+                If more than 1, object's streams are alternated and added into
                 Mix object's streams.
-            
+
         """
         return Mix(self, voices)
 
@@ -721,80 +1357,89 @@ class PyoObject(PyoObjectBase):
 
         :Args:
 
-            min : float
+            min: float
                 Minimum value of the output signal.
-            max : float
+            max: float
                 Maximum value of the output signal.
 
         """
+        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
         self.setMul(mul)
         self.setAdd(add)
         return self
-        
+
     def setMul(self, x):
         """
         Replace the `mul` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `mul` attribute.
-        
+
         """
+        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):
         """
         Replace the `add` attribute.
-                
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `add` attribute.
-        
+
         """
+        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):
         """
-        Replace and inverse the `mul` attribute.
-        
+        Replace and inverse the `add` attribute.
+
         :Args:
 
-            x : float or PyoObject
-                New inversed `mul` attribute.
-        
+            x: float or PyoObject
+                New inversed `add` attribute.
+
         """
+        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):
         """
-        Replace and inverse the `add` attribute.
-                
+        Replace and inverse the `mul` attribute.
+
         :Args:
 
-            x : float or PyoObject
-                New inversed `add` attribute.
+            x: float or PyoObject
+                New inversed `mul` attribute.
 
         """
+        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):
+    def set(self, attr, value, port=0.025, callback=None):
         """
         Replace any attribute with portamento.
 
@@ -804,115 +1449,130 @@ class PyoObject(PyoObjectBase):
 
         :Args:
 
-            attr : string
+            attr: string
                 Name of the attribute as a string.
-            value : float
+            value: float
                 New value.
-            port : float, optional
+            port: float, optional
                 Time, in seconds, to reach the new value.
+            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.
 
         """
+        pyoArgsAssert(self, "SnnC", attr, value, port, callback)
         self._target_dict[attr] = value
+        self._callback_dict[attr] = callback
         init = getattr(self, attr)
-        if self._signal_dict.has_key(attr):
+        if attr in self._signal_dict:
             if isinstance(self._signal_dict[attr], VarPort):
                 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):
         if isinstance(getattr(self, attr), VarPort):
             setattr(self, attr, self._target_dict[attr])
+            if self._callback_dict[attr] is not None:
+                self._callback_dict[attr]()
+                del self._callback_dict[attr]
         self._signal_dict[attr].stop()
-        
+
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         """
-        Opens a sliders window to control the parameters of the object. 
-        Only parameters that can be set to a PyoObject are allowed 
+        Opens a sliders window to control the parameters of the object.
+        Only parameters that can be set to a PyoObject are allowed
         to be mapped on a slider.
 
-        If a list of values are given to a parameter, a multisliders 
+        If a list of values are given to a parameter, a multisliders
         will be used to control each stream independently.
 
         :Args:
 
-            map_list : list of SLMap objects, optional
-                Users defined set of parameters scaling. There is default 
+            map_list: list of SLMap objects, optional
+                Users defined set of parameters scaling. There is default
                 scaling for each object that accept `ctrl` method.
-            title : string, optional
-                Title of the window. If none is provided, the name of the 
+            title: string, optional
+                Title of the window. If none is provided, the name of the
                 class is used.
-            wxnoserver : boolean, optional
-                With wxPython graphical toolkit, if True, tells the 
+            wxnoserver: boolean, optional
+                With wxPython graphical toolkit, if True, tells the
                 interpreter that there will be no server window.
-                
-        If `wxnoserver` is set to True, the interpreter will not wait for 
-        the server GUI before showing the controller window. 
+
+        If `wxnoserver` is set to True, the interpreter will not wait for
+        the server GUI before showing the controller window.
 
         """
-        if map_list == None:
+        if map_list is None:
             map_list = self._map_list
         if map_list == []:
-            print("There is 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)
 
     @property
     def mul(self):
-        """float or PyoObject. Multiplication factor.""" 
+        """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.""" 
+        """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
 ######################################################################
 class PyoTableObject(PyoObjectBase):
     """
-    Base class for all pyo table objects. 
-    
-    A table object is a buffer memory to store precomputed samples. 
-    
+    Base class for all pyo table objects.
+
+    A table object is a buffer memory to store precomputed samples.
+
     The user should never instantiate an object of this class.
-    
+
     :Parent: :py:class:`PyoObjectBase`
- 
+
     :Args:
 
-        size : int
-            Length of the table in samples. Usually provided by the child object.
+        size: int
+            Length of the table in samples. Usually provided by the
+            child object.
 
     """
-    
+
     _STREAM_TYPE = 'table'
 
     def __init__(self, size=0):
         PyoObjectBase.__init__(self)
         self._size = size
         self.viewFrame = None
+        self.graphFrame = None
 
-    def save(self, path, format=0, sampletype=0):
+    def save(self, path, format=0, sampletype=0, quality=0.4):
         """
         Writes the content of the table in an audio file.
-        
+
         The sampling rate of the file is the sampling rate of the server
         and the number of channels is the number of table streams of the
         object.
 
         :Args:
-        
-            path : string
+
+            path: string
                 Full path (including extension) of the new file.
-            format : int, optional
+            format: int, optional
                 Format type of the new file. Supported formats are:
                     0. WAVE - Microsoft WAV format (little endian) {.wav, .wave}
                     1. AIFF - Apple/SGI AIFF format (big endian) {.aif, .aiff}
@@ -922,9 +1582,9 @@ class PyoTableObject(PyoObjectBase):
                     5. FLAC - FLAC lossless file format {.flac}
                     6. CAF - Core Audio File format {.caf}
                     7. OGG - Xiph OGG container {.ogg}
-            sampletype : int, optional
-                Bit depth encoding of the audio file. 
-                
+            sampletype: int, optional
+                Bit depth encoding of the audio file.
+
                 SD2 and FLAC only support 16 or 24 bit int. Supported types are:
                     0. 16 bit int (default)
                     1. 24 bit int
@@ -933,33 +1593,39 @@ class PyoTableObject(PyoObjectBase):
                     4. 64 bit float
                     5. U-Law encoded
                     6. A-Law encoded
+            quality: float, optional
+                The encoding quality value, between 0.0 (lowest quality) and
+                1.0 (highest quality). This argument has an effect only with
+                FLAC and OGG compressed formats. Defaults to 0.4.
 
         """
+        pyoArgsAssert(self, "SIIN", path, format, sampletype, quality)
         ext = path.rsplit('.')
         if len(ext) >= 2:
             ext = ext[-1].lower()
-            if FILE_FORMATS.has_key(ext):
+            if ext in FILE_FORMATS:
                 format = FILE_FORMATS[ext]
-        savefileFromTable(self, path, format, sampletype)
-    
+        savefileFromTable(self, path, format, sampletype, quality)
+
     def write(self, path, oneline=True):
         """
         Writes the content of the table in a text file.
-        
+
         This function can be used to store the table data as a
         list of floats into a text file.
-        
+
         :Args:
-        
-            path : string
+
+            path: string
                 Full path of the generated file.
-            oneline : boolean, optional
+            oneline: boolean, optional
                 If True, list of samples will inserted on one line.
 
                 If False, list of samples will be truncated to 8 floats
                 per line.
 
         """
+        pyoArgsAssert(self, "SB", path, oneline)
         f = open(path, "w")
         if oneline:
             f.write(str([obj.getTable() for obj in self._base_objs]))
@@ -980,21 +1646,22 @@ class PyoTableObject(PyoObjectBase):
         """
         Reads the content of a text file and replaces the table data
         with the values stored in the file.
-        
+
         :Args:
-            
-            path : string
+
+            path: string
                 Full path of the file to read.
-        
-        The format is a list of lists of floats. For example, A two 
+
+        The format is a list of lists of floats. For example, A two
         tablestreams object must be given a content like this:
-        
+
         [ [ 0.0, 1.0, 0.5, ... ], [ 1.0, 0.99, 0.98, 0.97, ... ] ]
-        
-        Each object's tablestream will be resized according to the 
+
+        Each object's tablestream will be resized according to the
         length of the lists.
-        
+
         """
+        pyoArgsAssert(self, "S", path)
         f = open(path, "r")
         f_list = eval(f.read())
         f_len = len(f_list)
@@ -1002,18 +1669,42 @@ class PyoTableObject(PyoObjectBase):
         [obj.setData(f_list[i%f_len]) for i, obj in enumerate(self._base_objs)]
         self.refreshView()
 
+    def getBuffer(self, chnl=0):
+        """
+        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:
+
+            t = SndTable(SNDS_PATH+"/transparent.aif")
+            arr = numpy.asarray(t.getBuffer())
+
+        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.
+
+        """
+        if chnl < 0 or chnl >= len(self):
+            print("getBuffer(chnl): `chnl` argument out-of-range...")
+        else:
+            return self._base_objs[chnl].getTableStream()
+
     def setSize(self, size):
         """
-        Change the size of the table. 
-        
+        Change the size of the table.
+
         This will erase the previously drawn waveform.
-        
+
         :Args:
-        
-            size : int
+
+            size: int
                 New table size in samples.
-        
+
         """
+        pyoArgsAssert(self, "I", size)
         self._size = size
         [obj.setSize(size) for obj in self._base_objs]
         self.refreshView()
@@ -1021,19 +1712,20 @@ class PyoTableObject(PyoObjectBase):
     def getSize(self, all=False):
         """
         Return table size in samples.
- 
+
         :Args:
-        
-            all : boolean
+
+            all: boolean
                 If the table contains more than one stream and `all` is True,
                 returns a list of all sizes. Otherwise, returns only the
                 first size as an int. Defaults to False.
-       
+
         """
+        pyoArgsAssert(self, "B", all)
         if all:
             return [obj.getSize() for obj in self._base_objs]
         else:
-            if type(self._size) == ListType:
+            if isinstance(self._size, list):
                 return self._size[0]
             else:
                 return self._size
@@ -1041,54 +1733,59 @@ class PyoTableObject(PyoObjectBase):
     def put(self, value, pos=0):
         """
         Puts a value at specified sample position in the table.
-        
+
         If the object has more than 1 tablestream, the default is to
-        record the value in each table. User can call obj[x].put() 
+        record the value in each table. User can call obj[x].put()
         to record into a specific table.
-        
+
         :Args:
-        
-            value : float
+
+            value: float
                 Value, as floating-point, to record in the table.
-            pos : int, optional
+            pos: int, optional
                 Position, in samples, where to record value. Defaults to 0.
-        
+
         """
+        pyoArgsAssert(self, "NI", value, pos)
         [obj.put(value, pos) for obj in self._base_objs]
         self.refreshView()
 
     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 
+        return a list with the value of each tablestream. User can call
         obj[x].get() to get the value of a specific table.
-        
+
         :Args:
-        
-            pos : int, optional
+
+            pos: int, optional
                 Position, in samples, where to read the value. Defaults to 0.
-        
+
         """
+        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):
         """
         Returns the content of the table as list of floats.
-        
+
         :Args:
 
-            all : boolean, optional
+            all: boolean, optional
                 If True, all sub tables are retrieved and returned as a list
-                of list of floats. 
-                
-                If False, a single list containing the content of the first 
+                of list of floats.
+
+                If False, a single list containing the content of the first
                 subtable (or the only one) is returned.
 
         """
+        pyoArgsAssert(self, "B", all)
         if all:
             return [obj.getTable() for obj in self._base_objs]
         else:
@@ -1123,28 +1820,244 @@ class PyoTableObject(PyoObjectBase):
 
     def reverse(self):
         """
-        Reverse the table's data.
+        Reverse the table's data in time.
 
         """
         [obj.reverse() for obj in self._base_objs]
         self.refreshView()
         return self
 
+    def invert(self):
+        """
+        Reverse the table's data in amplitude.
+
+        """
+        [obj.invert() for obj in self._base_objs]
+        self.refreshView()
+        return self
+
+    def rectify(self):
+        """
+        Positive rectification of the table's data.
+
+        """
+        [obj.rectify() for obj in self._base_objs]
+        self.refreshView()
+        return self
+
+    def pow(self, exp=10):
+        """
+        Apply a power function on each sample in the table.
+
+        :Args:
+
+            exp: float, optional
+                Exponent factor. Defaults to 10.
+
+        """
+        pyoArgsAssert(self, "N", exp)
+        [obj.pow(exp) for obj in self._base_objs]
+        self.refreshView()
+        return self
+
+    def bipolarGain(self, gpos=1, gneg=1):
+        """
+        Apply different gain factor for positive and negative samples.
+
+        :Args:
+
+            gpos: float, optional
+                Gain factor for positive samples. Defaults to 1.
+            gneg: float, optional
+                Gain factor for negative samples. Defaults to 1.
+
+        """
+        pyoArgsAssert(self, "NN", gpos, gneg)
+        [obj.bipolarGain(gpos, gneg) for obj in self._base_objs]
+        self.refreshView()
+        return self
+
+    def lowpass(self, freq=1000):
+        """
+        Apply a one-pole lowpass filter on table's samples.
+
+        :Args:
+
+            freq: float, optional
+                Filter's cutoff, in Hertz. Defaults to 1000.
+
+        """
+        pyoArgsAssert(self, "N", freq)
+        [obj.lowpass(freq) for obj in self._base_objs]
+        self.refreshView()
+        return self
+
+    def fadein(self, dur=0.1):
+        """
+        Apply a gradual increase in the level of the table's samples.
+
+        :Args:
+
+            dur: float, optional
+                Fade in duration, in seconds. Defaults to 0.1.
+
+        """
+        pyoArgsAssert(self, "N", dur)
+        [obj.fadein(dur) for obj in self._base_objs]
+        self.refreshView()
+        return self
+
+    def fadeout(self, dur=0.1):
+        """
+        Apply a gradual decrease in the level of the table's samples.
+
+        :Args:
+
+            dur: float, optional
+                Fade out duration, in seconds. Defaults to 0.1.
+
+        """
+        pyoArgsAssert(self, "N", dur)
+        [obj.fadeout(dur) for obj in self._base_objs]
+        self.refreshView()
+        return self
+
+    def add(self, x):
+        """
+        Performs addition on the table values.
+
+        Adds the argument to each table values, position by position
+        if the argument is a list or another PyoTableObject.
+
+        :Args:
+
+            x: float, list or PyoTableObject
+                value(s) to add.
+
+        """
+        pyoArgsAssert(self, "T", x)
+        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, _ = convertArgsToLists(x)
+            [obj.add(wrap(x, i)) for i, obj in enumerate(self._base_objs)]
+        self.refreshView()
+        return self
+
+    def sub(self, x):
+        """
+        Performs substraction on the table values.
+
+        Substracts the argument to each table values, position by position
+        if the argument is a list or another PyoTableObject.
+
+        :Args:
+
+            x: float, list or PyoTableObject
+                value(s) to substract.
+
+        """
+        pyoArgsAssert(self, "T", x)
+        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, _ = convertArgsToLists(x)
+            [obj.sub(wrap(x, i)) for i, obj in enumerate(self._base_objs)]
+        self.refreshView()
+        return self
+
+    def mul(self, x):
+        """
+        Performs multiplication on the table values.
+
+        Multiply each table values by the argument, position by position
+        if the argument is a list or another PyoTableObject.
+
+        :Args:
+
+            x: float, list or PyoTableObject
+                value(s) to multiply.
+
+        """
+        pyoArgsAssert(self, "T", x)
+        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, _ = convertArgsToLists(x)
+            [obj.mul(wrap(x, i)) for i, obj in enumerate(self._base_objs)]
+        self.refreshView()
+        return self
+
+    def copyData(self, table, srcpos=0, destpos=0, length=-1):
+        """
+        Copy samples from a source table.
+
+        Copy `length` samples from a source table to this table.
+
+        :Args:
+
+            table: PyoTableObject
+                The source table.
+            srcpos: int, optional
+                The start position in the source table. Defaults to 0.
+            destpos ; int, optional
+                The start position in the destination (self) table. Defaults
+                to 0.
+            length: int, optional
+                The number of samples to copy from source to destination. if
+                length is negative, the length of the smallest table is used.
+                Defaults to -1.
+
+        """
+        pyoArgsAssert(self, "tIII", table, srcpos, destpos, length)
+        [obj.copyData(table[i], srcpos,
+                      destpos, length) for i, obj in enumerate(self._base_objs)]
+        self.refreshView()
+
+    def rotate(self, pos):
+        """
+        Rotate the table content to the left around the position given as argument.
+
+        Samples between the given position and the end of the table will
+        be relocated in front of the samples from the beginning to the
+        given position.
+
+        :Args:
+
+            pos: int
+                The rotation position in samples. A negative position means
+                a rotation to the right.
+
+        """
+        pyoArgsAssert(self, "I", pos)
+        [obj.rotate(pos) for obj in self._base_objs]
+        self.refreshView()
+
     def copy(self):
         """
         Returns a deep copy of the object.
-        
+
         """
         args = [getattr(self, att) for att in self.__dir__()]
         if self.__class__.__name__ == "SndTable":
             _size = self.getSize()
-            if type(_size) != ListType:
+            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)
@@ -1154,76 +2067,98 @@ class PyoTableObject(PyoObjectBase):
     def view(self, title="Table waveform", wxnoserver=False):
         """
         Opens a window showing the contents of the table.
-        
+
         :Args:
-        
-            title : string, optional
-                Window title. Defaults to "Table waveform". 
-            wxnoserver : boolean, optional
-                With wxPython graphical toolkit, if True, tells the 
+
+            title: string, optional
+                Window title. Defaults to "Table waveform".
+            wxnoserver: boolean, optional
+                With wxPython graphical toolkit, if True, tells the
                 interpreter that there will be no server window.
-                
-        If `wxnoserver` is set to True, the interpreter will not wait for 
-        the server GUI before showing the controller window. 
-        
+
+        If `wxnoserver` is set to True, the interpreter will not wait for
+        the server GUI before showing the controller window.
+
         """
-        samples = self._base_objs[0].getViewTable()
-        createViewTableWindow(samples, title, wxnoserver, self.__class__.__name__, self)
+        pyoArgsAssert(self, "SB", title, wxnoserver)
+        samples = self._base_objs[0].getViewTable((500, 200))
+        createViewTableWindow(samples, title, wxnoserver,
+                              self.__class__.__name__, self)
 
     def _setViewFrame(self, frame):
         self.viewFrame = frame
-        
+
+    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.
 
         """
-        if self.viewFrame != None:
-            samples = self._base_objs[0].getViewTable()
+        if self.viewFrame is not None:
+            size = self.viewFrame.wavePanel.GetSize()
+            samples = self._base_objs[0].getViewTable((size[0], size[1]))
             self.viewFrame.update(samples)
+        if self.graphFrame is not None:
+            data = self._get_current_data()
+            length = len(data)
+            flength = self.graphFrame.getLength()
+            if length < flength:
+                data = data + [0] * (flength - length)
+            elif length > flength:
+                data = data[:flength]
+            self.graphFrame.update(data)
 
     @property
     def size(self):
-        """int. Table size in samples.""" 
+        """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
 ######################################################################
 class PyoMatrixObject(PyoObjectBase):
     """
-    Base class for all pyo matrix objects. 
-    
-    A matrix object is a 2 dimensions buffer memory to store 
-    precomputed samples. 
-    
+    Base class for all pyo matrix objects.
+
+    A matrix object is a 2 dimensions buffer memory to store
+    precomputed samples.
+
     The user should never instantiate an object of this class.
-    
+
     :Parent: :py:class:`PyoObjectBase`
 
     """
-    
+
     _STREAM_TYPE = 'matrix'
 
     def __init__(self):
+        self._size = (0, 0)
         PyoObjectBase.__init__(self)
         self.viewFrame = None
 
     def write(self, path):
         """
         Writes the content of the matrix into a text file.
-        
+
         This function can be used to store the matrix data as a
         list of list of floats into a text file.
 
         :Args:
-            
-            path : string
+
+            path: string
                 Full path of the generated file.
-         
+
         """
+        pyoArgsAssert(self, "S", path)
         f = open(path, "w")
         f.write(str([obj.getData() for obj in self._base_objs]))
         f.close()
@@ -1232,23 +2167,24 @@ class PyoMatrixObject(PyoObjectBase):
         """
         Reads the content of a text file and replaces the matrix data
         with the values in the file.
-        
-        Format is a list of lists of floats. For example, A two 
+
+        Format is a list of lists of floats. For example, A two
         matrixstreams object must be given a content like this:
-        
+
         [ [ [0.0 ,1.0, 0.5, ... ], [1.0, 0.99, 0.98, 0.97, ... ] ],
         [ [0.0, 1.0, 0.5, ... ], [1.0, 0.99, 0.98, 0.97, ... ] ] ]
-        
-        Each object's matrixstream will be resized according to the 
+
+        Each object's matrixstream will be resized according to the
         length of the lists, but the number of matrixstreams must be
         the same.
- 
+
         :Args:
-            
-            path : string
+
+            path: string
                 Full path of the file to read.
-       
+
         """
+        pyoArgsAssert(self, "S", path)
         f = open(path, "r")
         f_list = eval(f.read())
         f_len = len(f_list)
@@ -1258,7 +2194,7 @@ class PyoMatrixObject(PyoObjectBase):
     def getSize(self):
         """
         Returns matrix size in samples. Size is a tuple (x, y).
-        
+
         """
         return self._size
 
@@ -1280,88 +2216,117 @@ class PyoMatrixObject(PyoObjectBase):
     def boost(self, min=-1.0, max=1.0, boost=0.01):
         """
         Boost the constrast of values in the matrix.
-        
+
         :Args:
-        
-            min : float, optional
+
+            min: float, optional
                 Minimum value. Defaults to -1.0.
-            max : float, optional
+            max: float, optional
                 Maximum value. Defaults to 1.0.
-            boost : float, optional
+            boost: float, optional
                 Amount of boost applied on each value. Defaults to 0.01.
 
         """
+        pyoArgsAssert(self, "NNN", min, max, boost)
         [obj.boost(min, max, boost) for obj in self._base_objs]
 
     def put(self, value, x=0, y=0):
         """
         Puts a value at specified position in the matrix.
-        
+
         If the object has more than 1 matrixstream, the default is to
-        record the value in each matrix. User can call obj[x].put() 
+        record the value in each matrix. User can call obj[x].put()
         to record in a specific matrix.
-        
+
         :Args:
-        
-            value : float
+
+            value: float
                 Value, as floating-point, to record in the matrix.
-            x : int, optional
+            x: int, optional
                 X position where to record value. Defaults to 0.
-            y : int, optional
+            y: int, optional
                 Y position where to record value. Defaults to 0.
-        
+
         """
+        pyoArgsAssert(self, "NII", value, x, y)
         [obj.put(value, x, y) for obj in self._base_objs]
 
-    def get(self, x, y):
+    def get(self, x=0, y=0):
         """
         Returns the value, as float, at specified position in the matrix.
-        
+
         If the object has more than 1 matrixstream, the default is to
-        return a list with the value of each matrixstream. User can call 
+        return a list with the value of each matrixstream. User can call
         obj[x].get() to get the value of a specific matrix.
-        
+
         :Args:
-        
-            x : int, optional
+
+            x: int, optional
                 X position where to get value. Defaults to 0.
-            y : int, optional
+            y: int, optional
                 Y position where to get value. Defaults to 0.
-        
+
         """
+        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 getInterpolated(self, x=0.0, y=0.0):
+        """
+        Returns the value, as float, at a normalized position in the matrix.
+
+        If the object has more than 1 matrixstream, the default is to
+        return a list with the value of each matrixstream. User can call
+        obj[x].getInterpolated() to get the value of a specific matrix.
+
+        :Args:
+
+            x: float {0 -> 1}
+                X normalized position where to get value. Defaults to 0.0.
+            y: int {0 -> 1}
+                Y normalized position where to get value. Defaults to 0.0.
+
+        """
+        pyoArgsAssert(self, "FF", x, y)
+        values = [obj.getInterpolated(x, y) for obj in self._base_objs]
+        if len(values) == 1:
+            return values[0]
+        else:
+            return values
 
     def view(self, title="Matrix viewer", wxnoserver=False):
         """
         Opens a window showing the contents of the matrix.
-        
+
         :Args:
-        
-            title : string, optional
-                Window title. Defaults to "Matrix viewer". 
-            wxnoserver : boolean, optional
-                With wxPython graphical toolkit, if True, tells the 
+
+            title: string, optional
+                Window title. Defaults to "Matrix viewer".
+            wxnoserver: boolean, optional
+                With wxPython graphical toolkit, if True, tells the
                 interpreter that there will be no server window.
-                
-        If `wxnoserver` is set to True, the interpreter will not wait for 
-        the server GUI before showing the controller window. 
-        
-        """        
-        samples = self._base_objs[0].getViewData()
+
+        If `wxnoserver` is set to True, the interpreter will not wait for
+        the server GUI before showing the controller window.
+
+        """
+        pyoArgsAssert(self, "SB", title, wxnoserver)
+        samples = self._base_objs[0].getImageData()
         createViewMatrixWindow(samples, self.getSize(), title, wxnoserver, self)
 
     def _setViewFrame(self, frame):
         self.viewFrame = frame
-        
+
     def refreshView(self):
         """
         Updates the graphical display of the matrix, if applicable.
 
         """
-        if self.viewFrame != None:
-            samples = self._base_objs[0].getViewData()
+        if self.viewFrame is not None:
+            samples = self._base_objs[0].getImageData()
             self.viewFrame.update(samples)
 
 ######################################################################
@@ -1370,13 +2335,13 @@ class PyoMatrixObject(PyoObjectBase):
 class PyoPVObject(PyoObjectBase):
     """
     Base class for objects working with phase vocoder's magnitude and frequency streams.
-    
+
     The user should never instantiate an object of this class.
 
     :Parent: :py:class:`PyoObjectBase`
 
     """
-    
+
     _STREAM_TYPE = 'pvoc'
 
     def __init__(self):
@@ -1384,6 +2349,7 @@ class PyoPVObject(PyoObjectBase):
         self._target_dict = {}
         self._signal_dict = {}
         self._map_list = []
+        self._base_players = None
 
     def isPlaying(self, all=False):
         """
@@ -1391,14 +2357,15 @@ class PyoPVObject(PyoObjectBase):
 
         :Args:
 
-            all : boolean, optional
+            all: boolean, optional
                 If True, the object returns a list with the state of all
                 streams managed by the object.
-                
-                If False, it return a boolean corresponding to the state 
+
+                If False, it return a boolean corresponding to the state
                 of the first stream.
 
         """
+        pyoArgsAssert(self, "B", all)
         if all:
             return [obj._getStream().isPlaying() for obj in self._base_objs]
         else:
@@ -1406,40 +2373,44 @@ class PyoPVObject(PyoObjectBase):
 
     def play(self, dur=0, delay=0):
         """
-        Start processing without sending samples to output. 
+        Start processing without sending samples to output.
         This method is called automatically at the object creation.
 
         This method returns `self`, allowing it to be applied at the object
         creation.
-        
+
         :Args:
-        
-            dur : float, optional
-                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.
-        
+
+            dur: float, optional
+                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.
+
         """
-        dur, delay, lmax = convertArgsToLists(dur, delay)
-        if hasattr(self, "_trig_objs"):
+        pyoArgsAssert(self, "nn", dur, delay)
+        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):
         """
         Stop processing.
 
         This method returns `self`, allowing it to be applied at the object
         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
@@ -1454,61 +2425,64 @@ class PyoPVObject(PyoObjectBase):
 
         :Args:
 
-            attr : string
+            attr: string
                 Name of the attribute as a string.
-            value : float
+            value: float
                 New value.
-            port : float, optional
+            port: float, optional
                 Time, in seconds, to reach the new value.
 
         """
+        pyoArgsAssert(self, "Snn", attr, value, port)
         self._target_dict[attr] = value
         init = getattr(self, attr)
-        if self._signal_dict.has_key(attr):
+        if attr in self._signal_dict:
             if isinstance(self._signal_dict[attr], VarPort):
                 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):
         if isinstance(getattr(self, attr), VarPort):
             setattr(self, attr, self._target_dict[attr])
         self._signal_dict[attr].stop()
-        
+
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         """
-        Opens a sliders window to control the parameters of the object. 
-        Only parameters that can be set to a PyoObject are allowed 
+        Opens a sliders window to control the parameters of the object.
+        Only parameters that can be set to a PyoObject are allowed
         to be mapped on a slider.
 
-        If a list of values are given to a parameter, a multisliders 
+        If a list of values are given to a parameter, a multisliders
         will be used to control each stream independently.
 
         :Args:
 
-            map_list : list of SLMap objects, optional
-                Users defined set of parameters scaling. There is default 
+            map_list: list of SLMap objects, optional
+                Users defined set of parameters scaling. There is default
                 scaling for each object that accept `ctrl` method.
-            title : string, optional
-                Title of the window. If none is provided, the name of the 
+            title: string, optional
+                Title of the window. If none is provided, the name of the
                 class is used.
-            wxnoserver : boolean, optional
-                With wxPython graphical toolkit, if True, tells the 
+            wxnoserver: boolean, optional
+                With wxPython graphical toolkit, if True, tells the
                 interpreter that there will be no server window.
-                
-        If `wxnoserver` is set to True, the interpreter will not wait for 
-        the server GUI before showing the controller window. 
+
+        If `wxnoserver` is set to True, the interpreter will not wait for
+        the server GUI before showing the controller window.
 
         """
-        if map_list == None:
+        if map_list is None:
             map_list = self._map_list
         if map_list == []:
-            print("There is 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)
-        
+
 ######################################################################
 ### Internal classes -> Used by pyo
 ######################################################################
@@ -1516,18 +2490,18 @@ class Mix(PyoObject):
     """
     Mix audio streams to arbitrary number of streams.
 
-    Mix the object's audio streams as `input` argument into `voices` 
+    Mix the object's audio streams as `input` argument into `voices`
     streams.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject or list of PyoObjects
+        input: PyoObject or list of PyoObjects
             Input signal(s) to mix the streams.
-        voices : int, optional
-            Number of streams of the Mix object. If more than 1, input 
-            object's streams are alternated and added into Mix object's 
+        voices: int, optional
+            Number of streams of the Mix object. If more than 1, input
+            object's streams are alternated and added into Mix object's
             streams. Defaults to 1.
 
     .. note::
@@ -1544,38 +2518,41 @@ class Mix(PyoObject):
     >>> s.start()
     >>> a = Sine([random.uniform(400,600) for i in range(50)], mul=.02)
     >>> b = Mix(a, voices=2).out()
-    >>> print len(a)
+    >>> print(len(a))
     50
-    >>> print len(b)
+    >>> print(len(b))
     1
 
     """
     def __init__(self, input, voices=1, mul=1, add=0):
+        pyoArgsAssert(self, "oIOO", input, voices, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         mul, add, lmax = convertArgsToLists(mul, add)
-        if type(input) == ListType:
+        if isinstance(input, list):
             input_objs = []
             input_objs = [obj for pyoObj in input for obj in pyoObj.getBaseObjects()]
-        else:    
+        else:
             input_objs = input.getBaseObjects()
         input_len = len(input_objs)
-        if voices < 1: 
+        if voices < 1:
             voices = 1
             num = 1
-        elif voices > input_len and voices > lmax: 
+        elif voices > input_len and voices > lmax:
             num = voices
         elif lmax > input_len:
-            num = lmax    
+            num = lmax
         else:
-            num = input_len   
+            num = input_len
         sub_lists = []
         for i in range(voices):
             sub_lists.append([])
         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):
     """
@@ -1587,8 +2564,8 @@ class Dummy(PyoObject):
 
     :Args:
 
-        objs_list : list of audio Stream objects
-            List of Stream objects return by the PyoObject hidden method 
+        objs_list: list of audio Stream objects
+            List of Stream objects return by the PyoObject hidden method
             getBaseObjects().
 
     .. note::
@@ -1597,16 +2574,16 @@ class Dummy(PyoObject):
         the PyoObject on which the operation is performed. A dummy object
         is created, which is just a copy of the audio Streams of the object,
         and the operation is applied on the Dummy, leaving the original
-        object unchanged. This lets the user performs multiple different 
+        object unchanged. This lets the user performs multiple different
         arithmetic operations on an object without conficts. Here, `b` is
-        a Dummy object with `a` as its input with a `mul` attribute of 0.5. 
+        a Dummy object with `a` as its input with a `mul` attribute of 0.5.
         attribute:
 
         >>> a = Sine()
         >>> b = a * .5
-        >>> print a
+        >>> print(a)
         <pyolib.input.Sine object at 0x11fd610>
-        >>> print b
+        >>> print(b)
         <pyolib._core.Dummy object at 0x11fd710>
 
     >>> s = Server().boot()
@@ -1616,7 +2593,7 @@ class Dummy(PyoObject):
     >>> a = SineLoop(p, feedback=.05, mul=.1).mix(2).out()
     >>> b = SineLoop(p*1.253, feedback=.05, mul=.06).mix(2).out()
     >>> c = SineLoop(p*1.497, feedback=.05, mul=.03).mix(2).out()
-    
+
     """
     def __init__(self, objs_list):
         PyoObject.__init__(self)
@@ -1628,21 +2605,21 @@ class Dummy(PyoObject):
             else:
                 tmp_list.append(x)
         self._base_objs = tmp_list
-        
+
 class InputFader(PyoObject):
     """
     Audio streams crossfader.
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal.
 
     .. note::
 
-        The setInput method, available to object with `input` attribute, 
-        uses an InputFader object internally to perform crossfade between 
-        the old and the new audio input assigned to the object. 
+        The setInput method, available to object with `input` attribute,
+        uses an InputFader object internally to perform crossfade between
+        the old and the new audio input assigned to the object.
 
     >>> s = Server().boot()
     >>> s.start()
@@ -1654,45 +2631,50 @@ class InputFader(PyoObject):
 
     """
     def __init__(self, input):
+        pyoArgsAssert(self, "o", input)
         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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Defaults to 0.05.
 
         """
+        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.""" 
+        """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):
     """
     Convert numeric value to PyoObject signal.
-    
+
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        value : float or PyoObject
+        value: float or PyoObject
             Numerical value to convert.
-    
+
     >>> import random
     >>> s = Server().boot()
     >>> s.start()
@@ -1706,10 +2688,13 @@ class Sig(PyoObject):
 
     """
     def __init__(self, value, mul=1, add=0):
+        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):
         """
@@ -1717,24 +2702,26 @@ class Sig(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 Numerical value to convert.
 
         """
+        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)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
-    
+
     @property
     def value(self):
-        """float or PyoObject. Numerical value to convert.""" 
+        """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):
     """
@@ -1748,39 +2735,47 @@ class VarPort(PyoObject):
 
     :Args:
 
-        value : float
+        value: float
             Numerical value to convert.
-        time : float, optional
+        time: float, optional
             Ramp time, in seconds, to reach the new value. Defaults to 0.025.
-        init : float, optional
+        init: float, optional
             Initial value of the internal memory. Defaults to 0.
-        function : Python callable, optional
-            If provided, it will be called at the end of the line. 
+        function: Python callable, optional
+            If provided, it will be called at the end of the line.
             Defaults to None.
-        arg : any Python object, optional
+        arg: any Python object, optional
             Optional argument sent to the function called at the end of the line.
             Defaults to None.
 
     .. 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()
     >>> def callback(arg):
-    ...     print "end of line"
-    ...     print arg
-    ... 
+    ...     print("end of line")
+    ...     print(arg)
+    ...
     >>> fr = VarPort(value=500, time=2, init=250, function=callback, arg="YEP!")
     >>> 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
-        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), wrap(function,i), wrap(arg,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        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)]
+        self.play()
 
     def setValue(self, x):
         """
@@ -1788,13 +2783,14 @@ class VarPort(PyoObject):
 
         :Args:
 
-            x : float
+            x: float
                 Numerical value to convert.
 
         """
+        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):
         """
@@ -1802,27 +2798,54 @@ class VarPort(PyoObject):
 
         :Args:
 
-            x : float
+            x: float
                 New ramp time.
 
         """
+        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):
+        """
+        Replace the `function` attribute.
+
+        :Args:
+
+            x: Python function
+                new `function` attribute.
+
+        """
+        pyoArgsAssert(self, "c", x)
+        self._function = getWeakMethodRef(x)
+        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.""" 
+        """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.""" 
+        """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)
 
 class Pow(PyoObject):
     """
@@ -1832,9 +2855,9 @@ class Pow(PyoObject):
 
     :Args:
 
-        base : float or PyoObject, optional
+        base: float or PyoObject, optional
             Base composant. Defaults to 10.
-        exponent : float or PyoObject, optional
+        exponent: float or PyoObject, optional
             Exponent composant. Defaults to 1.
 
     >>> s = Server().boot()
@@ -1846,11 +2869,14 @@ class Pow(PyoObject):
 
     """
     def __init__(self, base=10, exponent=1, mul=1, add=0):
+        pyoArgsAssert(self, "OOOO", base, exponent, mul, add)
         PyoObject.__init__(self, mul, add)
         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):
         """
@@ -1858,13 +2884,14 @@ class Pow(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `base` attribute.
 
         """
+        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):
         """
@@ -1872,49 +2899,53 @@ class Pow(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `exponent` attribute.
 
         """
+        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.""" 
+        """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.""" 
+        """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):
     """
     Wraps-around the signal that exceeds the `min` and `max` thresholds.
 
-    This object is useful for table indexing, phase shifting or for 
+    This object is useful for table indexing, phase shifting or for
     clipping and modeling an audio signal.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        min : float or PyoObject, optional
+        min: float or PyoObject, optional
             Minimum possible value. Defaults to 0.
-        max : float or PyoObject, optional
+        max: float or PyoObject, optional
             Maximum possible value. Defaults to 1.
 
     .. 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()
@@ -1930,13 +2961,17 @@ class Wrap(PyoObject):
 
     """
     def __init__(self, input, min=0.0, max=1.0, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOO", input, min, max, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         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):
         """
@@ -1944,12 +2979,13 @@ class Wrap(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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)
 
@@ -1959,13 +2995,14 @@ class Wrap(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `min` attribute.
 
         """
+        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):
         """
@@ -1973,13 +3010,14 @@ class Wrap(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `max` attribute.
 
         """
+        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),
@@ -1989,24 +3027,27 @@ class Wrap(PyoObject):
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """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.""" 
+        """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.""" 
+        """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):
     """
@@ -2020,11 +3061,11 @@ class Compare(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal.
-        comp : float or PyoObject
+        comp: float or PyoObject
             comparison signal.
-        mode : string, optional
+        mode: string, optional
             Comparison operator as a string. Allowed operator are "<", "<=",
             ">", ">=", "==", "!=". Default to "<".
 
@@ -2038,14 +3079,21 @@ class Compare(PyoObject):
 
     """
     def __init__(self, input, comp, mode="<", mul=1, add=0):
+        pyoArgsAssert(self, "oOsOO", input, comp, mode, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._comp = comp
         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)
@@ -2053,65 +3101,72 @@ class Compare(PyoObject):
     def setInput(self, x, fadetime=0.05):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     def setComp(self, x):
         """
         Replace the `comp` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: float or PyoObject
                 New comparison signal.
 
         """
+        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):
         """
-        Replace the `mode` attribute. 
-        
+        Replace the `mode` attribute.
+
         Allowed operator are "<", "<=", ">", ">=", "==", "!=".
-        
+
         :Args:
 
-            x : string
+            x: string
                 New `mode` attribute.
 
         """
+        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.""" 
+        """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.""" 
+        """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.""" 
+        """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 9845c77..1ed78f7 100644
--- a/pyolib/_maps.py
+++ b/pyolib/_maps.py
@@ -1,29 +1,29 @@
-# -*- coding: utf-8 -*-
+# encoding: utf-8
 """
-Copyright 2010 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+You should have received a copy of the GNU Lesser General Public
+License along with pyo.  If not, see <http://www.gnu.org/licenses/>.
 """
 from math import pow, log10
 
 ######################################################################
 ### Map -> rescale values from sliders
 ######################################################################
-class Map:
+class Map(object):
     """
     Converts value between 0 and 1 on various scales.
 
@@ -31,17 +31,17 @@ class Map:
 
     :Args:
 
-        min : int or float
+        min: int or float
             Lowest value of the range.
-        max : int or float
+        max: int or float
             Highest value of the range.
-        scale : string {'lin', 'log'}
+        scale: string {'lin', 'log'}
             Method used to scale the input value on the specified range.
 
     >>> m = Map(20., 20000., 'log')
-    >>> print m.get(.5)
+    >>> print(m.get(.5))
     632.455532034
-    >>> print m.set(12000)
+    >>> print(m.set(12000))
     0.926050416795
 
     """
@@ -51,47 +51,49 @@ class Map:
     def get(self, x):
         """
         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))
+            return pow(10, x * log10(self._max / self._min) + log10(self._min))
         else:
             return (self._max - self._min) * x + self._min
 
     def set(self, x):
         """
-        Takes `x` in the real range and returns value unscaled 
+        Takes `x` in the real range and returns value unscaled
         (between 0 and 1).
-        
+
         """
-        
+
         if self._scale == 'log':
-            return log10(x/self._min) / log10(self._max/self._min)
+            return log10(x / self._min) / log10(self._max / self._min)
         else:
             return (x - self._min) / (self._max - self._min)
 
     def setMin(self, x):
         """
         Replace the `min` attribute.
-        
+
         :Args:
 
-            x : float
+            x: float
                 New `min` attribute.
 
         """
         self._min = x
-        
+
     def setMax(self, x):
         """
         Replace the `max` attribute.
-        
+
         :Args:
 
-            x : float
+            x: float
                 New `max` attribute.
 
         """
@@ -100,92 +102,108 @@ class Map:
     def setScale(self, x):
         """
         Replace the `scale` attribute.
-        
+
         :Args:
 
-            x : string
+            x: string
                 New `scale` attribute.
 
         """
         self._scale = x
 
     @property
-    def min(self): 
+    def min(self):
         """int or float. Lowest value of the range."""
         return self._min
     @min.setter
-    def min(self, x): 
-        self.setMin(x)    
+    def min(self, x):
+        self.setMin(x)
     @property
-    def max(self): 
+    def max(self):
         """int or float. Highest value of the range."""
         return self._max
     @max.setter
-    def max(self, x): 
+    def max(self, x):
         self.setMax(x)
     @property
-    def scale(self): 
+    def scale(self):
         """string. Method used to scale the input value."""
         return self._scale
     @scale.setter
-    def scale(self, x): 
+    def scale(self, x):
         self.setScale(x)
 
 class SLMap(Map):
     """
     Base Map class used to manage control sliders.
 
-    Derived from Map class, a few parameters are added for sliders 
+    Derived from Map class, a few parameters are added for sliders
     initialization.
 
     :Parent: :py:class:`Map`
 
     :Args:
 
-        min : int or float
+        min: int or float
             Smallest value of the range.
-        max : int or float
+        max: int or float
             Highest value of the range.
-        scale : string {'lin', 'log'}
-            Method used to scale the input value on the specified range.    
-        name : string
+        scale: string {'lin', 'log'}
+            Method used to scale the input value on the specified range.
+        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.
-        res : string {'int', 'float'}, optional
+        init: int or float
+            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
-            Ramp time, in seconds, used to smooth the signal sent from slider 
+        ramp: float, optional
+            Ramp time, in seconds, used to smooth the signal sent from slider
             to object's attribute. Defaults to 0.025.
+        dataOnly: boolean, optional
+            Set this argument to True if the parameter does not accept audio
+            signal as control but discreet values. If True, label will be
+            marked with a star symbol (*). Defaults to False.
 
     >>> 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):
+    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 = name, init, res, ramp
+        self._name = name
+        self._init = init
+        self._res = res
+        self._ramp = ramp
+        self._dataOnly = dataOnly
 
     @property
-    def name(self): 
+    def name(self):
         """string. Name of the parameter to control."""
         return self._name
     @property
-    def init(self): 
+    def init(self):
         """float. Initial value of the slider."""
         return self._init
     @property
-    def res(self): 
+    def res(self):
         """string. Slider resolution {int or float}."""
         return self._res
     @property
-    def ramp(self): 
+    def ramp(self):
         """float. Ramp time in seconds."""
         return self._ramp
+    @property
+    def dataOnly(self):
+        """boolean. True if argument does not accept audio stream."""
+        return self._dataOnly
 
 class SLMapFreq(SLMap):
     """
@@ -195,13 +213,13 @@ class SLMapFreq(SLMap):
 
     :Args:
 
-        init : int or float, optional
+        init: int or float, optional
             Initial value. Specified in the real range, not between 0 and 1.
             Defaults to 1000.
 
     .. note::
 
-        SLMapFreq values are: 
+        SLMapFreq values are:
 
         - min = 20.0
         - max = 20000.0
@@ -222,7 +240,7 @@ class SLMapMul(SLMap):
 
     :Args:
 
-        init : int or float, optional
+        init: int or float, optional
             Initial value. Specified in the real range, not between 0 and 1.
             Defaults to 1.
 
@@ -249,13 +267,13 @@ class SLMapPhase(SLMap):
 
     :Args:
 
-        init : int or float, optional
+        init: int or float, optional
             Initial value. Specified in the real range, not between 0 and 1.
             Defaults to 0.
 
     .. note::
 
-        SLMapPhase values are: 
+        SLMapPhase values are:
 
         - min = 0.0
         - max = 1.0
@@ -276,13 +294,13 @@ class SLMapPan(SLMap):
 
     :Args:
 
-        init : int or float, optional
+        init: int or float, optional
             Initial value. Specified in the real range, not between 0 and 1.
             Defaults to 0.
 
     .. note::
 
-        SLMapPhase values are: 
+        SLMapPhase values are:
 
         - min = 0.0
         - max = 1.0
@@ -303,13 +321,13 @@ class SLMapQ(SLMap):
 
     :Args:
 
-        init : int or float, optional
+        init: int or float, optional
             Initial value. Specified in the real range, not between 0 and 1.
             Defaults to 1.
 
     .. note::
 
-        SLMapQ values are: 
+        SLMapQ values are:
 
         - min = 0.1
         - max = 100.0
@@ -330,13 +348,13 @@ class SLMapDur(SLMap):
 
     :Args:
 
-        init : int or float, optional
+        init: int or float, optional
             Initial value. Specified in the real range, not between 0 and 1.
             Defaults to 1.
 
     .. note::
 
-        SLMapDur values are: 
+        SLMapDur values are:
 
         - min = 0.
         - max = 60.0
diff --git a/pyolib/_tkwidgets.py b/pyolib/_tkwidgets.py
index 8057194..4216428 100644
--- a/pyolib/_tkwidgets.py
+++ b/pyolib/_tkwidgets.py
@@ -1,32 +1,39 @@
+# encoding: utf-8
 """
-Copyright 2010 Olivier Belanger
+This module defines GUI widgets built with tkinter.
 
-This file is part of pyo.
+"""
+from __future__ import division
+from __future__ import print_function
+from __future__ import absolute_import
+"""
+Copyright 2009-2015 Olivier Belanger
+
+This file is part of pyo, a python module to help digital signal
+processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+You should have received a copy of the GNU Lesser General Public
+License along with pyo.  If not, see <http://www.gnu.org/licenses/>.
 """
-from types import ListType, FloatType, IntType
-import math, sys, os
-from Tkinter import *
-
-try:
-    from PIL import Image, ImageDraw, ImageTk
-except:
-    pass
-    
+import math
+import sys
+if sys.version_info[0] < 3:
+    import Tkinter as tk
+else:
+    import tkinter as tk
+
 # constants for platform displays with Tk
-if sys.platform == 'linux2':
+if sys.platform.startswith('linux'):
     Y_OFFSET = 0
     VM_OFFSET = 2
 elif sys.platform == 'win32':
@@ -39,59 +46,79 @@ else:
 ######################################################################
 ### Multisliders
 ######################################################################
-class MultiSlider(Frame):
-    def __init__(self, master, init, key, command): 
-        Frame.__init__(self, master, bd=0, relief=FLAT)
+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):
+        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
             x = self._values[i] * w
             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
+            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
+        slide = (event.y - Y_OFFSET) // self._height
         val = event.x / float(w)
         self._values[slide] = val
         y = self._height * slide + Y_OFFSET
         self.canvas.coords(self._lines[slide], 0, y, event.x, y+self._height-1)
         self._command(self._key, self._values)
-       
+
 ######################################################################
 ### 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
@@ -99,10 +126,22 @@ 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)
-        from controls import SigTo
+        tk.Frame.__init__(self, master, bd=1, relief=tk.GROOVE)
+        from .controls import SigTo
         self.bind('<Destroy>', self._destroy)
         self._obj = obj
         self._map_list = map_list
@@ -115,34 +154,41 @@ class PyoObjectControl(Frame):
         for i, m in enumerate(self._map_list):
             key, init = m.name, m.init
             # filters PyoObjects
-            if type(init) not in [ListType, FloatType, IntType]:
+            if type(init) not in [list, float, int]:
                 self._excluded.append(key)
-            else:    
+            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) != ListType:
-                    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)) 
-                    disp_height = len(init)   
-                self._sliders[-1].grid(row=i, column=1, sticky=E+W)
+                    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=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) != ListType:
+                if not isinstance(init, list):
                     self._displays[key].set("%.4f" % init)
                 else:
                     self._displays[key].set("\n".join(["%.4f" % i for i in init]))
-                # set obj attribute to PyoObject SigTo     
+                # set obj attribute to PyoObject SigTo
                 self._sigs[key] = SigTo(init, .025, init)
                 refStream = self._obj.getBaseObjects()[0]._getStream()
                 server = self._obj.getBaseObjects()[0].getServer()
@@ -150,12 +196,12 @@ class PyoObjectControl(Frame):
                     curStream = self._sigs[key].getBaseObjects()[k]._getStream()
                     server.changeStreamPosition(refStream, curStream)
                 setattr(self._obj, key, self._sigs[key])
-        # padding        
+        # padding
         top = self.winfo_toplevel()
         top.rowconfigure(0, weight=1)
-        top.columnconfigure(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:
@@ -165,44 +211,32 @@ class PyoObjectControl(Frame):
                 del self._sigs[key]
 
     def setval(self, key, x):
-        if type(x) != ListType:
+        "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:    
-            value = [self._maps[key].get(float(y)) for y in x] 
+        else:
+            value = [self._maps[key].get(float(y)) for y in x]
             self._displays[key].set("\n".join(["%.4f" % i for i in value]))
-        
+
         self._values[key] = value
         setattr(self._sigs[key], "value", value)
 
 ######################################################################
 ### View window for PyoTableObject
 ######################################################################
-class ViewTable_withPIL(Frame):
-    def __init__(self, master=None, samples=None):
-        Frame.__init__(self, master, bd=1, relief=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")
-        print Image
-        im = Image.new("L", (self.width, self.height), 255)
-        draw = ImageDraw.Draw(im)
-        draw.line(samples, fill=0, width=1)
-        self.img = ImageTk.PhotoImage(im)
-        self.canvas.create_image(self.width/2,self.height/2,image=self.img)
-        self.canvas.create_line(0, self.half_height+2, self.width, self.half_height+2, fill='grey', dash=(4,2))    
-        self.canvas.grid()
-        self.grid(ipadx=10, ipady=10)
-    
-class ViewTable_withoutPIL(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.half_height = self.height // 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)
@@ -210,30 +244,21 @@ class ViewTable_withoutPIL(Frame):
 ######################################################################
 ## View window for PyoMatrixObject
 #####################################################################
-class ViewMatrix_withPIL(Frame):
-    def __init__(self, master=None, samples=None, size=None):
-        Frame.__init__(self, master, bd=1, relief=GROOVE)
-        self.canvas = Canvas(self, width=size[0], height=size[1], relief=SUNKEN, bd=1, bg="#EFEFEF")
-        im = Image.new("L", size, None)
-        im.putdata(samples)
-        self.img = ImageTk.PhotoImage(im)
-        self.canvas.create_image(size[0]/2+Y_OFFSET,size[1]/2+Y_OFFSET,image=self.img)
-        self.canvas.grid()
-        self.grid(ipadx=0, ipady=0)
-
-class ViewMatrix_withoutPIL(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
-            x1 = x+Y_OFFSET
-            y1 = y+Y_OFFSET
-            x2 = x+Y_OFFSET+1
-            y2 = y+Y_OFFSET+1
+            y = i // self.width
+            x1 = x + Y_OFFSET
+            y1 = y + Y_OFFSET
+            x2 = x + Y_OFFSET + 1
+            y2 = y + Y_OFFSET + 1
             amp = int(samples[i])
             amp = hex(amp).replace('0x', '')
             if len(amp) == 1:
@@ -246,10 +271,12 @@ class ViewMatrix_withoutPIL(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
@@ -273,71 +300,86 @@ class ServerGUI(Frame):
         self.createWidgets()
         if started == 1:
             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 != None:
-            self.interp_label = Label(self, text='Interpreter')
+        if self.locals is not None:
+            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
@@ -345,40 +387,46 @@ 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)
-        else:    
+        else:
             self.text.insert("1.0", self._history[self._histo_count])
         return "break"
-    
+
     def getText(self, event):
-        source = self.text.get("1.0", END)
-        self.text.delete("1.0", END)
-        exec source in self.locals
+        "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')
@@ -388,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.
@@ -403,7 +453,17 @@ class ServerGUI(Frame):
                 self.vumeter.coords(self.green[i], 0, y, self.B1, y)
                 self.vumeter.coords(self.yellow[i], self.B1, y, amp, y)
                 self.vumeter.coords(self.red[i], self.B2, y, self.B2, y)
-            else:    
+            else:
                 self.vumeter.coords(self.green[i], 0, y, self.B1, y)
                 self.vumeter.coords(self.yellow[i], self.B1, y, self.B2, y)
                 self.vumeter.coords(self.red[i], self.B2, y, amp, y)
+
+    def setStartButtonState(self, state):
+        if state:
+            self._started = True
+            self.startStringVar.set('Stop')
+            self.quitButton.configure(state=tk.DISABLED)
+        else:
+            self._started = False
+            self.startStringVar.set('Start')
+            self.quitButton.configure(state=tk.NORMAL)
diff --git a/pyolib/_widgets.py b/pyolib/_widgets.py
index 518299c..6f2f348 100644
--- a/pyolib/_widgets.py
+++ b/pyolib/_widgets.py
@@ -1,55 +1,72 @@
-# -*- coding: utf-8 -*-
+# encoding: utf-8
 """
-Copyright 2010 Olivier Belanger
+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
+"""
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public Licensehack for OSX display
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+You should have received a copy of the GNU Lesser General Public
+License along with pyo.  If not, see <http://www.gnu.org/licenses/>.
 """
-from types import ListType, FloatType, IntType
-import math, sys, os, random
-
-try:
-    from PIL import Image, ImageDraw, ImageTk
-    WITH_PIL = True
-except:
-    WITH_PIL = False
-
-try:
-    import wxversion
-    if (wxversion.checkInstalled("2.8")):
-        wxversion.ensureMinimal("2.8")
-    import wx
-    from _wxwidgets import *
-    PYO_USE_WX = True
-except:
+import sys
+import os
+import random
+
+use_wx = 1
+if "PYO_GUI_WX" in os.environ:
+    use_wx = int(os.environ["PYO_GUI_WX"])
+
+if use_wx:
+    try:
+        import wx
+        from ._wxwidgets import *
+        PYO_USE_WX = True
+    except:
+        PYO_USE_WX = False
+        print("""
+WxPython is not found for the current python version.
+Pyo will use a minimal GUI toolkit written with Tkinter (if available).
+This toolkit has limited functionnalities and is no more
+maintained or updated. If you want to use all of pyo's
+GUI features, you should install WxPython, available here:
+http://www.wxpython.org/
+""")
+else:
     PYO_USE_WX = False
 
+PYO_USE_TK = False
 if not PYO_USE_WX:
     try:
-        from Tkinter import *
-        from _tkwidgets import *
-    except:
-        if sys.platform == "linux2":
-            response = raw_input("""python-tk package is missing! It is needed to use pyo graphical interfaces.
-Do you want to install it? (yes/no): """)
-            if response == 'yes':
-                os.system('sudo apt-get install python-tk')
+        if sys.version_info[0] < 3:
+            import Tkinter as tk
         else:
-            print "Tkinter is missing! It is needed to use pyo graphical interfaces. Please install it!"
-        sys.exit()
+            import tkinter as tk
+        from ._tkwidgets import *
+        PYO_USE_TK = True
+    except:
+        PYO_USE_TK = False
+        print("""
+Neither WxPython nor Tkinter are found for the current python version.
+Pyo's GUI features are disabled. For a complete GUI toolkit, you should
+consider installing WxPython, available here: http://www.wxpython.org/
+""")
 
 X, Y, CURRENT_X, MAX_X, NEXT_Y = 800, 700, 30, 30, 30
 WINDOWS = []
@@ -60,251 +77,338 @@ TABLEWINDOWS = []
 SNDTABLEWINDOWS = []
 MATRIXWINDOWS = []
 SPECTRUMWINDOWS = []
+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:
             return None
-    else:        
-        if wx.GetApp() == None: 
-            win = wx.App(False) 
+    else:
+        if wx.GetApp() is None:
+            win = wx.App()
             return win
         else:
             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): 
+    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()
-    if sys.platform == "linux2":
+    if sys.platform.startswith("linux"):
         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 != None:
+    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] == 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] == 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])
-        if win[2] == None: title = win[0].__class__.__name__
+        win[0]._setGraphFrame(f)
+        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]
-        if WITH_PIL: f = ViewTable_withPIL(None, win[0], win[1], object)
-        else: f = ViewTable_withoutPIL(None, win[0], win[1], object)
-        if object != None:
+        f = ViewTable(None, win[0], win[1], object)
+        if object is not None:
             object._setViewFrame(f)
         wxDisplayWindow(f, win[2])
 
 def wxCreateDelayedSndTableWindows():
-    global CURRENT_X, MAX_X, NEXT_Y
+    "Postponed a wxpython window display."
     for win in SNDTABLEWINDOWS:
-        if WITH_PIL: f = SndViewTable_withPIL(None, win[0], win[1], win[3])
-        else: f = SndViewTable_withoutPIL(None, win[0], win[1], win[3])
+        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]
-        if WITH_PIL: f = ViewMatrix_withPIL(None, win[0], win[1], object)
-        else: f = ViewMatrix_withoutPIL(None, win[0], win[1], object)
-        if object != None:
+        f = ViewMatrix(None, win[0], win[1], object)
+        if object is not None:
             object._setViewFrame(f)
         wxDisplayWindow(f, win[2])
 
 def wxCreateDelayedSpectrumWindows():
+    "Postponed a wxpython window display."
     for win in SPECTRUMWINDOWS:
         f = SpectrumDisplay(None, win[0])
-        if win[1] == None: title = win[0].__class__.__name__
-        else: title = win[1]
-        if win[0] != None:
+        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[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]
+        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 == None: title = obj.__class__.__name__
+        if title is None:
+            title = obj.__class__.__name__
         win.title(title)
     else:
-        if wxnoserver or wx.GetApp() != None:
+        if wxnoserver or wx.GetApp() is not None:
             root = createRootWindow()
             f = PyoObjectControl(None, obj, map_list)
-            if title == 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."
+        print("WxPython must be installed to use the 'graph()' method.")
     else:
-        if wxnoserver or wx.GetApp() != None:
+        if wxnoserver or wx.GetApp() is not None:
             root = createRootWindow()
             f = TableGrapher(None, obj, mode, xlen, yrange)
-            if title == 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])   
+            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."
+        print("WxPython must be installed to use the 'graph()' method.")
     else:
-        if wxnoserver or wx.GetApp() != None:
+        if wxnoserver or wx.GetApp() is not None:
             root = createRootWindow()
             f = DataTableGrapher(None, obj, yrange)
-            if title == 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):
+            DATAGRAPHWINDOWS.append([obj, yrange, title])
+
+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()
-        if WITH_PIL: f = ViewTable_withPIL(win, samples)
-        else: f = ViewTable_withoutPIL(win, samples)
+        f = ViewTable(win, samples)
         win.resizable(False, False)
         win.title(title)
     else:
-        if wxnoserver or wx.GetApp() != None:
+        if wxnoserver or wx.GetApp() is not None:
             root = createRootWindow()
-            if WITH_PIL: f = ViewTable_withPIL(None, samples, tableclass)
-            else: f = ViewTable_withoutPIL(None, samples, tableclass)
-            wxShowWindow(f, title, root)
-            if object != None:
+            f = ViewTable(None, samples, tableclass, object)
+            if object is not None:
                 object._setViewFrame(f)
+            wxShowWindow(f, title, root)
         else:
-            TABLEWINDOWS.append([samples, tableclass, title, object])    
+            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()
-        if WITH_PIL: f = ViewTable_withPIL(win, obj._base_objs[0].getViewTable())
-        else: f = ViewTable_withoutPIL(win, obj._base_objs[0].getViewTable())
+        f = ViewTable(win, obj._base_objs[0].getViewTable())
         win.resizable(False, False)
         win.title(title)
     else:
-        if wxnoserver or wx.GetApp() != None:
+        if wxnoserver or wx.GetApp() is not None:
             root = createRootWindow()
-            if WITH_PIL: f = SndViewTable_withPIL(None, obj, tableclass, mouse_callback)
-            else: f = SndViewTable_withoutPIL(None, obj, tableclass, mouse_callback)
-            if title == None: title = obj.__class__.__name__
-            wxShowWindow(f, title, root)
+            f = SndViewTable(None, obj, tableclass, mouse_callback)
+            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):
-    if not WITH_PIL: print """The Python Imaging Library is not installed. 
-It helps a lot to speed up matrix drawing!"""
+
+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()    
+        createRootWindow()
         win = tkCreateToplevelWindow()
-        if WITH_PIL: f = ViewMatrix_withPIL(win, samples, size)
-        else: f = ViewMatrix_withoutPIL(win, samples, size)
+        f = ViewMatrix(win, samples, size)
         win.resizable(False, False)
         win.title(title)
     else:
-        if wxnoserver or wx.GetApp() != None:
+        if wxnoserver or wx.GetApp() is not None:
             root = createRootWindow()
-            if WITH_PIL: f = ViewMatrix_withPIL(None, samples, size)
-            else: f = ViewMatrix_withoutPIL(None, samples, size)
-            wxShowWindow(f, title, root)
-            if object != None:
+            f = ViewMatrix(None, samples, size, object)
+            if object is not None:
                 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."
+        print("WxPython must be installed to use the Spectrum display.")
     else:
-        if wxnoserver or wx.GetApp() != None:
+        if wxnoserver or wx.GetApp() is not None:
             root = createRootWindow()
             f = SpectrumDisplay(None, object)
-            if title == 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)
-            if object != None:
+        else:
+            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 object is not None:
                 object._setViewFrame(f)
+            wxShowWindow(f, title, root)
         else:
-            SPECTRUMWINDOWS.append([object, title])   
-        
-def createServerGUI(nchnls, start, stop, recstart, recstop, setAmp, started, locals, shutdown, meter, timer, amp):
+            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__
+            wxShowWindow(f, title, root)
+        else:
+            EXPREDITORWINDOWS.append([object, title])
+
+def createServerGUI(nchnls, start, stop, recstart, recstop, setAmp, started,
+                    locals, shutdown, meter, timer, amp, exit, title):
+    "Creates the server's GUI."
     global X, Y, MAX_X, NEXT_Y
+    if title is None:
+        title = "Pyo Server"
     if not PYO_USE_WX:
         createRootWindow()
         win = tkCreateToplevelWindow()
-        f = ServerGUI(win, nchnls, start, stop, recstart, recstop, setAmp, started, locals, shutdown, meter, timer, amp)
-        f.master.title("pyo server")
+        f = ServerGUI(win, nchnls, start, stop, recstart, recstop, setAmp,
+                      started, locals, shutdown, meter, timer, amp)
+        f.master.title(title)
         f.focus_set()
     else:
         win = createRootWindow()
-        f = ServerGUI(None, nchnls, start, stop, recstart, recstop, setAmp, started, locals, shutdown, meter, timer, amp) 
-        f.SetTitle("pyo server")
+        f = ServerGUI(None, nchnls, start, stop, recstart, recstop, setAmp,
+                      started, locals, shutdown, meter, timer, amp, exit)
+        f.SetTitle(title)
         f.SetPosition((30, 30))
         f.Show()
-        X,Y = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_X)-50, wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y)-50
-        if sys.platform == "linux2":
+        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:
             MAX_X, NEXT_Y = f.GetSize()[0]+30, f.GetSize()[1]+30
@@ -315,6 +419,7 @@ def createServerGUI(nchnls, start, stop, recstart, recstop, setAmp, started, loc
         wx.CallAfter(wxCreateDelayedMatrixWindows)
         wx.CallAfter(wxCreateDelayedCtrlWindows)
         wx.CallAfter(wxCreateDelayedSpectrumWindows)
+        wx.CallAfter(wxCreateDelayedScopeWindows)
+        wx.CallAfter(wxCreateDelayedExprEditorWindows)
         wx.CallAfter(f.Raise)
     return f, win
-        
\ No newline at end of file
diff --git a/pyolib/_wxwidgets.py b/pyolib/_wxwidgets.py
index 4e85080..01dce27 100644
--- a/pyolib/_wxwidgets.py
+++ b/pyolib/_wxwidgets.py
@@ -1,147 +1,68 @@
+from __future__ import division
+from __future__ import print_function
+from __future__ import absolute_import
 """
-Copyright 2010 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
-This file is part of pyo.
+This file is part of pyo, a python module to help digital signal
+processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+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 wx, os, sys, math, time, random, unicodedata
+import wx.stc as stc
 
-import wx, os, sys, math, time, random
-from types import ListType, FloatType, IntType
-from wx.lib.embeddedimage import PyEmbeddedImage
+if "phoenix" in wx.version():
+    wx.GraphicsContext_Create = wx.GraphicsContext.Create
+    wx.EmptyBitmap = wx.Bitmap
+    wx.EmptyImage = wx.Image
+    wx.BitmapFromImage = wx.Bitmap
 
-try:
-    from PIL import Image, ImageDraw, ImageTk
-except:
-    pass
-    
 BACKGROUND_COLOUR = "#EBEBEB"
 
-vu_metre = PyEmbeddedImage(
-    "iVBORw0KGgoAAAANSUhEUgAAAMgAAAAFCAIAAACPTDSjAAAAAXNSR0IArs4c6QAAACF0RVh0"
-    "U29mdHdhcmUAR3JhcGhpY0NvbnZlcnRlciAoSW50ZWwpd4f6GQAAAMJJREFUeJxiYBgFo4BG"
-    "wHWbO1bEKc6JS4pXiddxtTNWKTFLMYspVlilpFyk9WsNsUopR6toF+lglVJP0wDKYpUCmiYX"
-    "II9VyqTTFOgSrFI28+0E9YSwSgE9hcfXLNwsZEgBDcQVVkBnAB2DKxi7qg13LHHERIEeMvWF"
-    "ulilYoIUM2JUsUoVp2vGKyjsdbDHRH0G+u4SElilZpkYW4uIYJXaaGNtwMDwHxsaTVijCWs0"
-    "YY0mrNGENZqwRhMWAAAA//8DAHGDnlocOW36AAAAAElFTkSuQmCC")
-
-vu_metre_dark = PyEmbeddedImage(
-    "iVBORw0KGgoAAAANSUhEUgAAAMgAAAAFCAYAAAAALqP0AAAAAXNSR0IArs4c6QAAAAlwSFlz"
-    "AAALEgAACxIB0t1+/AAADst0RVh0Q29tbWVudABwclZXIGNodW5rbGVuIDMwMiBpZ25vcmVk"
-    "Og1BU0NJSTogeJzt0U1WwjAuwPHpLohUKS5tibG3yM4ude11ei4u4OtdvIE4ky76cOVz+/9l"
-    "LuYjaS68f759yKu8nMys6zTPc8rm9Exq1C6nLicuS7UwcS5ljHGMMopEyyQu0S5FJGUuLi4u"
-    "Li5Xdb2pd/cuu1pj899y+6ixrTV+lufcktvvLl7p1ut+8C7r9efnUut2Kb/PhOshu5vK9I5l"
-    "LtrQtiG0wdmmq3IuT7ffLp1vOt9rLnvfaVjprfSNdo69jvy+P5fPjZbDfunZuSYNSEVYOiA3"
-    "ODlDRUREMTRENTZDMjMwMTBDMEYxRTkwNzg4NTQyOTBENkQ4OUIxQjdDOENFMDM3NUVENzU3"
-    "QTE5MEZFMEVCNURCQzgxMzg5MzAyRkE3MEU1NzNGQkZGNjUxQUU2MjM2OTE3QkM3RkJFN0RD"
-    "OEFCQkM5Q0NDQUNFQjM0Q0Y3M0NBRTZGNDRDNkFENDE4QTcxODI3MTE0QkI1MzA3MTFDNjU4"
-    "QzcxOEMzMjhBNDRDQjI0MUFEMTE1NDUyNDY1MDAwMDAwMDAwMA1ta0JGIGNodW5rbGVuIDcy"
-    "IGlnbm9yZWQ6DUFTQ0lJOiD63sr+Li4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u"
-    "Li4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4NSEVYOiBGQURFQ0FGRTAwMDAw"
-    "MDA0MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw"
-    "MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw"
-    "MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDANbWtUUyBjaHVua2xlbiA4ODg2IGlnbm9yZWQ6DUFT"
-    "Q0lJOiB4nO1dWXPbSJLG9ozbLd/unph92C5FbGzsU2twLnwuRVHSWC6HpHy9OHjB1rSPLllW"
-    "t5fB/76ZWVUgUCiAOChSni6rW0WiUC6+zPwqqyouOnnWup51ensuM2ve+8cpJKHfLobj+cvj"
-    "vXBmzl+x5MVRO5zZtjk/PC6EM2/e2++Hs4Y97/XPLyC7dS4uhPRv3j0+vp61uvBrb3fweWZs"
-    "LiNjbLwxusbU+C6fLoz386PTLsi5LjkuIccyfobcLuN3uOP9vNc+LmGVuw1IRVg6IDc4OUNF"
-    "RDVENTk3M0RCNDg5MkM2RjY4Q0RCMkRERkVFOUU5ODdERDgxNzQ1NkM2Q0VDNTM2QjcwMTM3"
-    "QzE0NDU1MUQyNTgwNzg3QTQ3Q0JEMzg3OEMxRDZCNDhGMUU1OTU2Qjc5N0MxRkZCRTk5NTk1"
-    "NTIwNTAyODgwMzgyODUyOUUyRUFCNUI0NUEyNTAwN0JFQ0NGQzJBQUIyQTBCM0E3OUQ2QkE5"
-    "RTc1N0E3QjE3MzM2QkRFRkJDNzI5MjRBMURGMDg4NkUzDW1rQlMgY2h1bmtsZW4gMTkwIGln"
-    "bm9yZWQ6DUFTQ0lJOiB4nF1Oyy6CMC7szd/wLi6DwFHKq2GrLmoub2hswlWTJmaz/27Lw4Nz"
-    "mcnMzmZknS4sLj6iTy5wjS71M11FpjEu91QupdGPLmryVqPj9jLag7S0Lb2AoC6DcOgupnV5"
-    "t/GlLkdwlG9kLi5sYC72ZC+2ZT7Jdi452C7PXZPXzshBLi6y/C7dqZg2zfS38NzZ2Z5HlS7D"
-    "g1R7LjH2SC77UYlsxEgnOopp0YOOnqvexY9w1WEuJ0SZOi6kLl+6Ll+mDUhFWDogNzg5QzVE"
-    "NEVDQjBFODIzMDEwRUNDRERGRjAxMzAwODNDMDUxQ0FBQjYxQUIwNjZBMDQ2RjY4NkNDMjU1"
-    "OTMyNjY2QjNGRjZFQ0JDMzgzNzM5OUM5Q0NDRTY2NjQ5RDFBMkMxQTNFQTI0RjFENzA4RDFF"
-    "RjUzMzVENDVBNjMxMDhGNzU0MDlBNUQxOEYwMjZBRjI1NkEzRTNGNjMyREE4M0I0QjQyREJE"
-    "ODBBMDA3ODM3MEU4MERBNjc1NzlCN0YxQTUwMTQ3NzANbWtCVCBjaHVua2xlbiAxMTQ1IGln"
-    "bm9yZWQ6DUFTQ0lJOiD6zsr+Ln84xS4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u"
-    "Li4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4ueJztmolt6zAuLl1ILkkhKSSN"
-    "pJAukkZSiD82+GM8bEjZsWT4mi4udJDisctDIrXfK6WUUkoppZRSSv3X9/f3/uvra0qF34Oy"
-    "LpdM+y7pX1NVn91uN+Xz83P/+vr6c37LdacuVdYtVb5/eXk52GPr9K+t9P/7+/svSnWseg1I"
-    "RVg6IEZBQ0VDQUZFMDA3RjM4QzUwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw"
-    "MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw"
-    "MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwNzg5Q0VE"
-    "OUE4OTZERUIzMDEwMDU1RDQ4MUE0OTIxMjkyNDhEQTQ5MDE0OTI0NjUyDW1rQlQgY2h1bmts"
-    "ZW4gMzM5IGlnbm9yZWQ6DUFTQ0lJOiD6zsr+Ln9ViS4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u"
-    "Li4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4ueJzt1uFpg2Au"
-    "hlEucS4ucS4ucS4ucS4usbyBLremIf+KLueBQ5tP++tNbM5TkiRJkiRJkiRJkiRJkiRJkiRJ"
-    "LtFxLue+70/nOcu1d/e/uk/3b13Xcy7Hc5qmx8/sLv0s99S9dS7LsjxexzAuf76HdO+yY5V9"
-    "s2F2rc37PQ1IRVg6IEZBQ0VDQUZFMDA3RjU1ODkwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw"
-    "MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw"
-    "MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw"
-    "MDAwNzg5Q0VERDZFMTY5ODM2MDE0ODY1MTA3NzExMTA3NzExMDE3NzExMDA3NzExMTA3DW1r"
-    "QlQgY2h1bmtsZW4gMzc5OSBpZ25vcmVkOg1BU0NJSTog+s7K/i5/n3guLi4uLi4uLi4uLi4u"
-    "Li4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u"
-    "Lnic7Z2NkS4pLoUuiC5xIC7EiTguLuJELshe6eo+17tnSUDPz/5Yr2pqZ7tpLi4u0IOel5fB"
-    "YDAuLi6DwWAwLi4ug8HgP/z69evl58+ff3ziOveq5+JzpawuZfj3wf9R6fmK/jN8//795dOn"
-    "T3984jr3Mnz58uXfzy6+ffsNSEVYOiBGQUNFQ0FGRTAwN0Y5Rjc4MDAwMDAwMDAwMDAwMDAw"
-    "MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw"
-    "MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw"
-    "MDAwMDAwMDAwMDAwMDc4OUNFRDlEOEQ5MTFDMjkwQzg1MUQ4ODEzNzEyMDBFQzQ4OTM4MTAw"
-    "N0UyNDQxQw1ta0JUIGNodW5rbGVuIDI3NDEgaWdub3JlZDoNQVNDSUk6IPrOyv4uf69+Li4u"
-    "Li4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u"
-    "Li4uLi4uLi4uLi54nO2djZHbOC5GU0guSSEpJI2kkC6SRlJIbpCbd/PuLkjJWa8u23gzntXq"
-    "h6QuLqIukPr5cy6GYS6GYS6GYS6GYXhJvn///tvvx48u/y67J1WOe5fh2fnw4cNvv69fv/6q"
-    "99q+Z/1XOaouw/uBvM/i9vCW/rm7to7Vbyd/DUhFWDogRkFDRUNBRkUwMDdGQUY3RTAwMDAw"
-    "MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw"
-    "MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw"
-    "MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDA3ODlDRUQ5RDhEOTFEQjM4MEM0NjUzNDgxQTQ5MjEy"
-    "OTI0OERBNDkwMTQ5MjQ2NTINbWtCVCBjaHVua2xlbiAxMDc3NSBpZ25vcmVkOg1BU0NJSTog"
-    "+s7K/i5/1PAuLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4uLi4u"
-    "Li4uLi4uLi4uLi4uLi4uLi4uLi4uLnic7X0ruOwo1vaSSCwuicQikUgkLi6JxCIjkVgkLi6J"
-    "jYyMjI0smX9R+5zunp7p+dT/1Ihac+k+VXvXLrAu77suVObnfTaeLtqzkS3G10Zgh6PDLnBd"
-    "xS5rLt+FfsPzYi7ggS4uLrYuLtCeJMF33ZPZsYTB8c18c/zxQ28NSEVYOiBGQUNFQ0FGRTAw"
-    "N0ZENEYwMDAwMDAwMDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw"
-    "MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw"
-    "MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDc4OUNFRDdEMkJCOEVDMjhENkY2"
-    "OTI0ODJDMTI4OUM0MjI5MTQ4MjQxNjE5ODlDNIWzHPoAAAAhdEVYdFNvZnR3YXJlAEdyYXBo"
-    "aWNDb252ZXJ0ZXIgKEludGVsKXeH+hkAAADWSURBVHic7JO7CsJAEEVH95UHpFBEhBUTJIpB"
-    "I0GFFDYRBNHSxr/Zn/B/R9c+Ewvt5sLtDswwwwHgcDh06muAVE3Y62TipA+HM80MxgLKoyGZ"
-    "kRWw3GmSsbmEealIJi2Ue3Mk4+dMUukopqj1Z2+KqRqDybBPMv4239xRqt8wflbXP/zOfveu"
-    "n9VVgLcmam1mJew3hmQWmXJFrklmu9K41to94hjbegoCzKQEirmEIVohSOYeRWiVhud0hm1l"
-    "QVgQFoQFYUFYEBaEBWFB/iLICwAA//8DAHqeTXUOgGpTAAAAAElFTkSuQmCC")
-
 def interpFloat(t, v1, v2):
     "interpolator for a single value; interprets t in [0-1] between v1 and v2"
-    return (v2-v1)*t + v1
+    return (v2 - v1) * t + v1
 
 def tFromValue(value, v1, v2):
     "returns a t (in range 0-1) given a value in the range v1 to v2"
-    return float(value-v1)/(v2-v1)
+    if (v2 - v1) == 0:
+        return 1.0
+    else:
+        return float(value - v1) / (v2 - v1)
 
 def clamp(v, minv, maxv):
     "clamps a value within a range"
-    if v<minv: v=minv
-    if v> maxv: v=maxv
+    if v < minv: v = minv
+    if v > maxv: v = maxv
     return v
 
 def toLog(t, v1, v2):
-    return math.log10(t/v1) / math.log10(v2/v1)
+    return math.log10(t / v1) / math.log10(v2 / v1)
 
 def toExp(t, v1, v2):
     return math.pow(10, t * (math.log10(v2) - math.log10(v1)) + math.log10(v1))
 
 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 ):
     maskColor = wx.Color(0,0,0)
     shownColor = wx.Color(5,5,5)
@@ -156,23 +77,32 @@ def GetRoundBitmap( w, h, r ):
     b.SetMaskColour(maskColor)
     return b
 
-def GetRoundShape( w, h, r ):
-    return wx.RegionFromBitmap( GetRoundBitmap(w,h,r) )
-
 class ControlSlider(wx.Panel):
-    def __init__(self, parent, minvalue, maxvalue, init=None, pos=(0,0), size=(200,16), log=False, outFunction=None, integer=False, powoftwo=False, backColour=None):
-        wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY, pos=pos, size=size, style=wx.NO_BORDER | wx.WANTS_CHARS | wx.EXPAND)
+
+    def __init__(self, parent, minvalue, maxvalue, init=None, pos=(0,0), size=(200,16), log=False,
+                 outFunction=None, integer=False, powoftwo=False, backColour=None, orient=wx.HORIZONTAL,
+                 ctrllabel=""):
+        if size == (200,16) and orient == wx.VERTICAL:
+            size = (40, 200)
+        wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY, pos=pos, size=size,
+                            style=wx.NO_BORDER | wx.WANTS_CHARS | wx.EXPAND)
         self.parent = parent
-        if backColour: 
+        if backColour:
             self.backgroundColour = backColour
-        else: 
+        else:
             self.backgroundColour = BACKGROUND_COLOUR
-        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)  
+        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
         self.SetBackgroundColour(self.backgroundColour)
-        self.SetMinSize(self.GetSize())
-        self.knobSize = 40
-        self.knobHalfSize = 20
-        self.sliderHeight = size[1] - 5
+        self.orient = orient
+        # self.SetMinSize(self.GetSize())
+        if self.orient == wx.VERTICAL:
+            self.knobSize = 17
+            self.knobHalfSize = 8
+            self.sliderWidth = size[0] - 29
+        else:
+            self.knobSize = 40
+            self.knobHalfSize = 20
+            self.sliderHeight = size[1] - 5
         self.outFunction = outFunction
         self.integer = integer
         self.log = log
@@ -180,6 +110,7 @@ class ControlSlider(wx.Panel):
         if self.powoftwo:
             self.integer = True
             self.log = False
+        self.ctrllabel = ctrllabel
         self.SetRange(minvalue, maxvalue)
         self.borderWidth = 1
         self.selected = False
@@ -187,10 +118,10 @@ class ControlSlider(wx.Panel):
         self.propagate = True
         self.midictl = None
         self.new = ''
-        if init != None: 
+        if init is not None:
             self.SetValue(init)
             self.init = init
-        else: 
+        else:
             self.SetValue(minvalue)
             self.init = minvalue
         self.clampPos()
@@ -202,8 +133,14 @@ class ControlSlider(wx.Panel):
         self.Bind(wx.EVT_SIZE, self.OnResize)
         self.Bind(wx.EVT_KEY_DOWN, self.keyDown)
         self.Bind(wx.EVT_KILL_FOCUS, self.LooseFocus)
-        self.createSliderBitmap()
-        self.createKnobBitmap()
+
+        if sys.platform == "win32" or sys.platform.startswith("linux"):
+            self.dcref = wx.BufferedPaintDC
+        else:
+            self.dcref = wx.PaintDC
+
+    def getCtrlLabel(self):
+        return self.ctrllabel
 
     def setMidiCtl(self, x, propagate=True):
         self.propagate = propagate
@@ -221,54 +158,23 @@ class ControlSlider(wx.Panel):
 
     def Enable(self):
         self._enable = True
-        self.Refresh()
+        wx.CallAfter(self.Refresh)
 
     def Disable(self):
         self._enable = False
-        self.Refresh()
-        
+        wx.CallAfter(self.Refresh)
+
     def setSliderHeight(self, height):
         self.sliderHeight = height
-        self.createSliderBitmap()
-        self.createKnobBitmap()
         self.Refresh()
 
-    def createSliderBitmap(self):
-        w, h = self.GetSize()
-        b = wx.EmptyBitmap(w,h)
-        dc = wx.MemoryDC(b)
-        dc.SetPen(wx.Pen(self.backgroundColour, width=1))
-        dc.SetBrush(wx.Brush(self.backgroundColour))
-        dc.DrawRectangle(0,0,w,h)
-        dc.SetBrush(wx.Brush("#999999"))
-        dc.SetPen(wx.Pen(self.backgroundColour, width=1))
-        h2 = self.sliderHeight / 4
-        dc.DrawRoundedRectangle(0,h2,w,self.sliderHeight,2)
-        dc.SelectObject(wx.NullBitmap)
-        b.SetMaskColour("#999999")
-        self.sliderMask = b
-
-    def createKnobBitmap(self):
-        w, h = self.knobSize, self.GetSize()[1]
-        b = wx.EmptyBitmap(w,h)
-        dc = wx.MemoryDC(b)
-        rec = wx.Rect(0, 0, w, h)
-        dc.SetPen(wx.Pen(self.backgroundColour, width=1))
-        dc.SetBrush(wx.Brush(self.backgroundColour))
-        dc.DrawRectangleRect(rec)
-        h2 = self.sliderHeight / 4
-        rec = wx.Rect(0, h2, w, self.sliderHeight)
-        dc.GradientFillLinear(rec, "#414753", "#99A7CC", wx.BOTTOM)
-        dc.SetBrush(wx.Brush("#999999"))
-        dc.DrawRoundedRectangle(0,0,w,h,2)
-        dc.SelectObject(wx.NullBitmap)
-        b.SetMaskColour("#999999")
-        self.knobMask = b
+    def setSliderWidth(self, width):
+        self.sliderWidth = width
 
     def getInit(self):
         return self.init
 
-    def SetRange(self, minvalue, maxvalue):   
+    def SetRange(self, minvalue, maxvalue):
         self.minvalue = minvalue
         self.maxvalue = maxvalue
 
@@ -276,11 +182,15 @@ class ControlSlider(wx.Panel):
         return [self.minvalue, self.maxvalue]
 
     def scale(self):
-        inter = tFromValue(self.pos, self.knobHalfSize, self.GetSize()[0]-self.knobHalfSize)
+        if self.orient == wx.VERTICAL:
+            h = self.GetSize()[1]
+            inter = tFromValue(h-self.pos, self.knobHalfSize, self.GetSize()[1]-self.knobHalfSize)
+        else:
+            inter = tFromValue(self.pos, self.knobHalfSize, self.GetSize()[0]-self.knobHalfSize)
         if not self.integer:
             return interpFloat(inter, self.minvalue, self.maxvalue)
         elif self.powoftwo:
-            return powOfTwo(int(interpFloat(inter, self.minvalue, self.maxvalue)))    
+            return powOfTwo(int(interpFloat(inter, self.minvalue, self.maxvalue)))
         else:
             return int(interpFloat(inter, self.minvalue, self.maxvalue))
 
@@ -289,7 +199,7 @@ class ControlSlider(wx.Panel):
         if self.HasCapture():
             self.ReleaseMouse()
         if self.powoftwo:
-            value = powOfTwoToInt(value)  
+            value = powOfTwoToInt(value)
         value = clamp(value, self.minvalue, self.maxvalue)
         if self.log:
             t = toLog(value, self.minvalue, self.maxvalue)
@@ -300,10 +210,10 @@ class ControlSlider(wx.Panel):
         if self.integer:
             self.value = int(self.value)
         if self.powoftwo:
-            self.value = powOfTwo(self.value)    
+            self.value = powOfTwo(self.value)
         self.clampPos()
         self.selected = False
-        self.Refresh()
+        wx.CallAfter(self.Refresh)
 
     def GetValue(self):
         if self.log:
@@ -348,7 +258,10 @@ class ControlSlider(wx.Panel):
             return
         if self._enable:
             size = self.GetSize()
-            self.pos = clamp(evt.GetPosition()[0], self.knobHalfSize, size[0]-self.knobHalfSize)
+            if self.orient == wx.VERTICAL:
+                self.pos = clamp(evt.GetPosition()[1], self.knobHalfSize, size[1]-self.knobHalfSize)
+            else:
+                self.pos = clamp(evt.GetPosition()[0], self.knobHalfSize, size[0]-self.knobHalfSize)
             self.value = self.scale()
             self.CaptureMouse()
             self.selected = False
@@ -363,23 +276,29 @@ class ControlSlider(wx.Panel):
         if self._enable:
             w, h = self.GetSize()
             pos = event.GetPosition()
-            if wx.Rect(self.pos-self.knobHalfSize, 0, self.knobSize, h).Contains(pos):
-                self.selected = True
+            if self.orient == wx.VERTICAL:
+                if wx.Rect(0, self.pos-self.knobHalfSize, w, self.knobSize).Contains(pos):
+                    self.selected = True
+            else:
+                if wx.Rect(self.pos-self.knobHalfSize, 0, self.knobSize, h).Contains(pos):
+                    self.selected = True
             self.Refresh()
         event.Skip()
-            
+
     def MouseMotion(self, evt):
         if self._enable:
             size = self.GetSize()
             if self.HasCapture():
-                self.pos = clamp(evt.GetPosition()[0], self.knobHalfSize, size[0]-self.knobHalfSize)
+                if self.orient == wx.VERTICAL:
+                    self.pos = clamp(evt.GetPosition()[1], self.knobHalfSize, size[1]-self.knobHalfSize)
+                else:
+                    self.pos = clamp(evt.GetPosition()[0], self.knobHalfSize, size[0]-self.knobHalfSize)
                 self.value = self.scale()
                 self.selected = False
                 self.Refresh()
 
     def OnResize(self, evt):
-        self.createSliderBitmap()
-        self.clampPos()    
+        self.clampPos()
         self.Refresh()
 
     def clampPos(self):
@@ -387,20 +306,23 @@ class ControlSlider(wx.Panel):
         if self.powoftwo:
             val = powOfTwoToInt(self.value)
         else:
-            val = self.value    
-        self.pos = tFromValue(val, self.minvalue, self.maxvalue) * (size[0] - self.knobSize) + self.knobHalfSize
-        self.pos = clamp(self.pos, self.knobHalfSize, size[0]-self.knobHalfSize)
-        
+            val = self.value
+        if self.orient == wx.VERTICAL:
+            self.pos = tFromValue(val, self.minvalue, self.maxvalue) * (size[1] - self.knobSize) + self.knobHalfSize
+            self.pos = clamp(size[1]-self.pos, self.knobHalfSize, size[1]-self.knobHalfSize)
+        else:
+            self.pos = tFromValue(val, self.minvalue, self.maxvalue) * (size[0] - self.knobSize) + self.knobHalfSize
+            self.pos = clamp(self.pos, self.knobHalfSize, size[0]-self.knobHalfSize)
+
     def setBackgroundColour(self, colour):
         self.backgroundColour = colour
         self.SetBackgroundColour(self.backgroundColour)
-        self.createSliderBitmap()
-        self.createKnobBitmap()
         self.Refresh()
 
     def OnPaint(self, evt):
         w,h = self.GetSize()
-        dc = wx.AutoBufferedPaintDC(self)
+        dc = self.dcref(self)
+        gc = wx.GraphicsContext_Create(dc)
 
         dc.SetBrush(wx.Brush(self.backgroundColour, wx.SOLID))
         dc.Clear()
@@ -408,41 +330,58 @@ class ControlSlider(wx.Panel):
         # Draw background
         dc.SetPen(wx.Pen(self.backgroundColour, width=self.borderWidth, style=wx.SOLID))
         dc.DrawRectangle(0, 0, w, h)
-        
+
         # Draw inner part
         if self._enable: sliderColour =  "#99A7CC"
         else: sliderColour = "#BBBBBB"
-        h2 = self.sliderHeight / 4
-        rec = wx.Rect(0, h2, w, self.sliderHeight)
-        dc.GradientFillLinear(rec, "#646986", sliderColour, wx.BOTTOM)
-        dc.DrawBitmap(self.sliderMask, 0, 0, True)
-
-        if self.midictl != None:
-            if sys.platform in ['win32', 'linux2']:
-                dc.SetFont(wx.Font(6, wx.ROMAN, wx.NORMAL, wx.NORMAL))
-            else:    
-                dc.SetFont(wx.Font(9, wx.ROMAN, wx.NORMAL, wx.NORMAL))
+        if self.orient == wx.VERTICAL:
+            w2 = (w - self.sliderWidth) // 2
+            rec = wx.Rect(w2, 0, self.sliderWidth, h)
+            brush = gc.CreateLinearGradientBrush(w2, 0, w2+self.sliderWidth, 0, "#646986", sliderColour)
+        else:
+            h2 = self.sliderHeight // 4
+            rec = wx.Rect(0, h2, w, self.sliderHeight)
+            brush = gc.CreateLinearGradientBrush(0, h2, 0, h2+self.sliderHeight, "#646986", sliderColour)
+        gc.SetBrush(brush)
+        gc.DrawRoundedRectangle(rec[0], rec[1], rec[2], rec[3], 2)
+
+        if self.midictl is not None:
+            if sys.platform == 'win32' or sys.platform.startswith('linux'):
+                dc.SetFont(wx.Font(6, wx.FONTFAMILY_ROMAN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
+            else:
+                dc.SetFont(wx.Font(9, wx.FONTFAMILY_ROMAN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
             dc.SetTextForeground('#FFFFFF')
-            dc.DrawLabel(str(self.midictl), wx.Rect(2,0,h,h), wx.ALIGN_CENTER)
-            dc.DrawLabel(str(self.midictl), wx.Rect(w-h,0,h,h), wx.ALIGN_CENTER)
+            if self.orient == wx.VERTICAL:
+                dc.DrawLabel(str(self.midictl), wx.Rect(w2,2,self.sliderWidth,12), wx.ALIGN_CENTER)
+                dc.DrawLabel(str(self.midictl), wx.Rect(w2,h-12,self.sliderWidth,12), wx.ALIGN_CENTER)
+            else:
+                dc.DrawLabel(str(self.midictl), wx.Rect(2,0,h,h), wx.ALIGN_CENTER)
+                dc.DrawLabel(str(self.midictl), wx.Rect(w-h,0,h,h), wx.ALIGN_CENTER)
 
         # Draw knob
         if self._enable: knobColour = '#888888'
         else: knobColour = "#DDDDDD"
-        rec = wx.Rect(self.pos-self.knobHalfSize, 0, self.knobSize, h)  
-        dc.GradientFillLinear(rec, "#424864", knobColour, wx.RIGHT)
-        dc.DrawBitmap(self.knobMask, rec[0], rec[1], True)
-        
-        if self.selected:
-            rec2 = wx.Rect(self.pos-self.knobHalfSize, 0, self.knobSize, h)  
-            dc.SetBrush(wx.Brush('#333333', wx.SOLID))
-            dc.SetPen(wx.Pen('#333333', width=self.borderWidth, style=wx.SOLID))  
-            dc.DrawRoundedRectangleRect(rec2, 3)
+        if self.orient == wx.VERTICAL:
+            rec = wx.Rect(0, self.pos-self.knobHalfSize, w, self.knobSize-1)
+            if self.selected:
+                brush = wx.Brush('#333333', wx.SOLID)
+            else:
+                brush = gc.CreateLinearGradientBrush(0, 0, w, 0, "#323854", knobColour)
+            gc.SetBrush(brush)
+            gc.DrawRoundedRectangle(rec[0], rec[1], rec[2], rec[3], 3)
+        else:
+            rec = wx.Rect(self.pos-self.knobHalfSize, 0, self.knobSize-1, h)
+            if self.selected:
+                brush = wx.Brush('#333333', wx.SOLID)
+            else:
+                brush = gc.CreateLinearGradientBrush(self.pos-self.knobHalfSize, 0, self.pos+self.knobHalfSize, 0, "#323854", knobColour)
+            gc.SetBrush(brush)
+            gc.DrawRoundedRectangle(rec[0], rec[1], rec[2], rec[3], 3)
 
-        if sys.platform in ['win32', 'linux2']:
-            dc.SetFont(wx.Font(7, wx.ROMAN, wx.NORMAL, wx.NORMAL))
-        else:    
-            dc.SetFont(wx.Font(10, wx.ROMAN, wx.NORMAL, wx.NORMAL))
+        if sys.platform == 'win32' or sys.platform.startswith('linux'):
+            dc.SetFont(wx.Font(7, wx.FONTFAMILY_ROMAN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
+        else:
+            dc.SetFont(wx.Font(10, wx.FONTFAMILY_ROMAN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
 
         # Draw text
         if self.selected and self.new:
@@ -458,7 +397,7 @@ class ControlSlider(wx.Panel):
                 val = '%.3f' % self.GetValue()
             elif abs(self.GetValue()) < 10:
                 val = '%.4f' % self.GetValue()
-        if sys.platform == 'linux2':
+        if sys.platform.startswith('linux'):
             width = len(val) * (dc.GetCharWidth() - 3)
         else:
             width = len(val) * dc.GetCharWidth()
@@ -472,11 +411,14 @@ class ControlSlider(wx.Panel):
 
         evt.Skip()
 
+# TODO: key, command and slmap should be removed from the multislider widget.
+# It should work in the same way as the ControlSlider widget.
 class MultiSlider(wx.Panel):
-    def __init__(self, parent, init, key, command, slmap): 
+
+    def __init__(self, parent, init, key, command, slmap, ctrllabel=""):
         wx.Panel.__init__(self, parent, size=(250,250))
         self.backgroundColour = BACKGROUND_COLOUR
-        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)  
+        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
         self.SetBackgroundColour(self.backgroundColour)
         self.Bind(wx.EVT_SIZE, self.OnResize)
         self.Bind(wx.EVT_PAINT, self.OnPaint)
@@ -484,24 +426,28 @@ class MultiSlider(wx.Panel):
         self.Bind(wx.EVT_LEFT_UP, self.MouseUp)
         self.Bind(wx.EVT_MOTION, self.MouseMotion)
         self._slmap = slmap
+        self.ctrllabel = ctrllabel
         self._values = [slmap.set(x) for x in init]
         self._nchnls = len(init)
         self._labels = init
         self._key = key
         self._command = command
         self._height = 16
-        if sys.platform in ['win32', 'linux2']:
-            self._font = wx.Font(7, wx.ROMAN, wx.NORMAL, wx.NORMAL)
-        else:    
-            self._font = wx.Font(10, wx.ROMAN, wx.NORMAL, wx.NORMAL)
-            
+        if sys.platform == 'win32' or sys.platform.startswith('linux'):
+            self._font = wx.Font(7, wx.FONTFAMILY_ROMAN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
+        else:
+            self._font = wx.Font(10, wx.FONTFAMILY_ROMAN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
+
         self.SetSize((250, self._nchnls*16))
         self.SetMinSize((250,self._nchnls*16))
 
+    def getCtrlLabel(self):
+        return self.ctrllabel
+
     def OnResize(self, event):
         self.Layout()
         self.Refresh()
-        
+
     def OnPaint(self, event):
         w,h = self.GetSize()
         dc = wx.AutoBufferedPaintDC(self)
@@ -514,17 +460,20 @@ class MultiSlider(wx.Panel):
         for i in range(self._nchnls):
             x = int(self._values[i] * w)
             y = self._height * i
-            dc.DrawRectangle(0, y+1, x, self._height-2)
-            rec = wx.Rect(w/2-15, y, 30, self._height)
+            dc.DrawRectangle(0, y + 1, x, self._height-2)
+            rec = wx.Rect(w // 2 - 15, y, 30, self._height)
             dc.DrawLabel("%s" % self._labels[i], rec, wx.ALIGN_CENTER)
 
     def MouseDown(self, evt):
         w,h = self.GetSize()
         pos = evt.GetPosition()
-        slide = pos[1] / self._height
-        if 0 <= slide < self._nchnls:
+        slide = pos[1] // self._height
+        if slide >= 0 and slide < self._nchnls:
             self._values[slide] = pos[0] / float(w)
-            self._labels = [self._slmap.get(x) for x in self._values]
+            if self._slmap._res == 'int':
+                self._labels = [int(self._slmap.get(x)) for x in self._values]
+            else:
+                self._labels = [self._slmap.get(x) for x in self._values]
             self._command(self._key, self._labels)
             self.CaptureMouse()
         self.Refresh()
@@ -538,57 +487,120 @@ class MultiSlider(wx.Panel):
         w,h = self.GetSize()
         pos = evt.GetPosition()
         if evt.Dragging() and evt.LeftIsDown():
-            slide = pos[1] / self._height
-            if 0 <= slide < self._nchnls:
+            slide = pos[1] // self._height
+            if slide >= 0 and slide < self._nchnls:
                 self._values[slide] = pos[0] / float(w)
-                self._labels = [self._slmap.get(x) for x in self._values]
+                if self._slmap._res == 'int':
+                    self._labels = [int(self._slmap.get(x)) for x in self._values]
+                else:
+                    self._labels = [self._slmap.get(x) for x in self._values]
                 self._command(self._key, self._labels)
             self.Refresh()
-        
+
+    def GetValue(self):
+        return self._labels
+
 class VuMeter(wx.Panel):
-    def __init__(self, parent, size=(200,11), numSliders=2):
-        wx.Panel.__init__(self, parent, -1, size=size)
+
+    def __init__(self, parent, size=(200,11), numSliders=2, orient=wx.HORIZONTAL,
+                 pos=wx.DefaultPosition, style=0):
+        if orient == wx.HORIZONTAL:
+            size = (size[0], numSliders * 5 + 1)
+        else:
+            size = (numSliders * 5 + 1, size[1])
+        wx.Panel.__init__(self, parent, -1, pos=pos, size=size, style=style)
         self.parent = parent
+        self.orient = orient
         self.SetBackgroundColour("#000000")
         self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
         self.old_nchnls = numSliders
         self.numSliders = numSliders
-        self.SetMinSize((200,5*self.numSliders+1))
-        self.SetSize((200, 5*self.numSliders+1))
-        self.bitmap = vu_metre.GetBitmap()
-        self.backBitmap = vu_metre_dark.GetBitmap()
         self.amplitude = [0] * self.numSliders
+        self.createBitmaps()
 
         self.Bind(wx.EVT_PAINT, self.OnPaint)
-        self.Bind(wx.EVT_CLOSE, self.OnClose)   
+        self.Bind(wx.EVT_SIZE, self.OnSize)
+        self.Bind(wx.EVT_CLOSE, self.OnClose)
+
+    def OnSize(self, evt):
+        self.createBitmaps()
+        wx.CallAfter(self.Refresh)
+
+    def createBitmaps(self):
+        w, h = self.GetSize()
+        b = wx.EmptyBitmap(w,h)
+        f = wx.EmptyBitmap(w,h)
+        dcb = wx.MemoryDC(b)
+        dcf = wx.MemoryDC(f)
+        dcb.SetPen(wx.Pen("#000000", width=1))
+        dcf.SetPen(wx.Pen("#000000", width=1))
+        if self.orient == wx.HORIZONTAL:
+            height = 6
+            steps = int(w / 10.0 + 0.5)
+        else:
+            width = 6
+            steps = int(h / 10.0 + 0.5)
+        bounds = int(steps / 6.0)
+        for i in range(steps):
+            if i == (steps - 1):
+                dcb.SetBrush(wx.Brush("#770000"))
+                dcf.SetBrush(wx.Brush("#FF0000"))
+            elif i >= (steps - bounds):
+                dcb.SetBrush(wx.Brush("#440000"))
+                dcf.SetBrush(wx.Brush("#CC0000"))
+            elif i >= (steps - (bounds*2)):
+                dcb.SetBrush(wx.Brush("#444400"))
+                dcf.SetBrush(wx.Brush("#CCCC00"))
+            else:
+                dcb.SetBrush(wx.Brush("#004400"))
+                dcf.SetBrush(wx.Brush("#00CC00"))
+            if self.orient == wx.HORIZONTAL:
+                dcb.DrawRectangle(i*10, 0, 11, height)
+                dcf.DrawRectangle(i*10, 0, 11, height)
+            else:
+                ii = steps - 1 - i
+                dcb.DrawRectangle(0, ii*10, width, 11)
+                dcf.DrawRectangle(0, ii*10, width, 11)
+        if self.orient == wx.HORIZONTAL:
+            dcb.DrawLine(w-1, 0, w-1, height)
+            dcf.DrawLine(w-1, 0, w-1, height)
+        else:
+            dcb.DrawLine(0, 0, width, 0)
+            dcf.DrawLine(0, 0, width, 0)
+        dcb.SelectObject(wx.NullBitmap)
+        dcf.SelectObject(wx.NullBitmap)
+        self.backBitmap = b
+        self.bitmap = f
 
     def setNumSliders(self, numSliders):
+        w, h = self.GetSize()
         oldChnls = self.old_nchnls
         self.numSliders = numSliders
         self.amplitude = [0] * self.numSliders
         gap = (self.numSliders - oldChnls) * 5
         parentSize = self.parent.GetSize()
-        if sys.platform == 'linux2':
-            self.SetSize((200, 5*self.numSliders+1))
-            self.SetMinSize((200, 5*self.numSliders+1))
+        if self.orient == wx.HORIZONTAL:
+            self.SetSize((w, self.numSliders * 5 + 1))
+            self.SetMinSize((w, 5*self.numSliders+1))
             self.parent.SetSize((parentSize[0], parentSize[1]+gap))
             self.parent.SetMinSize((parentSize[0], parentSize[1]+gap))
         else:
-            self.SetSize((200, 5*self.numSliders+1))
-            self.SetMinSize((200, 5*self.numSliders+1))
-            self.parent.SetSize((parentSize[0], parentSize[1]+gap))
-            self.parent.SetMinSize((parentSize[0], parentSize[1]+gap))
-        self.Refresh()
-        self.parent.Layout()
+            self.SetSize((self.numSliders * 5 + 1, h))
+            self.SetMinSize((5*self.numSliders+1, h))
+            self.parent.SetSize((parentSize[0]+gap, parentSize[1]))
+            self.parent.SetMinSize((parentSize[0]+gap, parentSize[1]))
+        wx.CallAfter(self.Refresh)
+        wx.CallAfter(self.parent.Layout)
+        wx.CallAfter(self.parent.Refresh)
 
     def setRms(self, *args):
-        if args[0] < 0: 
+        if args[0] < 0:
             return
         if not args:
-            self.amplitude = [0 for i in range(self.numSliders)]                
+            self.amplitude = [0 for i in range(self.numSliders)]
         else:
             self.amplitude = args
-        wx.CallAfter(self.Refresh)   
+        wx.CallAfter(self.Refresh)
 
     def OnPaint(self, event):
         w,h = self.GetSize()
@@ -596,46 +608,73 @@ class VuMeter(wx.Panel):
         dc.SetBrush(wx.Brush("#000000"))
         dc.Clear()
         dc.DrawRectangle(0,0,w,h)
-        for i in range(self.numSliders):
-            db = math.log10(self.amplitude[i]+0.00001) * 0.2 + 1.
-            width = int(db*w)
-            dc.DrawBitmap(self.backBitmap, 0, i*5)
-            dc.SetClippingRegion(0, i*5, width, 5)
-            dc.DrawBitmap(self.bitmap, 0, i*5)
-            dc.DestroyClippingRegion()
+        if self.orient == wx.HORIZONTAL:
+            height = 6
+            for i in range(self.numSliders):
+                y = i * (height - 1)
+                if i < len(self.amplitude):
+                    db = math.log10(self.amplitude[i]+0.00001) * 0.2 + 1.
+                    width = int(db*w)
+                else:
+                    width = 0
+                dc.DrawBitmap(self.backBitmap, 0, y)
+                if width > 0:
+                    dc.SetClippingRegion(0, y, width, height)
+                    dc.DrawBitmap(self.bitmap, 0, y)
+                    dc.DestroyClippingRegion()
+        else:
+            width = 6
+            for i in range(self.numSliders):
+                y = i * (width - 1)
+                if i < len(self.amplitude):
+                    db = math.log10(self.amplitude[i]+0.00001) * 0.2 + 1.
+                    height = int(db*h)
+                else:
+                    height = 0
+                dc.DrawBitmap(self.backBitmap, y, 0)
+                if height > 0:
+                    dc.SetClippingRegion(y, h-height, width, height)
+                    dc.DrawBitmap(self.bitmap, y, 0)
+                    dc.DestroyClippingRegion()
         event.Skip()
-        
+
     def OnClose(self, evt):
         self.Destroy()
 
+# TODO: BACKGROUND_COLOUR hard-coded all over the place in this class.
 class RangeSlider(wx.Panel):
-    def __init__(self, parent, minvalue, maxvalue, init=None, pos=(0,0), size=(200,15), 
-                 valtype='int', log=False, function=None):
+
+    def __init__(self, parent, minvalue, maxvalue, init=None, pos=(0,0), size=(200,15),
+                 valtype='int', log=False, function=None, backColour=None):
         wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY, pos=pos, size=size, style=wx.NO_BORDER)
-        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)  
-        self.SetBackgroundColour(BACKGROUND_COLOUR)
+        if backColour:
+            self.backgroundColour = backColour
+        else:
+            self.backgroundColour = BACKGROUND_COLOUR
+        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+        self.SetBackgroundColour(self.backgroundColour)
         self.SetMinSize(self.GetSize())
         self.sliderHeight = 15
         self.borderWidth = 1
         self.action = None
-        self.fillcolor = "#AAAAAA" #SLIDER_BACK_COLOUR
-        self.knobcolor = "#333333" #SLIDER_KNOB_COLOUR
+        self.fillcolor = "#AAAAAA"  # SLIDER_BACK_COLOUR
+        self.knobcolor = "#333333"  # SLIDER_KNOB_COLOUR
         self.handlecolor = wx.Colour(int(self.knobcolor[1:3])-10, int(self.knobcolor[3:5])-10, int(self.knobcolor[5:7])-10)
         self.outFunction = function
-        if valtype.startswith('i'): self.myType = IntType
-        else: self.myType = FloatType
+        if valtype.startswith('i'): self.myType = int
+        else: self.myType = float
         self.log = log
         self.SetRange(minvalue, maxvalue)
         self.handles = [minvalue, maxvalue]
-        if init != None:
-            if type(init) in [ListType, TupleType]:
+        if init is not None:
+            if type(init) in [list, tuple]:
                 if len(init) == 1:
                     self.SetValue([init[0],init[0]])
                 else:
-                    self.SetValue([init[0],init[1]])    
-            else: 
+                    self.SetValue([init[0],init[1]])
+            else:
                 self.SetValue([minvalue,maxvalue])
-        else: 
+        else:
             self.SetValue([minvalue,maxvalue])
         self.Bind(wx.EVT_LEFT_DOWN, self.MouseDown)
         self.Bind(wx.EVT_RIGHT_DOWN, self.MouseRightDown)
@@ -649,12 +688,12 @@ class RangeSlider(wx.Panel):
         w, h = self.GetSize()
         b = wx.EmptyBitmap(w,h)
         dc = wx.MemoryDC(b)
-        dc.SetPen(wx.Pen(BACKGROUND_COLOUR, width=1))
-        dc.SetBrush(wx.Brush(BACKGROUND_COLOUR))
+        dc.SetPen(wx.Pen(self.backgroundColour, width=1))
+        dc.SetBrush(wx.Brush(self.backgroundColour))
         dc.DrawRectangle(0,0,w,h)
         dc.SetBrush(wx.Brush("#777777"))
         dc.SetPen(wx.Pen("#FFFFFF", width=1))
-        h2 = self.sliderHeight / 4
+        h2 = self.sliderHeight // 4
         dc.DrawRoundedRectangle(0, h2, w, self.sliderHeight, 4)
         dc.SelectObject(wx.NullBitmap)
         b.SetMaskColour("#777777")
@@ -666,7 +705,7 @@ class RangeSlider(wx.Panel):
         self.handlecolor = wx.Colour(self.knobcolor[0]*0.35, self.knobcolor[1]*0.35, self.knobcolor[2]*0.35)
         self.createSliderBitmap()
 
-    def SetRange(self, minvalue, maxvalue):   
+    def SetRange(self, minvalue, maxvalue):
         self.minvalue = minvalue
         self.maxvalue = maxvalue
 
@@ -688,11 +727,11 @@ class RangeSlider(wx.Panel):
             self.handles = self.scale(self.handlePos)
             self.CaptureMouse()
             self.Refresh()
-        
+
     def MouseDown(self, evt):
         size = self.GetSize()
         xpos = evt.GetPosition()[0]
-        self.middle = (self.handlePos[1] - self.handlePos[0]) / 2 + self.handlePos[0]
+        self.middle = (self.handlePos[1] - self.handlePos[0]) // 2 + self.handlePos[0]
         midrec = wx.Rect(self.middle-7, 4, 15, size[1]-9)
         if midrec.Contains(evt.GetPosition()):
             self.lastpos = xpos
@@ -715,7 +754,7 @@ class RangeSlider(wx.Panel):
             if self.action == 'drag':
                 off = xpos - self.lastpos
                 self.lastpos = xpos
-                self.handlePos[0] = clamp(self.handlePos[0] + off, 1, size[0]-self.length) 
+                self.handlePos[0] = clamp(self.handlePos[0] + off, 1, size[0]-self.length)
                 self.handlePos[1] = clamp(self.handlePos[1] + off, self.length, size[0]-1)
             if self.action == 'left':
                 self.handlePos[0] = clamp(xpos, 1, self.handlePos[1]-20)
@@ -744,10 +783,12 @@ class RangeSlider(wx.Panel):
         self.handlePos = tmp
 
 class HRangeSlider(RangeSlider):
-    def __init__(self, parent, minvalue, maxvalue, init=None, pos=(0,0), size=(200,15), 
-                 valtype='int', log=False, function=None):
-        RangeSlider.__init__(self, parent, minvalue, maxvalue, init, pos, size, valtype, log, function)
+
+    def __init__(self, parent, minvalue, maxvalue, init=None, pos=(0,0), size=(200,15),
+                 valtype='int', log=False, function=None, backColour=None):
+        RangeSlider.__init__(self, parent, minvalue, maxvalue, init, pos, size, valtype, log, function, backColour)
         self.SetMinSize((50, 15))
+
         self.createSliderBitmap()
         #self.createBackgroundBitmap()
         self.clampHandlePos()
@@ -763,15 +804,15 @@ class HRangeSlider(RangeSlider):
         self.backgroundBitmap = wx.EmptyBitmap(w,h)
         dc = wx.MemoryDC(self.backgroundBitmap)
 
-        dc.SetBrush(wx.Brush(BACKGROUND_COLOUR, wx.SOLID))
+        dc.SetBrush(wx.Brush(self.backgroundColour, wx.SOLID))
         dc.Clear()
 
         # Draw background
-        dc.SetPen(wx.Pen(BACKGROUND_COLOUR, width=self.borderWidth, style=wx.SOLID))
+        dc.SetPen(wx.Pen(self.backgroundColour, width=self.borderWidth, style=wx.SOLID))
         dc.DrawRectangle(0, 0, w, h)
 
         # Draw inner part
-        h2 = self.sliderHeight / 4
+        h2 = self.sliderHeight // 4
         rec = wx.Rect(0, h2, w, self.sliderHeight)
         dc.GradientFillLinear(rec, "#666666", self.fillcolor, wx.BOTTOM)
         dc.DrawBitmap(self.sliderMask, 0, 0, True)
@@ -786,7 +827,7 @@ class HRangeSlider(RangeSlider):
         else:
             t = tFromValue(value, self.minvalue, self.maxvalue)
             value = interpFloat(t, self.minvalue, self.maxvalue)
-        if self.myType == IntType:
+        if self.myType == int:
             value = int(value)
         self.handles[which] = value
         self.OnResize(None)
@@ -802,10 +843,10 @@ class HRangeSlider(RangeSlider):
             else:
                 t = tFromValue(value, self.minvalue, self.maxvalue)
                 value = interpFloat(t, self.minvalue, self.maxvalue)
-            if self.myType == IntType:
+            if self.myType == int:
                 value = int(value)
             tmp.append(value)
-        self.handles = tmp        
+        self.handles = tmp
         self.OnResize(None)
 
     def GetValue(self):
@@ -816,10 +857,10 @@ class HRangeSlider(RangeSlider):
                 val = toExp(t, self.minvalue, self.maxvalue)
             else:
                 val = value
-            if self.myType == IntType:
+            if self.myType == int:
                 val = int(val)
             tmp.append(val)
-        tmp = [min(tmp), max(tmp)]    
+        tmp = [min(tmp), max(tmp)]
         return tmp
 
     def OnPaint(self, evt):
@@ -827,24 +868,24 @@ class HRangeSlider(RangeSlider):
         dc = wx.AutoBufferedPaintDC(self)
 
         # Draw background
-        dc.SetBrush(wx.Brush(BACKGROUND_COLOUR))
+        dc.SetBrush(wx.Brush(self.backgroundColour))
         dc.Clear()
-        dc.SetPen(wx.Pen(BACKGROUND_COLOUR))
+        dc.SetPen(wx.Pen(self.backgroundColour))
         dc.DrawRectangle(0, 0, w, h)
-        
+
         #dc.DrawBitmap(self.backgroundBitmap, 0, 0)
 
         # Draw handles
         dc.SetPen(wx.Pen(self.handlecolor, width=1, style=wx.SOLID))
         dc.SetBrush(wx.Brush(self.handlecolor))
-        
-        rec = wx.Rect(self.handlePos[0], 3, self.handlePos[1]-self.handlePos[0], h-7)  
-        dc.DrawRoundedRectangleRect(rec, 4)
+
+        rec = (self.handlePos[0], 3, self.handlePos[1]-self.handlePos[0], h-7)
+        dc.DrawRoundedRectangle(rec[0], rec[1], rec[2], rec[3], 4)
         dc.SetPen(wx.Pen(self.fillcolor, width=1, style=wx.SOLID))
         dc.SetBrush(wx.Brush(self.fillcolor))
-        mid = (self.handlePos[1]-self.handlePos[0]) / 2 + self.handlePos[0]
-        rec = wx.Rect(mid-4, 4, 8, h-9)
-        dc.DrawRoundedRectangleRect(rec, 3)
+        mid = (self.handlePos[1] - self.handlePos[0]) // 2 + self.handlePos[0]
+        rec = (mid-4, 4, 8, h-9)
+        dc.DrawRoundedRectangle(rec[0], rec[1], rec[2], rec[3], 3)
 
         # Send value
         if self.outFunction:
@@ -854,6 +895,7 @@ class HRangeSlider(RangeSlider):
 ### Control window for PyoObject
 ######################################################################
 class Command:
+
     def __init__(self, func, key):
         self.func = func
         self.key = key
@@ -862,13 +904,19 @@ class Command:
         self.func(self.key, value)
 
 class PyoObjectControl(wx.Frame):
+
     def __init__(self, parent=None, obj=None, map_list=None):
         wx.Frame.__init__(self, parent)
-        from controls import SigTo
-        self.menubar = wx.MenuBar()        
+        from .controls import SigTo
+        self.menubar = wx.MenuBar()
         self.fileMenu = wx.Menu()
-        self.fileMenu.Append(-1, 'Close\tCtrl+W', kind=wx.ITEM_NORMAL)
-        self.fileMenu.Bind(wx.EVT_MENU, self._destroy)
+        self.fileMenu.Append(9999, 'Close\tCtrl+W', kind=wx.ITEM_NORMAL)
+        self.fileMenu.Bind(wx.EVT_MENU, self._destroy, id=9999)
+        self.fileMenu.AppendSeparator()
+        self.fileMenu.Append(10000, 'Copy all parameters to the clipboard (4 digits of precision)\tCtrl+C', kind=wx.ITEM_NORMAL)
+        self.Bind(wx.EVT_MENU, self.copy, id=10000)
+        self.fileMenu.Append(10001, 'Copy all parameters to the clipboard (full precision)\tShift+Ctrl+C', kind=wx.ITEM_NORMAL)
+        self.Bind(wx.EVT_MENU, self.copy, id=10001)
         self.menubar.Append(self.fileMenu, "&File")
         self.SetMenuBar(self.menubar)
         self.Bind(wx.EVT_CLOSE, self._destroy)
@@ -880,70 +928,111 @@ class PyoObjectControl(wx.Frame):
         self._displays = {}
         self._maps = {}
         self._sigs = {}
-        
+
         panel = wx.Panel(self)
         panel.SetBackgroundColour(BACKGROUND_COLOUR)
         mainBox = wx.BoxSizer(wx.VERTICAL)
         self.box = wx.FlexGridSizer(10,2,5,5)
-        
+
         for i, m in enumerate(self._map_list):
-            key, init, mini, maxi, scl, res = m.name, m.init, m.min, m.max, m.scale, m.res
+            key, init, mini, maxi, scl, res, dataOnly = m.name, m.init, m.min, m.max, m.scale, m.res, m.dataOnly
             # filters PyoObjects
-            if type(init) not in [ListType, FloatType, IntType]:
+            if type(init) not in [list, float, int]:
                 self._excluded.append(key)
-            else:    
+            else:
                 self._maps[key] = m
                 # label (param name)
-                label = wx.StaticText(panel, -1, key)
+                if dataOnly:
+                    label = wx.StaticText(panel, -1, key+" *")
+                else:
+                    label = wx.StaticText(panel, -1, key)
                 # create and pack slider
-                if type(init) != ListType:
+                if type(init) != list:
                     if scl == 'log': scl = True
                     else: scl = False
                     if res == 'int': res = True
                     else: res = False
                     self._sliders.append(ControlSlider(panel, mini, maxi, init, log=scl, size=(300,16),
-                                        outFunction=Command(self.setval, key), integer=res))
-                    self.box.AddMany([(label, 0, wx.LEFT, 5), (self._sliders[-1], 1, wx.EXPAND | wx.LEFT, 5)])   
+                                        outFunction=Command(self.setval, key), integer=res, ctrllabel=key))
+                    self.box.AddMany([(label, 0, wx.LEFT, 5), (self._sliders[-1], 1, wx.EXPAND | wx.LEFT, 5)])
                 else:
-                    self._sliders.append(MultiSlider(panel, init, key, self.setval, m))
-                    self.box.AddMany([(label, 0, wx.LEFT, 5), (self._sliders[-1], 1, wx.EXPAND | wx.LEFT, 5)])   
-                # set obj attribute to PyoObject SigTo  
-                self._values[key] = init
-                self._sigs[key] = SigTo(init, .025, init)
-                refStream = self._obj.getBaseObjects()[0]._getStream()
-                server = self._obj.getBaseObjects()[0].getServer()
-                for k in range(len(self._sigs[key].getBaseObjects())):
-                    curStream = self._sigs[key].getBaseObjects()[k]._getStream()
-                    server.changeStreamPosition(refStream, curStream)
-                setattr(self._obj, key, self._sigs[key])
-        self.box.AddGrowableCol(1, 1) 
+                    self._sliders.append(MultiSlider(panel, init, key, self.setval, m, ctrllabel=key))
+                    self.box.AddMany([(label, 0, wx.LEFT, 5), (self._sliders[-1], 1, wx.EXPAND | wx.LEFT, 5)])
+                # set obj attribute to PyoObject SigTo
+                if not dataOnly:
+                    self._values[key] = init
+                    self._sigs[key] = SigTo(init, .025, init)
+                    refStream = self._obj.getBaseObjects()[0]._getStream()
+                    server = self._obj.getBaseObjects()[0].getServer()
+                    for k in range(len(self._sigs[key].getBaseObjects())):
+                        curStream = self._sigs[key].getBaseObjects()[k]._getStream()
+                        server.changeStreamPosition(refStream, curStream)
+                    setattr(self._obj, key, self._sigs[key])
+        self.box.AddGrowableCol(1, 1)
         mainBox.Add(self.box, 1, wx.EXPAND | wx.TOP | wx.BOTTOM | wx.RIGHT, 10)
 
         panel.SetSizerAndFit(mainBox)
         self.SetClientSize(panel.GetSize())
         self.SetMinSize(self.GetSize())
         self.SetMaxSize((-1, self.GetSize()[1]))
-        
+
     def _destroy(self, event):
         for m in self._map_list:
             key = m.name
-            if key not in self._excluded:
+            if key not in self._excluded and key in self._values:
                 setattr(self._obj, key, self._values[key])
                 del self._sigs[key]
-        self.Destroy()        
+        self.Destroy()
 
     def setval(self, key, x):
-        self._values[key] = x
-        setattr(self._sigs[key], "value", x)
+        if key in self._values:
+            self._values[key] = x
+            setattr(self._sigs[key], "value", x)
+        else:
+            setattr(self._obj, key, x)
+
+    def copy(self, evt):
+        labels = [slider.getCtrlLabel() for slider in self._sliders]
+        values = [slider.GetValue() for slider in self._sliders]
+        if evt.GetId() == 10000:
+            pstr = ""
+            for i in range(len(labels)):
+                pstr += "%s=" % labels[i]
+                if type(values[i]) == list:
+                    pstr += "["
+                    pstr += ", ".join(["%.4f" % val for val in values[i]])
+                    pstr += "]"
+                else:
+                    pstr += "%.4f" % values[i]
+                if i < (len(labels)-1):
+                    pstr += ", "
+        else:
+            pstr = ""
+            for i in range(len(labels)):
+                pstr += "%s=" % labels[i]
+                if type(values[i]) == list:
+                    pstr += "["
+                    pstr += ", ".join([str(val) for val in values[i]])
+                    pstr += "]"
+                else:
+                    pstr += str(values[i])
+                if i < (len(labels)-1):
+                    pstr += ", "
+        data = wx.TextDataObject(pstr)
+        if wx.TheClipboard.Open():
+            wx.TheClipboard.Clear()
+            wx.TheClipboard.SetData(data)
+            wx.TheClipboard.Close()
 
 ######################################################################
 ### View window for PyoTableObject
 ######################################################################
 class ViewTable(wx.Frame):
+
     def __init__(self, parent, samples=None, tableclass=None, object=None):
-        wx.Frame.__init__(self, parent)
-        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
-        menubar = wx.MenuBar()        
+        wx.Frame.__init__(self, parent, size=(500,200))
+        self.SetMinSize((300, 150))
+        menubar = wx.MenuBar()
         fileMenu = wx.Menu()
         closeItem = fileMenu.Append(-1, 'Close\tCtrl+W', kind=wx.ITEM_NORMAL)
         self.Bind(wx.EVT_MENU, self._destroy, closeItem)
@@ -951,103 +1040,161 @@ class ViewTable(wx.Frame):
         self.SetMenuBar(menubar)
         self.tableclass = tableclass
         self.object = object
-        self.Bind(wx.EVT_PAINT, self.OnPaint)
         self.Bind(wx.EVT_CLOSE, self._destroy)
-        self.width, self.height = 500, 200
-        self.half_height = self.height / 2
-        self.SetClientSize((self.width+10, self.height+10))
-        self.SetMinSize(self.GetSize())
-        self.SetMaxSize(self.GetSize())
-        self.draw(samples)
+        self.panel = wx.Panel(self)
+        self.panel.SetBackgroundColour(BACKGROUND_COLOUR)
+        self.box = wx.BoxSizer(wx.VERTICAL)
+        self.wavePanel = ViewTablePanel(self.panel, object)
+        self.box.Add(self.wavePanel, 1, wx.EXPAND|wx.ALL, 5)
+        self.panel.SetSizerAndFit(self.box)
+        self.update(samples)
 
     def update(self, samples):
-        wx.CallAfter(self.draw, samples)
+        self.wavePanel.draw(samples)
 
     def _destroy(self, evt):
         self.object._setViewFrame(None)
         self.Destroy()
-        
-class ViewTable_withPIL(ViewTable):
-    _WITH_PIL = True
-    def __init__(self, parent, samples=None, tableclass=None, object=None):
-        ViewTable.__init__(self, parent, samples, tableclass, object)
 
-    def draw(self, samples):
-        im = Image.new("L", (self.width, self.height), 255)
-        draw = ImageDraw.Draw(im)
-        draw.line(samples, fill=0, width=1)
-        image = wx.EmptyImage(self.width, self.height)
-        image.SetData(im.convert("RGB").tostring())
-        self.img = wx.BitmapFromImage(image)
-        self.Refresh()
+class ViewTablePanel(wx.Panel):
 
-    def OnPaint(self, evt):
-        dc = wx.PaintDC(self)
-        dc.DrawBitmap(self.img, 0, 0)
-        dc.SetPen(wx.Pen('#BBBBBB', width=1, style=wx.SOLID))  
-        dc.DrawLine(0, self.half_height+1, self.width, self.half_height+1)
+    def __init__(self, parent, obj):
+        wx.Panel.__init__(self, parent)
+        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+        self.obj = obj
+        self.samples = []
+        self.Bind(wx.EVT_PAINT, self.OnPaint)
+        self.Bind(wx.EVT_SIZE, self.OnSize)
+        if sys.platform == "win32" or sys.platform.startswith("linux"):
+            self.dcref = wx.BufferedPaintDC
+        else:
+            self.dcref = wx.PaintDC
 
-class ViewTable_withoutPIL(ViewTable):
-    _WITH_PIL = False
-    def __init__(self, parent, samples=None, tableclass=None, object=None):
-        ViewTable.__init__(self, parent, samples, tableclass, object)
-        
     def draw(self, samples):
-        if sys.platform == 'win32':
-            if self.tableclass == 'SndTable':
-                self.samples = [(samples[i], samples[i+1], samples[i+2], samples[i+3]) for i in range(0, len(samples), 4)]
-            else:    
-                self.samples = [(samples[i], samples[i+1]) for i in range(0, len(samples), 2)]
-        else:        
-            self.samples = [(samples[i], samples[i+1], samples[i+2], samples[i+3]) for i in range(0, len(samples), 4)]
-        self.Refresh()
+        self.samples = samples
+        wx.CallAfter(self.Refresh)
 
     def OnPaint(self, evt):
         w,h = self.GetSize()
-        dc = wx.AutoBufferedPaintDC(self)
+        dc = self.dcref(self)
+        gc = wx.GraphicsContext_Create(dc)
         dc.SetBrush(wx.Brush("#FFFFFF"))
+        dc.SetPen(wx.Pen('#BBBBBB', width=1, style=wx.SOLID))
         dc.Clear()
         dc.DrawRectangle(0,0,w,h)
-        if sys.platform == 'win32':
-            if self.tableclass == 'SndTable':
-                dc.DrawLineList(self.samples)
-            else:
-                dc.DrawPointList(self.samples)
-        else:
-            dc.DrawLineList(self.samples)
-        dc.SetPen(wx.Pen('#BBBBBB', width=1, style=wx.SOLID))  
-        dc.DrawLine(0, self.half_height+1, self.width, self.half_height+1)
+        gc.SetPen(wx.Pen('#000000', width=1, style=wx.SOLID))
+        gc.SetBrush(wx.Brush("#FFFFFF"))
+        if len(self.samples) > 1:
+            gc.DrawLines(self.samples)
+        dc.DrawLine(0, h // 2 + 1, w, h // 2 + 1)
+
+    def OnSize(self, evt):
+        wx.CallAfter(self.obj.refreshView)
 
 class SndViewTable(wx.Frame):
+
     def __init__(self, parent, obj=None, tableclass=None, mouse_callback=None):
         wx.Frame.__init__(self, parent, size=(500,250))
-        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
-        self.menubar = wx.MenuBar()        
+        self.SetMinSize((300, 150))
+        self.menubar = wx.MenuBar()
         self.fileMenu = wx.Menu()
         closeItem = self.fileMenu.Append(-1, 'Close\tCtrl+W', kind=wx.ITEM_NORMAL)
         self.Bind(wx.EVT_MENU, self._destroy, closeItem)
         self.menubar.Append(self.fileMenu, "&File")
         self.SetMenuBar(self.menubar)
         self.Bind(wx.EVT_CLOSE, self._destroy)
-        self.Bind(wx.EVT_PAINT, self.OnPaint)
-        self.Bind(wx.EVT_SIZE, self.OnSize)
-        self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
-        self.Bind(wx.EVT_LEFT_UP, self.OnMouseUp)
-        self.Bind(wx.EVT_MOTION, self.OnMotion)
         self.obj = obj
         self.chnls = len(self.obj)
-        self.mouse_callback = mouse_callback
+        self.dur = self.obj.getDur(False)
+        self.panel = wx.Panel(self)
+        self.panel.SetBackgroundColour(BACKGROUND_COLOUR)
+        self.box = wx.BoxSizer(wx.VERTICAL)
+        self.wavePanel = SndViewTablePanel(self.panel, obj, mouse_callback)
+        self.box.Add(self.wavePanel, 1, wx.EXPAND|wx.ALL, 5)
+        self.zoomH = HRangeSlider(self.panel, minvalue=0, maxvalue=1, init=None, pos=(0,0), size=(200,15),
+                 valtype='float', log=False, function=self.setZoomH)
+        self.box.Add(self.zoomH, 0, wx.EXPAND|wx.LEFT|wx.RIGHT, 5)
+        self.panel.SetSizer(self.box)
+
+    def setZoomH(self, values):
+        self.wavePanel.setBegin(self.dur * values[0])
+        self.wavePanel.setEnd(self.dur * values[1])
+        self.update()
 
     def update(self):
-        wx.CallAfter(self.setImage)
+        self.wavePanel.setImage()
 
     def _destroy(self, evt):
         self.obj._setViewFrame(None)
         self.Destroy()
 
-    def OnSize(self, evt):
+class SndViewTablePanel(wx.Panel):
+
+    def __init__(self, parent, obj=None, mouse_callback=None, select_callback=None):
+        wx.Panel.__init__(self, parent)
+        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+        self.Bind(wx.EVT_PAINT, self.OnPaint)
+        self.Bind(wx.EVT_LEFT_DOWN, self.OnMouseDown)
+        self.Bind(wx.EVT_LEFT_UP, self.OnMouseUp)
+        self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
+        self.Bind(wx.EVT_RIGHT_UP, self.OnMouseUp)
+        self.Bind(wx.EVT_MOTION, self.OnMotion)
+        self.Bind(wx.EVT_SIZE, self.OnSize)
+        self.refresh_from_selection = False
+        self.background_bitmap = None
+        self.obj = obj
+        self.selstart = self.selend = self.movepos = None
+        self.moveSelection = False
+        self.createSelection = False
+        self.begin = 0
+        if self.obj is not None:
+            self.chnls = len(self.obj)
+            self.end = self.obj.getDur(False)
+        else:
+            self.chnls = 1
+            self.end = 1.0
+        self.img = [[]]
+        self.mouse_callback = mouse_callback
+        self.select_callback = select_callback
+        if sys.platform == "win32" or sys.platform.startswith("linux"):
+            self.dcref = wx.BufferedPaintDC
+        else:
+            self.dcref = wx.PaintDC
         self.setImage()
+
+    def getDur(self):
+        if self.obj is not None:
+            return self.obj.getDur(False)
+        else:
+            return 1.0
+
+    def resetSelection(self):
+        self.selstart = self.selend = None
+        if self.background_bitmap is not None:
+            self.refresh_from_selection = True
+        self.Refresh()
+        if self.select_callback is not None:
+            self.select_callback((0.0, 1.0))
+
+    def setSelection(self, start, stop):
+        self.selstart = start
+        self.selend = stop
+        if self.background_bitmap is not None:
+            self.refresh_from_selection = True
         self.Refresh()
+        if self.select_callback is not None:
+            self.select_callback((self.selstart, self.selend))
+
+    def setBegin(self, x):
+        self.begin = x
+
+    def setEnd(self, x):
+        self.end = x
+
+    def setImage(self):
+        if self.obj is not None:
+            self.img = self.obj.getViewTable(self.GetSize(), self.begin, self.end)
+            wx.CallAfter(self.Refresh)
 
     def clipPos(self, pos):
         if pos[0] < 0.0: x = 0.0
@@ -1056,116 +1203,171 @@ class SndViewTable(wx.Frame):
         if pos[1] < 0.0: y = 0.0
         elif pos[1] > 1.0: y = 1.0
         else: y = pos[1]
+        if self.obj is not None:
+            x = x * ((self.end - self.begin) / self.obj.getDur(False)) + (self.begin / self.obj.getDur(False))
         return (x, y)
 
     def OnMouseDown(self, evt):
         size = self.GetSize()
         pos = evt.GetPosition()
         if pos[1] <= 0:
-            pos = (float(pos[0])/size[0], 1.0)
+            pos = (float(pos[0]) / size[0], 1.0)
         else:
-            pos = (float(pos[0])/size[0], 1.-(float(pos[1])/size[1]))
+            pos = (float(pos[0]) / size[0], 1. - (float(pos[1]) / size[1]))
         pos = self.clipPos(pos)
-        if self.mouse_callback != None:
+        if self.mouse_callback is not None:
             self.mouse_callback(pos)
         self.CaptureMouse()
 
+    def OnRightDown(self, evt):
+        size = self.GetSize()
+        pos = evt.GetPosition()
+        if pos[1] <= 0:
+            pos = (float(pos[0]) / size[0], 1.0)
+        else:
+            pos = (float(pos[0]) / size[0], 1. - (float(pos[1]) / size[1]))
+        pos = self.clipPos(pos)
+        if evt.ShiftDown():
+            if self.selstart is not None and self.selend is not None:
+                self.moveSelection = True
+                self.movepos = pos[0]
+        elif evt.CmdDown():
+            self.selstart = self.selend = None
+            self.refresh_from_selection = True
+            self.Refresh()
+            if self.select_callback is not None:
+                self.select_callback((0.0, 1.0))
+        else:
+            self.createSelection = True
+            self.selstart = pos[0]
+        self.CaptureMouse()
+
     def OnMotion(self, evt):
         if self.HasCapture():
             size = self.GetSize()
             pos = evt.GetPosition()
             if pos[1] <= 0:
-                pos = (float(pos[0])/size[0], 1.0)
+                pos = (float(pos[0]) / size[0], 1.0)
             else:
-                pos = (float(pos[0])/size[0], 1.-(float(pos[1])/size[1]))
+                pos = (float(pos[0]) / size[0], 1. - (float(pos[1]) / size[1]))
             pos = self.clipPos(pos)
-            if self.mouse_callback != None:
-                self.mouse_callback(pos)
+            if evt.LeftIsDown():
+                if self.mouse_callback is not None:
+                    self.mouse_callback(pos)
+            elif evt.RightIsDown():
+                refresh = False
+                if self.createSelection:
+                    self.selend = pos[0]
+                    refresh = True
+                elif self.moveSelection:
+                    diff = pos[0] - self.movepos
+                    self.movepos = pos[0]
+                    self.selstart += diff
+                    self.selend += diff
+                    refresh = True
+                if refresh:
+                    self.refresh_from_selection = True
+                    self.Refresh()
+                    if self.select_callback is not None:
+                        self.select_callback((self.selstart, self.selend))
 
     def OnMouseUp(self, evt):
         if self.HasCapture():
             self.ReleaseMouse()
+        self.createSelection = self.moveSelection = False
 
-class SndViewTable_withPIL(SndViewTable):
-    def __init__(self, parent, obj=None, tableclass=None, mouse_callback=None):
-        SndViewTable.__init__(self, parent, obj, tableclass, mouse_callback)
-        self.setImage()
-
-    def setImage(self):
-        w, h = self.GetSize()
-        self.img = []
-        imgHeight = h/self.chnls
-        for i in range(self.chnls):
-            im = Image.new("L", (w, imgHeight), 255)
-            draw = ImageDraw.Draw(im)
-            samples = self.obj._base_objs[i].getViewTable((w, imgHeight))
-            draw.line(samples, fill=0, width=1)
-            image = wx.EmptyImage(w, imgHeight)
-            image.SetData(im.convert("RGB").tostring())
-            self.img.append(wx.BitmapFromImage(image))
-        self.Refresh()
+    def create_background(self):
+        w,h = self.GetSize()
+        self.background_bitmap = wx.EmptyBitmap(w, h)
+        dc = wx.MemoryDC(self.background_bitmap)
+        gc = wx.GraphicsContext_Create(dc)
+        dc.SetBrush(wx.Brush("#FFFFFF"))
+        dc.Clear()
+        dc.DrawRectangle(0,0,w,h)
 
-    def OnPaint(self, evt):
-        w, h = self.GetSize()
-        dc = wx.AutoBufferedPaintDC(self)
-        dc.SetPen(wx.Pen('#444444', width=1, style=wx.SHORT_DASH))
-        off = h/self.chnls/2
-        for i, img in enumerate(self.img):
-            y = h/self.chnls*i
-            dc.DrawBitmap(img, 0, y)
+        off = h // self.chnls // 2
+        gc.SetPen(wx.Pen('#000000', width=1, style=wx.SOLID))
+        gc.SetBrush(wx.Brush("#FFFFFF", style=wx.TRANSPARENT))
+        dc.SetTextForeground("#444444")
+        if sys.platform in "darwin":
+            font, ptsize = dc.GetFont(), dc.GetFont().GetPointSize()
+            font.SetPointSize(ptsize - 3)
+            dc.SetFont(font)
+        else:
+            font = dc.GetFont()
+            font.SetPointSize(8)
+            dc.SetFont(font)
+        tickstep = w // 10
+        if tickstep < 40:
+            timelabel = "%.1f"
+        elif tickstep < 80:
+            timelabel = "%.2f"
+        elif tickstep < 120:
+            timelabel = "%.3f"
+        else:
+            timelabel = "%.4f"
+        timestep = (self.end - self.begin) * 0.1
+        for i, samples in enumerate(self.img):
+            y = h // self.chnls * i
+            if len(samples):
+                gc.DrawLines(samples)
+            dc.SetPen(wx.Pen('#888888', width=1, style=wx.DOT))
             dc.DrawLine(0, y+off, w, y+off)
+            for j in range(10):
+                dc.SetPen(wx.Pen('#888888', width=1, style=wx.DOT))
+                dc.DrawLine(j*tickstep, 0, j*tickstep, h)
+                dc.DrawText(timelabel % (self.begin+j*timestep), j*tickstep+2, h-y-12)
+            dc.SetPen(wx.Pen('#000000', width=1))
+            dc.DrawLine(0, h-y, w, h-y)
 
-class SndViewTable_withoutPIL(SndViewTable):
-    def __init__(self, parent, obj=None, tableclass=None, mouse_callback=None):
-        SndViewTable.__init__(self, parent, obj, tableclass, mouse_callback)
-        self.tableclass = tableclass
-        self.setImage()
-
-    def setImage(self):
-        w, h = self.GetSize()
-        self.img = []
-        imgHeight = h/self.chnls
-        for j in range(self.chnls):
-            off = h/self.chnls*j
-            samples = self.obj._base_objs[j].getViewTable((w, imgHeight))
-            if sys.platform == 'win32':
-                if self.tableclass == 'SndTable':
-                    samples = [(samples[i], samples[i+1]+off, samples[i+2], samples[i+3]+off) for i in range(0, len(samples), 4)]
-                else:
-                    samples = [(samples[i], samples[i+1]+off) for i in range(0, len(samples), 2)]
-            else:
-                samples = [(samples[i], samples[i+1]+off, samples[i+2], samples[i+3]+off) for i in range(0, len(samples), 4)]
-            self.img.append(samples)
-        self.Refresh()
+        dc.SelectObject(wx.NullBitmap)
 
     def OnPaint(self, evt):
         w,h = self.GetSize()
-        dc = wx.AutoBufferedPaintDC(self)
+        dc = self.dcref(self)
+        gc = wx.GraphicsContext_Create(dc)
         dc.SetBrush(wx.Brush("#FFFFFF"))
         dc.Clear()
         dc.DrawRectangle(0,0,w,h)
-        off = h/self.chnls/2
-        for i, samples in enumerate(self.img):
-            dc.SetPen(wx.Pen('#000000', width=1, style=wx.SOLID))  
-            y = h/self.chnls*i
-            if sys.platform == 'win32':
-                if self.tableclass == 'SndTable':
-                    dc.DrawLineList(samples)
-                else:
-                    dc.DrawPointList(samples)
+
+        if not self.refresh_from_selection:
+            self.create_background()
+
+        dc.DrawBitmap(self.background_bitmap, 0, 0)
+
+        if self.selstart is not None and self.selend is not None:
+            gc.SetPen(wx.Pen(wx.Colour(0, 0, 0, 64)))
+            gc.SetBrush(wx.Brush(wx.Colour(0, 0, 0, 64)))
+            if self.obj is not None:
+                dur = self.obj.getDur(False)
             else:
-                dc.DrawLineList(samples)
-            dc.SetPen(wx.Pen('#444444', width=1, style=wx.SHORT_DASH))  
-            dc.DrawLine(0, y+off, w, y+off)
+                dur = 1.0
+            selstartabs = min(self.selstart, self.selend) * dur
+            selendabs = max(self.selstart, self.selend) * dur
+            if selstartabs < self.begin:
+                startpix = 0
+            else:
+                startpix = ((selstartabs - self.begin) / (self.end - self.begin)) * w
+            if selendabs > self.end:
+                endpix = w
+            else:
+                endpix = ((selendabs - self.begin) / (self.end - self.begin)) * w
+            gc.DrawRectangle(startpix, 0, endpix - startpix, h)
+
+        self.refresh_from_selection = False
+
+    def OnSize(self, evt):
+        wx.CallAfter(self.setImage)
 
 ######################################################################
 ## View window for PyoMatrixObject
 #####################################################################
-class ViewMatrix(wx.Frame):
+class ViewMatrixBase(wx.Frame):
+
     def __init__(self, parent, size=None, object=None):
         wx.Frame.__init__(self, parent)
         self.object = object
-        self.menubar = wx.MenuBar()        
+        self.menubar = wx.MenuBar()
         self.fileMenu = wx.Menu()
         closeItem = self.fileMenu.Append(-1, 'Close\tCtrl+W', kind=wx.ITEM_NORMAL)
         self.Bind(wx.EVT_MENU, self._destroy, closeItem)
@@ -1178,64 +1380,37 @@ class ViewMatrix(wx.Frame):
         self.SetMaxSize(self.GetSize())
 
     def update(self, samples):
-        wx.CallAfter(self.setImage, samples)
+        self.setImage(samples)
 
     def _destroy(self, evt):
         self.object._setViewFrame(None)
         self.Destroy()
 
-class ViewMatrix_withPIL(ViewMatrix):
-    _WITH_PIL = True
+class ViewMatrix(ViewMatrixBase):
     def __init__(self, parent, samples=None, size=None, object=None):
-        ViewMatrix.__init__(self, parent, size, object)
+        ViewMatrixBase.__init__(self, parent, size, object)
         self.size = size
         self.setImage(samples)
-        
+
     def setImage(self, samples):
-        im = Image.new("L", self.size, None)
-        im.putdata(samples)
         image = wx.EmptyImage(self.size[0], self.size[1])
-        image.SetData(im.convert("RGB").tostring())
+        image.SetData(samples)
         self.img = wx.BitmapFromImage(image)
-        self.Refresh()
+        wx.CallAfter(self.Refresh)
 
     def OnPaint(self, evt):
         dc = wx.PaintDC(self)
         dc.DrawBitmap(self.img, 0, 0)
 
-class ViewMatrix_withoutPIL(ViewMatrix):
-    _WITH_PIL = False
-    def __init__(self, parent, samples=None, size=None, object=None):
-        ViewMatrix.__init__(self, parent, size, object)
-        self.width = size[0]
-        self.height = size[1]
-        self.setImage(samples)
-    
-    def setImage(self, samples):
-        self.samples = samples
-        self.Refresh()
-
-    def OnPaint(self, evt):
-        dc = wx.PaintDC(self)
-        for i in range(self.width*self.height):
-            x = i % self.width
-            y = i / self.width
-            amp = int(self.samples[i])
-            amp = hex(amp).replace('0x', '')
-            if len(amp) == 1:
-                amp = "0%s" % amp
-            amp = "#%s%s%s" % (amp, amp, amp)
-            dc.SetPen(wx.Pen(amp, width=1, style=wx.SOLID))  
-            dc.DrawPoint(x, y)
-
 ######################################################################
 ## Spectrum Display
 ######################################################################
 class SpectrumDisplay(wx.Frame):
+
     def __init__(self, parent, obj=None):
         wx.Frame.__init__(self, parent, size=(600,350))
         self.SetMinSize((400,240))
-        self.menubar = wx.MenuBar()        
+        self.menubar = wx.MenuBar()
         self.fileMenu = wx.Menu()
         closeItem = self.fileMenu.Append(-1, 'Close\tCtrl+W', kind=wx.ITEM_NORMAL)
         self.Bind(wx.EVT_MENU, self._destroy, closeItem)
@@ -1275,7 +1450,7 @@ class SpectrumDisplay(wx.Frame):
         self.magTog = wx.ToggleButton(self.panel, -1, label="Mag Log", size=(tw+X_OFF, th+10))
         self.magTog.SetValue(1)
         self.magTog.Bind(wx.EVT_TOGGLEBUTTON, self.setMagScale)
-        self.toolBox.Add(self.magTog, 0, wx.TOP|wx.LEFT, 5)        
+        self.toolBox.Add(self.magTog, 0, wx.TOP|wx.LEFT, 5)
         tw, th = self.GetTextExtent("Blackman 3-term")
         self.winPopup = wx.Choice(self.panel, -1, choices=["Rectangular", "Hamming", "Hanning", "Bartlett", "Blackman 3-term",
                                     "Blackman-Harris 4-term", "Blackman-Harris 7-term", "Tuckey", "Half-sine"], size=(tw+X_OFF, th+10))
@@ -1294,15 +1469,14 @@ class SpectrumDisplay(wx.Frame):
         self.spectrumPanel = SpectrumPanel(self.panel, len(self.obj), self.obj.getLowfreq(), self.obj.getHighfreq(),
                                             self.obj.getFscaling(), self.obj.getMscaling())
         self.box.Add(self.spectrumPanel, 1, wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, 5)
-        self.zoomH = HRangeSlider(self.panel, minvalue=0, maxvalue=0.5, init=None, pos=(0,0), size=(200,15), 
+        self.zoomH = HRangeSlider(self.panel, minvalue=0, maxvalue=0.5, init=None, pos=(0,0), size=(200,15),
                  valtype='float', log=False, function=self.setZoomH)
         self.box.Add(self.zoomH, 0, wx.EXPAND|wx.LEFT|wx.RIGHT, 5)
         self.dispBox.Add(self.box, 1, wx.EXPAND, 0)
-        self.gainSlider = wx.Slider(self.panel, -1, 0, -24, 24, style=wx.SL_VERTICAL|wx.SL_INVERSE)
-        self.gainSlider.Bind(wx.EVT_SLIDER, self.setGain)
-        self.dispBox.Add(self.gainSlider, 0, wx.EXPAND|wx.BOTTOM, 15)
-        self.dispBox.AddSpacer(5)  
-        self.mainBox.Add(self.dispBox, 1, wx.EXPAND) 
+        self.gainSlider = ControlSlider(self.panel, -24, 24, 0, outFunction=self.setGain, orient=wx.VERTICAL)
+        self.dispBox.Add(self.gainSlider, 0, wx.EXPAND|wx.TOP, 5)
+        self.dispBox.AddSpacer(5)
+        self.mainBox.Add(self.dispBox, 1, wx.EXPAND)
         self.panel.SetSizer(self.mainBox)
 
     def activate(self, evt):
@@ -1334,8 +1508,8 @@ class SpectrumDisplay(wx.Frame):
         size = 1 << (evt.GetInt() + 6)
         self.obj.size = size
 
-    def setGain(self, evt):
-        self.obj.setGain(pow(10.0, evt.GetInt() * 0.05))
+    def setGain(self, gain):
+        self.obj.setGain(pow(10.0, gain * 0.05))
 
     def setZoomH(self, values):
         self.spectrumPanel.setLowFreq(self.obj.setLowbound(values[0]))
@@ -1345,9 +1519,9 @@ class SpectrumDisplay(wx.Frame):
     def setDisplaySize(self, size):
         self.obj.setWidth(size[0])
         self.obj.setHeight(size[1])
-        
+
     def update(self, points):
-        wx.CallAfter(self.spectrumPanel.setImage, points)
+        self.spectrumPanel.setImage(points)
 
     def setFscaling(self, x):
         self.spectrumPanel.setFscaling(x)
@@ -1361,40 +1535,50 @@ class SpectrumDisplay(wx.Frame):
         self.obj._setViewFrame(None)
         self.Destroy()
 
+# TODO: Adjust the font size according to the size of the panel.
 class SpectrumPanel(wx.Panel):
-    def __init__(self, parent, chnls, lowfreq, highfreq, fscaling, mscaling):
-        wx.Panel.__init__(self, parent)
+
+    def __init__(self, parent, chnls, lowfreq, highfreq, fscaling, mscaling,
+                 pos=wx.DefaultPosition, size=wx.DefaultSize, style=0):
+        wx.Panel.__init__(self, parent, pos=pos, size=size, style=style)
         self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
         self.Bind(wx.EVT_PAINT, self.OnPaint)
         self.Bind(wx.EVT_SIZE, self.OnSize)
-        self.chnls = chnls
+        #self.chnls = chnls
         self.img = None
+        self.obj = None
         self.lowfreq = lowfreq
         self.highfreq = highfreq
         self.fscaling = fscaling
         self.mscaling = mscaling
-        if self.chnls == 1:
-            self.pens = [wx.Pen(wx.Colour(100,0,0))]
-            self.brushes = [wx.Brush(wx.Colour(166,4,0))]
-        else:
-            self.pens = [wx.Pen(wx.Colour(166,4,0)), wx.Pen(wx.Colour(8,11,116)), wx.Pen(wx.Colour(0,204,0)),
-                        wx.Pen(wx.Colour(255,167,0)), wx.Pen(wx.Colour(133,0,75)), wx.Pen(wx.Colour(255,236,0)),
-                        wx.Pen(wx.Colour(1,147,154)), wx.Pen(wx.Colour(162,239,0))]
-            self.brushes = [wx.Brush(wx.Colour(166,4,0,128)), wx.Brush(wx.Colour(8,11,116,128)), wx.Brush(wx.Colour(0,204,0,128)),
-                            wx.Brush(wx.Colour(255,167,0,128)), wx.Brush(wx.Colour(133,0,75,128)), wx.Brush(wx.Colour(255,236,0,128)),
-                            wx.Brush(wx.Colour(1,147,154,128)), wx.Brush(wx.Colour(162,239,0,128))]
-        if sys.platform == "win32":
+        self.pens = [wx.Pen(wx.Colour(166,4,0)), wx.Pen(wx.Colour(8,11,116)), wx.Pen(wx.Colour(0,204,0)),
+                    wx.Pen(wx.Colour(255,167,0)), wx.Pen(wx.Colour(133,0,75)), wx.Pen(wx.Colour(255,236,0)),
+                    wx.Pen(wx.Colour(1,147,154)), wx.Pen(wx.Colour(162,239,0))]
+        self.brushes = [wx.Brush(wx.Colour(166,4,0,128)), wx.Brush(wx.Colour(8,11,116,128)), wx.Brush(wx.Colour(0,204,0,128)),
+                        wx.Brush(wx.Colour(255,167,0,128)), wx.Brush(wx.Colour(133,0,75,128)), wx.Brush(wx.Colour(255,236,0,128)),
+                        wx.Brush(wx.Colour(1,147,154,128)), wx.Brush(wx.Colour(162,239,0,128))]
+        if sys.platform == "win32" or sys.platform.startswith("linux"):
             self.dcref = wx.BufferedPaintDC
         else:
             self.dcref = wx.PaintDC
 
     def OnSize(self, evt):
-        self.GetParent().GetParent().setDisplaySize(self.GetSize())
+        try:
+            self.GetParent().GetParent().setDisplaySize(self.GetSize())
+        except:
+            pass
+        try:
+            size = self.GetSize()
+            self.obj.setWidth(size[0])
+            self.obj.setHeight(size[1])
+        except:
+            pass
+
         self.Refresh()
 
     def setImage(self, points):
-        self.img = [points[i] for i in range(self.chnls)]
-        self.Refresh()
+        self.img = [points[i] for i in range(len(points))]
+        wx.CallAfter(self.Refresh)
 
     def setFscaling(self, x):
         self.fscaling = x
@@ -1416,7 +1600,7 @@ class SpectrumPanel(wx.Panel):
 
         # background
         background = gc.CreatePath()
-        background.AddRectangle(0,0,w,h)
+        background.AddRectangle(0,0,w-1,h-1)
         gc.SetPen(wx.BLACK_PEN)
         gc.SetBrush(wx.WHITE_BRUSH)
         gc.DrawPath(background)
@@ -1430,30 +1614,30 @@ class SpectrumPanel(wx.Panel):
             tw, th = dc.GetTextExtent(text)
             step = (self.highfreq - self.lowfreq) / 8
             dc.DrawText(text, 2, 2)
-            w8 = w / 8
+            w8 = w // 8
             for i in range(1,8):
-                pos = w8*i
+                pos = w8 * i
                 dc.DrawLine(pos, th+4, pos, h-2)
-                text = str(int(self.lowfreq+step*i))
+                text = str(int(self.lowfreq + step * i))
                 tw, th = dc.GetTextExtent(text)
-                dc.DrawText(text, pos-tw/2, 2)
+                dc.DrawText(text, pos - tw // 2, 2)
         # frequency logarithmic grid
         else:
             if self.lowfreq < 20:
                 lf = math.log10(20)
             else:
                 lf = math.log10(self.lowfreq)
-            
+
             hf = math.log10(self.highfreq)
             lrange = hf - lf
             mag = pow(10.0, math.floor(lf))
             if lrange > 6:
                 t = pow(10.0, math.ceil(lf))
-                base = pow(10.0, math.floor(lrange/6))
+                base = pow(10.0, math.floor(lrange / 6))
                 def inc(t, floor_t):
                     return t*base-t
             else:
-                t = math.ceil(pow(10.0,lf)/mag)*mag
+                t = math.ceil(pow(10.0, lf) / mag) * mag
                 def inc(t, floor_t):
                     return pow(10.0, floor_t)
 
@@ -1467,18 +1651,18 @@ class SpectrumPanel(wx.Panel):
                     tw, th = dc.GetTextExtent(ticklabel)
                 else:
                     if hf-lf < 2:
-                        minortick = int(t/pow(10.0,majortick)+.5)
-                        ticklabel = '%de%d'%(minortick,majortick)
+                        minortick = int(t / pow(10.0, majortick) + .5)
+                        ticklabel = '%de%d' % (minortick, majortick)
                         ticklabel = str(int(float(ticklabel)))
                         tw, th = dc.GetTextExtent(ticklabel)
                         if not minortick%2 == 0:
                             ticklabel = ''
                     else:
                         ticklabel = ''
-                pos = (math.log10(t) - lf) / lrange * w
+                pos = int((math.log10(t) - lf) / lrange * w)
                 if pos < (w-25):
-                    dc.DrawLine(pos, th+4, pos, h-2)
-                    dc.DrawText(ticklabel, pos-tw/2, 2)
+                    dc.DrawLine(pos, th + 4, pos, h - 2)
+                    dc.DrawText(ticklabel, pos - tw // 2, 2)
                 t += inc(t, floor_t)
 
         # magnitude linear grid
@@ -1489,18 +1673,18 @@ class SpectrumPanel(wx.Panel):
                 pos = int(h - i * step)
                 text = "%.1f" % (i * 0.1)
                 tw, th = dc.GetTextExtent(text)
-                dc.DrawText(text, w-tw-2, pos-th/2)
-                dc.DrawLine(0, pos, w-tw-4, pos)
+                dc.DrawText(text, w - tw - 2, pos - th // 2)
+                dc.DrawLine(0, pos, w - tw - 4, pos)
             dc.SetPen(wx.Pen("#555555", style=wx.SOLID))
-            dc.DrawLine(0, pos, w-tw-6, pos)
+            dc.DrawLine(0, pos, w - tw - 6, pos)
             dc.SetPen(wx.Pen("#555555", style=wx.DOT))
             i += 1
             while (i*step < (h-th-5)):
                 pos = int(h - i * step)
                 text = "%.1f" % (i * 0.1)
                 tw, th = dc.GetTextExtent(text)
-                dc.DrawText(text, w-tw-2, pos-th/2)
-                dc.DrawLine(0, pos, w-tw-6, pos)
+                dc.DrawText(text, w - tw - 2, pos - th // 2)
+                dc.DrawLine(0, pos, w - tw - 6, pos)
                 i += 1
         # magnitude logarithmic grid
         else:
@@ -1514,7 +1698,7 @@ class SpectrumPanel(wx.Panel):
                     mval = 0
                 text = "%d" % mval
                 tw, th = dc.GetTextExtent(text)
-                dc.DrawText(text, w-tw-2, pos-th/2)
+                dc.DrawText(text, w-tw-2, pos - th // 2)
                 dc.DrawLine(0, pos, w-mw-6, pos)
             dc.SetPen(wx.Pen("#555555", style=wx.SOLID))
             dc.DrawLine(0, pos, w-mw-4, pos)
@@ -1524,39 +1708,206 @@ class SpectrumPanel(wx.Panel):
                 pos = int(h - i * step)
                 text = "%d" % int((10-i) * -6.0)
                 tw, th = dc.GetTextExtent(text)
-                dc.DrawText(text, w-tw-2, pos-th/2)
+                dc.DrawText(text, w-tw-2, pos - th // 2)
                 dc.DrawLine(0, pos, w-mw-6, pos)
                 i += 1
 
-        last_tw = tw
-        # legend
-        tw, th = dc.GetTextExtent("chan 8")
-        for i in range(self.chnls):
-            dc.SetTextForeground(self.pens[i].GetColour())
-            dc.DrawText("chan %d" % (i+1), w-tw-20-last_tw, i*th+th+7)
-
         # spectrum
-        if self.img != None:
+        if self.img is not None:
+            last_tw = tw
+            # legend
+            tw, th = dc.GetTextExtent("chan 8")
+            for i in range(len(self.img)):
+                dc.SetTextForeground(self.pens[i%8].GetColour())
+                dc.DrawText("chan %d" % (i+1), w-tw-20-last_tw, i*th+th+7)
+            # channel spectrums
             for i, samples in enumerate(self.img):
-                gc.SetPen(self.pens[i])  
-                gc.SetBrush(self.brushes[i])
+                gc.SetPen(self.pens[i%8])
+                gc.SetBrush(self.brushes[i%8])
+                gc.DrawLines(samples)
+
+######################################################################
+## Spectrum Display
+######################################################################
+class ScopeDisplay(wx.Frame):
+
+    def __init__(self, parent, obj=None):
+        wx.Frame.__init__(self, parent, size=(600,350))
+        self.SetMinSize((400,240))
+        self.menubar = wx.MenuBar()
+        self.fileMenu = wx.Menu()
+        closeItem = self.fileMenu.Append(-1, 'Close\tCtrl+W', kind=wx.ITEM_NORMAL)
+        self.Bind(wx.EVT_MENU, self._destroy, closeItem)
+        self.menubar.Append(self.fileMenu, "&File")
+        self.SetMenuBar(self.menubar)
+        self.Bind(wx.EVT_CLOSE, self._destroy)
+        self.obj = obj
+        gain = self.obj.gain
+        length = self.obj.length
+        self.panel = wx.Panel(self)
+        self.panel.SetBackgroundColour(BACKGROUND_COLOUR)
+        self.mainBox = wx.BoxSizer(wx.VERTICAL)
+        self.toolBox = wx.BoxSizer(wx.HORIZONTAL)
+        if sys.platform == "darwin":
+            X_OFF = 24
+        else:
+            X_OFF = 16
+        tw, th = self.GetTextExtent("Start")
+        self.activeTog = wx.ToggleButton(self.panel, -1, label="Start", size=(tw+X_OFF, th+10))
+        self.activeTog.SetValue(1)
+        self.activeTog.Bind(wx.EVT_TOGGLEBUTTON, self.activate)
+        self.toolBox.Add(self.activeTog, 0, wx.TOP|wx.LEFT|wx.RIGHT, 5)
+        self.toolBox.AddSpacer(10)
+        self.toolBox.Add(wx.StaticText(self.panel, -1, label="Window length (ms):"), 0, wx.TOP, 11)
+        self.lenSlider = ControlSlider(self.panel, 10, 1000, length * 1000, log=True, outFunction=self.setLength)
+        self.toolBox.Add(self.lenSlider, 1, wx.TOP|wx.LEFT|wx.RIGHT, 11)
+        self.toolBox.AddSpacer(40)
+        self.mainBox.Add(self.toolBox, 0, wx.EXPAND)
+        self.dispBox = wx.BoxSizer(wx.HORIZONTAL)
+        self.box = wx.BoxSizer(wx.VERTICAL)
+        self.scopePanel = ScopePanel(self.panel, self.obj)
+        self.box.Add(self.scopePanel, 1, wx.EXPAND|wx.LEFT|wx.RIGHT, 5)
+        self.dispBox.Add(self.box, 1, wx.EXPAND|wx.BOTTOM, 5)
+        self.gainSlider = ControlSlider(self.panel, -24, 24, 20.0 * math.log10(gain), outFunction=self.setGain, orient=wx.VERTICAL)
+        self.dispBox.Add(self.gainSlider, 0, wx.EXPAND|wx.BOTTOM, 5)
+        self.dispBox.AddSpacer(5)
+        self.mainBox.Add(self.dispBox, 1, wx.EXPAND)
+        self.panel.SetSizer(self.mainBox)
+
+    def activate(self, evt):
+        self.obj.poll(evt.GetInt())
+
+    def setLength(self, length):
+        length *= 0.001
+        self.obj.setLength(length)
+        self.scopePanel.setLength(length)
+
+    def setGain(self, gain):
+        gain = pow(10.0, gain * 0.05)
+        self.scopePanel.setGain(gain)
+        self.obj.setGain(gain)
+
+    def update(self, points):
+        self.scopePanel.setImage(points)
+
+    def _destroy(self, evt):
+        self.obj._setViewFrame(None)
+        self.Destroy()
+
+class ScopePanel(wx.Panel):
+
+    def __init__(self, parent, obj=None, pos=wx.DefaultPosition,
+                 size=wx.DefaultSize, style=0):
+        wx.Panel.__init__(self, parent, pos=pos, size=size, style=style)
+        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
+        self.Bind(wx.EVT_PAINT, self.OnPaint)
+        self.Bind(wx.EVT_SIZE, self.OnSize)
+        self.img = [[]]
+        self.obj = obj
+        if self.obj is not None:
+            self.gain = self.obj.gain
+            self.length = self.obj.length
+        else:
+            self.gain = 1
+            self.length = 0.05
+        #self.chnls = len(self.obj)
+        self.pens = [wx.Pen(wx.Colour(166,4,0), width=2), wx.Pen(wx.Colour(8,11,116), width=2), wx.Pen(wx.Colour(0,204,0), width=2),
+                    wx.Pen(wx.Colour(255,167,0), width=2), wx.Pen(wx.Colour(133,0,75), width=2), wx.Pen(wx.Colour(255,236,0), width=2),
+                    wx.Pen(wx.Colour(1,147,154), width=2), wx.Pen(wx.Colour(162,239,0), width=2)]
+
+        if sys.platform == "win32" or sys.platform.startswith("linux"):
+            self.dcref = wx.BufferedPaintDC
+        else:
+            self.dcref = wx.PaintDC
+
+    def OnSize(self, evt):
+        try:
+            size = self.GetSize()
+            self.obj.setWidth(size[0])
+            self.obj.setHeight(size[1])
+        except:
+            pass
+        wx.CallAfter(self.Refresh)
+
+    def setGain(self, gain):
+        self.gain = gain
+
+    def setLength(self, length):
+        self.length = length
+
+    def setImage(self, points):
+        self.img = points
+        wx.CallAfter(self.Refresh)
+
+    def OnPaint(self, evt):
+        w,h = self.GetSize()
+        dc = self.dcref(self)
+        gc = wx.GraphicsContext_Create(dc)
+        tw, th = dc.GetTextExtent("0")
+        dc.SetBrush(wx.Brush("#FFFFFF"))
+        dc.Clear()
+        dc.DrawRectangle(0,0,w,h)
+        gc.SetPen(wx.Pen('#000000', width=1, style=wx.SOLID))
+        gc.SetBrush(wx.Brush("#FFFFFF", style=wx.TRANSPARENT))
+        dc.SetTextForeground("#444444")
+        if sys.platform in "darwin":
+            font, ptsize = dc.GetFont(), dc.GetFont().GetPointSize()
+            font.SetPointSize(ptsize - 3)
+            dc.SetFont(font)
+        elif sys.platform == "win32":
+            font = dc.GetFont()
+            font.SetPointSize(8)
+            dc.SetFont(font)
+
+        dc.SetPen(wx.Pen('#888888', width=1, style=wx.DOT))
+        # horizontal grid
+        step = h // 6
+        ampstep = 1.0 / 3.0 / self.gain
+        for i in range(1, 6):
+            pos = int(h - i * step)
+            npos = i - 3
+            text = "%.2f" % (ampstep * npos)
+            tw, th = dc.GetTextExtent(text)
+            dc.DrawText(text, w-tw-2, pos - th // 2)
+            dc.DrawLine(0, pos, w-tw-10, pos)
+
+        # vertical grid
+        tickstep = w // 4
+        timestep = self.length * 0.25
+        for j in range(4):
+            dc.SetPen(wx.Pen('#888888', width=1, style=wx.DOT))
+            dc.DrawLine(j*tickstep, 0, j*tickstep, h)
+            dc.DrawText("%.3f" % (j*timestep), j*tickstep+2, h-15)
+        # draw waveforms
+        for i, samples in enumerate(self.img):
+            gc.SetPen(self.pens[i%8])
+            if len(samples):
                 gc.DrawLines(samples)
 
+        # legend
+        last_tw = tw
+        tw, th = dc.GetTextExtent("chan 8")
+        for i in range(len(self.img)):
+            dc.SetTextForeground(self.pens[i%8].GetColour())
+            dc.DrawText("chan %d" % (i+1), w-tw-20-last_tw, i*th+10)
+
 ######################################################################
 ## Grapher window for PyoTableObject control
 ######################################################################
-OFF = 15
+OFF = 10
 OFF2 = OFF*2
 RAD = 3
 RAD2 = RAD*2
 AREA = RAD+2
 AREA2 = AREA*2
 class Grapher(wx.Panel):
-    def __init__(self, parent, xlen=8192, yrange=(0.0, 1.0), init=[(0.0,0.0),(1.0,1.0)], mode=0, 
-                 exp=10.0, inverse=True, tension=0.0, bias=0.0, outFunction=None): 
-        wx.Panel.__init__(self, parent, size=(500,250), style=wx.SUNKEN_BORDER)
+
+    def __init__(self, parent, xlen=8192, yrange=(0.0, 1.0), init=[(0.0,0.0),(1.0,1.0)], mode=0,
+                 exp=10.0, inverse=True, tension=0.0, bias=0.0, outFunction=None, pos=(0, 0),
+                 size=(300, 200), style=0):
+        wx.Panel.__init__(self, parent, pos=pos, size=size, style=style)
         self.backgroundColour = BACKGROUND_COLOUR
-        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)  
+        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
         self.SetBackgroundColour(self.backgroundColour)
         self.Bind(wx.EVT_LEAVE_WINDOW, self.OnLeave)
         self.Bind(wx.EVT_PAINT, self.OnPaint)
@@ -1576,15 +1927,22 @@ class Grapher(wx.Panel):
         self.xlen = xlen
         self.yrange = yrange
         self.init = [tup for tup in init]
-        self.points = init
+        self.points = [tup for tup in init]
         self.outFunction = outFunction
-        
+
+        if sys.platform == "win32" or sys.platform.startswith("linux"):
+            self.dcref = wx.BufferedPaintDC
+        else:
+            self.dcref = wx.PaintDC
+
         self.SetFocus()
+        wx.CallAfter(self.sendValues)
 
     def setInitPoints(self, pts):
         self.init = [(p[0],p[1]) for p in pts]
         self.points = [(p[0],p[1]) for p in pts]
         self.selected = None
+        self.sendValues()
         self.Refresh()
 
     def pointToPixels(self, pt):
@@ -1603,11 +1961,16 @@ class Grapher(wx.Panel):
 
     def pointToValues(self, pt):
         x = pt[0] * self.xlen
-        if type(self.xlen) == IntType:
+        if type(self.xlen) == int:
             x = int(x)
         y = pt[1] * (self.yrange[1]-self.yrange[0]) + self.yrange[0]
         return x, y
 
+    def valuesToPoint(self, val):
+        x = val[0] / float(self.xlen)
+        y = (val[1] - self.yrange[0]) / float(self.yrange[1]-self.yrange[0])
+        return x, y
+
     def borderClip(self, pos):
         w,h = self.GetSize()
         if pos[0] < (OFF+RAD): pos[0] = (OFF+RAD)
@@ -1625,7 +1988,7 @@ class Grapher(wx.Panel):
             leftclip = x
         if self.selected == (len(self.points) - 1):
             rightclip = w-OFF-RAD
-        else:    
+        else:
             x,y = self.pointToPixels(self.points[self.selected+1])
             rightclip = x
 
@@ -1636,7 +1999,7 @@ class Grapher(wx.Panel):
         return pos
 
     def reset(self):
-        self.points = self.init
+        self.points = [tup for tup in self.init]
         self.Refresh()
 
     def getPoints(self):
@@ -1650,7 +2013,7 @@ class Grapher(wx.Panel):
         return values
 
     def sendValues(self):
-        if self.outFunction != None:
+        if self.outFunction is not None:
             values = self.getValues()
             self.outFunction(values)
 
@@ -1663,7 +2026,7 @@ class Grapher(wx.Panel):
         self.Refresh()
 
     def OnKeyDown(self, evt):
-        if self.selected != None and evt.GetKeyCode() in [wx.WXK_BACK, wx.WXK_DELETE, wx.WXK_NUMPAD_DELETE]:
+        if self.selected is not None and evt.GetKeyCode() in [wx.WXK_BACK, wx.WXK_DELETE, wx.WXK_NUMPAD_DELETE]:
             del self.points[self.selected]
             self.sendValues()
             self.selected = None
@@ -1676,6 +2039,7 @@ class Grapher(wx.Panel):
             self.points = [(pt[0], pt[1]-0.002) for pt in self.points]
             self.sendValues()
             self.Refresh()
+        evt.Skip()
 
     def MouseDown(self, evt):
         self.CaptureMouse()
@@ -1699,7 +2063,7 @@ class Grapher(wx.Panel):
         self.Refresh()
 
     def MouseUp(self, evt):
-        if self.HasCapture(): 
+        if self.HasCapture():
             self.ReleaseMouse()
             self.sendValues()
 
@@ -1708,13 +2072,13 @@ class Grapher(wx.Panel):
         self.pos = self.borderClip(evt.GetPosition())
         self.pos[1] = h - self.pos[1]
         if self.HasCapture():
-            if self.selected != None:
+            if self.selected is not None:
                 self.pos = self.pointClip(self.pos)
                 x, y = self.pixelsToPoint(self.pos)
                 if self.mode == 4 and y <= 0:
                     y = 0.000001
                 self.points[self.selected] = (x, y)
-        self.Refresh()
+            self.Refresh()
 
     def getLogPoints(self, pt1, pt2):
         tmp = []
@@ -1728,7 +2092,7 @@ class Grapher(wx.Panel):
         else:
             low = pt1[1]
             high = pt2[1]
-        
+
         steps = pt2[0] - pt1[0]
         if steps > 0:
             lrange = high - low
@@ -1782,7 +2146,7 @@ class Grapher(wx.Panel):
             mu = float(i) / steps
             mu2 = (1. - math.cos(mu*math.pi)) * 0.5
             tmp.append((pt1[0]+i, pt1[1] * (1. - mu2) + pt2[1] * mu2))
-        return tmp    
+        return tmp
 
     def getExpPoints(self, pt1, pt2):
         tmp = []
@@ -1845,12 +2209,15 @@ class Grapher(wx.Panel):
             a2 = mu3 - mu2
             a3 = -2.0 * mu3 + 3.0 * mu2
             tmp.append((pt1[0]+i, a0*y1 + a1*m0 + a2*m1 + a3*y2))
-        return tmp    
-        
+        return tmp
+
     def OnPaint(self, evt):
         w,h = self.GetSize()
         corners = [(OFF,OFF),(w-OFF,OFF),(w-OFF,h-OFF),(OFF,h-OFF)]
-        dc = wx.AutoBufferedPaintDC(self)
+        dc = self.dcref(self)
+        gc = wx.GraphicsContext_Create(dc)
+        gc.SetBrush(wx.Brush("#000000"))
+        gc.SetPen(wx.Pen("#000000"))
         if sys.platform == "darwin":
             font, ptsize = dc.GetFont(), dc.GetFont().GetPointSize()
         else:
@@ -1862,31 +2229,31 @@ class Grapher(wx.Panel):
 
         # Draw grid
         dc.SetPen(wx.Pen("#CCCCCC", 1))
-        xstep = int(round((w-OFF2) / float(10)))
-        ystep = int(round((h-OFF2) / float(10)))
+        xstep = int(round((w-OFF2) / 10.0))
+        ystep = int(round((h-OFF2) / 10.0))
         for i in range(10):
             xpos = i * xstep + OFF
             dc.DrawLine(xpos, OFF, xpos, h-OFF)
             ypos = i * ystep + OFF
             dc.DrawLine(OFF, ypos, w-OFF, ypos)
             if i > 0:
-                if type(self.xlen) == IntType:
+                if type(self.xlen) == int:
                     t = "%d" % int(self.xlen * i * 0.1)
                 else:
                     t = "%.2f" % (self.xlen * i * 0.1)
                 dc.DrawText(t, xpos+2, h-OFF-10)
             if i < 9:
-                t = "%.2f" % ((9-i) * 0.1 * (self.yrange[1]-self.yrange[0]) + self.yrange[0])    
-                dc.DrawText(t, OFF+1, ypos+ystep-10)
+                t = "%.2f" % ((9-i) * 0.1 * (self.yrange[1]-self.yrange[0]) + self.yrange[0])
+                dc.DrawText(t, OFF+2, ypos+ystep-10)
             else:
-                t = "%.2f" % ((9-i) * 0.1 * (self.yrange[1]-self.yrange[0]) + self.yrange[0])    
-                dc.DrawText(t, OFF+1, h-OFF-10)
+                t = "%.2f" % ((9-i) * 0.1 * (self.yrange[1]-self.yrange[0]) + self.yrange[0])
+                dc.DrawText(t, OFF+2, h-OFF-10)
 
         dc.SetPen(wx.Pen("#000000", 1))
         dc.SetBrush(wx.Brush("#000000"))
-        # Draw bounding box        
+        # Draw bounding box
         for i in range(4):
-            dc.DrawLinePoint(corners[i], corners[(i+1)%4])
+            dc.DrawLine(corners[i][0], corners[i][1], corners[(i+1)%4][0], corners[(i+1)%4][1])
 
         # Convert points in pixels
         w,h = w-OFF2-RAD2, h-OFF2-RAD2
@@ -1904,44 +2271,44 @@ class Grapher(wx.Panel):
         if len(tmp) > 1:
             if self.mode == 0:
                 for i in range(len(tmp)-1):
-                    dc.DrawLinePoint(tmp[i], tmp[i+1])
+                    gc.DrawLines([tmp[i], tmp[i+1]])
             elif self.mode == 1:
                 for i in range(len(tmp)-1):
                     tmp2 = self.getCosPoints(tmp[i], tmp[i+1])
                     if i == 0 and len(tmp2) < 2:
-                        dc.DrawLinePoint(tmp[i], tmp[i+1])
-                    if last_p != None:
-                        dc.DrawLinePoint(last_p, tmp[i])
+                        gc.DrawLines([tmp[i], tmp[i+1]])
+                    if last_p is not None:
+                        gc.DrawLines([last_p, tmp[i]])
                     for j in range(len(tmp2)-1):
-                        dc.DrawLinePoint(tmp2[j], tmp2[j+1])
+                        gc.DrawLines([tmp2[j], tmp2[j+1]])
                         last_p = tmp2[j+1]
-                if last_p != None:
-                    dc.DrawLinePoint(last_p, tmp[-1])
+                if last_p is not None:
+                    gc.DrawLines([last_p, tmp[-1]])
             elif self.mode == 2:
                 for i in range(len(tmp)-1):
                     tmp2 = self.getExpPoints(tmp[i], tmp[i+1])
                     if i == 0 and len(tmp2) < 2:
-                        dc.DrawLinePoint(tmp[i], tmp[i+1])
-                    if last_p != None:
-                        dc.DrawLinePoint(last_p, tmp[i])
+                        gc.DrawLines([tmp[i], tmp[i+1]])
+                    if last_p is not None:
+                        gc.DrawLines([last_p, tmp[i]])
                     for j in range(len(tmp2)-1):
-                        dc.DrawLinePoint(tmp2[j], tmp2[j+1])
+                        gc.DrawLines([tmp2[j], tmp2[j+1]])
                         last_p = tmp2[j+1]
-                if last_p != None:
-                    dc.DrawLinePoint(last_p, tmp[-1])
+                if last_p is not None:
+                    gc.DrawLines([last_p, tmp[-1]])
             elif self.mode == 3:
                 curvetmp = self.addImaginaryPoints(tmp)
                 for i in range(1, len(curvetmp)-2):
                     tmp2 = self.getCurvePoints(curvetmp[i-1], curvetmp[i], curvetmp[i+1], curvetmp[i+2])
                     if i == 1 and len(tmp2) < 2:
-                        dc.DrawLinePoint(curvetmp[i], curvetmp[i+1])
-                    if last_p != None:
-                        dc.DrawLinePoint(last_p, curvetmp[i])
+                        gc.DrawLines([curvetmp[i], curvetmp[i+1]])
+                    if last_p is not None:
+                        gc.DrawLines([last_p, curvetmp[i]])
                     for j in range(len(tmp2)-1):
-                        dc.DrawLinePoint(tmp2[j], tmp2[j+1])
+                        gc.DrawLines([tmp2[j], tmp2[j+1]])
                         last_p = tmp2[j+1]
-                if last_p != None:
-                    dc.DrawLinePoint(last_p, tmp[-1])
+                if last_p is not None:
+                    gc.DrawLines([last_p, tmp[-1]])
             elif self.mode == 4:
                 back_tmp = [p for p in tmp]
                 for i in range(len(tmp)):
@@ -1951,14 +2318,14 @@ class Grapher(wx.Panel):
                     for j in range(len(tmp2)):
                         tmp2[j] = (tmp2[j][0], int(round((1.0-tmp2[j][1]) * h)) + OFF + RAD)
                     if i == 0 and len(tmp2) < 2:
-                        dc.DrawLinePoint(back_tmp[i], back_tmp[i+1])
-                    if last_p != None:
-                        dc.DrawLinePoint(last_p, back_tmp[i])
+                        gc.DrawLines([back_tmp[i], back_tmp[i+1]])
+                    if last_p is not None:
+                        gc.DrawLines([last_p, back_tmp[i]])
                     for j in range(len(tmp2)-1):
-                        dc.DrawLinePoint(tmp2[j], tmp2[j+1])
+                        gc.DrawLines([tmp2[j], tmp2[j+1]])
                         last_p = tmp2[j+1]
-                if last_p != None:
-                    dc.DrawLinePoint(last_p, back_tmp[-1])
+                if last_p is not None:
+                    gc.DrawLines([last_p, back_tmp[-1]])
                 tmp = [p for p in back_tmp]
             elif self.mode == 5:
                 back_tmp = [p for p in tmp]
@@ -1969,36 +2336,39 @@ class Grapher(wx.Panel):
                     for j in range(len(tmp2)):
                         tmp2[j] = (tmp2[j][0], int(round((1.0-tmp2[j][1]) * h)) + OFF + RAD)
                     if i == 0 and len(tmp2) < 2:
-                        dc.DrawLinePoint(back_tmp[i], back_tmp[i+1])
-                    if last_p != None:
-                        dc.DrawLinePoint(last_p, back_tmp[i])
+                        gc.DrawLines([back_tmp[i], back_tmp[i+1]])
+                    if last_p is not None:
+                        gc.DrawLines([last_p, back_tmp[i]])
                     for j in range(len(tmp2)-1):
-                        dc.DrawLinePoint(tmp2[j], tmp2[j+1])
+                        gc.DrawLines([tmp2[j], tmp2[j+1]])
                         last_p = tmp2[j+1]
-                if last_p != None:
-                    dc.DrawLinePoint(last_p, back_tmp[-1])
+                if last_p is not None:
+                    gc.DrawLines([last_p, back_tmp[-1]])
                 tmp = [p for p in back_tmp]
 
         # Draw points
         for i,p in enumerate(tmp):
             if i == self.selected:
+                gc.SetBrush(wx.Brush("#FFFFFF"))
                 dc.SetBrush(wx.Brush("#FFFFFF"))
             else:
+                gc.SetBrush(wx.Brush("#000000"))
                 dc.SetBrush(wx.Brush("#000000"))
-            dc.DrawCircle(p[0],p[1],RAD)
-        
+            gc.DrawEllipse(p[0]-RAD,p[1]-RAD,RAD2,RAD2)
+
         # Draw position values
         font.SetPointSize(ptsize-3)
         dc.SetFont(font)
         dc.SetTextForeground("#222222")
         posptx, pospty = self.pixelsToPoint(self.pos)
         xval, yval = self.pointToValues((posptx, pospty))
-        if type(self.xlen) == IntType:
+        if type(self.xlen) == int:
             dc.DrawText("%d, %.3f" % (xval, yval), w-75, OFF)
         else:
             dc.DrawText("%.3f, %.3f" % (xval, yval), w-75, OFF)
 
 class TableGrapher(wx.Frame):
+
     def __init__(self, parent=None, obj=None, mode=0, xlen=8192, yrange=(0.0, 1.0)):
         wx.Frame.__init__(self, parent, size=(500,250))
         pts = obj.getPoints()
@@ -2014,7 +2384,7 @@ class TableGrapher(wx.Frame):
         else:
             self.graph = Grapher(self, xlen=xlen, yrange=yrange, init=pts, mode=mode, outFunction=obj.replace)
 
-        self.menubar = wx.MenuBar()        
+        self.menubar = wx.MenuBar()
         self.fileMenu = wx.Menu()
         self.fileMenu.Append(9999, 'Close\tCtrl+W', kind=wx.ITEM_NORMAL)
         self.Bind(wx.EVT_MENU, self.close, id=9999)
@@ -2038,16 +2408,16 @@ class TableGrapher(wx.Frame):
             pstr = "["
             for i, pt in enumerate(pts):
                 pstr += "("
-                if type(pt[0]) == IntType:
+                if type(pt[0]) == int:
                     pstr += "%d," % pt[0]
                 else:
                     pstr += "%.4f," % pt[0]
                 pstr += "%.4f)" % pt[1]
                 if i < (len(pts)-1):
                     pstr += ","
-            pstr += "]" 
+            pstr += "]"
         else:
-            pstr = str(pts)           
+            pstr = str(pts)
         data = wx.TextDataObject(pstr)
         if wx.TheClipboard.Open():
             wx.TheClipboard.Clear()
@@ -2058,29 +2428,41 @@ class TableGrapher(wx.Frame):
         self.graph.reset()
 
 class DataMultiSlider(wx.Panel):
-    def __init__(self, parent, init, yrange=(0,1), outFunction=None): 
-        wx.Panel.__init__(self, parent, size=(250,250), style=wx.SUNKEN_BORDER)
+
+    def __init__(self, parent, init, yrange=(0,1), outFunction=None,
+                pos=(0, 0), size=(300, 200), style=0):
+        wx.Panel.__init__(self, parent, pos=pos, size=size, style=style)
         self.backgroundColour = BACKGROUND_COLOUR
-        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)  
+        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
         self.SetBackgroundColour(self.backgroundColour)
         self.Bind(wx.EVT_SIZE, self.OnResize)
         self.Bind(wx.EVT_PAINT, self.OnPaint)
         self.Bind(wx.EVT_LEFT_DOWN, self.MouseDown)
         self.Bind(wx.EVT_LEFT_UP, self.MouseUp)
         self.Bind(wx.EVT_MOTION, self.MouseMotion)
-        self.values = init
+        self.changed = True
+        self.values = [v for v in init]
         self.len = len(self.values)
-        self.yrange = yrange
+        self.yrange = (float(yrange[0]), float(yrange[1]))
         self.outFunction = outFunction
-        if sys.platform == "win32":
+
+        if sys.platform == "win32" or sys.platform.startswith("linux"):
             self.dcref = wx.BufferedPaintDC
         else:
             self.dcref = wx.PaintDC
 
     def OnResize(self, event):
         self.Layout()
-        self.Refresh()
-        
+        wx.CallAfter(self.Refresh)
+
+    def update(self, points):
+        self.values = points
+        self.changed = True
+        wx.CallAfter(self.Refresh)
+
+    def getValues(self):
+        return self.values
+
     def OnPaint(self, event):
         w,h = self.GetSize()
         dc = self.dcref(self)
@@ -2113,7 +2495,8 @@ class DataMultiSlider(wx.Panel):
         points.append((w,y))
         points.append((w,h))
         gc.DrawLines(points)
-        if self.outFunction != None:
+        if self.outFunction is not None and self.changed:
+            self.changed = False
             self.outFunction(self.values)
 
     def MouseDown(self, evt):
@@ -2126,7 +2509,8 @@ class DataMultiSlider(wx.Panel):
         x = int(pos[0] / bw)
         y = (h - pos[1]) / float(h) * scl + mini
         self.values[x] = y
-        self.Refresh()
+        self.changed = True
+        wx.CallAfter(self.Refresh)
         evt.Skip()
 
     def MouseUp(self, evt):
@@ -2156,43 +2540,338 @@ class DataMultiSlider(wx.Panel):
             if step > 1:
                 inc = (y2 - y1) / step
                 if x2 > x1:
-                    for i in range(0, step): 
+                    for i in range(0, step):
                         self.values[x1+i] = y1 + inc * i
                 else:
-                    for i in range(1, step): 
+                    for i in range(1, step):
                         self.values[x1-i] = y1 + inc * i
             if x2 >= 0 and x2 < self.len:
-                self.values[x2] = y2                    
+                self.values[x2] = y2
             self.lastpos = pos
-            self.Refresh()
+            self.changed = True
+            wx.CallAfter(self.Refresh)
 
 class DataTableGrapher(wx.Frame):
+
     def __init__(self, parent=None, obj=None, yrange=(0.0, 1.0)):
         wx.Frame.__init__(self, parent, size=(500,250))
         self.obj = obj
-        self.multi = DataMultiSlider(self, self.obj.getTable(), yrange, outFunction=self.obj.replace)
-        self.menubar = wx.MenuBar()        
+        self.length = len(self.obj._get_current_data())
+        self.multi = DataMultiSlider(self, self.obj._get_current_data(), yrange, outFunction=self.obj.replace)
+        self.menubar = wx.MenuBar()
         self.fileMenu = wx.Menu()
         self.fileMenu.Append(9999, 'Close\tCtrl+W', kind=wx.ITEM_NORMAL)
         self.Bind(wx.EVT_MENU, self.close, id=9999)
+        self.fileMenu.AppendSeparator()
+        self.fileMenu.Append(10000, 'Copy all points to the clipboard (4 digits of precision)\tCtrl+C', kind=wx.ITEM_NORMAL)
+        self.Bind(wx.EVT_MENU, self.copy, id=10000)
+        self.fileMenu.Append(10001, 'Copy all points to the clipboard (full precision)\tShift+Ctrl+C', kind=wx.ITEM_NORMAL)
+        self.Bind(wx.EVT_MENU, self.copy, id=10001)
         self.menubar.Append(self.fileMenu, "&File")
         self.SetMenuBar(self.menubar)
 
+    def getLength(self):
+        return self.length
+
+    def close(self, evt):
+        self.Destroy()
+
+    def update(self, samples):
+        self.multi.update(samples)
+
+    def copy(self, evt):
+        values = self.multi.getValues()
+        if evt.GetId() == 10000:
+            pstr = "["
+            for i, val in enumerate(values):
+                pstr += "%.4f" % val
+                if i < (len(values)-1):
+                    pstr += ", "
+            pstr += "]"
+        else:
+            pstr = str(values)
+        data = wx.TextDataObject(pstr)
+        if wx.TheClipboard.Open():
+            wx.TheClipboard.Clear()
+            wx.TheClipboard.SetData(data)
+            wx.TheClipboard.Close()
+
+class ExprLexer(object):
+    """Defines simple interface for custom lexer objects."""
+    STC_EXPR_DEFAULT, STC_EXPR_KEYWORD, STC_EXPR_KEYWORD2, STC_EXPR_COMMENT, \
+    STC_EXPR_VARIABLE, STC_EXPR_LETVARIABLE = list(range(6))
+    def __init__(self):
+        super(ExprLexer, self).__init__()
+
+        self.alpha = "abcdefghijklmnopqrstuvwxyz"
+        self.digits = "0123456789"
+        self.keywords = ["sin", "cos", "tan", "tanh", "atan", "atan2", "sqrt", "log",
+                         "log2", "log10", "pow", "abs", "floor", "ceil", "exp", "round",
+                         "min", "max", "randf", "randi", "sah", "count", "pi", "twopi",
+                         "e", "if", "rpole", "rzero", "neg", "and", "or", "wrap"]
+        self.keywords2 = ["define", "load", "var", "let"]
+
+    def StyleText(self, evt):
+        """Handle the EVT_STC_STYLENEEDED event."""
+        stc = evt.GetEventObject()
+        last_styled_pos = stc.GetEndStyled()
+        line = stc.LineFromPosition(last_styled_pos)
+        start_pos = stc.PositionFromLine(line)
+        end_pos = evt.GetPosition()
+        var = letvar = False
+        while start_pos < end_pos:
+            stc.StartStyling(start_pos, 0x1f)
+            curchar = chr(stc.GetCharAt(start_pos))
+            if curchar == "$":
+                var = True
+            elif var and curchar in " \t\n()":
+                var = False
+            if curchar == "#":
+                letvar = True
+            elif letvar and curchar in " \t\n()":
+                letvar = False
+
+            if var:
+                style = self.STC_EXPR_VARIABLE
+                stc.SetStyling(1, style)
+                start_pos += 1
+            elif letvar:
+                style = self.STC_EXPR_LETVARIABLE
+                stc.SetStyling(1, style)
+                start_pos += 1
+            elif curchar in self.alpha:
+                start = stc.WordStartPosition(start_pos, True)
+                end = stc.WordEndPosition(start, True)
+                word = stc.GetTextRange(start, end)
+                if word in self.keywords:
+                    style = self.STC_EXPR_KEYWORD
+                    stc.SetStyling(len(word), style)
+                elif word in self.keywords2:
+                    style = self.STC_EXPR_KEYWORD2
+                    stc.SetStyling(len(word), style)
+                else:
+                    style = self.STC_EXPR_DEFAULT
+                    stc.SetStyling(len(word), style)
+                start_pos += len(word)
+            elif curchar == "/" and chr(stc.GetCharAt(start_pos+1)) == "/":
+                eol = stc.GetLineEndPosition(stc.LineFromPosition(start_pos))
+                style = self.STC_EXPR_COMMENT
+                stc.SetStyling(eol-start_pos, style)
+                start_pos = eol
+            else:
+                style = self.STC_EXPR_DEFAULT
+                stc.SetStyling(1, style)
+                start_pos += 1
+
+class ExprEditor(stc.StyledTextCtrl):
+
+    def __init__(self, parent, id=-1, obj=None):
+        stc.StyledTextCtrl.__init__(self, parent, id)
+
+        self.obj = obj
+
+        if sys.platform == "darwin":
+            accel_ctrl = wx.ACCEL_CMD
+            self.faces = {'mono' : 'Monospace', 'size' : 16}
+        else:
+            accel_ctrl = wx.ACCEL_CTRL
+            self.faces = {'mono' : 'Monospace', 'size' : 10}
+
+        atable = wx.AcceleratorTable([(accel_ctrl, wx.WXK_RETURN, 10000),
+                                      (accel_ctrl, ord("z"), wx.ID_UNDO),
+                                      (accel_ctrl|wx.ACCEL_SHIFT, ord("z"), wx.ID_REDO)])
+        self.SetAcceleratorTable(atable)
+
+        self.Bind(wx.EVT_MENU, self.onExecute, id=10000)
+        self.Bind(wx.EVT_MENU, self.undo, id=wx.ID_UNDO)
+        self.Bind(wx.EVT_MENU, self.redo, id=wx.ID_REDO)
+        self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
+
+        self.lexer = ExprLexer()
+
+        self.currentfile = ""
+        self.modified = False
+
+        self.setup()
+        self.setCmdKeys()
+        self.setStyle()
+
+        self.SetText(self.obj.expr)
+
+    def undo(self, evt):
+        self.Undo()
+
+    def redo(self, evt):
+        self.Redo()
+
+    def setup(self):
+        self.SetIndent(2)
+        self.SetBackSpaceUnIndents(True)
+        self.SetTabIndents(True)
+        self.SetTabWidth(2)
+        self.SetUseTabs(False)
+        self.SetMargins(2, 2)
+        self.SetMarginWidth(1, 1)
+
+    def setCmdKeys(self):
+        self.CmdKeyAssign(ord('='), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
+        self.CmdKeyAssign(ord('-'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
+
+    def setStyle(self):
+        self.SetLexer(wx.stc.STC_LEX_CONTAINER)
+        self.SetStyleBits(5)
+        self.Bind(wx.stc.EVT_STC_STYLENEEDED, self.OnStyling)
+
+        self.SetCaretForeground("#000000")
+        self.SetCaretWidth(2)
+        # Global default styles for all languages
+        self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % self.faces)
+        self.StyleClearAll()
+
+        self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % self.faces)
+        self.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "face:%(mono)s" % self.faces)
+        self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, "fore:#FFFFFF,back:#0000FF,bold")
+        self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, "fore:#000000,back:#FF0000,bold")
+
+        # Expr specific styles
+        self.StyleSetSpec(self.lexer.STC_EXPR_DEFAULT, "fore:#000000,face:%(mono)s,size:%(size)d" % self.faces)
+        self.StyleSetSpec(self.lexer.STC_EXPR_KEYWORD, "fore:#3300DD,face:%(mono)s,size:%(size)d,bold" % self.faces)
+        self.StyleSetSpec(self.lexer.STC_EXPR_KEYWORD2, "fore:#0033FF,face:%(mono)s,size:%(size)d,bold" % self.faces)
+        self.StyleSetSpec(self.lexer.STC_EXPR_VARIABLE, "fore:#006600,face:%(mono)s,size:%(size)d,bold" % self.faces)
+        self.StyleSetSpec(self.lexer.STC_EXPR_LETVARIABLE, "fore:#555500,face:%(mono)s,size:%(size)d,bold" % self.faces)
+        self.StyleSetSpec(self.lexer.STC_EXPR_COMMENT, "fore:#444444,face:%(mono)s,size:%(size)d,italic" % self.faces)
+
+        self.SetSelBackground(1, "#CCCCDD")
+
+    def OnStyling(self, evt):
+        self.lexer.StyleText(evt)
+
+    def loadfile(self, filename):
+        self.LoadFile(filename)
+        self.currentfile = filename
+        self.GetParent().SetTitle(self.currentfile)
+
+    def savefile(self, filename):
+        self.currentfile = filename
+        self.GetParent().SetTitle(self.currentfile)
+        self.SaveFile(filename)
+        self.OnUpdateUI(None)
+
+    def OnUpdateUI(self, evt):
+        # check for matching braces
+        braceAtCaret = -1
+        braceOpposite = -1
+        charBefore = None
+        caretPos = self.GetCurrentPos()
+
+        if caretPos > 0:
+            charBefore = self.GetCharAt(caretPos - 1)
+            styleBefore = self.GetStyleAt(caretPos - 1)
+
+        # check before
+        if charBefore and chr(charBefore) in "[]{}()":
+            braceAtCaret = caretPos - 1
+
+        # check after
+        if braceAtCaret < 0:
+            charAfter = self.GetCharAt(caretPos)
+            styleAfter = self.GetStyleAt(caretPos)
+
+            if charAfter and chr(charAfter) in "[]{}()":
+                braceAtCaret = caretPos
+        if braceAtCaret >= 0:
+            braceOpposite = self.BraceMatch(braceAtCaret)
+
+        if braceAtCaret != -1 and braceOpposite == -1:
+            self.BraceBadLight(braceAtCaret)
+        else:
+            self.BraceHighlight(braceAtCaret, braceOpposite)
+        # Check if horizontal scrollbar is needed
+        self.checkScrollbar()
+
+    def checkScrollbar(self):
+        lineslength = [self.LineLength(i)+1 for i in range(self.GetLineCount())]
+        maxlength = max(lineslength)
+        width = self.GetCharWidth() + (self.GetZoom() * 0.5)
+        if (self.GetSize()[0]) < (maxlength * width):
+            self.SetUseHorizontalScrollBar(True)
+        else:
+            self.SetUseHorizontalScrollBar(False)
+
+    def onExecute(self, evt):
+        pos = self.GetCurrentPos()
+        self.obj.expr = self.GetText()
+        self.SetCurrentPos(pos)
+        self.SetSelection(pos, pos)
+
+class ExprEditorFrame(wx.Frame):
+
+    def __init__(self, parent=None, obj=None):
+        wx.Frame.__init__(self, parent, size=(500,350))
+        self.obj = obj
+        self.obj._editor = self
+        self.editor = ExprEditor(self, -1, self.obj)
+        self.menubar = wx.MenuBar()
+        self.fileMenu = wx.Menu()
+        self.fileMenu.Append(wx.ID_OPEN, "Open\tCtrl+O")
+        self.Bind(wx.EVT_MENU, self.open, id=wx.ID_OPEN)
+        self.fileMenu.Append(wx.ID_CLOSE, 'Close\tCtrl+W', kind=wx.ITEM_NORMAL)
+        self.Bind(wx.EVT_MENU, self.close, id=wx.ID_CLOSE)
+        self.fileMenu.AppendSeparator()
+        self.fileMenu.Append(wx.ID_SAVE, "Save\tCtrl+S")
+        self.Bind(wx.EVT_MENU, self.save, id=wx.ID_SAVE)
+        self.fileMenu.Append(wx.ID_SAVEAS, "Save As...\tShift+Ctrl+S")
+        self.Bind(wx.EVT_MENU, self.saveas, id=wx.ID_SAVEAS)
+        self.menubar.Append(self.fileMenu, "&File")
+        self.SetMenuBar(self.menubar)
+
+    def open(self, evt):
+        dlg = wx.FileDialog(self, message="Choose a file",
+                            defaultDir=os.path.expanduser("~"),
+                            defaultFile="", style=wx.OPEN)
+        if dlg.ShowModal() == wx.ID_OK:
+            path = ensureNFD(dlg.GetPath())
+            self.editor.loadfile(path)
+        dlg.Destroy()
+
     def close(self, evt):
+        self.obj._editor = None
         self.Destroy()
 
+    def save(self, evt):
+        path = self.editor.currentfile
+        if not path:
+            self.saveas(None)
+        else:
+            self.editor.savefile(path)
+
+    def saveas(self, evt):
+        deffile = os.path.split(self.editor.currentfile)[1]
+        dlg = wx.FileDialog(self, message="Save file as ...",
+                            defaultDir=os.path.expanduser("~"),
+                            defaultFile=deffile, style=wx.SAVE)
+        dlg.SetFilterIndex(0)
+        if dlg.ShowModal() == wx.ID_OK:
+            path = ensureNFD(dlg.GetPath())
+            self.editor.savefile(path)
+        dlg.Destroy()
+
+    def update(self, text):
+        self.editor.SetText(text)
+
 class ServerGUI(wx.Frame):
-    def __init__(self, parent=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.):
-        wx.Frame.__init__(self, parent)
 
-        self.SetTitle("pyo server")
-        
+    def __init__(self, parent=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.,
+                exit=True):
+        wx.Frame.__init__(self, parent, style=wx.DEFAULT_FRAME_STYLE ^ wx.RESIZE_BORDER)
+
         self.menubar = wx.MenuBar()
         self.menu = wx.Menu()
         self.menu.Append(22999, 'Start/Stop\tCtrl+R', kind=wx.ITEM_NORMAL)
         self.Bind(wx.EVT_MENU, self.start, id=22999)
-        quit_item = self.menu.Append(wx.ID_EXIT, "Quit\tCtrl+Q")  
+        quit_item = self.menu.Append(wx.ID_EXIT, "Quit\tCtrl+Q")
         self.Bind(wx.EVT_MENU, self.on_quit, id=wx.ID_EXIT)
         self.menubar.Append(self.menu, "&File")
         self.SetMenuBar(self.menubar)
@@ -2205,6 +2884,7 @@ class ServerGUI(wx.Frame):
         self.recstartf = recstartf
         self.recstopf = recstopf
         self.ampf = ampf
+        self.exit = exit
         self._started = False
         self._recstarted = False
         self._history = []
@@ -2237,10 +2917,10 @@ class ServerGUI(wx.Frame):
 
         box.Add(wx.StaticText(panel, -1, "Amplitude (dB)"), 0, wx.LEFT, leftMargin)
         ampBox = wx.BoxSizer(wx.HORIZONTAL)
-        self.ampScale = ControlSlider(panel, -60, 18, 20.0 * math.log10(amp), size=(203, 16), outFunction=self.setAmp)
+        self.ampScale = ControlSlider(panel, -60, 18, 20.0 * math.log10(amp), size=(202, 16), outFunction=self.setAmp)
         ampBox.Add(self.ampScale, 0, wx.LEFT, leftMargin-10)
         box.Add(ampBox, 0, wx.LEFT | wx.RIGHT, 8)
-        
+
         if meter:
             box.AddSpacer(10)
             self.meter = VuMeter(panel, size=(200,5*self.nchnls+1), numSliders=self.nchnls)
@@ -2249,60 +2929,72 @@ class ServerGUI(wx.Frame):
 
         if timer:
             box.AddSpacer(10)
-            tt = wx.StaticText(panel, -1, "Elapsed time (hh : mm : ss : ms)")
+            tt = wx.StaticText(panel, -1, "Elapsed time (hh:mm:ss:ms)")
             box.Add(tt, 0, wx.LEFT, leftMargin)
             box.AddSpacer(3)
             self.timetext = wx.StaticText(panel, -1, "00 : 00 : 00 : 000")
             box.Add(self.timetext, 0, wx.LEFT, leftMargin)
 
-        if self.locals != None:
+        if self.locals is not None:
             box.AddSpacer(10)
             t = wx.StaticText(panel, -1, "Interpreter")
             box.Add(t, 0, wx.LEFT, leftMargin)
-            self.text = wx.TextCtrl(panel, -1, "", size=(200, -1), style=wx.TE_PROCESS_ENTER)
+            tw, th = self.GetTextExtent("|")
+            self.text = wx.TextCtrl(panel, -1, "", size=(202, th+8), style=wx.TE_PROCESS_ENTER)
             self.text.Bind(wx.EVT_TEXT_ENTER, self.getText)
             self.text.Bind(wx.EVT_CHAR, self.onChar)
-            box.Add(self.text, 0, wx.LEFT, leftMargin)
+            box.Add(self.text, 0, wx.LEFT, leftMargin-1)
 
         box.AddSpacer(10)
         panel.SetSizerAndFit(box)
         self.SetClientSize(panel.GetSize())
-        self.SetMinSize(self.GetSize())
-        self.SetMaxSize(self.GetSize())
+
+        self.Bind(wx.EVT_CLOSE, self.on_quit)
 
         if started == 1:
             self.start(None, True)
 
     def setTime(self, *args):
         wx.CallAfter(self.timetext.SetLabel, "%02d : %02d : %02d : %03d" % (args[0], args[1], args[2], args[3]))
-        
+
     def start(self, evt=None, justSet=False):
         if self._started == False:
+            self._started = True
+            wx.CallAfter(self.startButton.SetLabel, 'Stop')
+            if self.exit:
+                wx.CallAfter(self.quitButton.Disable)
             if not justSet:
                 self.startf()
-            self._started = True
-            self.startButton.SetLabel('Stop')
-            self.quitButton.Disable()
         else:
-            self.stopf()
             self._started = False
-            self.startButton.SetLabel('Start')
-            self.quitButton.Enable()
+            wx.CallAfter(self.startButton.SetLabel, 'Start')
+            if self.exit:
+                wx.CallAfter(self.quitButton.Enable)
+            # TODO: Need a common method for every OSes.
+            #wx.CallLater(100, self.stopf)
+            #wx.CallAfter(self.stopf)
+            self.stopf()
 
     def record(self, evt):
         if self._recstarted == False:
             self.recstartf()
             self._recstarted = True
-            self.recButton.SetLabel('Rec Stop')
+            wx.CallAfter(self.recButton.SetLabel, 'Rec Stop')
         else:
             self.recstopf()
             self._recstarted = False
-            self.recButton.SetLabel('Rec Start')
+            wx.CallAfter(self.recButton.SetLabel, 'Rec Start')
+
+    def quit_from_code(self):
+        wx.CallAfter(self.on_quit, None)
 
     def on_quit(self, evt):
-        self.shutdown()
+        if self.exit:
+            self.shutdown()
+            time.sleep(0.25)
         self.Destroy()
-        sys.exit()
+        if self.exit:
+            sys.exit()
 
     def getPrev(self):
         self.text.Clear()
@@ -2317,24 +3009,27 @@ class ServerGUI(wx.Frame):
         self._histo_count += 1
         if self._histo_count >= len(self._history):
             self._histo_count = len(self._history)
-        else:    
+        else:
             self.text.SetValue(self._history[self._histo_count])
-            self.text.SetInsertionPointEnd()
+            wx.CallAfter(self.text.SetInsertionPointEnd)
 
     def getText(self, evt):
         source = self.text.GetValue()
         self.text.Clear()
         self._history.append(source)
         self._histo_count = len(self._history)
-        exec source in self.locals
+        exec(source, self.locals)
 
     def onChar(self, evt):
         key = evt.GetKeyCode()
         if key == 315:
             self.getPrev()
+            evt.StopPropagation()
         elif key == 317:
-            self.getNext()  
-        evt.Skip()      
+            self.getNext()
+            evt.StopPropagation()
+        else:
+            evt.Skip()
 
     def setAmp(self, value):
         self.ampf(math.pow(10.0, float(value) * 0.05))
@@ -2342,12 +3037,40 @@ class ServerGUI(wx.Frame):
     def setRms(self, *args):
         self.meter.setRms(*args)
 
-if __name__ == "__main__":
-    def pprint(values):
-        print values
-
-    app = wx.App(False)
-    values = [random.uniform(10, 25) for i in range(10)]
-    f = DataTableGrapher(init=values, yrange=(2, 50))
-    f.Show()
-    app.MainLoop()
+    def setStartButtonState(self, state):
+        if state:
+            self._started = True
+            wx.CallAfter(self.startButton.SetLabel, 'Stop')
+            if self.exit:
+                wx.CallAfter(self.quitButton.Disable)
+        else:
+            self._started = False
+            wx.CallAfter(self.startButton.SetLabel, 'Start')
+            if self.exit:
+                wx.CallAfter(self.quitButton.Enable)
+
+def ensureNFD(unistr):
+    if sys.platform == 'win32' or sys.platform.startswith('linux'):
+        encodings = [sys.getdefaultencoding(), sys.getfilesystemencoding(),
+                     'cp1252', 'iso-8859-1', 'utf-16']
+        format = 'NFC'
+    else:
+        encodings = [sys.getdefaultencoding(), sys.getfilesystemencoding(),
+                     'macroman', 'iso-8859-1', 'utf-16']
+        format = 'NFC'
+    decstr = unistr
+    if type(decstr) != unicode_t:
+        for encoding in encodings:
+            try:
+                decstr = decstr.decode(encoding)
+                break
+            except UnicodeDecodeError:
+                continue
+            except:
+                decstr = "UnableToDecodeString"
+                print("Unicode encoding not in a recognized format...")
+                break
+    if decstr == "UnableToDecodeString":
+        return unistr
+    else:
+        return unicodedata.normalize(format, decstr)
diff --git a/pyolib/analysis.py b/pyolib/analysis.py
index ffcdc53..4189cbf 100644
--- a/pyolib/analysis.py
+++ b/pyolib/analysis.py
@@ -1,55 +1,63 @@
+from __future__ import division
+from __future__ import absolute_import
 """
 Tools to analyze audio signals.
 
 These objects are designed to retrieve specific informations
-from an audio stream. Analysis are sent at audio rate, user 
+from an audio stream. Analysis are sent at audio rate, user
 can use them for controlling parameters of others objects.
 
 """
 
 """
-Copyright 2010 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+You should have received a copy of the GNU Lesser General Public
+License along with pyo.  If not, see <http://www.gnu.org/licenses/>.
 """
 
-from _core import *
-from _maps import *
+from ._core import *
+from ._maps import *
+from ._widgets import createSpectrumWindow, createScopeWindow
+from .pattern import Pattern
 
 class Follower(PyoObject):
     """
     Envelope follower.
-    
+
     Output signal is the continuous mean amplitude of an input signal.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
-    
-        input : PyoObject
+
+        input: PyoObject
             Input signal to process.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Cutoff frequency of the filter in hertz. Default to 20.
 
     .. note::
 
-        The out() method is bypassed. Follower's signal can not be sent to 
+        The out() method is bypassed. Follower's signal can not be sent to
         audio outs.
-    
+
+    .. seealso::
+
+        :py:class:`Follower2`, :py:class: `Balance`
+
     >>> s = Server().boot()
     >>> s.start()
     >>> sf = SfPlayer(SNDS_PATH + "/transparent.aif", loop=True, mul=.4).out()
@@ -58,38 +66,42 @@ class Follower(PyoObject):
 
     """
     def __init__(self, input, freq=20, mul=1, add=0):
+        pyoArgsAssert(self, "oOOO", input, freq, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._freq = freq
         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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
-        
+
     def setFreq(self, x):
         """
         Replace the `freq` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `freq` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -100,7 +112,7 @@ class Follower(PyoObject):
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMap(1., 500., 'log', 'freq', self._freq)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
-      
+
     @property
     def input(self):
         """PyoObject. Input signal to process."""
@@ -125,18 +137,22 @@ class Follower2(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        risetime : float or PyoObject, optional
+        risetime: float or PyoObject, optional
             Time to reach upward value in seconds. Default to 0.01.
-        falltime : float or PyoObject, optional
+        falltime: float or PyoObject, optional
             Time to reach downward value in seconds. Default to 0.1.
 
     .. note::
 
-        The out() method is bypassed. Follower's signal can not be sent to 
+        The out() method is bypassed. Follower's signal can not be sent to
         audio outs.
 
+    .. seealso::
+
+        :py:class:`Follower`, :py:class: `Balance`
+
     >>> s = Server().boot()
     >>> s.start()
     >>> sf = SfPlayer(SNDS_PATH + "/transparent.aif", loop=True, mul=.4).out()
@@ -145,6 +161,7 @@ class Follower2(PyoObject):
 
     """
     def __init__(self, input, risetime=0.01, falltime=0.1, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOO", input, risetime, falltime, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._risetime = risetime
@@ -152,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):
         """
@@ -159,12 +177,13 @@ class Follower2(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
@@ -174,10 +193,11 @@ class Follower2(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `risetime` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._risetime = x
         x, lmax = convertArgsToLists(x)
         [obj.setRisetime(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -188,10 +208,11 @@ class Follower2(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `falltime` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._falltime = x
         x, lmax = convertArgsToLists(x)
         [obj.setFalltime(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -205,21 +226,21 @@ class Follower2(PyoObject):
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def risetime(self):
-        """float or PyoObject. Time to reach upward value in seconds.""" 
+        """float or PyoObject. Time to reach upward value in seconds."""
         return self._risetime
     @risetime.setter
     def risetime(self, x): self.setRisetime(x)
 
     @property
     def falltime(self):
-        """float or PyoObject. Time to reach downward value in seconds.""" 
+        """float or PyoObject. Time to reach downward value in seconds."""
         return self._falltime
     @falltime.setter
     def falltime(self, x): self.setFalltime(x)
@@ -227,26 +248,26 @@ class Follower2(PyoObject):
 class ZCross(PyoObject):
     """
     Zero-crossing counter.
-    
-    Output signal is the number of zero-crossing occured during each 
+
+    Output signal is the number of zero-crossing occured during each
     buffer size, normalized between 0 and 1.
- 
+
     :Parent: :py:class:`PyoObject`
-   
+
     :Args:
-    
-        input : PyoObject
+
+        input: PyoObject
             Input signal to process.
-        thresh : float, optional
-            Minimum amplitude difference allowed between adjacent samples 
+        thresh: float, optional
+            Minimum amplitude difference allowed between adjacent samples
             to be included in the zeros count.
 
     .. note::
 
-        The out() method is bypassed. ZCross's signal can not be sent to 
+        The out() method is bypassed. ZCross's signal can not be sent to
         audio outs.
-    
-    >>> s = Server(duplex=1).boot()
+
+    >>> s = Server().boot()
     >>> s.start()
     >>> a = SfPlayer(SNDS_PATH + "/transparent.aif", loop=True, mul=.4).out()
     >>> b = ZCross(a, thresh=.02)
@@ -254,55 +275,63 @@ class ZCross(PyoObject):
 
     """
     def __init__(self, input, thresh=0., mul=1, add=0):
+        pyoArgsAssert(self, "onOO", input, thresh, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._thresh = thresh
         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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     def setThresh(self, x):
         """
         Replace the `thresh` attribute.
-        
+
         :Args:
 
-            x : float
+            x: float
                 New amplitude difference threshold.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._thresh = x
         x, lmax = convertArgsToLists(x)
         [obj.setThresh(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
-     
+
+    def ctrl(self, map_list=None, title=None, wxnoserver=False):
+        self._map_list = [SLMap(0., 0.5, 'lin', 'thresh', self._thresh)]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def thresh(self):
-        """float. Amplitude difference threshold.""" 
+        """float. Amplitude difference threshold."""
         return self._thresh
     @thresh.setter
     def thresh(self, x): self.setThresh(x)
@@ -310,41 +339,41 @@ class ZCross(PyoObject):
 class Yin(PyoObject):
     """
     Pitch tracker using the Yin algorithm.
-    
+
     Pitch tracker using the Yin algorithm based on the implementation in C of aubio.
     This algorithm was developped by A. de Cheveigne and H. Kawahara and published in
-    
+
     de Cheveigne, A., Kawahara, H. (2002) 'YIN, a fundamental frequency estimator for
     speech and music', J. Acoust. Soc. Am. 111, 1917-1930.
-    
+
     The audio output of the object is the estimated frequency, in Hz, of the input sound.
- 
+
     :Parent: :py:class:`PyoObject`
-   
+
     :Args:
-    
-        input : PyoObject
+
+        input: PyoObject
             Input signal to process.
-        tolerance : float, optional
+        tolerance: float, optional
             Parameter for minima selection, between 0 and 1. Defaults to 0.2.
-        minfreq : float, optional
-            Minimum estimated frequency in Hz. Frequency below this threshold will 
+        minfreq: float, optional
+            Minimum estimated frequency in Hz. Frequency below this threshold will
             be ignored. Defaults to 40.
-        maxfreq : float, optional
-            Maximum estimated frequency in Hz. Frequency above this threshold will 
+        maxfreq: float, optional
+            Maximum estimated frequency in Hz. Frequency above this threshold will
             be ignored. Defaults to 1000.
-        cutoff : float, optional
+        cutoff: float, optional
             Cutoff frequency, in Hz, of the lowpass filter applied on the input sound.
             Defaults to 1000.
-            
+
             The lowpass filter helps the algorithm to detect the fundamental frequency by filtering
-            higher harmonics. 
-        winsize : int, optional
+            higher harmonics.
+        winsize: int, optional
             Size, in samples, of the analysis window. Must be higher that two period
             of the lowest desired frequency.
-            
+
             Available at initialization time only.  Defaults to 1024.
-            
+
 
     >>> s = Server(duplex=1).boot()
     >>> s.start()
@@ -357,6 +386,7 @@ class Yin(PyoObject):
 
     """
     def __init__(self, input, tolerance=0.2, minfreq=40, maxfreq=1000, cutoff=1000, winsize=1024, mul=1, add=0):
+        pyoArgsAssert(self, "onnnniOO", input, tolerance, minfreq, maxfreq, cutoff, winsize, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._tolerance = tolerance
@@ -366,32 +396,35 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     def setTolerance(self, x):
         """
         Replace the `tolerance` attribute.
-        
+
         :Args:
 
-            x : float
+            x: float
                 New parameter for minima selection, between 0 and 1.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._tolerance = x
         x, lmax = convertArgsToLists(x)
         [obj.setTolerance(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -399,13 +432,14 @@ class Yin(PyoObject):
     def setMinfreq(self, x):
         """
         Replace the `minfreq` attribute.
-        
+
         :Args:
 
-            x : float
+            x: float
                 New minimum frequency detected.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._minfreq = x
         x, lmax = convertArgsToLists(x)
         [obj.setMinfreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -413,13 +447,14 @@ class Yin(PyoObject):
     def setMaxfreq(self, x):
         """
         Replace the `maxfreq` attribute.
-        
+
         :Args:
 
-            x : float
+            x: float
                 New maximum frequency detected.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._maxfreq = x
         x, lmax = convertArgsToLists(x)
         [obj.setMaxfreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -427,51 +462,1144 @@ class Yin(PyoObject):
     def setCutoff(self, x):
         """
         Replace the `cutoff` attribute.
-        
-        :Args: 
 
-            x : float
+        :Args:
+
+            x: float
                 New input lowpass filter cutoff frequency.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._cutoff = x
         x, lmax = convertArgsToLists(x)
         [obj.setCutoff(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
-     
+
+    def ctrl(self, map_list=None, title=None, wxnoserver=False):
+        self._map_list = [SLMap(0, 1, 'lin', 'tolerance', self._tolerance, dataOnly=True),
+                          SLMap(20, 400, 'log', 'minfreq', self._minfreq, dataOnly=True),
+                          SLMap(500, 5000, 'log', 'maxfreq', self._maxfreq, dataOnly=True),
+                          SLMap(200, 15000, 'log', 'cutoff', self._cutoff, dataOnly=True)]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def tolerance(self):
-        """float. Parameter for minima selection.""" 
+        """float. Parameter for minima selection."""
         return self._tolerance
     @tolerance.setter
     def tolerance(self, x): self.setTolerance(x)
 
     @property
     def minfreq(self):
-        """float. Minimum frequency detected.""" 
+        """float. Minimum frequency detected."""
         return self._minfreq
     @minfreq.setter
     def minfreq(self, x): self.setMinfreq(x)
 
     @property
     def maxfreq(self):
-        """float. Maximum frequency detected.""" 
+        """float. Maximum frequency detected."""
         return self._maxfreq
     @maxfreq.setter
     def maxfreq(self, x): self.setMaxfreq(x)
 
     @property
     def cutoff(self):
-        """float. Input lowpass filter cutoff frequency.""" 
+        """float. Input lowpass filter cutoff frequency."""
+        return self._cutoff
+    @cutoff.setter
+    def cutoff(self, x): self.setCutoff(x)
+
+class Centroid(PyoObject):
+    """
+    Computes the spectral centroid of an input signal.
+
+    Output signal is the spectral centroid, in Hz, of the input signal.
+    It indicates where the "center of mass" of the spectrum is. Perceptually,
+    it has a robust connection with the impression of "brightness" of a sound.
+
+    Centroid does its computation with two overlaps, so a new output value
+    comes every half of the FFT window size.
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        input: PyoObject
+            Input signal to process.
+        size: int, optional
+            Size, as a power-of-two, of the FFT used to compute the centroid.
+
+            Available at initialization time only.  Defaults to 1024.
+
+
+    .. note::
+
+        The out() method is bypassed. Centroid's signal can not be sent to
+        audio outs.
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> a = SfPlayer(SNDS_PATH + "/transparent.aif", loop=True, mul=.4).out()
+    >>> b = Centroid(a, 1024)
+    >>> c = Port(b, 0.05, 0.05)
+    >>> d = ButBP(Noise(0.2), freq=c, q=5).out(1)
+
+    """
+    def __init__(self, input, size=1024, mul=1, add=0):
+        pyoArgsAssert(self, "oiOO", input, size, mul, add)
+        PyoObject.__init__(self, mul, add)
+        self._input = input
+        self._size = size
+        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):
+        """
+        Replace the `input` attribute.
+
+        :Args:
+
+            x: PyoObject
+                New signal to process.
+            fadetime: float, optional
+                Crossfade time between old and new input. Default to 0.05.
+
+        """
+        pyoArgsAssert(self, "oN", x, fadetime)
+        self._input = x
+        self._in_fader.setInput(x, fadetime)
+
+    def out(self, chnl=0, inc=1, dur=0, delay=0):
+        return self.play(dur, delay)
+
+    def ctrl(self, map_list=None, title=None, wxnoserver=False):
+        self._map_list = []
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
+    @property
+    def input(self):
+        """PyoObject. Input signal to process."""
+        return self._input
+    @input.setter
+    def input(self, x): self.setInput(x)
+
+class AttackDetector(PyoObject):
+    """
+    Audio signal onset detection.
+
+    AttackDetector analyses an audio signal in input and output a trigger each
+    time an onset is detected. An onset is a sharp amplitude rising while the
+    signal had previously fall below a minimum threshold. Parameters must be
+    carefully tuned depending on the nature of the analysed signal and the level
+    of the background noise.
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        input: PyoObject
+            Input signal to process.
+        deltime: float, optional
+            Delay time, in seconds, between previous and current rms analysis to compare.
+            Defaults to 0.005.
+        cutoff: float, optional
+            Cutoff frequency, in Hz, of the amplitude follower's lowpass filter.
+            Defaults to 10.
+
+            Higher values are more responsive and also more likely to give false onsets.
+        maxthresh: float, optional
+            Attack threshold in positive dB (current rms must be higher than previous
+            rms + maxthresh to be reported as an attack). Defaults to 3.0.
+        minthresh: float, optional
+            Minimum threshold in dB (signal must fall below this threshold to allow
+            a new attack to be detected). Defaults to -30.0.
+        reltime: float, optional
+            Time, in seconds, to wait before reporting a new attack. Defaults to 0.1.
+
+
+    >>> s = Server(duplex=1).boot()
+    >>> s.start()
+    >>> a = Input()
+    >>> d = AttackDetector(a, deltime=0.005, cutoff=10, maxthresh=4, minthresh=-20, reltime=0.05)
+    >>> exc = TrigEnv(d, HannTable(), dur=0.005, mul=BrownNoise(0.3))
+    >>> wgs = Waveguide(exc, freq=[100,200.1,300.3,400.5], dur=30).out()
+
+    """
+    def __init__(self, input, deltime=0.005, cutoff=10, maxthresh=3, minthresh=-30, reltime=0.1, mul=1, add=0):
+        pyoArgsAssert(self, "onnnnnOO", input, deltime, cutoff, maxthresh, minthresh, reltime, mul, add)
+        PyoObject.__init__(self, mul, add)
+        self._input = input
+        self._deltime = deltime
+        self._cutoff = cutoff
+        self._maxthresh = maxthresh
+        self._minthresh = minthresh
+        self._reltime = reltime
+        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):
+        """
+        Replace the `input` attribute.
+
+        :Args:
+
+            x: PyoObject
+                New signal to process.
+            fadetime: float, optional
+                Crossfade time between old and new input. Default to 0.05.
+
+        """
+        pyoArgsAssert(self, "oN", x, fadetime)
+        self._input = x
+        self._in_fader.setInput(x, fadetime)
+
+    def setDeltime(self, x):
+        """
+        Replace the `deltime` attribute.
+
+        :Args:
+
+            x: float
+                New delay between rms analysis.
+
+        """
+        pyoArgsAssert(self, "n", x)
+        self._deltime = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setDeltime(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def setCutoff(self, x):
+        """
+        Replace the `cutoff` attribute.
+
+        :Args:
+
+            x: float
+                New cutoff for the follower lowpass filter.
+
+        """
+        pyoArgsAssert(self, "n", x)
+        self._cutoff = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setCutoff(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def setMaxthresh(self, x):
+        """
+        Replace the `maxthresh` attribute.
+
+        :Args:
+
+            x: float
+                New attack threshold in dB.
+
+        """
+        pyoArgsAssert(self, "n", x)
+        self._maxthresh = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setMaxthresh(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def setMinthresh(self, x):
+        """
+        Replace the `minthresh` attribute.
+
+        :Args:
+
+            x: float
+                New minimum threshold in dB.
+
+        """
+        pyoArgsAssert(self, "n", x)
+        self._minthresh = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setMinthresh(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def setReltime(self, x):
+        """
+        Replace the `reltime` attribute.
+
+        :Args:
+
+            x: float
+                Time, in seconds, to wait before reporting a new attack.
+
+        """
+        pyoArgsAssert(self, "n", x)
+        self._reltime = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setReltime(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def readyToDetect(self):
+        """
+        Initializes variables in the ready state to detect an attack.
+
+        """
+        [obj.readyToDetect() for obj in self._base_objs]
+
+    def out(self, chnl=0, inc=1, dur=0, delay=0):
+        return self.play(dur, delay)
+
+    def ctrl(self, map_list=None, title=None, wxnoserver=False):
+        self._map_list = [SLMap(0.001, 0.05, 'lin', 'deltime', self._deltime, dataOnly=True),
+                          SLMap(1.0, 1000.0, 'log', 'cutoff', self._cutoff, dataOnly=True),
+                          SLMap(0.0, 18.0, 'lin', 'maxthresh', self._maxthresh, dataOnly=True),
+                          SLMap(-90.0, 0.0, 'lin', 'minthresh', self._minthresh, dataOnly=True),
+                          SLMap(0.001, 1.0, 'log', 'reltime', self._reltime, dataOnly=True)]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
+    @property
+    def input(self):
+        """PyoObject. Input signal to process."""
+        return self._input
+    @input.setter
+    def input(self, x): self.setInput(x)
+
+    @property
+    def deltime(self):
+        """float. Delay between rms analysis."""
+        return self._deltime
+    @deltime.setter
+    def deltime(self, x): self.setDeltime(x)
+
+    @property
+    def cutoff(self):
+        """float. Cutoff for the follower lowpass filter."""
         return self._cutoff
     @cutoff.setter
     def cutoff(self, x): self.setCutoff(x)
+
+    @property
+    def maxthresh(self):
+        """float. Attack threshold in dB."""
+        return self._maxthresh
+    @maxthresh.setter
+    def maxthresh(self, x): self.setMaxthresh(x)
+
+    @property
+    def minthresh(self):
+        """float. Minimum threshold in dB."""
+        return self._minthresh
+    @minthresh.setter
+    def minthresh(self, x): self.setMinthresh(x)
+
+    @property
+    def reltime(self):
+        """float. Time to wait before reporting a new attack."""
+        return self._reltime
+    @reltime.setter
+    def reltime(self, x): self.setReltime(x)
+
+class Spectrum(PyoObject):
+    """
+    Spectrum analyzer and display.
+
+    Spectrum measures the magnitude of an input signal versus frequency
+    within a user defined range. It can show both magnitude and frequency
+    on linear or logarithmic scale.
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        input: PyoObject
+            Input signal to process.
+        size: int {pow-of-two > 4}, optional
+            FFT size. Must be a power of two greater than 4.
+            The FFT size is the number of samples used in each
+            analysis frame. Defaults to 1024.
+        wintype: int, optional
+            Shape of the envelope used to filter each input frame.
+            Possible shapes are :
+                0. rectangular (no windowing)
+                1. Hamming
+                2. Hanning
+                3. Bartlett (triangular)
+                4. Blackman 3-term
+                5. Blackman-Harris 4-term
+                6. Blackman-Harris 7-term
+                7. Tuckey (alpha = 0.66)
+                8. Sine (half-sine window)
+        function: python callable, optional
+            If set, this function will be called with magnitudes (as
+            list of lists, one list per channel). Useful if someone
+            wants to save the analysis data into a text file.
+            Defaults to None.
+
+    .. note::
+
+        Spectrum has no `out` method.
+
+        Spectrum has no `mul` and `add` attributes.
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> a = SuperSaw(freq=[500,750], detune=0.6, bal=0.7, mul=0.5).out()
+    >>> spec = Spectrum(a, size=1024)
+
+    """
+    def __init__(self, input, size=1024, wintype=2, function=None):
+        pyoArgsAssert(self, "oiiC", input, size, wintype, function)
+        PyoObject.__init__(self)
+        self.points = None
+        self.viewFrame = None
+        self._input = input
+        self._size = size
+        self._wintype = wintype
+        self._function = getWeakMethodRef(function)
+        self._fscaling = 0
+        self._mscaling = 1
+        self._lowbound = 0
+        self._highbound = 0.5
+        self._width = 500
+        self._height = 400
+        self._gain = 1
+        self._in_fader = InputFader(input)
+        in_fader, size, wintype, lmax = convertArgsToLists(self._in_fader, size, wintype)
+        self._base_objs = [Spectrum_base(wrap(in_fader,i), wrap(size,i), wrap(wintype,i)) for i in range(lmax)]
+        self._timer = Pattern(self.refreshView, 0.05).play()
+        if function is None:
+            self.view()
+        self.play()
+
+    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. Default to 0.05.
+
+        """
+        pyoArgsAssert(self, "oN", x, fadetime)
+        self._input = x
+        self._in_fader.setInput(x, fadetime)
+
+    def setSize(self, x):
+        """
+        Replace the `size` attribute.
+
+        :Args:
+
+            x: int
+                new `size` attribute.
+
+        """
+        pyoArgsAssert(self, "i", x)
+        self._size = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setSize(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def setWinType(self, x):
+        """
+        Replace the `wintype` attribute.
+
+        :Args:
+
+            x: int
+                new `wintype` attribute.
+
+        """
+        pyoArgsAssert(self, "i", x)
+        self._wintype = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setWinType(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def setFunction(self, function):
+        """
+        Sets the function to be called to retrieve the analysis data.
+
+        :Args:
+
+            function: python callable
+                The function called by the internal timer to retrieve the
+                analysis data. The function must be created with one argument
+                and will receive the data as a list of lists (one list per channel).
+
+        """
+        pyoArgsAssert(self, "C", function)
+        self._function = getWeakMethodRef(function)
+
+    def poll(self, active):
+        """
+        Turns on and off the analysis polling.
+
+        :Args:
+
+            active: boolean
+                If True, starts the analysis polling, False to stop it.
+                defaults to True.
+
+        """
+        pyoArgsAssert(self, "B", active)
+        if active:
+            self._timer.play()
+        else:
+            self._timer.stop()
+
+    def polltime(self, time):
+        """
+        Sets the polling time in seconds.
+
+        :Args:
+
+            time: float
+                Adjusts the frequency of the internal timer used to
+                retrieve the current analysis frame. defaults to 0.05.
+
+        """
+        pyoArgsAssert(self, "N", time)
+        self._timer.time = time
+
+    def setLowFreq(self, x):
+        """
+        Sets the lower frequency, in Hz, returned by the analysis.
+
+        :Args:
+
+            x: float
+                New low frequency in Hz. Adjusts the `lowbound` attribute, as `x / sr`.
+
+        """
+        pyoArgsAssert(self, "n", x)
+        x /= self.getServer().getSamplingRate()
+        self._lowbound = x
+        x, lmax = convertArgsToLists(x)
+        tmp = [obj.setLowbound(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def setHighFreq(self, x):
+        """
+        Sets the higher frequency, in Hz, returned by the analysis.
+
+        :Args:
+
+            x: float
+                New high frequency in Hz. Adjusts the `highbound` attribute, as `x / sr`.
+
+        """
+        pyoArgsAssert(self, "n", x)
+        x /= self.getServer().getSamplingRate()
+        self._highbound = x
+        x, lmax = convertArgsToLists(x)
+        tmp = [obj.setHighbound(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def setLowbound(self, x):
+        """
+        Sets the lower frequency, as multiplier of sr, returned by the analysis.
+
+        Returns the real low frequency en Hz.
+
+        :Args:
+
+            x: float {0 <= x <= 0.5}
+                new `lowbound` attribute.
+
+        """
+        pyoArgsAssert(self, "n", x)
+        self._lowbound = x
+        x, lmax = convertArgsToLists(x)
+        tmp = [obj.setLowbound(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+        return tmp[0]
+
+    def setHighbound(self, x):
+        """
+        Sets the higher frequency, as multiplier of sr, returned by the analysis.
+
+        Returns the real high frequency en Hz.
+
+        :Args:
+
+            x: float {0 <= x <= 0.5}
+                new `highbound` attribute.
+
+        """
+        pyoArgsAssert(self, "n", x)
+        self._highbound = x
+        x, lmax = convertArgsToLists(x)
+        tmp = [obj.setHighbound(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+        return tmp[0]
+
+    def getLowfreq(self):
+        """
+        Returns the current lower frequency, in Hz, used by the analysis.
+
+        """
+
+        return self._base_objs[0].getLowfreq()
+
+    def getHighfreq(self):
+        """
+        Returns the current higher frequency, in Hz, used by the analysis.
+
+        """
+        return self._base_objs[0].getHighfreq()
+
+    def setWidth(self, x):
+        """
+        Sets the width, in pixels, of the current display.
+
+        Used internally to build the list of points to draw.
+
+        :Args:
+
+            x: int
+                new `width` attribute.
+
+        """
+        pyoArgsAssert(self, "i", x)
+        self._width = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setWidth(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def setHeight(self, x):
+        """
+        Sets the height, in pixels, of the current display.
+
+        Used internally to build the list of points to draw.
+
+        :Args:
+
+            x: int
+                new `height` attribute.
+
+        """
+        pyoArgsAssert(self, "i", x)
+        self._height = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setHeight(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def setFscaling(self, x):
+        """
+        Sets the frequency display to linear or logarithmic.
+
+        :Args:
+
+            x: boolean
+                If True, the frequency display is logarithmic. False turns
+                it back to linear. Defaults to False.
+
+        """
+        pyoArgsAssert(self, "b", x)
+        self._fscaling = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setFscaling(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+        if self.viewFrame is not None:
+            self.viewFrame.setFscaling(self._fscaling)
+
+    def setMscaling(self, x):
+        """
+        Sets the magnitude display to linear or logarithmic.
+
+        :Args:
+
+            x: boolean
+                If True, the magnitude display is logarithmic (which means in dB).
+                False turns it back to linear. Defaults to True.
+
+        """
+        pyoArgsAssert(self, "b", x)
+        self._mscaling = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setMscaling(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+        if self.viewFrame is not None:
+            self.viewFrame.setMscaling(self._mscaling)
+
+    def getFscaling(self):
+        """
+        Returns the scaling of the frequency display.
+
+        Returns True for logarithmic or False for linear.
+
+        """
+        return self._fscaling
+
+    def getMscaling(self):
+        """
+        Returns the scaling of the magnitude display.
+
+        Returns True for logarithmic or False for linear.
+
+        """
+        return self._mscaling
+
+    def setGain(self, x):
+        """
+        Set the gain of the analysis data. For drawing purpose.
+
+        :Args:
+
+            x: float
+                new `gain` attribute, as linear values.
+
+        """
+        pyoArgsAssert(self, "n", x)
+        self._gain = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setGain(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def view(self, title="Spectrum", wxnoserver=False):
+        """
+        Opens a window showing the result of the analysis.
+
+        :Args:
+
+            title: string, optional
+                Window title. Defaults to "Spectrum".
+            wxnoserver: boolean, optional
+                With wxPython graphical toolkit, if True, tells the
+                interpreter that there will be no server window.
+
+        If `wxnoserver` is set to True, the interpreter will not wait for
+        the server GUI before showing the controller window.
+
+        """
+        pyoArgsAssert(self, "SB", title, wxnoserver)
+        createSpectrumWindow(self, title, wxnoserver)
+
+    def _setViewFrame(self, frame):
+        self.viewFrame = frame
+
+    def refreshView(self):
+        """
+        Updates the graphical display of the spectrum.
+
+        Called automatically by the internal timer.
+
+        """
+        self.points = [obj.display() for obj in self._base_objs]
+        if self._function is not None:
+            self._function(self.points)
+        if self.viewFrame is not None:
+            self.viewFrame.update(self.points)
+
+    @property
+    def input(self):
+        """PyoObject. Input signal to process."""
+        return self._input
+    @input.setter
+    def input(self, x): self.setInput(x)
+
+    @property
+    def size(self):
+        """int. FFT size."""
+        return self._size
+    @size.setter
+    def size(self, x): self.setSize(x)
+
+    @property
+    def wintype(self):
+        """int. Windowing method."""
+        return self._wintype
+    @wintype.setter
+    def wintype(self, x): self.setWinType(x)
+
+    @property
+    def gain(self):
+        """float. Sets the gain of the analysis data."""
+        return self._gain
+    @gain.setter
+    def gain(self, x): self.setGain(x)
+
+    @property
+    def lowbound(self):
+        """float. Lowest frequency (multiplier of sr) to output."""
+        return self._lowbound
+    @lowbound.setter
+    def lowbound(self, x): self.setLowbound(x)
+
+    @property
+    def highbound(self):
+        """float. Highest frequency (multiplier of sr) to output."""
+        return self._highbound
+    @highbound.setter
+    def highbound(self, x): self.setHighbound(x)
+
+    @property
+    def width(self):
+        """int. Width, in pixels, of the current display."""
+        return self._width
+    @width.setter
+    def width(self, x): self.setWidth(x)
+
+    @property
+    def height(self):
+        """int. Height, in pixels, of the current display."""
+        return self._height
+    @height.setter
+    def height(self, x): self.setHeight(x)
+
+    @property
+    def fscaling(self):
+        """boolean. Scaling of the frequency display."""
+        return self._fscaling
+    @fscaling.setter
+    def fscaling(self, x): self.setFscaling(x)
+
+    @property
+    def mscaling(self):
+        """boolean. Scaling of the magnitude display."""
+        return self._mscaling
+    @mscaling.setter
+    def mscaling(self, x): self.setMscaling(x)
+
+class Scope(PyoObject):
+    """
+    Oscilloscope - audio waveform display.
+
+    Oscilloscopes are used to observe the change of an electrical
+    signal over time.
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        input: PyoObject
+            Input signal to process.
+        length: float, optional
+            Length, in seconds, of the displayed window. Can't be a list.
+            Defaults to 0.05.
+        gain: float, optional
+            Linear gain applied to the signal to be displayed.
+            Can't be a list. Defaults to 0.67.
+        function: python callable, optional
+            If set, this function will be called with samples (as
+            list of lists, one list per channel). Useful if someone
+            wants to save the analysis data into a text file.
+            Defaults to None.
+
+    .. note::
+
+        Scope has no `out` method.
+
+        Scope has no `mul` and `add` attributes.
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> a = Sine([100,100.2], mul=0.7)
+    >>> b = Noise(0.1)
+    >>> scope = Scope(a+b)
+
+    """
+    def __init__(self, input, length=0.05, gain=0.67, function=None):
+        pyoArgsAssert(self, "oNNC", input, length, gain, function)
+        PyoObject.__init__(self)
+        self.points = None
+        self.viewFrame = None
+        self._input = input
+        self._length = length
+        self._gain = gain
+        self._function = function
+        self._width = 500
+        self._height = 400
+        self._in_fader = InputFader(input)
+        in_fader, lmax = convertArgsToLists(self._in_fader)
+        self._base_objs = [Scope_base(wrap(in_fader,i), length) for i in range(lmax)]
+        self._timer = Pattern(self.refreshView, length).play()
+        if function is None:
+            self.view()
+        self.play()
+
+    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. Default to 0.05.
+
+        """
+        pyoArgsAssert(self, "oN", x, fadetime)
+        self._input = x
+        self._in_fader.setInput(x, fadetime)
+
+    def setLength(self, x):
+        """
+        Replace the `length` attribute.
+
+        :Args:
+
+            x: float
+                new `length` attribute.
+
+        """
+        pyoArgsAssert(self, "N", x)
+        self._length = x
+        self._timer.time = x
+        [obj.setLength(x) for obj in self._base_objs]
+
+    def setGain(self, x):
+        """
+        Set the gain boost applied to the analysed data. For drawing purpose.
+
+        :Args:
+
+            x: float
+                new `gain` attribute, as linear values.
+
+        """
+        pyoArgsAssert(self, "n", x)
+        self._gain = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setGain(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def poll(self, active):
+        """
+        Turns on and off the analysis polling.
+
+        :Args:
+
+            active: boolean
+                If True, starts the analysis polling, False to stop it.
+                defaults to True.
+
+        """
+        pyoArgsAssert(self, "B", active)
+        if active:
+            self._timer.play()
+        else:
+            self._timer.stop()
+
+    def setWidth(self, x):
+        """
+        Gives the width of the display to the analyzer.
+
+        The analyzer needs this value to construct the list
+        of points to draw on the display.
+
+        :Args:
+
+            x: int
+                Width of the display in pixel value. The default
+                width is 500.
+
+        """
+        pyoArgsAssert(self, "I", x)
+        self._width = x
+        [obj.setWidth(x) for obj in self._base_objs]
+
+    def setHeight(self, x):
+        """
+        Gives the height of the display to the analyzer.
+
+        The analyzer needs this value to construct the list
+        of points to draw on the display.
+
+        :Args:
+
+            x: int
+                Height of the display in pixel value. The default
+                height is 400.
+
+        """
+        pyoArgsAssert(self, "I", x)
+        self._height = x
+        [obj.setHeight(x) for obj in self._base_objs]
+
+    def view(self, title="Scope", wxnoserver=False):
+        """
+        Opens a window showing the result of the analysis.
+
+        :Args:
+
+            title: string, optional
+                Window title. Defaults to "Spectrum".
+            wxnoserver: boolean, optional
+                With wxPython graphical toolkit, if True, tells the
+                interpreter that there will be no server window.
+
+        If `wxnoserver` is set to True, the interpreter will not wait for
+        the server GUI before showing the controller window.
+
+        """
+        pyoArgsAssert(self, "SB", title, wxnoserver)
+        createScopeWindow(self, title, wxnoserver)
+
+    def setFunction(self, function):
+        """
+        Sets the function to be called to retrieve the analysis data.
+
+        :Args:
+
+            function: python callable
+                The function called by the internal timer to retrieve the
+                analysis data. The function must be created with one argument
+                and will receive the data as a list of lists (one list per channel).
+
+        """
+        pyoArgsAssert(self, "C", function)
+        self._function = getWeakMethodRef(function)
+
+    def _setViewFrame(self, frame):
+        self.viewFrame = frame
+
+    def refreshView(self):
+        """
+        Updates the graphical display of the scope.
+
+        Called automatically by the internal timer.
+
+        """
+        self.points = [obj.display() for obj in self._base_objs]
+        if self.viewFrame is not None:
+            self.viewFrame.update(self.points)
+        if self._function is not None:
+            self._function(self.points)
+
+    @property
+    def input(self):
+        """PyoObject. Input signal to process."""
+        return self._input
+    @input.setter
+    def input(self, x): self.setInput(x)
+
+    @property
+    def length(self):
+        """float. Window length."""
+        return self._length
+    @length.setter
+    def length(self, x): self.setLength(x)
+
+    @property
+    def gain(self):
+        """float. Sets the gain of the analysis data."""
+        return self._gain
+    @gain.setter
+    def gain(self, x): self.setGain(x)
+
+class PeakAmp(PyoObject):
+    """
+    Peak amplitude follower.
+
+    Output signal is the continuous peak amplitude of an input signal.
+    A new peaking value is computed every buffer size. If `function`
+    argument is not None, it should be a function that will be called
+    every buffer size with a variable-length argument list containing
+    the peaking values of all object's streams. Useful for meter drawing.
+    Function definition must look like this:
+
+    >>> def getValues(*args)
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        input: PyoObject
+            Input signal to process.
+        function: callable, optional
+            Function that will be called with amplitude values in arguments.
+            Default to None.
+
+    .. note::
+
+        The out() method is bypassed. PeakAmp's signal can not be sent to
+        audio outs.
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> sf = SfPlayer(SNDS_PATH + "/transparent.aif", loop=True, mul=.4).out()
+    >>> amp = PeakAmp(sf)
+    >>> n = Noise(mul=Port(amp)).out(1)
+
+    """
+    def __init__(self, input, function=None, mul=1, add=0):
+        pyoArgsAssert(self, "oCOO", input, function, mul, add)
+        PyoObject.__init__(self, mul, add)
+        self._input = input
+        if callable(function):
+            self._function = getWeakMethodRef(function)
+        else:
+            self._function = None
+        self._in_fader = InputFader(input)
+        in_fader, mul, add, lmax = convertArgsToLists(self._in_fader, mul, add)
+        self._base_objs = [PeakAmp_base(wrap(in_fader,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        sr = self.getSamplingRate()
+        bs = self.getBufferSize()
+        self._timer = Pattern(self._buildList, 0.06).play()
+        self.play()
+
+    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. Default to 0.05.
+
+        """
+        pyoArgsAssert(self, "oN", x, fadetime)
+        self._input = x
+        self._in_fader.setInput(x, fadetime)
+
+    def setFunction(self, x):
+        """
+        Replace the `function` attribute.
+
+        :Args:
+
+            x: callable
+                New function to call with amplitude values in arguments.
+
+        """
+        pyoArgsAssert(self, "C", x)
+        if callable(x):
+            self._function = getWeakMethodRef(x)
+
+    def polltime(self, x):
+        """
+        Sets the delay, in seconds, between each call of the function.
+
+        :Args:
+
+            x: float
+                New polling time in seconds.
+
+        """
+        pyoArgsAssert(self, "N", x)
+        self._timer.time = x
+
+    def out(self, chnl=0, inc=1, dur=0, delay=0):
+        return self.play(dur, delay)
+
+    def _buildList(self):
+        if self._function is not None:
+            values = [obj.getValue() for obj in self._base_objs]
+            self._function(*values)
+
+    def ctrl(self, map_list=None, title=None, wxnoserver=False):
+        self._map_list = []
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
+    @property
+    def input(self):
+        """PyoObject. Input signal to process."""
+        return self._input
+    @input.setter
+    def input(self, x): self.setInput(x)
+
+    @property
+    def function(self):
+        """PyoObject. function signal to process."""
+        return self._function
+    @function.setter
+    def function(self, x): self.setFunction(x)
diff --git a/pyolib/arithmetic.py b/pyolib/arithmetic.py
index bf10013..f38e056 100644
--- a/pyolib/arithmetic.py
+++ b/pyolib/arithmetic.py
@@ -1,29 +1,30 @@
+from __future__ import absolute_import
 """
 Tools to perform arithmetic operations on audio signals.
 
 """
 """
-Copyright 2010 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+You should have received a copy of the GNU Lesser General Public
+License along with pyo.  If not, see <http://www.gnu.org/licenses/>.
 """
 
-from _core import *
-from _maps import *
+from ._core import *
+from ._maps import *
 
 class Sin(PyoObject):
     """
@@ -35,9 +36,9 @@ class Sin(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal, angle in radians.
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> import math
@@ -47,30 +48,33 @@ class Sin(PyoObject):
     """
 
     def __init__(self, input, mul=1, add=0):
+        pyoArgsAssert(self, "oOO", input, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -85,7 +89,7 @@ class Cos(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal, angle in radians.
 
     >>> s = Server().boot()
@@ -96,11 +100,13 @@ class Cos(PyoObject):
 
     """
     def __init__(self, input, mul=1, add=0):
+        pyoArgsAssert(self, "oOO", input, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         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):
         """
@@ -108,18 +114,19 @@ class Cos(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -134,7 +141,7 @@ class Tan(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal, angle in radians.
 
     >>> s = Server().boot()
@@ -152,11 +159,13 @@ class Tan(PyoObject):
 
     """
     def __init__(self, input, mul=1, add=0):
+        pyoArgsAssert(self, "oOO", input, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         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):
         """
@@ -164,18 +173,19 @@ class Tan(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -190,7 +200,7 @@ class Abs(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
 
     >>> s = Server().boot()
@@ -203,11 +213,13 @@ class Abs(PyoObject):
     """
 
     def __init__(self, input, mul=1, add=0):
+        pyoArgsAssert(self, "oOO", input, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         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):
         """
@@ -215,18 +227,19 @@ class Abs(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -241,7 +254,7 @@ class Sqrt(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
 
     >>> s = Server().boot()
@@ -259,11 +272,13 @@ class Sqrt(PyoObject):
     """
 
     def __init__(self, input, mul=1, add=0):
+        pyoArgsAssert(self, "oOO", input, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         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):
         """
@@ -271,18 +286,19 @@ class Sqrt(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -291,14 +307,14 @@ class Log(PyoObject):
     """
     Performs a natural log function on audio signal.
 
-    Returns the natural log value of of audio signal as input. 
+    Returns the natural log value of of audio signal as input.
     Values less than 0.0 return 0.0.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
 
     >>> s = Server().boot()
@@ -311,11 +327,13 @@ class Log(PyoObject):
     """
 
     def __init__(self, input, mul=1, add=0):
+        pyoArgsAssert(self, "oOO", input, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         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):
         """
@@ -323,18 +341,19 @@ class Log(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -343,14 +362,14 @@ class Log2(PyoObject):
     """
     Performs a base 2 log function on audio signal.
 
-    Returns the base 2 log value of audio signal as input. 
+    Returns the base 2 log value of audio signal as input.
     Values less than 0.0 return 0.0.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
 
     >>> s = Server().boot()
@@ -363,11 +382,13 @@ class Log2(PyoObject):
     """
 
     def __init__(self, input, mul=1, add=0):
+        pyoArgsAssert(self, "oOO", input, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         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):
         """
@@ -375,18 +396,19 @@ class Log2(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -395,14 +417,14 @@ class Log10(PyoObject):
     """
     Performs a base 10 log function on audio signal.
 
-    Returns the base 10 log value of audio signal as input. 
+    Returns the base 10 log value of audio signal as input.
     Values less than 0.0 return 0.0.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
 
     >>> s = Server().boot()
@@ -415,11 +437,13 @@ class Log10(PyoObject):
     """
 
     def __init__(self, input, mul=1, add=0):
+        pyoArgsAssert(self, "oOO", input, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         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):
         """
@@ -427,18 +451,19 @@ class Log10(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -447,17 +472,17 @@ class Atan2(PyoObject):
     """
     Computes the principal value of the arc tangent of b/a.
 
-    Computes the principal value of the arc tangent of b/a, 
-    using the signs of both arguments to determine the quadrant 
+    Computes the principal value of the arc tangent of b/a,
+    using the signs of both arguments to determine the quadrant
     of the return value.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        b : float or PyoObject, optional
+        b: float or PyoObject, optional
             Numerator. Defaults to 1.
-        a : float or PyoObject, optional
+        a: float or PyoObject, optional
             Denominator. Defaults to 1.
 
     >>> s = Server().boot()
@@ -470,11 +495,13 @@ class Atan2(PyoObject):
 
     """
     def __init__(self, b=1, a=1, mul=1, add=0):
+        pyoArgsAssert(self, "OOOO", b, a, mul, add)
         PyoObject.__init__(self, mul, add)
         self._b = b
         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):
         """
@@ -482,10 +509,11 @@ class Atan2(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `b` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._b = x
         x, lmax = convertArgsToLists(x)
         [obj.setB(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -496,24 +524,25 @@ class Atan2(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `a` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._a = x
         x, lmax = convertArgsToLists(x)
         [obj.setA(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     @property
     def b(self):
-        """float or PyoObject. Numerator.""" 
+        """float or PyoObject. Numerator."""
         return self._b
     @b.setter
     def b(self, x): self.setB(x)
 
     @property
     def a(self):
-        """float or PyoObject. Denominator.""" 
+        """float or PyoObject. Denominator."""
         return self._a
     @a.setter
     def a(self, x): self.setA(x)
@@ -522,14 +551,14 @@ class Floor(PyoObject):
     """
     Rounds to largest integral value not greater than audio signal.
 
-    For each samples in the input signal, rounds to the largest integral 
+    For each samples in the input signal, rounds to the largest integral
     value not greater than the sample value.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
 
     >>> s = Server().boot()
@@ -542,11 +571,13 @@ class Floor(PyoObject):
     """
 
     def __init__(self, input, mul=1, add=0):
+        pyoArgsAssert(self, "oOO", input, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         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):
         """
@@ -554,18 +585,19 @@ class Floor(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -574,14 +606,14 @@ class Ceil(PyoObject):
     """
     Rounds to smallest integral value greater than or equal to the input signal.
 
-    For each samples in the input signal, rounds to the smallest integral 
+    For each samples in the input signal, rounds to the smallest integral
     value greater than or equal to the sample value.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
 
     >>> s = Server().boot()
@@ -594,11 +626,13 @@ class Ceil(PyoObject):
     """
 
     def __init__(self, input, mul=1, add=0):
+        pyoArgsAssert(self, "oOO", input, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         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):
         """
@@ -606,18 +640,19 @@ class Ceil(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -626,14 +661,14 @@ class Round(PyoObject):
     """
     Rounds to the nearest integer value in a floating-point format.
 
-    For each samples in the input signal, rounds to the nearest integer 
+    For each samples in the input signal, rounds to the nearest integer
     value of the sample value.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
 
     >>> s = Server().boot()
@@ -646,11 +681,123 @@ class Round(PyoObject):
     """
 
     def __init__(self, input, mul=1, add=0):
+        pyoArgsAssert(self, "oOO", input, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         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):
+        """
+        Replace the `input` attribute.
+
+        :Args:
+
+            x: PyoObject
+                New signal to process.
+            fadetime: float, optional
+                Crossfade time between old and new input. Default to 0.05.
+
+        """
+        pyoArgsAssert(self, "oN", x, fadetime)
+        self._input = x
+        self._in_fader.setInput(x, fadetime)
+
+    @property
+    def input(self):
+        """PyoObject. Input signal to process."""
+        return self._input
+    @input.setter
+    def input(self, x): self.setInput(x)
+
+class Tanh(PyoObject):
+    """
+    Performs a hyperbolic tangent function on audio signal.
+
+    Returns the hyperbolic tangent of audio signal as input.
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        input: PyoObject
+            Input signal, angle in radians.
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> import math
+    >>> a = Phasor(250, mul=math.pi*2)
+    >>> b = Tanh(Sin(a, mul=10), mul=0.3).mix(2).out()
+
+    """
+
+    def __init__(self, input, mul=1, add=0):
+        pyoArgsAssert(self, "oOO", input, mul, add)
+        PyoObject.__init__(self, mul, add)
+        self._input = input
+        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):
+        """
+        Replace the `input` attribute.
+
+        :Args:
+
+            x: PyoObject
+                New signal to process.
+            fadetime: float, optional
+                Crossfade time between old and new input. Default to 0.05.
+
+        """
+        pyoArgsAssert(self, "oN", x, fadetime)
+        self._input = x
+        self._in_fader.setInput(x, fadetime)
+
+    @property
+    def input(self):
+        """PyoObject. Input signal to process."""
+        return self._input
+    @input.setter
+    def input(self, x): self.setInput(x)
+
+class Exp(PyoObject):
+    """
+    Calculates the value of e to the power of x.
+
+    Returns the value of e to the power of x, where e is the base of the
+    natural logarithm, 2.718281828...
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        input: PyoObject
+            Input signal, the exponent.
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> a = Sine(freq=200)
+    >>> lf = Sine(freq=.5, mul=5, add=6)
+    >>> # Tanh style distortion
+    >>> t = Exp(2 * a * lf)
+    >>> th = (t - 1) / (t + 1)
+    >>> out = (th * 0.3).out()
+
+    """
+
+    def __init__(self, input, mul=1, add=0):
+        pyoArgsAssert(self, "oOO", input, mul, add)
+        PyoObject.__init__(self, mul, add)
+        self._input = input
+        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):
         """
@@ -658,18 +805,19 @@ class Round(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
diff --git a/pyolib/controls.py b/pyolib/controls.py
index d993bbc..f1db3d9 100644
--- a/pyolib/controls.py
+++ b/pyolib/controls.py
@@ -1,38 +1,39 @@
 """
-Objects designed to create parameter's control at audio rate. 
+Objects designed to create parameter's control at audio rate.
 
-These objects can be used to create envelopes, line segments 
-and conversion from python number to audio signal. 
+These objects can be used to create envelopes, line segments
+and conversion from python number to audio signal.
 
-The audio streams of these objects can't be sent to the output 
+The audio streams of these objects can't be sent to the output
 soundcard.
- 
+
 """
 
+from __future__ import absolute_import
 """
-Copyright 2010 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+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 sys
-from _core import *
-from _maps import *
-from _widgets import createGraphWindow
-from types import ListType, TupleType
+from ._core import *
+from ._maps import *
+from ._widgets import createGraphWindow
 
 ######################################################################
 ### Controls
@@ -40,32 +41,35 @@ from types import ListType, TupleType
 class Fader(PyoObject):
     """
     Fadein - fadeout envelope generator.
-    
-    Generate an amplitude envelope between 0 and 1 with control on fade 
+
+    Generate an amplitude envelope between 0 and 1 with control on fade
     times and total duration of the envelope.
-    
-    The play() method starts the envelope and is not called at the 
+
+    The play() method starts the envelope and is not called at the
     object creation time.
-    
+
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        fadein : float, optional
+        fadein: float, optional
             Rising time of the envelope in seconds. Defaults to 0.01.
-        fadeout : float, optional
+        fadeout: float, optional
             Falling time of the envelope in seconds. Defaults to 0.1.
-        dur : float, optional
-            Total duration of the envelope. Defaults to 0, which means wait 
+        dur: float, optional
+            Total duration of the envelope. Defaults to 0, which means wait
             for the stop() method to start the fadeout.
 
     .. note::
 
         The out() method is bypassed. Fader's signal can not be sent to audio outs.
-        
+
         The play() method starts the envelope.
-        
-        The stop() calls the envelope's release phase if `dur` = 0.
+
+        The stop() method calls the envelope's release phase if `dur` = 0.
+
+        As of version 0.8.0, exponential or logarithmic envelopes can be created
+        with the exponent factor (see setExp() method).
 
     >>> s = Server().boot()
     >>> s.start()
@@ -74,13 +78,15 @@ class Fader(PyoObject):
     >>> def repeat():
     ...     f.play()
     >>> pat = Pattern(function=repeat, time=2).play()
-    
+
     """
     def __init__(self, fadein=0.01, fadeout=0.1, dur=0, mul=1, add=0):
+        pyoArgsAssert(self, "nnnOO", fadein, fadeout, dur, mul, add)
         PyoObject.__init__(self, mul, add)
         self._fadein = fadein
         self._fadeout = fadeout
         self._dur = dur
+        self._exp = 1.0
         fadein, fadeout, dur, mul, add, lmax = convertArgsToLists(fadein, fadeout, dur, mul, add)
         self._base_objs = [Fader_base(wrap(fadein,i), wrap(fadeout,i), wrap(dur,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
 
@@ -90,13 +96,14 @@ class Fader(PyoObject):
     def setFadein(self, x):
         """
         Replace the `fadein` attribute.
-        
+
         :Args:
 
-            x : float
+            x: float
                 new `fadein` attribute.
-        
+
         """
+        pyoArgsAssert(self, "n", x)
         self._fadein = x
         x, lmax = convertArgsToLists(x)
         [obj.setFadein(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -104,13 +111,14 @@ class Fader(PyoObject):
     def setFadeout(self, x):
         """
         Replace the `fadeout` attribute.
-        
+
         :Args:
 
-            x : float
+            x: float
                 new `fadeout` attribute.
-        
+
         """
+        pyoArgsAssert(self, "n", x)
         self._fadeout = x
         x, lmax = convertArgsToLists(x)
         [obj.setFadeout(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -118,76 +126,110 @@ class Fader(PyoObject):
     def setDur(self, x):
         """
         Replace the `dur` attribute.
-        
+
         :Args:
 
-            x : float
+            x: float
                 new `dur` attribute.
-        
+
         """
+        pyoArgsAssert(self, "n", x)
         self._dur = x
         x, lmax = convertArgsToLists(x)
         [obj.setDur(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
+    def setExp(self, x):
+        """
+        Sets an exponent factor to create exponential or logarithmic envelope.
+
+        The default value is 1.0, which means linear segments. A value
+        higher than 1.0 will produce exponential segments while a value
+        between 0 and 1 will produce logarithmic segments. Must be > 0.0.
+
+        :Args:
+
+            x: float
+                new `exp` attribute.
+
+        """
+        pyoArgsAssert(self, "n", x)
+        self._exp = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setExp(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, 10., 'lin', 'fadein', self._fadein, dataOnly=True),
+                          SLMap(0, 10., 'lin', 'fadeout', self._fadeout, dataOnly=True),
+                          SLMap(0, 20., 'lin', 'dur', self._dur, dataOnly=True)]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
     @property
     def fadein(self):
-        """float. Rising time of the envelope in seconds.""" 
+        """float. Rising time of the envelope in seconds."""
         return self._fadein
     @fadein.setter
     def fadein(self, x): self.setFadein(x)
 
     @property
     def fadeout(self):
-        """float. Falling time of the envelope in seconds.""" 
+        """float. Falling time of the envelope in seconds."""
         return self._fadeout
     @fadeout.setter
     def fadeout(self, x): self.setFadeout(x)
 
     @property
     def dur(self):
-        """float. Total duration of the envelope.""" 
+        """float. Total duration of the envelope."""
         return self._dur
     @dur.setter
     def dur(self, x): self.setDur(x)
 
+    @property
+    def exp(self):
+        """float. Exponent factor of the envelope."""
+        return self._exp
+    @exp.setter
+    def exp(self, x): self.setExp(x)
+
 
 class Adsr(PyoObject):
     """
     Attack - Decay - Sustain - Release envelope generator.
-    
-    Calculates the classical ADSR envelope using linear segments. 
-    Duration can be set to 0 to give an infinite sustain. In this 
+
+    Calculates the classical ADSR envelope using linear segments.
+    Duration can be set to 0 to give an infinite sustain. In this
     case, the stop() method calls the envelope release part.
-     
-    The play() method starts the envelope and is not called at the 
+
+    The play() method starts the envelope and is not called at the
     object creation time.
-    
+
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        attack : float, optional
+        attack: float, optional
             Duration of the attack phase in seconds. Defaults to 0.01.
-        decay : float, optional
+        decay: float, optional
             Duration of the decay in seconds. Defaults to 0.05.
-        sustain : float, optional
+        sustain: float, optional
             Amplitude of the sustain phase. Defaults to 0.707.
-        release : float, optional
+        release: float, optional
             Duration of the release in seconds. Defaults to 0.1.
-        dur : float, optional
-            Total duration of the envelope. Defaults to 0, which means wait 
+        dur: float, optional
+            Total duration of the envelope. Defaults to 0, which means wait
             for the stop() method to start the release phase.
-        
-    
+
+
     .. note::
 
         The out() method is bypassed. Adsr's signal can not be sent to audio outs.
 
         The play() method starts the envelope.
-        
-        The stop() calls the envelope's release phase if `dur` = 0.
-    
-        Shape of a classical Adsr:
+
+        The stop() method calls the envelope's release phase if `dur` = 0.
+
+        As of version 0.8.0, exponential or logarithmic envelopes can be created
+        with the exponent factor (see setExp() method).
 
     >>> s = Server().boot()
     >>> s.start()
@@ -196,15 +238,17 @@ class Adsr(PyoObject):
     >>> def repeat():
     ...     f.play()
     >>> pat = Pattern(function=repeat, time=2).play()
-    
+
     """
     def __init__(self, attack=0.01, decay=0.05, sustain=0.707, release=0.1, dur=0, mul=1, add=0):
+        pyoArgsAssert(self, "nnnnnOO", attack, decay, sustain, release, dur, mul, add)
         PyoObject.__init__(self, mul, add)
         self._attack = attack
         self._decay = decay
         self._sustain = sustain
         self._release = release
         self._dur = dur
+        self._exp = 1.0
         attack, decay, sustain, release, dur, mul, add, lmax = convertArgsToLists(attack, decay, sustain, release, dur, mul, add)
         self._base_objs = [Adsr_base(wrap(attack,i), wrap(decay,i), wrap(sustain,i), wrap(release,i), wrap(dur,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
 
@@ -214,13 +258,14 @@ class Adsr(PyoObject):
     def setAttack(self, x):
         """
         Replace the `attack` attribute.
-        
+
         :Args:
 
-            x : float
+            x: float
                 new `attack` attribute.
-        
+
         """
+        pyoArgsAssert(self, "n", x)
         self._attack = x
         x, lmax = convertArgsToLists(x)
         [obj.setAttack(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -228,13 +273,14 @@ class Adsr(PyoObject):
     def setDecay(self, x):
         """
         Replace the `decay` attribute.
-        
+
         :Args:
 
-            x : float
+            x: float
                 new `decay` attribute.
-        
+
         """
+        pyoArgsAssert(self, "n", x)
         self._decay = x
         x, lmax = convertArgsToLists(x)
         [obj.setDecay(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -242,13 +288,14 @@ class Adsr(PyoObject):
     def setSustain(self, x):
         """
         Replace the `sustain` attribute.
-        
+
         :Args:
 
-            x : float
+            x: float
                 new `sustain` attribute.
-        
+
         """
+        pyoArgsAssert(self, "n", x)
         self._sustain = x
         x, lmax = convertArgsToLists(x)
         [obj.setSustain(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -256,13 +303,14 @@ class Adsr(PyoObject):
     def setRelease(self, x):
         """
         Replace the `sustain` attribute.
-        
+
         :Args:
 
-            x : float
+            x: float
                 new `sustain` attribute.
-        
+
         """
+        pyoArgsAssert(self, "n", x)
         self._release = x
         x, lmax = convertArgsToLists(x)
         [obj.setRelease(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -270,71 +318,106 @@ class Adsr(PyoObject):
     def setDur(self, x):
         """
         Replace the `dur` attribute.
-        
+
         :Args:
 
-            x : float
+            x: float
                 new `dur` attribute.
-        
+
         """
+        pyoArgsAssert(self, "n", x)
         self._dur = x
         x, lmax = convertArgsToLists(x)
         [obj.setDur(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
+    def setExp(self, x):
+        """
+        Sets an exponent factor to create exponential or logarithmic envelope.
+
+        The default value is 1.0, which means linear segments. A value
+        higher than 1.0 will produce exponential segments while a value
+        between 0 and 1 will produce logarithmic segments. Must be > 0.0.
+
+        :Args:
+
+            x: float
+                new `exp` attribute.
+
+        """
+        pyoArgsAssert(self, "n", x)
+        self._exp = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setExp(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, 5, 'lin', 'attack', self._attack, dataOnly=True),
+                          SLMap(0, 5, 'lin', 'decay', self._decay, dataOnly=True),
+                          SLMap(0, 1, 'lin', 'sustain', self._sustain, dataOnly=True),
+                          SLMap(0, 10, 'lin', 'release', self._release, dataOnly=True),
+                          SLMap(0, 20., 'lin', 'dur', self._dur, dataOnly=True)]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
     @property
     def attack(self):
-        """float. Duration of the attack phase in seconds.""" 
+        """float. Duration of the attack phase in seconds."""
         return self._attack
     @attack.setter
     def attack(self, x): self.setAttack(x)
 
     @property
     def decay(self):
-        """float. Duration of the decay phase in seconds.""" 
+        """float. Duration of the decay phase in seconds."""
         return self._decay
     @decay.setter
     def decay(self, x): self.setDecay(x)
 
     @property
     def sustain(self):
-        """float. Amplitude of the sustain phase.""" 
+        """float. Amplitude of the sustain phase."""
         return self._sustain
     @sustain.setter
     def sustain(self, x): self.setSustain(x)
 
     @property
     def release(self):
-        """float. Duration of the release phase in seconds.""" 
+        """float. Duration of the release phase in seconds."""
         return self._release
     @release.setter
     def release(self, x): self.setRelease(x)
 
     @property
     def dur(self):
-        """float. Total duration of the envelope.""" 
+        """float. Total duration of the envelope."""
         return self._dur
     @dur.setter
     def dur(self, x): self.setDur(x)
 
+    @property
+    def exp(self):
+        """float. Exponent factor of the envelope."""
+        return self._exp
+    @exp.setter
+    def exp(self, x): self.setExp(x)
+
 class Linseg(PyoObject):
     """
-    Trace a series of line segments between specified break-points. 
-    
-    The play() method starts the envelope and is not called at the 
+    Draw a series of line segments between specified break-points.
+
+    The play() method starts the envelope and is not called at the
     object creation time.
-    
+
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        list : list of tuples
+        list: list of tuples
             Points used to construct the line segments. Each tuple is a
-            new point in the form (time, value). 
-            
+            new point in the form (time, value).
+
             Times are given in seconds and must be in increasing order.
-        loop : boolean, optional
+        loop: boolean, optional
             Looping mode. Defaults to False.
-        initToFirstVal : boolean, optional
+        initToFirstVal: boolean, optional
             If True, audio buffer will be filled at initialization with the
             first value of the line. Defaults to False.
 
@@ -348,20 +431,15 @@ class Linseg(PyoObject):
     >>> a = Sine(freq=l, mul=.3).mix(2).out()
     >>> # then call:
     >>> l.play()
-    
+
     """
     def __init__(self, list, loop=False, initToFirstVal=False, mul=1, add=0):
+        pyoArgsAssert(self, "lbbOO", list, loop, initToFirstVal, mul, add)
         PyoObject.__init__(self, mul, add)
-        if type(list) != ListType:
-            print >> sys.stderr, 'TypeError: "list" argument of %s must be a list of tuples.\n' % self.__class__.__name__
-            exit()
-        if type(list[0]) != TupleType:
-            print >> sys.stderr, 'TypeError: "list" argument of %s must be a list of tuples.\n' % self.__class__.__name__
-            exit()
         self._list = list
         self._loop = loop
         initToFirstVal, loop, mul, add, lmax = convertArgsToLists(initToFirstVal, loop, mul, add)
-        if type(list[0]) != ListType:
+        if type(list[0]) != list:
             self._base_objs = [Linseg_base(list, wrap(loop,i), wrap(initToFirstVal,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
         else:
             listlen = len(list)
@@ -374,15 +452,16 @@ class Linseg(PyoObject):
     def setList(self, x):
         """
         Replace the `list` attribute.
-        
+
         :Args:
 
-            x : list of tuples
+            x: list of tuples
                 new `list` attribute.
-        
+
         """
+        pyoArgsAssert(self, "l", x)
         self._list = x
-        if type(x[0]) != ListType:
+        if type(x[0]) != list:
             [obj.setList(x) for i, obj in enumerate(self._base_objs)]
         else:
             [obj.setList(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -393,9 +472,9 @@ class Linseg(PyoObject):
 
         :Args:
 
-            x : list of tuples
+            x: list of tuples
                 new `list` attribute.
-        
+
         """
         self.setList(x)
 
@@ -405,51 +484,59 @@ class Linseg(PyoObject):
     def setLoop(self, x):
         """
         Replace the `loop` attribute.
-        
+
         :Args:
 
-            x : boolean
+            x: boolean
                 new `loop` attribute.
-        
+
         """
+        pyoArgsAssert(self, "b", x)
         self._loop = x
         x, lmax = convertArgsToLists(x)
         [obj.setLoop(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
+    def pause(self):
+        """
+        Toggles between play and stop mode without reset.
+
+        """
+        [obj.pause() for obj in self._base_objs]
+
     def graph(self, xlen=None, yrange=None, title=None, wxnoserver=False):
         """
         Opens a grapher window to control the shape of the envelope.
 
         When editing the grapher with the mouse, the new set of points
-        will be send to the object on mouse up. 
+        will be send to the object on mouse up.
 
-        Ctrl+C with focus on the grapher will copy the list of points to the 
+        Ctrl+C with focus on the grapher will copy the list of points to the
         clipboard, giving an easy way to insert the new shape in a script.
 
         :Args:
 
-            xlen : float, optional
+            xlen: float, optional
                 Set the maximum value of the X axis of the graph. If None, the
                 maximum value is retrieve from the current list of points.
-            yrange : tuple, optional
+            yrange: tuple, optional
                 Set the min and max values of the Y axis of the graph. If
                 None, min and max are retrieve from the current list of points.
-            title : string, optional
-                Title of the window. If none is provided, the name of the 
+            title: string, optional
+                Title of the window. If none is provided, the name of the
                 class is used.
-            wxnoserver : boolean, optional
-                With wxPython graphical toolkit, if True, tells the 
+            wxnoserver: boolean, optional
+                With wxPython graphical toolkit, if True, tells the
                 interpreter that there will be no server window.
-                
-        If `wxnoserver` is set to True, the interpreter will not wait for the 
-        server GUI before showing the controller window. 
+
+        If `wxnoserver` is set to True, the interpreter will not wait for the
+        server GUI before showing the controller window.
 
         """
-        if xlen == None:
+        if xlen is None:
             xlen = float(self._list[-1][0])
         else:
             xlen = float(xlen)
-        if yrange == None:
+        if yrange is None:
             ymin = float(min([x[1] for x in self._list]))
             ymax = float(max([x[1] for x in self._list]))
             if ymin == ymax:
@@ -460,43 +547,43 @@ class Linseg(PyoObject):
 
     @property
     def list(self):
-        """float. List of points (time, value).""" 
+        """float. List of points (time, value)."""
         return self._list
     @list.setter
     def list(self, x): self.setList(x)
 
     @property
     def loop(self):
-        """boolean. Looping mode.""" 
+        """boolean. Looping mode."""
         return self._loop
     @loop.setter
     def loop(self, x): self.setLoop(x)
 
 class Expseg(PyoObject):
     """
-    Trace a series of exponential segments between specified break-points. 
+    Draw a series of exponential segments between specified break-points.
 
-    The play() method starts the envelope and is not called at the 
+    The play() method starts the envelope and is not called at the
     object creation time.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        list : list of tuples
+        list: list of tuples
             Points used to construct the line segments. Each tuple is a
-            new point in the form (time, value). 
-            
+            new point in the form (time, value).
+
             Times are given in seconds and must be in increasing order.
-        loop : boolean, optional
+        loop: boolean, optional
             Looping mode. Defaults to False.
-        exp : float, optional
+        exp: float, optional
             Exponent factor. Used to control the slope of the curves.
             Defaults to 10.
-        inverse : boolean, optional
-            If True, downward slope will be inversed. Useful to create 
+        inverse: boolean, optional
+            If True, downward slope will be inversed. Useful to create
             biexponential curves. Defaults to True.
-        initToFirstVal : boolean, optional
+        initToFirstVal: boolean, optional
             If True, audio buffer will be filled at initialization with the
             first value of the line. Defaults to False.
 
@@ -513,19 +600,14 @@ class Expseg(PyoObject):
 
     """
     def __init__(self, list, loop=False, exp=10, inverse=True, initToFirstVal=False, mul=1, add=0):
+        pyoArgsAssert(self, "lbnbbOO", list, loop, exp, inverse, initToFirstVal, mul, add)
         PyoObject.__init__(self, mul, add)
-        if type(list) != ListType:
-            print >> sys.stderr, 'TypeError: "list" argument of %s must be a list of tuples.\n' % self.__class__.__name__
-            exit()
-        if type(list[0]) != TupleType:
-            print >> sys.stderr, 'TypeError: "list" argument of %s must be a list of tuples.\n' % self.__class__.__name__
-            exit()
         self._list = list
         self._loop = loop
         self._exp = exp
         self._inverse = inverse
         loop, exp, inverse, initToFirstVal, mul, add, lmax = convertArgsToLists(loop, exp, inverse, initToFirstVal, mul, add)
-        if type(list[0]) != ListType:
+        if type(list[0]) != list:
             self._base_objs = [Expseg_base(list, wrap(loop,i), wrap(exp,i), wrap(inverse,i), wrap(initToFirstVal,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
         else:
             listlen = len(list)
@@ -541,12 +623,13 @@ class Expseg(PyoObject):
 
         :Args:
 
-            x : list of tuples
+            x: list of tuples
                 new `list` attribute.
 
         """
+        pyoArgsAssert(self, "l", x)
         self._list = x
-        if type(x[0]) != ListType:
+        if type(x[0]) != list:
             [obj.setList(x) for i, obj in enumerate(self._base_objs)]
         else:
             [obj.setList(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -557,10 +640,11 @@ class Expseg(PyoObject):
 
         :Args:
 
-            x : boolean
+            x: boolean
                 new `loop` attribute.
 
         """
+        pyoArgsAssert(self, "b", x)
         self._loop = x
         x, lmax = convertArgsToLists(x)
         [obj.setLoop(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -571,10 +655,11 @@ class Expseg(PyoObject):
 
         :Args:
 
-            x : float
+            x: float
                 new `exp` attribute.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._exp = x
         x, lmax = convertArgsToLists(x)
         [obj.setExp(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -585,10 +670,11 @@ class Expseg(PyoObject):
 
         :Args:
 
-            x : boolean
+            x: boolean
                 new `inverse` attribute.
 
         """
+        pyoArgsAssert(self, "b", x)
         self._inverse = x
         x, lmax = convertArgsToLists(x)
         [obj.setInverse(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -599,12 +685,19 @@ class Expseg(PyoObject):
 
         :Args:
 
-            x : list of tuples
+            x: list of tuples
                 new `list` attribute.
 
         """
         self.setList(x)
 
+    def pause(self):
+        """
+        Toggles between play and stop mode without reset.
+
+        """
+        [obj.pause() for obj in self._base_objs]
+
     def getPoints(self):
         return self._list
 
@@ -613,37 +706,37 @@ class Expseg(PyoObject):
         Opens a grapher window to control the shape of the envelope.
 
         When editing the grapher with the mouse, the new set of points
-        will be send to the object on mouse up. 
+        will be send to the object on mouse up.
 
-        Ctrl+C with focus on the grapher will copy the list of points to the 
+        Ctrl+C with focus on the grapher will copy the list of points to the
         clipboard, giving an easy way to insert the new shape in a script.
 
         :Args:
 
-            xlen : float, optional
+            xlen: float, optional
                 Set the maximum value of the X axis of the graph. If None, the
                 maximum value is retrieve from the current list of points.
                 Defaults to None.
-            yrange : tuple, optional
+            yrange: tuple, optional
                 Set the min and max values of the Y axis of the graph. If
                 None, min and max are retrieve from the current list of points.
                 Defaults to None.
-            title : string, optional
-                Title of the window. If none is provided, the name of the 
+            title: string, optional
+                Title of the window. If none is provided, the name of the
                 class is used.
-            wxnoserver : boolean, optional
-                With wxPython graphical toolkit, if True, tells the 
+            wxnoserver: boolean, optional
+                With wxPython graphical toolkit, if True, tells the
                 interpreter that there will be no server window.
-                
-        If `wxnoserver` is set to True, the interpreter will not wait for the 
-        server GUI before showing the controller window. 
+
+        If `wxnoserver` is set to True, the interpreter will not wait for the
+        server GUI before showing the controller window.
 
         """
-        if xlen == None:
+        if xlen is None:
             xlen = float(self._list[-1][0])
         else:
             xlen = float(xlen)
-        if yrange == None:
+        if yrange is None:
             ymin = float(min([x[1] for x in self._list]))
             ymax = float(max([x[1] for x in self._list]))
             if ymin == ymax:
@@ -654,28 +747,28 @@ class Expseg(PyoObject):
 
     @property
     def list(self):
-        """float. List of points (time, value).""" 
+        """float. List of points (time, value)."""
         return self._list
     @list.setter
     def list(self, x): self.setList(x)
 
     @property
     def loop(self):
-        """boolean. Looping mode.""" 
+        """boolean. Looping mode."""
         return self._loop
     @loop.setter
     def loop(self, x): self.setLoop(x)
 
     @property
     def exp(self):
-        """float. Exponent factor.""" 
+        """float. Exponent factor."""
         return self._exp
     @exp.setter
     def exp(self, x): self.setExp(x)
 
     @property
     def inverse(self):
-        """boolean. Inverse downward slope.""" 
+        """boolean. Inverse downward slope."""
         return self._inverse
     @inverse.setter
     def inverse(self, x): self.setInverse(x)
@@ -683,22 +776,22 @@ class Expseg(PyoObject):
 class SigTo(PyoObject):
     """
     Convert numeric value to PyoObject signal with portamento.
-    
-    When `value` is changed, a ramp is applied from the current 
+
+    When `value` is changed, a ramp is applied from the current
     value to the new value. Can be used with PyoObject to apply
     a linear portamento on an audio signal.
-    
+
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        value : float or PyoObject
+        value: float or PyoObject
             Numerical value to convert.
-        time : float, optional
+        time: float or PyoObject, optional
             Ramp time, in seconds, to reach the new value. Defaults to 0.025.
-        init : float, optional
+        init: float, optional
             Initial value of the internal memory. Defaults to 0.
-    
+
     .. note::
 
         The out() method is bypassed. SigTo's signal can not be sent to audio outs.
@@ -715,11 +808,13 @@ class SigTo(PyoObject):
 
     """
     def __init__(self, value, time=0.025, init=0.0, mul=1, add=0):
+        pyoArgsAssert(self, "OOnOO", value, time, init, mul, add)
         PyoObject.__init__(self, mul, add)
         self._value = value
         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):
         """
@@ -727,10 +822,11 @@ class SigTo(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 Numerical value to convert.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._value = x
         x, lmax = convertArgsToLists(x)
         [obj.setValue(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -741,24 +837,29 @@ class SigTo(PyoObject):
 
         :Args:
 
-            x : float
-                New ramp time.
+            x: float or PyoObject
+                New ramp time in seconds.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._time = x
         x, lmax = convertArgsToLists(x)
         [obj.setTime(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, 10, 'lin', 'time', self._time)]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
     @property
     def value(self):
-        """float or PyoObject. Numerical value to convert.""" 
+        """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)
 
     @property
     def time(self):
-        """float. Ramp time.""" 
+        """floator PyoObject. Ramp time in seconds."""
         return self._time
     @time.setter
-    def time(self, x): self.setTime(x)    
+    def time(self, x): self.setTime(x)
diff --git a/pyolib/dynamics.py b/pyolib/dynamics.py
index 9e6abd8..1b45e52 100644
--- a/pyolib/dynamics.py
+++ b/pyolib/dynamics.py
@@ -3,43 +3,45 @@ Objects to modify the dynamic range and sample quality of audio signals.
 
 """
 
+from __future__ import absolute_import
 """
-Copyright 2010 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+You should have received a copy of the GNU Lesser General Public
+License along with pyo.  If not, see <http://www.gnu.org/licenses/>.
 """
-from _core import *
-from _maps import *
+
+from ._core import *
+from ._maps import *
 
 class Clip(PyoObject):
     """
     Clips a signal to a predefined limit.
-    
+
     :Parent: :py:class:`PyoObject`
 
     :Args:
-    
-        input : PyoObject
+
+        input: PyoObject
             Input signal to process.
-        min : float or PyoObject, optional
+        min: float or PyoObject, optional
             Minimum possible value. Defaults to -1.
-        max : float or PyoObject, optional
+        max: float or PyoObject, optional
             Maximum possible value. Defaults to 1.
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> a = SfPlayer(SNDS_PATH + "/transparent.aif", loop=True)
@@ -49,6 +51,7 @@ class Clip(PyoObject):
 
     """
     def __init__(self, input, min=-1.0, max=1.0, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOO", input, min, max, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._min = min
@@ -56,32 +59,35 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setMin(self, x):
         """
         Replace the `min` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `min` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._min = x
         x, lmax = convertArgsToLists(x)
         [obj.setMin(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -89,13 +95,14 @@ class Clip(PyoObject):
     def setMax(self, x):
         """
         Replace the `max` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `max` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._max = x
         x, lmax = convertArgsToLists(x)
         [obj.setMax(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -108,21 +115,21 @@ class Clip(PyoObject):
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def min(self):
-        """float or PyoObject. Minimum possible value.""" 
+        """float or PyoObject. Minimum possible value."""
         return self._min
     @min.setter
     def min(self, x): self.setMin(x)
 
     @property
     def max(self):
-        """float or PyoObject. Maximum possible value.""" 
+        """float or PyoObject. Maximum possible value."""
         return self._max
     @max.setter
     def max(self, x): self.setMax(x)
@@ -138,15 +145,15 @@ class Mirror(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        min : float or PyoObject, optional
+        min: float or PyoObject, optional
             Minimum possible value. Defaults to 0.
-        max : float or PyoObject, optional
+        max: float or PyoObject, optional
             Maximum possible value. Defaults to 1.
 
     .. note::
-    
+
         If `min` is higher than `max`, then the output will be the average of the two.
 
     >>> s = Server().boot()
@@ -159,6 +166,7 @@ class Mirror(PyoObject):
 
     """
     def __init__(self, input, min=0.0, max=1.0, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOO", input, min, max, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._min = min
@@ -166,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):
         """
@@ -173,12 +182,13 @@ class Mirror(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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)
 
@@ -188,10 +198,11 @@ class Mirror(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `min` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._min = x
         x, lmax = convertArgsToLists(x)
         [obj.setMin(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -202,10 +213,11 @@ class Mirror(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `max` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._max = x
         x, lmax = convertArgsToLists(x)
         [obj.setMax(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -218,21 +230,21 @@ class Mirror(PyoObject):
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def min(self):
-        """float or PyoObject. Minimum possible value.""" 
+        """float or PyoObject. Minimum possible value."""
         return self._min
     @min.setter
     def min(self, x): self.setMin(x)
 
     @property
     def max(self):
-        """float or PyoObject. Maximum possible value.""" 
+        """float or PyoObject. Maximum possible value."""
         return self._max
     @max.setter
     def max(self, x): self.setMax(x)
@@ -240,23 +252,23 @@ class Mirror(PyoObject):
 class Degrade(PyoObject):
     """
     Signal quality reducer.
-    
-    Degrade takes an audio signal and reduces the sampling rate and/or 
+
+    Degrade takes an audio signal and reduces the sampling rate and/or
     bit-depth as specified.
-    
+
     :Parent: :py:class:`PyoObject`
 
     :Args:
-    
-        input : PyoObject
+
+        input: PyoObject
             Input signal to process.
-        bitdepth : float or PyoObject, optional
+        bitdepth: float or PyoObject, optional
             Signal quantization in bits. Must be in range 1 -> 32.
             Defaults to 16.
-        srscale : float or PyoObject, optional
+        srscale: float or PyoObject, optional
             Sampling rate multiplier. Must be in range 0.0009765625 -> 1.
             Defaults to 1.
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> t = SquareTable()
@@ -264,9 +276,10 @@ class Degrade(PyoObject):
     >>> lfo = Sine(freq=.2, mul=6, add=8)
     >>> lfo2 = Sine(freq=.25, mul=.45, add=.55)
     >>> b = Degrade(a, bitdepth=lfo, srscale=lfo2, mul=.3).out()
-    
+
     """
     def __init__(self, input, bitdepth=16, srscale=1.0, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOO", input, bitdepth, srscale, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._bitdepth = bitdepth
@@ -274,32 +287,35 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setBitdepth(self, x):
         """
         Replace the `bitdepth` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `bitdepth` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._bitdepth = x
         x, lmax = convertArgsToLists(x)
         [obj.setBitdepth(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -307,13 +323,14 @@ class Degrade(PyoObject):
     def setSrscale(self, x):
         """
         Replace the `srscale` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `srscale` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._srscale = x
         x, lmax = convertArgsToLists(x)
         [obj.setSrscale(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -326,21 +343,21 @@ class Degrade(PyoObject):
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def bitdepth(self):
-        """float or PyoObject. Signal quantization in bits.""" 
+        """float or PyoObject. Signal quantization in bits."""
         return self._bitdepth
     @bitdepth.setter
     def bitdepth(self, x): self.setBitdepth(x)
 
     @property
     def srscale(self):
-        """float or PyoObject. Sampling rate multiplier.""" 
+        """float or PyoObject. Sampling rate multiplier."""
         return self._srscale
     @srscale.setter
     def srscale(self, x): self.setSrscale(x)
@@ -349,52 +366,53 @@ class Compress(PyoObject):
     """
     Reduces the dynamic range of an audio signal.
 
-    Compress reduces the volume of loud sounds or amplifies quiet sounds by 
+    Compress reduces the volume of loud sounds or amplifies quiet sounds by
     narrowing or compressing an audio signal's dynamic range.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        thresh : float or PyoObject, optional
-            Level, expressed in dB, above which the signal is reduced. 
+        thresh: float or PyoObject, optional
+            Level, expressed in dB, above which the signal is reduced.
             Reference level is 0dB. Defaults to -20.
-        ratio : float or PyoObject, optional
-            Determines the input/output ratio for signals above the 
+        ratio: float or PyoObject, optional
+            Determines the input/output ratio for signals above the
             threshold. Defaults to 2.
-        risetime : float or PyoObject, optional
-            Used in amplitude follower, time to reach upward value in 
+        risetime: float or PyoObject, optional
+            Used in amplitude follower, time to reach upward value in
             seconds. Defaults to 0.01.
-        falltime : float or PyoObject, optional
-            Used in amplitude follower, time to reach downward value in 
+        falltime: float or PyoObject, optional
+            Used in amplitude follower, time to reach downward value in
             seconds. Defaults to 0.1.
-        lookahead : float, optional
+        lookahead: float, optional
             Delay length, in ms, for the "look-ahead" buffer. Range is
             0 -> 25 ms. Defaults to 5.0.
-        knee : float optional
+        knee: float optional
             Shape of the transfert function around the threshold, specified
-            in the range 0 -> 1. 
-            
-            A value of 0 means a hard knee and a value of 1.0 means a softer 
+            in the range 0 -> 1.
+
+            A value of 0 means a hard knee and a value of 1.0 means a softer
             knee. Defaults to 0.
-        outputAmp : boolean, optional
+        outputAmp: boolean, optional
             If True, the object's output signal will be the compression level
-            alone, not the compressed signal. 
-            
-            It can be useful if 2 or more channels need to linked on the same 
+            alone, not the compressed signal.
+
+            It can be useful if 2 or more channels need to linked on the same
             compression slope. Defaults to False.
-            
-            Available at initialization only. 
+
+            Available at initialization only.
 
     >>> s = Server().boot()
     >>> s.start()
     >>> a = SfPlayer(SNDS_PATH + '/transparent.aif', loop=True)
     >>> b = Compress(a, thresh=-24, ratio=6, risetime=.01, falltime=.2, knee=0.5).mix(2).out()
-    
+
     """
     def __init__(self, input, thresh=-20, ratio=2, risetime=0.01, falltime=0.1, lookahead=5.0, knee=0, outputAmp=False, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOOnnbOO", input, thresh, ratio, risetime, falltime, lookahead, knee, outputAmp, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._thresh = thresh
@@ -406,60 +424,65 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setThresh(self, x):
         """
         Replace the `thresh` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `thresh` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._thresh = x
         x, lmax = convertArgsToLists(x)
         [obj.setThresh(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
- 
+
     def setRatio(self, x):
         """
         Replace the `ratio` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `ratio` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._ratio = x
         x, lmax = convertArgsToLists(x)
         [obj.setRatio(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
-        
+
     def setRiseTime(self, x):
         """
         Replace the `risetime` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `risetime` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._risetime = x
         x, lmax = convertArgsToLists(x)
         [obj.setRiseTime(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -467,13 +490,14 @@ class Compress(PyoObject):
     def setFallTime(self, x):
         """
         Replace the `falltime` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `falltime` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._falltime = x
         x, lmax = convertArgsToLists(x)
         [obj.setFallTime(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -484,10 +508,11 @@ class Compress(PyoObject):
 
         :Args:
 
-            x : float
+            x: float
                 New `lookahead` attribute.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._lookahead = x
         x, lmax = convertArgsToLists(x)
         [obj.setLookAhead(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -498,46 +523,49 @@ class Compress(PyoObject):
 
         :Args:
 
-            x : float
+            x: float
                 New `knee` attribute.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._knee = x
         x, lmax = convertArgsToLists(x)
         [obj.setKnee(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(-60., 0., 'lin', 'thresh',  self._thresh),
-                          SLMap(1., 10., 'lin', 'ratio',  self._ratio),
-                          SLMap(0.001, .3, 'lin', 'risetime',  self._risetime),
-                          SLMap(0.001, .3, 'lin', 'falltime',  self._falltime),
+        self._map_list = [SLMap(-60., 0., 'lin', 'thresh', self._thresh),
+                          SLMap(1., 10., 'lin', 'ratio', self._ratio),
+                          SLMap(0.001, .3, 'lin', 'risetime', self._risetime),
+                          SLMap(0.001, .3, 'lin', 'falltime', self._falltime),
+                          SLMap(0, 25, 'lin', 'lookahead', self._lookahead, dataOnly=True),
+                          SLMap(0, 1, 'lin', 'knee', self._knee, dataOnly=True),
                           SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def thresh(self):
-        """float or PyoObject. Level above which the signal is reduced.""" 
+        """float or PyoObject. Level above which the signal is reduced."""
         return self._thresh
     @thresh.setter
     def thresh(self, x): self.setThresh(x)
 
     @property
     def ratio(self):
-        """float or PyoObject. in/out ratio for signals above the threshold.""" 
+        """float or PyoObject. in/out ratio for signals above the threshold."""
         return self._ratio
     @ratio.setter
     def ratio(self, x): self.setRatio(x)
 
     @property
     def risetime(self):
-        """float or PyoObject. Time to reach upward value in seconds.""" 
+        """float or PyoObject. Time to reach upward value in seconds."""
         return self._risetime
     @risetime.setter
     def risetime(self, x): self.setRiseTime(x)
@@ -548,7 +576,7 @@ class Compress(PyoObject):
         return self._falltime
     @falltime.setter
     def falltime(self, x): self.setFallTime(x)
-    
+
     @property
     def lookahead(self):
         """float. Delay length, in ms, of the "look-ahead" buffer."""
@@ -567,35 +595,35 @@ class Gate(PyoObject):
     """
     Allows a signal to pass only when its amplitude is above a set threshold.
 
-    A noise gate is used when the level of the signal is below the level of 
-    the noise floor. The threshold is set above the level of the noise and so when 
-    there is no signal the gate is closed. A noise gate does not remove noise 
-    from the signal. When the gate is open both the signal and the noise will 
+    A noise gate is used when the level of the signal is below the level of
+    the noise floor. The threshold is set above the level of the noise and so when
+    there is no signal the gate is closed. A noise gate does not remove noise
+    from the signal. When the gate is open both the signal and the noise will
     pass through.
-    
+
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        thresh : float or PyoObject, optional
-            Level, expressed in dB, below which the gate is closed. 
+        thresh: float or PyoObject, optional
+            Level, expressed in dB, below which the gate is closed.
             Reference level is 0dB. Defaults to -70.
-        risetime : float or PyoObject, optional
+        risetime: float or PyoObject, optional
             Time to open the gate in seconds. Defaults to 0.01.
-        falltime : float or PyoObject, optional
+        falltime: float or PyoObject, optional
             Time to close the gate in seconds. Defaults to 0.05.
-        lookahead : float, optional
+        lookahead: float, optional
             Delay length, in ms, for the "look-ahead" buffer. Range is
             0 -> 25 ms. Defaults to 5.0.
-        outputAmp : boolean, optional
+        outputAmp: boolean, optional
             If True, the object's output signal will be the gating level
-            alone, not the gated signal. 
-            
-            It can be useful if 2 or more channels need to linked on the 
+            alone, not the gated signal.
+
+            It can be useful if 2 or more channels need to linked on the
             same gating slope. Defaults to False.
-            
+
             Available at initialization only.
 
     >>> s = Server().boot()
@@ -605,6 +633,7 @@ class Gate(PyoObject):
 
     """
     def __init__(self, input, thresh=-70, risetime=0.01, falltime=0.05, lookahead=5.0, outputAmp=False, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOnbOO", input, thresh, risetime, falltime, lookahead, outputAmp, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._thresh = thresh
@@ -614,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):
         """
@@ -621,12 +651,13 @@ class Gate(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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)
 
@@ -636,10 +667,11 @@ class Gate(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `thresh` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._thresh = x
         x, lmax = convertArgsToLists(x)
         [obj.setThresh(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -650,10 +682,11 @@ class Gate(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `risetime` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._risetime = x
         x, lmax = convertArgsToLists(x)
         [obj.setRiseTime(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -664,10 +697,11 @@ class Gate(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `falltime` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._falltime = x
         x, lmax = convertArgsToLists(x)
         [obj.setFallTime(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -678,38 +712,40 @@ class Gate(PyoObject):
 
         :Args:
 
-            x : float
+            x: float
                 New `lookahead` attribute.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._lookahead = x
         x, lmax = convertArgsToLists(x)
         [obj.setLookAhead(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(-100., 0., 'lin', 'thresh',  self._thresh),
-                          SLMap(0.0001, .3, 'lin', 'risetime',  self._risetime),
-                          SLMap(0.0001, .3, 'lin', 'falltime',  self._falltime),
+        self._map_list = [SLMap(-100., 0., 'lin', 'thresh', self._thresh),
+                          SLMap(0.0001, .3, 'lin', 'risetime', self._risetime),
+                          SLMap(0.0001, .3, 'lin', 'falltime', self._falltime),
+                          SLMap(0, 25, 'lin', 'lookahead', self._lookahead, dataOnly=True),
                           SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def thresh(self):
-        """float or PyoObject. Level below which the gate is closed.""" 
+        """float or PyoObject. Level below which the gate is closed."""
         return self._thresh
     @thresh.setter
     def thresh(self, x): self.setThresh(x)
 
     @property
     def risetime(self):
-        """float or PyoObject. Time to open the gate in seconds.""" 
+        """float or PyoObject. Time to open the gate in seconds."""
         return self._risetime
     @risetime.setter
     def risetime(self, x): self.setRiseTime(x)
@@ -738,11 +774,11 @@ class Balance(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        input2 : PyoObject
+        input2: PyoObject
             Comparator signal.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Cutoff frequency of the lowpass filter in hertz. Default to 10.
 
     >>> s = Server().boot()
@@ -753,6 +789,7 @@ class Balance(PyoObject):
 
     """
     def __init__(self, input, input2, freq=10, mul=1, add=0):
+        pyoArgsAssert(self, "ooOOO", input, input2, freq, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._input2 = input2
@@ -761,53 +798,57 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         Input signal to process.
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     def setInput2(self, x, fadetime=0.05):
         """
         Replace the `input2` attribute.
-        
+
         Comparator signal.
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input2 = x
         self._in_fader2.setInput(x, fadetime)
 
     def setFreq(self, x):
         """
         Replace the `freq` attribute.
-        
+
         Cutoff frequency of the lowpass filter, in Hertz.
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `freq` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -818,21 +859,21 @@ class Balance(PyoObject):
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def input2(self):
-        """PyoObject. Comparator signal.""" 
+        """PyoObject. Comparator signal."""
         return self._input2
     @input2.setter
     def input2(self, x): self.setInput2(x)
 
     @property
     def freq(self):
-        """float or PyoObject. Cutoff frequency of the lowpass filter.""" 
+        """float or PyoObject. Cutoff frequency of the lowpass filter."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
@@ -840,17 +881,17 @@ class Balance(PyoObject):
 class Min(PyoObject):
     """
     Outputs the minimum of two values.
- 
+
     :Parent: :py:class:`PyoObject`
-   
+
     :Args:
-    
-        input : PyoObject
+
+        input: PyoObject
             Input signal to process.
-        comp : float or PyoObject, optional
+        comp: float or PyoObject, optional
             Comparison value. If `input` is lower than this value,
             `input` is send to the output, otherwise, `comp` is outputted.
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> # Triangle wave
@@ -860,38 +901,42 @@ class Min(PyoObject):
 
     """
     def __init__(self, input, comp=0.5, mul=1, add=0):
+        pyoArgsAssert(self, "oOOO", input, comp, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._comp = comp
         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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
-        
+
     def setComp(self, x):
         """
         Replace the `comp` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `comp` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._comp = x
         x, lmax = convertArgsToLists(x)
         [obj.setComp(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -899,17 +944,17 @@ class Min(PyoObject):
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMap(0,1,"lin", "comp", self._comp), SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
-      
+
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def comp(self):
-        """float or PyoObject. Comparison value.""" 
+        """float or PyoObject. Comparison value."""
         return self._comp
     @comp.setter
     def comp(self, x): self.setComp(x)
@@ -917,17 +962,17 @@ class Min(PyoObject):
 class Max(PyoObject):
     """
     Outputs the maximum of two values.
- 
+
     :Parent: :py:class:`PyoObject`
-   
+
     :Args:
-    
-        input : PyoObject
+
+        input: PyoObject
             Input signal to process.
-        comp : float or PyoObject, optional
+        comp: float or PyoObject, optional
             Comparison value. If `input` is higher than this value,
             `input` is send to the output, otherwise, `comp` is outputted.
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> # Assimetrical clipping
@@ -937,38 +982,42 @@ class Max(PyoObject):
 
     """
     def __init__(self, input, comp=0.5, mul=1, add=0):
+        pyoArgsAssert(self, "oOOO", input, comp, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._comp = comp
         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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
-        
+
     def setComp(self, x):
         """
         Replace the `comp` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `comp` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._comp = x
         x, lmax = convertArgsToLists(x)
         [obj.setComp(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -976,17 +1025,17 @@ class Max(PyoObject):
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMap(0,1,"lin", "comp", self._comp), SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
-      
+
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def comp(self):
-        """float or PyoObject. Comparison value.""" 
+        """float or PyoObject. Comparison value."""
         return self._comp
     @comp.setter
     def comp(self, x): self.setComp(x)
diff --git a/pyolib/effects.py b/pyolib/effects.py
index 09024ed..221025b 100644
--- a/pyolib/effects.py
+++ b/pyolib/effects.py
@@ -4,45 +4,63 @@ as distortions, delays, chorus and reverbs.
 
 """
 
+from __future__ import absolute_import
 """
-Copyright 2010 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+You should have received a copy of the GNU Lesser General Public
+License along with pyo.  If not, see <http://www.gnu.org/licenses/>.
 """
-from _core import *
-from _maps import *
+
+from ._core import *
+from ._maps import *
+from .generators import Sine
+from .filters import Hilbert
 
 class Disto(PyoObject):
     """
-    Arc tangent distortion.
+    Kind of Arc tangent distortion.
+
+    Apply a kind of arc tangent distortion with controllable drive, followed
+    by a one pole lowpass filter, to the input signal.
+
+    As of version 0.8.0, this object use a simple but very efficient (4x
+    faster than tanh or atan2 functions) waveshaper formula describe here:
+
+    http://musicdsp.org/archive.php?classid=4#46
+
+    The waveshaper algorithm is:
+
+        y[n] = (1 + k) * x[n] / (1 + k * abs(x[n]))
 
-    Apply an arc tangent distortion with controllable drive to the input signal. 
+    where:
+
+        k = (2 * drive) / (1 - drive)
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        drive : float or PyoObject, optional
-            Amount of distortion applied to the signal, between 0 and 1. 
+        drive: float or PyoObject, optional
+            Amount of distortion applied to the signal, between 0 and 1.
             Defaults to 0.75.
-        slope : float or PyoObject, optional
-            Slope of the lowpass filter applied after distortion, 
+        slope: float or PyoObject, optional
+            Slope of the lowpass filter applied after distortion,
             between 0 and 1. Defaults to 0.5.
 
     >>> s = Server().boot()
@@ -53,6 +71,7 @@ class Disto(PyoObject):
 
     """
     def __init__(self, input, drive=.75, slope=.5, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOO", input, drive, slope, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._drive = drive
@@ -60,32 +79,35 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setDrive(self, x):
         """
         Replace the `drive` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `drive` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._drive = x
         x, lmax = convertArgsToLists(x)
         [obj.setDrive(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -93,13 +115,14 @@ class Disto(PyoObject):
     def setSlope(self, x):
         """
         Replace the `slope` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `slope` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._slope = x
         x, lmax = convertArgsToLists(x)
         [obj.setSlope(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -112,21 +135,21 @@ class Disto(PyoObject):
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def drive(self):
-        """float or PyoObject. Amount of distortion.""" 
+        """float or PyoObject. Amount of distortion."""
         return self._drive
     @drive.setter
     def drive(self, x): self.setDrive(x)
 
     @property
     def slope(self):
-        """float or PyoObject. Slope of the lowpass filter.""" 
+        """float or PyoObject. Slope of the lowpass filter."""
         return self._slope
     @slope.setter
     def slope(self, x): self.setSlope(x)
@@ -139,17 +162,28 @@ class Delay(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to delayed.
-        delay : float or PyoObject, optional
+        delay: float or PyoObject, optional
             Delay time in seconds. Defaults to 0.25.
-        feedback : float or PyoObject, optional
+        feedback: float or PyoObject, optional
             Amount of output signal sent back into the delay line.
             Defaults to 0.
-        maxdelay : float, optional
-            Maximum delay length in seconds. Available only at initialization. 
+        maxdelay: float, optional
+            Maximum delay length in seconds. Available only at initialization.
             Defaults to 1.
 
+    .. note::
+
+        The minimum delay time allowed with Delay is one sample. It can be computed
+        with :
+
+        onesamp = 1.0 / s.getSamplingRate()
+
+    .. seealso::
+
+        :py:class:`SDelay`, :py:class:`Waveguide`
+
     >>> s = Server().boot()
     >>> s.start()
     >>> a = SfPlayer(SNDS_PATH + "/transparent.aif", loop=True, mul=.3).mix(2).out()
@@ -157,6 +191,7 @@ class Delay(PyoObject):
 
     """
     def __init__(self, input, delay=0.25, feedback=0, maxdelay=1, mul=1, add=0):
+        pyoArgsAssert(self, "oOOnOO", input, delay, feedback, maxdelay, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._delay = delay
@@ -165,32 +200,35 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to delayed.
-            fadetime : float, optional
+            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 setDelay(self, x):
         """
         Replace the `delay` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `delay` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._delay = x
         x, lmax = convertArgsToLists(x)
         [obj.setDelay(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -198,13 +236,14 @@ class Delay(PyoObject):
     def setFeedback(self, x):
         """
         Replace the `feedback` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `feedback` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._feedback = x
         x, lmax = convertArgsToLists(x)
         [obj.setFeedback(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -212,33 +251,33 @@ class Delay(PyoObject):
     def reset(self):
         """
         Reset the memory buffer to zeros.
-        
+
         """
         [obj.reset() for obj in self._base_objs]
 
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
-        self._map_list = [SLMap(0.001, self._maxdelay, 'log', 'delay',  self._delay),
+        self._map_list = [SLMap(0.001, self._maxdelay, 'log', 'delay', self._delay),
                           SLMap(0., 1., 'lin', 'feedback', self._feedback),
                           SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def input(self):
-        """PyoObject. Input signal to delayed.""" 
+        """PyoObject. Input signal to delayed."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
- 
+
     @property
     def delay(self):
-        """float or PyoObject. Delay time in seconds.""" 
+        """float or PyoObject. Delay time in seconds."""
         return self._delay
     @delay.setter
     def delay(self, x): self.setDelay(x)
 
     @property
     def feedback(self):
-        """float or PyoObject. Amount of output signal sent back into the delay line.""" 
+        """float or PyoObject. Amount of output signal sent back into the delay line."""
         return self._feedback
     @feedback.setter
     def feedback(self, x): self.setFeedback(x)
@@ -251,14 +290,18 @@ class SDelay(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to delayed.
-        delay : float or PyoObject, optional
+        delay: float or PyoObject, optional
             Delay time in seconds. Defaults to 0.25.
-        maxdelay : float, optional
-            Maximum delay length in seconds. Available only at initialization. 
+        maxdelay: float, optional
+            Maximum delay length in seconds. Available only at initialization.
             Defaults to 1.
 
+    .. seealso::
+
+        :py:class:`Delay`, :py:class:`Delay1`
+
     >>> s = Server().boot()
     >>> s.start()
     >>> srPeriod = 1. / s.getSamplingRate()
@@ -268,6 +311,7 @@ class SDelay(PyoObject):
 
     """
     def __init__(self, input, delay=0.25, maxdelay=1, mul=1, add=0):
+        pyoArgsAssert(self, "oOnOO", input, delay, maxdelay, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._delay = delay
@@ -275,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):
         """
@@ -282,12 +327,13 @@ class SDelay(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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)
 
@@ -297,10 +343,11 @@ class SDelay(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `delay` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._delay = x
         x, lmax = convertArgsToLists(x)
         [obj.setDelay(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -308,25 +355,25 @@ class SDelay(PyoObject):
     def reset(self):
         """
         Reset the memory buffer to zeros.
-        
+
         """
         [obj.reset() for obj in self._base_objs]
 
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
-        self._map_list = [SLMap(0.001, self._maxdelay, 'log', 'delay',  self._delay),
+        self._map_list = [SLMap(0.0001, self._maxdelay, 'log', 'delay', self._delay),
                           SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def input(self):
-        """PyoObject. Input signal to delayed.""" 
+        """PyoObject. Input signal to delayed."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def delay(self):
-        """float or PyoObject. Delay time in seconds.""" 
+        """float or PyoObject. Delay time in seconds."""
         return self._delay
     @delay.setter
     def delay(self, x): self.setDelay(x)
@@ -335,23 +382,23 @@ class Waveguide(PyoObject):
     """
     Basic waveguide model.
 
-    This waveguide model consisting of one delay-line with a simple 
+    This waveguide model consisting of one delay-line with a simple
     lowpass filtering and lagrange interpolation.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        freq : float or PyoObject, optional
-            Frequency, in cycle per second, of the waveguide (i.e. the inverse 
+        freq: float or PyoObject, optional
+            Frequency, in cycle per second, of the waveguide (i.e. the inverse
             of delay time). Defaults to 100.
-        dur : float or PyoObject, optional
-            Duration, in seconds, for the waveguide to drop 40 dB below it's 
+        dur: float or PyoObject, optional
+            Duration, in seconds, for the waveguide to drop 40 dB below it's
             maxima. Defaults to 10.
-        minfreq : float, optional
-            Minimum possible frequency, used to initialized delay length. 
+        minfreq: float, optional
+            Minimum possible frequency, used to initialized delay length.
             Available only at initialization. Defaults to 20.
 
     >>> s = Server().boot()
@@ -362,6 +409,7 @@ class Waveguide(PyoObject):
 
     """
     def __init__(self, input, freq=100, dur=10, minfreq=20, mul=1, add=0):
+        pyoArgsAssert(self, "oOOnOO", input, freq, dur, minfreq, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._freq = freq
@@ -369,32 +417,35 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setFreq(self, x):
         """
         Replace the `freq` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `freq` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -402,40 +453,48 @@ class Waveguide(PyoObject):
     def setDur(self, x):
         """
         Replace the `dur` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            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_objs)]
 
+    def reset(self):
+        """
+        Reset the memory buffer to zeros.
+
+        """
+        [obj.reset() for obj in self._base_objs]
+
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
-        self._map_list = [SLMap(10, 500., 'log', 'freq',  self._freq),
+        self._map_list = [SLMap(10, 500., 'log', 'freq', self._freq),
                           SLMapDur(self._dur),
                           SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
- 
+
     @property
     def freq(self):
-        """float or PyoObject. Frequency in cycle per second.""" 
+        """float or PyoObject. Frequency in cycle per second."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
     def dur(self):
-        """float or PyoObject. Resonance duration in seconds.""" 
+        """float or PyoObject. Resonance duration in seconds."""
         return self._dur
     @dur.setter
     def dur(self, x): self.setDur(x)
@@ -451,19 +510,19 @@ class AllpassWG(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        freq : float or PyoObject, optional
-            Frequency, in cycle per second, of the waveguide (i.e. the inverse 
+        freq: float or PyoObject, optional
+            Frequency, in cycle per second, of the waveguide (i.e. the inverse
             of delay time). Defaults to 100.
-        feed : float or PyoObject, optional
+        feed: float or PyoObject, optional
             Amount of output signal (between 0 and 1) sent back into the delay line.
             Defaults to 0.95.
-        detune : float or PyoObject, optional
-            Control the depth of the allpass delay-line filter, i.e. the depth of 
+        detune: float or PyoObject, optional
+            Control the depth of the allpass delay-line filter, i.e. the depth of
             the detuning. Should be in the range 0 to 1. Defaults to 0.5.
-        minfreq : float, optional
-            Minimum possible frequency, used to initialized delay length. 
+        minfreq: float, optional
+            Minimum possible frequency, used to initialized delay length.
             Available only at initialization. Defaults to 20.
 
     >>> s = Server().boot()
@@ -476,6 +535,7 @@ class AllpassWG(PyoObject):
 
     """
     def __init__(self, input, freq=100, feed=0.95, detune=0.5, minfreq=20, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOnOO", input, freq, feed, detune, minfreq, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._freq = freq
@@ -484,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):
         """
@@ -491,12 +552,13 @@ class AllpassWG(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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)
 
@@ -506,10 +568,11 @@ class AllpassWG(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `freq` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -520,10 +583,11 @@ class AllpassWG(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `feed` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._feed = x
         x, lmax = convertArgsToLists(x)
         [obj.setFeed(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -534,16 +598,24 @@ class AllpassWG(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `detune` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._detune = x
         x, lmax = convertArgsToLists(x)
         [obj.setDetune(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
+    def reset(self):
+        """
+        Reset the memory buffer to zeros.
+
+        """
+        [obj.reset() for obj in self._base_objs]
+
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
-        self._map_list = [SLMap(20., 500., 'log', 'freq',  self._freq),
+        self._map_list = [SLMap(20., 500., 'log', 'freq', self._freq),
                           SLMap(0., 1., 'lin', 'feed', self._feed),
                           SLMap(0., 1., 'lin', 'detune', self._detune),
                           SLMapMul(self._mul)]
@@ -551,28 +623,28 @@ class AllpassWG(PyoObject):
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def freq(self):
-        """float or PyoObject. Frequency in cycle per second.""" 
+        """float or PyoObject. Frequency in cycle per second."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
     def feed(self):
-        """float or PyoObject. Amount of output signal sent back into the delay line.""" 
+        """float or PyoObject. Amount of output signal sent back into the delay line."""
         return self._feed
     @feed.setter
     def feed(self, x): self.setFeed(x)
 
     @property
     def detune(self):
-        """float or PyoObject. Depth of the detuning.""" 
+        """float or PyoObject. Depth of the detuning."""
         return self._detune
     @detune.setter
     def detune(self, x): self.setDetune(x)
@@ -581,26 +653,26 @@ class Freeverb(PyoObject):
     """
     Implementation of Jezar's Freeverb.
 
-    Freeverb is a reverb unit generator based on Jezar's public domain 
-    C++ sources, composed of eight parallel comb filters, followed by four 
-    allpass units in series. Filters on each stream are slightly detuned 
+    Freeverb is a reverb unit generator based on Jezar's public domain
+    C++ sources, composed of eight parallel comb filters, followed by four
+    allpass units in series. Filters on each stream are slightly detuned
     in order to create multi-channel effects.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        size : float or PyoObject, optional
-            Controls the length of the reverb,  between 0 and 1. A higher 
+        size: float or PyoObject, optional
+            Controls the length of the reverb,  between 0 and 1. A higher
             value means longer reverb. Defaults to 0.5.
-        damp : float or PyoObject, optional
-            High frequency attenuation, between 0 and 1. A higher value 
-            will result in a faster decay of the high frequency range. 
+        damp: float or PyoObject, optional
+            High frequency attenuation, between 0 and 1. A higher value
+            will result in a faster decay of the high frequency range.
             Defaults to 0.5.
-        bal : float or PyoObject, optional
-            Balance between wet and dry signal, between 0 and 1. 0 means no 
+        bal: float or PyoObject, optional
+            Balance between wet and dry signal, between 0 and 1. 0 means no
             reverb. Defaults to 0.5.
 
     >>> s = Server().boot()
@@ -610,6 +682,7 @@ class Freeverb(PyoObject):
 
     """
     def __init__(self, input, size=.5, damp=.5, bal=.5, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOOO", input, size, damp, bal, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._size = size
@@ -618,32 +691,35 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setSize(self, x):
         """
         Replace the `size` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `size` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._size = x
         x, lmax = convertArgsToLists(x)
         [obj.setSize(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -651,13 +727,14 @@ class Freeverb(PyoObject):
     def setDamp(self, x):
         """
         Replace the `damp` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `damp` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._damp = x
         x, lmax = convertArgsToLists(x)
         [obj.setDamp(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -665,48 +742,56 @@ class Freeverb(PyoObject):
     def setBal(self, x):
         """
         Replace the `bal` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `bal` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._bal = x
         x, lmax = convertArgsToLists(x)
         [obj.setMix(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
+    def reset(self):
+        """
+        Reset the memory buffer to zeros.
+
+        """
+        [obj.reset() for obj in self._base_objs]
+
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
-        self._map_list = [SLMap(0., 1., 'lin', 'size',  self._size),
-                          SLMap(0., 1., 'lin', 'damp',  self._damp),
-                          SLMap(0., 1., 'lin', 'bal',  self._bal),
+        self._map_list = [SLMap(0., 1., 'lin', 'size', self._size),
+                          SLMap(0., 1., 'lin', 'damp', self._damp),
+                          SLMap(0., 1., 'lin', 'bal', self._bal),
                           SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def size(self):
-        """float or PyoObject. Room size.""" 
+        """float or PyoObject. Room size."""
         return self._size
     @size.setter
     def size(self, x): self.setSize(x)
 
     @property
     def damp(self):
-        """float or PyoObject. High frequency damping.""" 
+        """float or PyoObject. High frequency damping."""
         return self._damp
     @damp.setter
     def damp(self, x): self.setDamp(x)
 
     @property
     def bal(self):
-        """float or PyoObject. Balance between wet and dry signal.""" 
+        """float or PyoObject. Balance between wet and dry signal."""
         return self._bal
     @bal.setter
     def bal(self, x): self.setBal(x)
@@ -715,24 +800,24 @@ class Convolve(PyoObject):
     """
     Implements filtering using circular convolution.
 
-    A circular convolution is defined as the integral of the product of two 
+    A circular convolution is defined as the integral of the product of two
     functions after one is reversed and shifted.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        table : PyoTableObject
+        table: PyoTableObject
             Table containning the impulse response.
-        size : int
-            Length, in samples, of the convolution. Available at initialization 
-            time only. 
-            
-            If the table changes during the performance, its size must egal or 
-            greater than this value. 
-            
+        size: int
+            Length, in samples, of the convolution. Available at initialization
+            time only.
+
+            If the table changes during the performance, its size must egal or
+            greater than this value.
+
             If greater only the first `size` samples will be used.
 
     .. note::
@@ -742,9 +827,9 @@ class Convolve(PyoObject):
 
         Usually convolution generates a high amplitude level, take care of the
         `mul` parameter!
-        
+
     .. seealso::
-        
+
         :py:class:`Follower`
 
     >>> s = Server().boot()
@@ -755,82 +840,86 @@ class Convolve(PyoObject):
 
     """
     def __init__(self, input, table, size, mul=1, add=0):
+        pyoArgsAssert(self, "otiOO", input, table, size, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._table = table
         self._size = size
         self._in_fader = InputFader(input)
-        in_fader, table, size, mul, add, lmax = convertArgsToLists(self._in_fader, table, size, mul, add)                     
+        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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default 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
+            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)]
 
     @property
     def input(self):
-        """PyoObject. Input signal to filter.""" 
+        """PyoObject. Input signal to filter."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def table(self):
-        """PyoTableObject. Table containing the impulse response.""" 
+        """PyoTableObject. Table containing the impulse response."""
         return self._table
     @table.setter
     def table(self, x): self.setTable(x)
 
 class WGVerb(PyoObject):
     """
-    8 delay line mono FDN reverb.
+    8 delay lines mono FDN reverb.
 
-    8 delay line FDN reverb, with feedback matrix based upon physical 
-    modeling scattering junction of 8 lossless waveguides of equal 
+    8 delay lines FDN reverb, with feedback matrix based upon physical
+    modeling scattering junction of 8 lossless waveguides of equal
     characteristic impedance.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        feedback : float or PyoObject, optional
+        feedback: float or PyoObject, optional
             Amount of output signal sent back into the delay lines.
             Defaults to 0.5.
 
-            0.6 gives a good small "live" room sound, 0.8 a small hall, 
+            0.6 gives a good small "live" room sound, 0.8 a small hall,
             and 0.9 a large hall.
-        cutoff : float or PyoObject, optional
-            cutoff frequency of simple first order lowpass filters in the 
+        cutoff: float or PyoObject, optional
+            cutoff frequency of simple first order lowpass filters in the
             feedback loop of delay lines, in Hz. Defaults to 5000.
-        bal : float or PyoObject, optional
-            Balance between wet and dry signal, between 0 and 1. 0 means no 
+        bal: float or PyoObject, optional
+            Balance between wet and dry signal, between 0 and 1. 0 means no
             reverb. Defaults to 0.5.
 
     >>> s = Server().boot()
@@ -840,6 +929,7 @@ class WGVerb(PyoObject):
 
     """
     def __init__(self, input, feedback=0.5, cutoff=5000, bal=0.5, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOOO", input, feedback, cutoff, bal, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._feedback = feedback
@@ -848,32 +938,35 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setFeedback(self, x):
         """
         Replace the `feedback` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `feedback` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._feedback = x
         x, lmax = convertArgsToLists(x)
         [obj.setFeedback(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -881,13 +974,14 @@ class WGVerb(PyoObject):
     def setCutoff(self, x):
         """
         Replace the `cutoff` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `cutoff` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._cutoff = x
         x, lmax = convertArgsToLists(x)
         [obj.setCutoff(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -895,17 +989,25 @@ class WGVerb(PyoObject):
     def setBal(self, x):
         """
         Replace the `bal` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `bal` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._bal = x
         x, lmax = convertArgsToLists(x)
         [obj.setMix(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
+    def reset(self):
+        """
+        Reset the memory buffer to zeros.
+
+        """
+        [obj.reset() for obj in self._base_objs]
+
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMap(0., 1., 'lin', 'feedback', self._feedback),
                           SLMap(500., 15000., 'log', 'cutoff', self._cutoff),
@@ -915,28 +1017,28 @@ class WGVerb(PyoObject):
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def feedback(self):
-        """float or PyoObject. Amount of output signal sent back into the delay lines.""" 
+        """float or PyoObject. Amount of output signal sent back into the delay lines."""
         return self._feedback
     @feedback.setter
     def feedback(self, x): self.setFeedback(x)
 
     @property
     def cutoff(self):
-        """float or PyoObject. Lowpass filter cutoff in Hz.""" 
+        """float or PyoObject. Lowpass filter cutoff in Hz."""
         return self._cutoff
     @cutoff.setter
     def cutoff(self, x): self.setCutoff(x)
 
     @property
     def bal(self):
-        """float or PyoObject. wet - dry balance.""" 
+        """float or PyoObject. wet - dry balance."""
         return self._bal
     @bal.setter
     def bal(self, x): self.setBal(x)
@@ -945,22 +1047,22 @@ class Chorus(PyoObject):
     """
     8 modulated delay lines chorus processor.
 
-    A chorus effect occurs when individual sounds with roughly the same timbre and 
+    A chorus effect occurs when individual sounds with roughly the same timbre and
     nearly (but never exactly) the same pitch converge and are perceived as one.
-    
+
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        depth : float or PyoObject, optional
+        depth: float or PyoObject, optional
             Chorus depth, between 0 and 5. Defaults to 1.
-        feedback : float or PyoObject, optional
+        feedback: float or PyoObject, optional
             Amount of output signal sent back into the delay lines.
             Defaults to 0.25.
-        bal : float or PyoObject, optional
-            Balance between wet and dry signals, between 0 and 1. 0 means no 
+        bal: float or PyoObject, optional
+            Balance between wet and dry signals, between 0 and 1. 0 means no
             chorus. Defaults to 0.5.
 
     >>> s = Server().boot()
@@ -970,6 +1072,7 @@ class Chorus(PyoObject):
 
     """
     def __init__(self, input, depth=1, feedback=0.25, bal=0.5, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOOO", input, depth, feedback, bal, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._depth = depth
@@ -978,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):
         """
@@ -985,12 +1089,13 @@ class Chorus(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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)
 
@@ -1000,10 +1105,11 @@ class Chorus(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `depth` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._depth = x
         x, lmax = convertArgsToLists(x)
         [obj.setDepth(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1014,10 +1120,11 @@ class Chorus(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `feedback` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._feedback = x
         x, lmax = convertArgsToLists(x)
         [obj.setFeedback(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1028,14 +1135,22 @@ class Chorus(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `bal` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._bal = x
         x, lmax = convertArgsToLists(x)
         [obj.setMix(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
+    def reset(self):
+        """
+        Reset the memory buffer to zeros.
+
+        """
+        [obj.reset() for obj in self._base_objs]
+
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMap(0., 5., 'lin', 'depth', self._depth),
                           SLMap(0., 1., 'lin', 'feedback', self._feedback),
@@ -1045,28 +1160,28 @@ class Chorus(PyoObject):
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def depth(self):
-        """float or PyoObject. Chorus depth, between 0 and 5.""" 
+        """float or PyoObject. Chorus depth, between 0 and 5."""
         return self._depth
     @depth.setter
     def depth(self, x): self.setDepth(x)
 
     @property
     def feedback(self):
-        """float or PyoObject. Amount of output signal sent back into the delay lines.""" 
+        """float or PyoObject. Amount of output signal sent back into the delay lines."""
         return self._feedback
     @feedback.setter
     def feedback(self, x): self.setFeedback(x)
 
     @property
     def bal(self):
-        """float or PyoObject. wet - dry balance.""" 
+        """float or PyoObject. wet - dry balance."""
         return self._bal
     @bal.setter
     def bal(self, x): self.setBal(x)
@@ -1079,15 +1194,15 @@ class Harmonizer(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        transpo : float or PyoObject, optional
+        transpo: float or PyoObject, optional
            Transposition factor in semitone. Defaults to -7.0.
-        feedback : float or PyoObject, optional
+        feedback: float or PyoObject, optional
             Amount of output signal sent back into the delay line.
             Defaults to 0.
-        winsize : float, optional
-            Window size in seconds (max = 1.0). 
+        winsize: float, optional
+            Window size in seconds (max = 1.0).
             Defaults to 0.1.
 
     >>> s = Server().boot()
@@ -1097,6 +1212,7 @@ class Harmonizer(PyoObject):
 
     """
     def __init__(self, input, transpo=-7.0, feedback=0, winsize=0.1, mul=1, add=0):
+        pyoArgsAssert(self, "oOOnOO", input, transpo, feedback, winsize, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._transpo = transpo
@@ -1105,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):
         """
@@ -1112,12 +1229,13 @@ class Harmonizer(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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)
 
@@ -1127,10 +1245,11 @@ class Harmonizer(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `transpo` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._transpo = x
         x, lmax = convertArgsToLists(x)
         [obj.setTranspo(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1141,10 +1260,11 @@ class Harmonizer(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `feedback` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._feedback = x
         x, lmax = convertArgsToLists(x)
         [obj.setFeedback(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1155,44 +1275,53 @@ class Harmonizer(PyoObject):
 
         :Args:
 
-            x : float
+            x: float
                 New `winsize` attribute.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._winsize = x
         x, lmax = convertArgsToLists(x)
         [obj.setWinsize(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
+    def reset(self):
+        """
+        Reset the memory buffer to zeros.
+
+        """
+        [obj.reset() for obj in self._base_objs]
+
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
-        self._map_list = [SLMap(-24.0, 24.0, 'lin', 'transpo',  self._transpo),
+        self._map_list = [SLMap(-24.0, 24.0, 'lin', 'transpo', self._transpo),
                           SLMap(0., 1., 'lin', 'feedback', self._feedback),
+                          SLMap(0.001, 1, 'log', 'winsize', self._winsize, dataOnly=True),
                           SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def input(self):
-        """PyoObject. Input signal to delayed.""" 
+        """PyoObject. Input signal to delayed."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def transpo(self):
-        """float or PyoObject. Transposition factor in semitone.""" 
+        """float or PyoObject. Transposition factor in semitone."""
         return self._transpo
     @transpo.setter
     def transpo(self, x): self.setTranspo(x)
 
     @property
     def feedback(self):
-        """float or PyoObject. Amount of output signal sent back into the delay line.""" 
+        """float or PyoObject. Amount of output signal sent back into the delay line."""
         return self._feedback
     @feedback.setter
     def feedback(self, x): self.setFeedback(x)
 
     @property
     def winsize(self):
-        """float. Window size in seconds (max = 1.0).""" 
+        """float. Window size in seconds (max = 1.0)."""
         return self._winsize
     @winsize.setter
     def winsize(self, x): self.setWinsize(x)
@@ -1200,14 +1329,14 @@ class Harmonizer(PyoObject):
 class Delay1(PyoObject):
     """
     Delays a signal by one sample.
- 
+
     :Parent: :py:class:`PyoObject`
-   
+
     :Args:
-    
-        input : PyoObject
+
+        input: PyoObject
             Input signal to process.
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> # 50th order FIR lowpass filter
@@ -1215,35 +1344,553 @@ class Delay1(PyoObject):
     >>> objs = [Noise(.3)]
     >>> for i in range(order):
     ...     objs.append(Delay1(objs[-1], add=objs[-1]))
-    ...     objs.append(objs[-1] * 0.5)    
+    ...     objs.append(objs[-1] * 0.5)
     >>> out = Sig(objs[-1]).out()
 
     """
     def __init__(self, input, mul=1, add=0):
+        pyoArgsAssert(self, "oOO", input, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     @property
     def input(self):
-        """PyoObject. Input signal to delayed.""" 
+        """PyoObject. Input signal to delayed."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
+
+class STRev(PyoObject):
+    """
+    Stereo reverb.
+
+    Stereo reverb based on WGVerb (8 delay line FDN reverb). A mono
+    input will produce two audio streams, left and right channels.
+    Therefore, a stereo input will produce four audio streams, left
+    and right channels for each input channel. Position of input
+    streams can be set with the `inpos` argument. To achieve a stereo
+    reverb, delay line lengths are slightly differents on both channels,
+    but also, pre-delays length and filter cutoff of both channels will
+    be affected to reflect the input position.
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        input: PyoObject
+            Input signal to process.
+        inpos: float or PyoObject, optional
+            Position of the source, between 0 and 1. 0 means fully left
+            and 1 means fully right. Defaults to 0.5.
+        revtime: float or PyoObject, optional
+            Duration, in seconds, of the reverberated sound, defined as
+            the time needed to the sound to drop 40 dB below its peak.
+            Defaults to 1.
+        cutoff: float or PyoObject, optional
+            cutoff frequency, in Hz, of a first order lowpass filters in the
+            feedback loop of delay lines. Defaults to 5000.
+        bal: float or PyoObject, optional
+            Balance between wet and dry signal, between 0 and 1. 0 means no
+            reverb. Defaults to 0.5.
+        roomSize: float, optional
+            Delay line length scaler, between 0.25 and 4. Values higher than
+            1 make the delay lines longer and simulate larger rooms. Defaults to 1.
+        firstRefGain: float, optional
+            Gain, in dB, of the first reflexions of the room. Defaults to -3.
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> t = SndTable(SNDS_PATH + "/transparent.aif")
+    >>> sf = Looper(t, dur=t.getDur()*2, xfade=0, mul=0.5)
+    >>> rev = STRev(sf, inpos=0.25, revtime=2, cutoff=5000, bal=0.25, roomSize=1).out()
+
+    """
+    def __init__(self, input, inpos=0.5, revtime=1, cutoff=5000, bal=.5, roomSize=1, firstRefGain=-3, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOOnnOO", input, inpos, revtime, cutoff, bal, roomSize, firstRefGain, mul, add)
+        PyoObject.__init__(self, mul, add)
+        self._input = input
+        self._inpos = inpos
+        self._revtime = revtime
+        self._cutoff = cutoff
+        self._bal = bal
+        self._roomSize = roomSize
+        self._firstRefGain = firstRefGain
+        self._in_fader = InputFader(input)
+        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):
+        """
+        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 setInpos(self, x):
+        """
+        Replace the `inpos` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                New `inpos` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._inpos = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setInpos(wrap(x,i)) for i, obj in enumerate(self._base_players)]
+
+    def setRevtime(self, x):
+        """
+        Replace the `revtime` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                New `revtime` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._revtime = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setRevtime(wrap(x,i)) for i, obj in enumerate(self._base_players)]
+
+    def setCutoff(self, x):
+        """
+        Replace the `cutoff` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                New `cutoff` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._cutoff = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setCutoff(wrap(x,i)) for i, obj in enumerate(self._base_players)]
+
+    def setBal(self, x):
+        """
+        Replace the `bal` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                New `bal` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._bal = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setMix(wrap(x,i)) for i, obj in enumerate(self._base_players)]
+
+    def setRoomSize(self, x):
+        """
+        Set the room size scaler, between 0.25 and 4.
+
+        :Args:
+
+            x: float
+                Room size scaler, between 0.25 and 4.0.
+
+        """
+        pyoArgsAssert(self, "n", x)
+        self._roomSize = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setRoomSize(wrap(x,i)) for i, obj in enumerate(self._base_players)]
+
+    def setFirstRefGain(self, x):
+        """
+        Set the gain of the first reflexions.
+
+        :Args:
+
+            x: float
+                Gain, in dB, of the first reflexions.
+
+        """
+        pyoArgsAssert(self, "n", x)
+        self._firstRefGain = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setFirstRefGain(wrap(x,i)) for i, obj in enumerate(self._base_players)]
+
+    def reset(self):
+        """
+        Reset the memory buffer to zeros.
+
+        """
+        [obj.reset() for obj in self._base_players]
+
+    def ctrl(self, map_list=None, title=None, wxnoserver=False):
+        self._map_list = [SLMap(0., 1., 'lin', 'inpos', self._inpos),
+                          SLMap(0.01, 120., 'log', 'revtime', self._revtime),
+                          SLMap(500., 15000., 'log', 'cutoff', self._cutoff),
+                          SLMap(0., 1., 'lin', 'bal', self._bal),
+                          SLMap(0.25, 4., 'lin', 'roomSize', self._roomSize, dataOnly=True),
+                          SLMap(-48, 12, 'lin', 'firstRefGain', self._firstRefGain, dataOnly=True),
+                          SLMapMul(self._mul)]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
+    @property
+    def input(self):
+        """PyoObject. Input signal to process."""
+        return self._input
+    @input.setter
+    def input(self, x): self.setInput(x)
+
+    @property
+    def inpos(self):
+        """float or PyoObject. Position of the source."""
+        return self._inpos
+    @inpos.setter
+    def inpos(self, x): self.setInpos(x)
+
+    @property
+    def revtime(self):
+        """float or PyoObject. Room size."""
+        return self._revtime
+    @revtime.setter
+    def revtime(self, x): self.setRevtime(x)
+
+    @property
+    def cutoff(self):
+        """float or PyoObject. High frequency damping."""
+        return self._cutoff
+    @cutoff.setter
+    def cutoff(self, x): self.setCutoff(x)
+
+    @property
+    def bal(self):
+        """float or PyoObject. Balance between wet and dry signal."""
+        return self._bal
+    @bal.setter
+    def bal(self, x): self.setBal(x)
+
+    @property
+    def roomSize(self):
+        """float. Room size scaler, between 0.25 and 4.0."""
+        return self._roomSize
+    @roomSize.setter
+    def roomSize(self, x): self.setRoomSize(x)
+
+    @property
+    def firstRefGain(self):
+        """float. Gain, in dB, of the first reflexions."""
+        return self._firstRefGain
+    @firstRefGain.setter
+    def firstRefGain(self, x): self.setFirstRefGain(x)
+
+class SmoothDelay(PyoObject):
+    """
+    Artifact free sweepable recursive delay.
+
+    SmoothDelay implements a delay line that does not produce
+    clicks or pitch shifting when the delay time is changing.
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        input: PyoObject
+            Input signal to delayed.
+        delay: float or PyoObject, optional
+            Delay time in seconds. Defaults to 0.25.
+        feedback: float or PyoObject, optional
+            Amount of output signal sent back into the delay line.
+            Defaults to 0.
+        crossfade: float, optional
+            Crossfade time, in seconds, between overlaped readers.
+            Defaults to 0.05.
+        maxdelay: float, optional
+            Maximum delay length in seconds. Available only at initialization.
+            Defaults to 1.
+
+    .. note::
+
+        The minimum delay time allowed with SmoothDelay is one sample.
+        It can be computed with :
+
+        onesamp = 1.0 / s.getSamplingRate()
+
+    .. seealso::
+
+        :py:class:`Delay`, :py:class:`Waveguide`
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> sf = SfPlayer(SNDS_PATH+"/transparent.aif", loop=True, mul=0.3).mix(2).out()
+    >>> lf = Sine(freq=0.1, mul=0.24, add=0.25)
+    >>> sd = SmoothDelay(sf, delay=lf, feedback=0.5, crossfade=0.05, mul=0.7).out()
+
+    """
+    def __init__(self, input, delay=0.25, feedback=0, crossfade=0.05, maxdelay=1, mul=1, add=0):
+        pyoArgsAssert(self, "oOOnnOO", input, delay, feedback, crossfade, maxdelay, mul, add)
+        PyoObject.__init__(self, mul, add)
+        self._input = input
+        self._delay = delay
+        self._feedback = feedback
+        self._crossfade = crossfade
+        self._maxdelay = maxdelay
+        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):
+        """
+        Replace the `input` attribute.
+
+        :Args:
+
+            x: PyoObject
+                New signal to delayed.
+            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 setDelay(self, x):
+        """
+        Replace the `delay` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                New `delay` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._delay = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setDelay(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def setFeedback(self, x):
+        """
+        Replace the `feedback` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                New `feedback` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._feedback = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setFeedback(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def setCrossfade(self, x):
+        """
+        Replace the `crossfade` attribute.
+
+        :Args:
+
+            x: float
+                New `crossfade` attribute.
+
+        """
+        pyoArgsAssert(self, "n", x)
+        self._crossfade = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setCrossfade(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def reset(self):
+        """
+        Reset the memory buffer to zeros.
+
+        """
+        [obj.reset() for obj in self._base_objs]
+
+    def ctrl(self, map_list=None, title=None, wxnoserver=False):
+        self._map_list = [SLMap(0.001, self._maxdelay, 'log', 'delay', self._delay),
+                          SLMap(0., 1., 'lin', 'feedback', self._feedback),
+                          SLMap(0., self._maxdelay, 'lin', 'crossfade', self._crossfade, dataOnly=True),
+                          SLMapMul(self._mul)]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
+    @property
+    def input(self):
+        """PyoObject. Input signal to delayed."""
+        return self._input
+    @input.setter
+    def input(self, x): self.setInput(x)
+
+    @property
+    def delay(self):
+        """float or PyoObject. Delay time in seconds."""
+        return self._delay
+    @delay.setter
+    def delay(self, x): self.setDelay(x)
+
+    @property
+    def feedback(self):
+        """float or PyoObject. Amount of output signal sent back into the delay line."""
+        return self._feedback
+    @feedback.setter
+    def feedback(self, x): self.setFeedback(x)
+
+    @property
+    def crossfade(self):
+        """float. Crossfade time, in seconds, between overlaps."""
+        return self._crossfade
+    @crossfade.setter
+    def crossfade(self, x): self.setCrossfade(x)
+
+class FreqShift(PyoObject):
+    """
+    Frequency shifting using single sideband amplitude modulation.
+
+    Shifting frequencies means that the input signal can be detuned,
+    where the harmonic components of the signal are shifted out of
+    harmonic alignment with each other, e.g. a signal with harmonics at
+    100, 200, 300, 400 and 500 Hz, shifted up by 50 Hz, will have harmonics
+    at 150, 250, 350, 450, and 550 Hz.
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        input: PyoObject
+            Input signal to process.
+        shift: float or PyoObject, optional
+            Amount of shifting in Hertz. Defaults to 100.
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> a = SineLoop(freq=300, feedback=.1, mul=.3)
+    >>> lf1 = Sine(freq=.04, mul=10)
+    >>> lf2 = Sine(freq=.05, mul=10)
+    >>> b = FreqShift(a, shift=lf1, mul=.5).out()
+    >>> c = FreqShift(a, shift=lf2, mul=.5).out(1)
+
+    """
+    def __init__(self, input, shift=100, mul=1, add=0):
+        pyoArgsAssert(self, "oOOO", input, shift, mul, add)
+        PyoObject.__init__(self, mul, add)
+        self._input = input
+        self._shift = shift
+        self._in_fader = InputFader(input)
+        in_fader, shift, mul, add, lmax = convertArgsToLists(self._in_fader, shift, mul, add)
+
+        self._hilb_objs = []
+        self._sin_objs = []
+        self._cos_objs = []
+        self._mod_objs = []
+        self._base_objs = []
+        for i in range(lmax):
+            self._hilb_objs.append(Hilbert(wrap(in_fader,i)))
+            self._sin_objs.append(Sine(freq=wrap(shift,i), mul=.707))
+            self._cos_objs.append(Sine(freq=wrap(shift,i), phase=0.25, mul=.707))
+            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)
+        [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._hilb_objs)]
+        [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._sin_objs)]
+        [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._cos_objs)]
+        [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._mod_objs)]
+        return PyoObject.play(self, dur, delay)
+
+    def stop(self):
+        [obj.stop() for obj in self._hilb_objs]
+        [obj.stop() for obj in self._sin_objs]
+        [obj.stop() for obj in self._cos_objs]
+        [obj.stop() for obj in self._mod_objs]
+        return PyoObject.stop(self)
+
+    def out(self, chnl=0, inc=1, dur=0, delay=0):
+        dur, delay, lmax = convertArgsToLists(dur, delay)
+        [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._hilb_objs)]
+        [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._sin_objs)]
+        [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._cos_objs)]
+        [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._mod_objs)]
+        return PyoObject.out(self, chnl, inc, dur, delay)
+
+    def setInput(self, x, fadetime=0.05):
+        """
+        Replace the `input` attribute.
+
+        Parameters:
+
+        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 setShift(self, x):
+        """
+        Replace the `shift` attribute.
+
+        Parameters:
+
+        x: float or PyoObject
+            New `shift` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._shift = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._sin_objs)]
+        [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._cos_objs)]
+
+    def ctrl(self, map_list=None, title=None, wxnoserver=False):
+        self._map_list = [SLMap(-2000., 2000., "lin", "shift", self._shift), SLMapMul(self._mul)]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
+    @property
+    def input(self):
+        """PyoObject. Input signal to pitch shift."""
+        return self._input
+    @input.setter
+    def input(self, x): self.setInput(x)
+
+    @property
+    def shift(self):
+        """float or PyoObject. Amount of pitch shift in Hertz."""
+        return self._shift
+    @shift.setter
+    def shift(self, x): self.setShift(x)
diff --git a/pyolib/expression.py b/pyolib/expression.py
new file mode 100644
index 0000000..e0aff58
--- /dev/null
+++ b/pyolib/expression.py
@@ -0,0 +1,558 @@
+from __future__ import absolute_import
+
+"""
+Prefix expression evaluators.
+
+API documentation
+=================
+
+* This API is in alpha stage and subject to future changes!
+
+Builtin functions
+-----------------
+
+Arithmetic operators:
+
+(+ x y) : returns the sum of two values.
+(- x y) : substracts the second value to the first and returns the result.
+(* x y) : returns the multiplication of two values.
+(/ x y) : returns the quotient of x/y.
+(^ x y) : returns x to the power y.
+(% x y) : returns the floating-point remainder of x/y.
+(neg x) : returns the negative of x.
+
+Moving phase operators:
+
+(++ x y) : increments its internal state by x and wrap around 0.0 and y.
+(-- x y) : decrements its internal state by x and wrap around 0.0 and y.
+(~ x y) : generates a periodic ramp from 0 to 1 with frequency x and phase y.
+
+Conditional operators:
+
+(< x y) : returns 1 if x is less than y, otherwise returns 0.
+(<= x y) : returns 1 if x is less than or equal to y, otherwise returns 0.
+(> x y) : returns 1 if x is greater than y, otherwise returns 0.
+(>= x y) : returns 1 if x is greater than or equal to y, otherwise returns 0.
+(== x y) : returns 1 if x is equal to y, otherwise returns 0.
+(!= x y) : returns 1 if x is not equal to y, otherwise returns 0.
+(if (cond) (then) (else)) : returns then for any non-zero value of cond, otherwise returns else.
+(and x y) : returns 1 if both x and y are not 0, otherwise returns 0.
+(or x y) : returns 1 if one of x or y are not 0, otherwise returns 0.
+
+Trigonometric functions:
+
+(sin x) : returns the sine of an angle of x radians.
+(cos x) : returns the cosine of an angle of x radians.
+(tan x) : returns the tangent of x radians.
+(tanh x) : returns the hyperbolic tangent of x radians.
+(atan x) : returns the principal value of the arc tangent of x, expressed in radians.
+(atan2 x y) : returns the principal value of the arc tangent of y/x, expressed in radians.
+
+Power and logarithmic functions:
+
+(sqrt x) : returns the square root of x.
+(log x) : returns the natural logarithm of x.
+(log2 x) : returns the binary (base-2) logarithm of x.
+(log10 x) : returns the common (base-10) logarithm of x.
+(pow x y) : returns x to the power y.
+
+Clipping functions:
+
+(abs x) : returns the absolute value of x.
+(floor x) : rounds x downward, returning the largest integral value that is not greater than x.
+(ceil x) : rounds x upward, returning the smallest integral value that is not less than x.
+(exp  x) : returns the constant e to the power x.
+(round x) : returns the integral value that is nearest to x.
+(min x y) : returns the smaller of its arguments: either x or y.
+(max x y) : returns the larger of its arguments: either x or y.
+(wrap x) : wraps x between 0 and 1.
+
+Random fuctions:
+
+(randf x y) : returns a pseudo-random floating-point number in the range between x and y.
+(randi x y) : returns a pseudo-random integral number in the range between x and y.
+
+Filter functions:
+
+(sah x y) : samples and holds x value whenever y is smaller than its previous state.
+(rpole x y) : real one-pole recursive filter. returns x + last_out * y.
+(rzero x y) : real one-zero non-recursive filter. returns x - last_x * y.
+
+Constants:
+
+(const x) : returns x.
+(pi) : returns an approximated value of pi.
+(twopi) : returns a constant with value pi*2.
+(e) : returns an approximated value of e.
+
+Comments
+--------
+
+A comment starts with two slashs ( // ) and ends at the end of the line:
+
+    // This is a comment!
+
+Input and Output signals
+------------------------
+
+User has access to the last buffer size of input and output samples.
+
+To use samples from past input, use $x[n] notation, where n is the position
+from the current time. $x[0] is the current input, $x[-1] is the previous
+one and $x[-buffersize] is the last available input sample.
+
+To use samples from past output, use $y[n] notation, where n is the position
+from the current time. $y[-1] is the previous output and $y[-buffersize] is
+the last available output sample.
+
+Here an example of a first-order IIR lowpass filter expression:
+
+    // A first-order IIR lowpass filter
+    + $x[0] (* (- $y[-1] $x[0]) 0.99)
+
+
+Defining custom functions
+-------------------------
+
+The define keyword starts the definition of a custom function.
+
+(define funcname (body))
+
+funcname is the name used to call the function in the expression and
+body is the sequence of functions to execute. Arguments of the function
+are extracted directly from the body. They must be named $1, $2, $3, ..., $9.
+
+Example of a sine wave function:
+
+    (define osc (
+        sin (* (twopi) (~ $1))
+        )
+    )
+    // play a sine wave
+    * (osc 440) 0.3
+
+
+State variables
+---------------
+
+User can create state variable with the keyword "let". This is useful
+to set an intermediate state to be used in multiple places in the
+processing chain. The syntax is:
+
+(let #var (body))
+
+The variable name must begin with a "#".
+
+    (let #sr 44100)
+    (let #freq 1000)
+    (let #coeff (
+        ^ (e) (/ (* (* -2 (pi)) #freq) #sr)
+        )
+    )
+    + $x[0] (* (- $y[-1] $x[0]) #coeff)
+
+The variable is private to a function if created inside a custom function.
+
+    (let #freq 250) // global #freq variable
+    (define osc (
+        (let #freq (* $1 $2)) // local #freq variable
+        sin (* (twopi) (~ #freq))
+        )
+    )
+    * (+ (osc 1 #freq) (osc 2 #freq)) 0.2
+
+State variables can be used to do 1 sample feedback if used before created.
+Undefined variables are initialized to 0.
+
+    (define oscloop (
+            (let #xsin
+                (sin (+ (* (~ $1) (twopi)) (* #xsin $2))) // #xsin used before...
+            ) // ... "let" statement finished!
+            #xsin // oscloop function outputs #xsin variable
+        )
+    )
+    * (oscloop 200 0.7) 0.3
+
+
+User variables
+--------------
+
+User variables are created with the keyword "var".
+
+(var #var (init))
+
+The variable name must begin with a "#".
+
+They are computed only at initialization, but can be changed from the python
+script with method calls (varname is a string and value is a float):
+
+obj.setVar(varname, value)
+
+Library importation
+-------------------
+
+Custom functions can be defined in an external file and imported with the
+"load" function:
+
+(load path/to/the/file)
+
+The content of the file will be inserted where the load function is called
+and all functions defined inside the file will then be accessible. The path
+can be absolute or relative to the current working directory.
+
+Examples
+--------
+
+A first-order IIR lowpass filter:
+
+    (var #sr 44100)
+    (var #cutoff 1000)
+    (let #coeff (exp (/ (* (* -2 (pi)) #cutoff) #sr)))
+    + $x[0] (* (- $y[-1] $x[0]) #coeff)
+
+A LFO'ed hyperbolic tangent distortion:
+
+    // $1 = lfo frequency, $2 = lfo depth
+    (define lfo (
+            (+ (* (sin (* (twopi) (~ $1))) (- $2 1)) $2)
+        )
+    )
+    tanh (* $x[0] (lfo .25 10))
+
+A triangle waveform generator (use Sig(0) as input argument to bypass input):
+
+    (var #freq 440)
+    // $1 = oscillator frequency
+    (define triangle (
+            (let #ph (~ $1))
+            (- (* (min #ph (- 1 #ph)) 4) 1)
+        )
+    )
+    triangle #freq
+
+"""
+
+"""
+Copyright 2015-16 Olivier Belanger
+
+This file is part of pyo, a python module to help digital signal
+processing script creation.
+
+pyo is free software: you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
+
+pyo is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU 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 os, sys
+from ._core import *
+from ._maps import *
+from ._widgets import createExprEditorWindow
+
+if sys.version_info[0] < 3:
+    def to_unicode(s):
+        try:
+            s = unicode(s.replace(r'\\', r'\\\\'), "unicode_escape")
+        except:
+            pass
+        return s
+else:
+    def to_unicode(s):
+        return s
+
+class Expr(PyoObject):
+    """
+    Prefix audio expression evaluator.
+
+    Expr implements a tiny functional programming language that can be
+    used to write synthesis or signal processing algorithms.
+
+    For documentation about the language, see the module's documentation.
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        input: PyoObject
+            Input signal to process.
+        expr: str, optional
+            Expression to evaluate as a string.
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> proc = '''
+    >>> (var #boost 1)
+    >>> (tanh (* $x[0] #boost))
+    >>> '''
+    >>> sf = SfPlayer(SNDS_PATH + "/transparent.aif", loop=True)
+    >>> ex = Expr(sf, proc, mul=0.4).out()
+    >>> lfo = Sine(freq=1).range(1, 20)
+    >>> def change():
+    ...     ex.setVar("#boost", lfo.get())
+    >>> pat = Pattern(change, 0.02).play()
+
+    """
+    def __init__(self, input, expr='', mul=1, add=0):
+        pyoArgsAssert(self, "osOO", input, expr, mul, add)
+        PyoObject.__init__(self, mul, add)
+        self._editor = None
+        self._input = input
+        self._expr = expr
+        expr = self._preproc(expr)
+        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):
+        """
+        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 setExpr(self, x):
+        """
+        Replace the `expr` attribute.
+
+        :Args:
+
+            x: string
+                New expression to process.
+
+        """
+        pyoArgsAssert(self, "s", x)
+        self._expr = x
+        if self._editor is not None:
+            self._editor.update(x)
+        x = self._preproc(x)
+        x = to_unicode(x)
+        x, lmax = convertArgsToLists(x)
+        [obj.setExpr(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def printNodes(self):
+        """
+        Print the list of current nodes.
+
+        """
+        [obj.printNodes() for i, obj in enumerate(self._base_objs)]
+
+    def setVar(self, varname, value):
+        pyoArgsAssert(self, "sn", varname, value)
+        varname, value, lmax = convertArgsToLists(varname, value)
+        [obj.setVar(wrap(varname,j), wrap(value,j)) for i, obj in enumerate(self._base_objs) for j in range(lmax)]
+
+    def _get_matching_bracket_pos(self, x, p1):
+        count = 1
+        p2 = p1 + 1
+        while True:
+            if x[p2] == "(":
+                count += 1
+            elif x[p2] == ")":
+                count -= 1
+            if count == 0:
+                break
+            p2 += 1
+            if p2 == len(x):
+                break
+        if count != 0:
+            return -1
+        else:
+            return p2
+
+    def _replace(self, x, lst):
+        lst.reverse()
+        for key, body in lst:
+            # find how many args waiting in function's body
+            numargs = 0
+            doll = body.find("$")
+            while doll != -1:
+                arg = int(body[doll+1])
+                if arg > numargs:
+                    numargs = arg
+                doll = body.find("$", doll+1)
+            occurences = 0
+            pos = x.find(key)
+            while pos != -1:
+                if x[pos-1] in " \t\n()" and x[pos+len(key)] in " \t\n()":
+                    # replace "#vars" with unique symbol
+                    body2 = body.replace("-%s" % key, ".%s.%d" % (key, occurences))
+                    occurences += 1
+                    # find limits
+                    is_inside_brackets = True
+                    start = pos - 1
+                    while x[start] != "(":
+                        start -= 1
+                        if start < 0:
+                            start = 0
+                            is_inside_brackets = False
+                            break
+                    if is_inside_brackets:
+                        end = self._get_matching_bracket_pos(x, start)
+                    else:
+                        end = len(x)
+                    # retrieve args
+                    args = []
+                    p1 = pos + len(key)
+                    p2 = -1
+                    for i in range(numargs):
+                        while x[p1] in " \t\n":
+                            p1 += 1
+                        if x[p1] == "(":
+                            p2 = self._get_matching_bracket_pos(x, p1)
+                            if p2 == -1 or p2 >= end:
+                                raise Exception("Mismatched brackets in function arguments.")
+                            p2 += 1
+                        else:
+                            p2 = p1 + 1
+                            if p2 < end:
+                                while x[p2] not in " \t\n()":
+                                    p2 += 1
+                                    if p2 == end:
+                                        break
+                        if x[p1:p2] != ")":
+                            args.append(x[p1:p2])
+                        if p2 == end:
+                            break
+                        else:
+                            p1 = p2
+                    # discard extra args
+                    if p2 != end and p2 != -1:
+                        x = x[:p2] + x[end:]
+                    # replace args
+                    if args != []:
+                        newbody = body2
+                        for i in range(numargs):
+                            if i < len(args):
+                                arg = args[i]
+                            else:
+                                arg = '0.0'
+                            newbody = newbody.replace("$%d" % (i+1), arg)
+                        x = x[:pos] + newbody + x[p2:]
+                    else:
+                        x = x[:pos] + body2 + x[pos+len(key):]
+                pos = x.find(key, pos+1)
+        return x
+
+    def _change_var_names(self, funcname, funcbody):
+        d = {}
+        letpos = funcbody.find("let ")
+        while letpos != -1:
+            pos = funcbody.find("#", letpos)
+            if pos == -1:
+                raise Exception("No #var defined inside a let function.")
+            p1 = pos
+            p2 = p1 + 1
+            while funcbody[p2] not in " \t\n()":
+                p2 += 1
+            label = funcbody[p1:p2]
+            d[label] = label + "-" + funcname
+            letpos = funcbody.find("let ", letpos + 4)
+        for label, newlabel in d.items():
+            funcbody = funcbody.replace(label, newlabel)
+        return funcbody
+
+    def _preproc(self, x):
+        # replace load functions with file body
+        while "(load" in x:
+            p1 = x.find("(load")
+            p2 = self._get_matching_bracket_pos(x, p1)
+            p2 += 1
+            text = x[p1:p2]
+            path = text.replace("(load", "").replace(")", "").strip()
+            if os.path.isfile(path):
+                with open(path, "r") as f:
+                    text = f.read()
+            x = x[:p1] + text + x[p2:]
+
+        # remove comments
+        while "//" in x:
+            start = x.find("//")
+            end = x.find("\n", start)
+            x = x[:start] + x[end:]
+
+        # expand defined functions
+        _defined = []
+        while "define" in x:
+            start = x.find("(define")
+            p1 = start + 7
+            # get function name
+            while x[p1] in " \t\n":
+                p1 += 1
+            p2 = p1+1
+            while x[p2] not in " \t\n":
+                p2 += 1
+            funcname = x[p1:p2]
+            # get function body
+            p1 = p2 + 1
+            while x[p1] != "(":
+                p1 += 1
+            p2 = self._get_matching_bracket_pos(x, p1)
+            if p2 == -1:
+                raise Exception("Mismatched brackets in function body.")
+            p2 += 1
+            funcbody = x[p1:p2]
+            # get end of the definition
+            while x[p2] in " \t\n":
+                p2 += 1
+            if x[p2] != ")":
+                raise Exception("Missing ending bracket in function definition.")
+            stop = p2
+            # save in dictionary and remove definition from the string
+            funcbody = self._change_var_names(funcname, funcbody)
+            _defined.append([funcname, funcbody])
+            x = x[:start] + x[stop+1:]
+        # replace calls to function with their function body
+        x = self._replace(x, _defined)
+        x = x.strip()
+        return x
+
+    def editor(self, title="Expr Editor", wxnoserver=False):
+        """
+        Opens the text editor for this object.
+
+        :Args:
+
+            title: string, optional
+                Title of the window. If none is provided, the name of the
+                class is used.
+            wxnoserver: boolean, optional
+                With wxPython graphical toolkit, if True, tells the
+                interpreter that there will be no server window.
+
+        If `wxnoserver` is set to True, the interpreter will not wait for
+        the server GUI before showing the controller window.
+
+        """
+        createExprEditorWindow(self, title, wxnoserver)
+
+    @property
+    def input(self):
+        """PyoObject. Input signal to process."""
+        return self._input
+    @input.setter
+    def input(self, x): self.setInput(x)
+
+    @property
+    def expr(self):
+        """string. New expression to process."""
+        return self._expr
+    @expr.setter
+    def expr(self, x): self.setExpr(x)
diff --git a/pyolib/filters.py b/pyolib/filters.py
index 1feb485..852f5af 100644
--- a/pyolib/filters.py
+++ b/pyolib/filters.py
@@ -1,66 +1,68 @@
+from __future__ import print_function
+from __future__ import absolute_import
 """
 Different kinds of audio filtering operations.
 
-An audio filter is designed to amplify, pass or attenuate (negative amplification) 
-some frequency ranges. Common types include low-pass, which pass through 
-frequencies below their cutoff frequencies, and progressively attenuates 
-frequencies above the cutoff frequency. A high-pass filter does the opposite, 
-passing high frequencies above the cutoff frequency, and progressively 
-attenuating frequencies below the cutoff frequency. A bandpass filter passes 
-frequencies between its two cutoff frequencies, while attenuating those outside 
-the range. A band-reject filter, attenuates frequencies between its two cutoff 
+An audio filter is designed to amplify, pass or attenuate (negative amplification)
+some frequency ranges. Common types include low-pass, which pass through
+frequencies below their cutoff frequencies, and progressively attenuates
+frequencies above the cutoff frequency. A high-pass filter does the opposite,
+passing high frequencies above the cutoff frequency, and progressively
+attenuating frequencies below the cutoff frequency. A bandpass filter passes
+frequencies between its two cutoff frequencies, while attenuating those outside
+the range. A band-reject filter, attenuates frequencies between its two cutoff
 frequencies, while passing those outside the 'reject' range.
 
-An all-pass filter, passes all frequencies, but affects the phase of any given 
+An all-pass filter, passes all frequencies, but affects the phase of any given
 sinusoidal component according to its frequency.
- 
+
 """
 
 """
-Copyright 2010 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+You should have received a copy of the GNU Lesser General Public
+License along with pyo.  If not, see <http://www.gnu.org/licenses/>.
 """
-from _core import *
-from _maps import *
+from ._core import *
+from ._maps import *
 
 class Biquad(PyoObject):
     """
-    A sweepable general purpose biquadratic digital filter. 
-    
+    A sweepable general purpose biquadratic digital filter.
+
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
-    
-        input : PyoObject
+
+        input: PyoObject
             Input signal to process.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Cutoff or center frequency of the filter. Defaults to 1000.
-        q : float or PyoObject, optional
-            Q of the filter, defined (for bandpass filters) as freq/bandwidth. 
+        q: float or PyoObject, optional
+            Q of the filter, defined (for bandpass filters) as freq/bandwidth.
             Should be between 1 and 500. Defaults to 1.
-        type : int, optional
+        type: int, optional
             Filter type. Five possible values :
                 0. lowpass (default)
                 1. highpass
                 2. bandpass
                 3. bandstop
                 4. allpass
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> a = Noise(mul=.7)
@@ -69,6 +71,7 @@ class Biquad(PyoObject):
 
     """
     def __init__(self, input, freq=1000, q=1, type=0, mul=1, add=0):
+        pyoArgsAssert(self, "oOOiOO", input, freq, q, type, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._freq = freq
@@ -77,32 +80,35 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setFreq(self, x):
         """
         Replace the `freq` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `freq` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -110,13 +116,14 @@ class Biquad(PyoObject):
     def setQ(self, x):
         """
         Replace the `q` attribute. Should be between 1 and 500.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `q` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._q = x
         x, lmax = convertArgsToLists(x)
         [obj.setQ(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -124,82 +131,85 @@ class Biquad(PyoObject):
     def setType(self, x):
         """
         Replace the `type` attribute.
-        
+
         :Args:
 
-            x : int
-                New `type` attribute. 
+            x: int
+                New `type` attribute.
                     0.lowpass
                     1. highpass
-                    2. bandpass 
-                    3. bandstop 
+                    2. bandpass
+                    3. bandstop
                     4. allpass
 
         """
+        pyoArgsAssert(self, "i", x)
         self._type = x
         x, lmax = convertArgsToLists(x)
         [obj.setType(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
-        self._map_list = [SLMapFreq(self._freq), SLMapQ(self._q), SLMapMul(self._mul)]
+        self._map_list = [SLMapFreq(self._freq), SLMapQ(self._q),
+                          SLMap(0, 4, 'lin', 'type', self._type, res="int", dataOnly=True),
+                          SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def freq(self):
-        """float or PyoObject. Cutoff or center frequency of the filter.""" 
+        """float or PyoObject. Cutoff or center frequency of the filter."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
     def q(self):
-        """float or PyoObject. Q of the filter.""" 
+        """float or PyoObject. Q of the filter."""
         return self._q
     @q.setter
     def q(self, x): self.setQ(x)
 
     @property
     def type(self):
-        """int. Filter type.""" 
+        """int. Filter type."""
         return self._type
     @type.setter
     def type(self, x): self.setType(x)
 
 class Biquadx(PyoObject):
     """
-    A multi-stages sweepable general purpose biquadratic digital filter. 
-    
+    A multi-stages sweepable general purpose biquadratic digital filter.
+
     Biquadx is equivalent to a filter consisting of more layers of Biquad
     with the same arguments, serially connected. It is faster than using
-    a large number of instances of the Biquad object, It uses less memory 
+    a large number of instances of the Biquad object, It uses less memory
     and allows filters with sharper cutoff.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Cutoff or center frequency of the filter. Defaults to 1000.
-        q : float or PyoObject, optional
-            Q of the filter, defined (for bandpass filters) as freq/bandwidth. 
+        q: float or PyoObject, optional
+            Q of the filter, defined (for bandpass filters) as freq/bandwidth.
             Should be between 1 and 500. Defaults to 1.
-        type : int, optional
+        type: int, optional
             Filter type. Five possible values :
                 0. lowpass (default)
                 1. highpass
                 2. bandpass
                 3. bandstop
                 4. allpass
-        stages : int, optional
+        stages: int, optional
             The number of filtering stages in the filter stack. Defaults to 4.
 
     >>> s = Server().boot()
@@ -210,6 +220,7 @@ class Biquadx(PyoObject):
 
     """
     def __init__(self, input, freq=1000, q=1, type=0, stages=4, mul=1, add=0):
+        pyoArgsAssert(self, "oOOiiOO", input, freq, q, type, stages, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._freq = freq
@@ -219,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):
         """
@@ -226,12 +238,13 @@ class Biquadx(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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)
 
@@ -241,10 +254,11 @@ class Biquadx(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `freq` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -255,10 +269,11 @@ class Biquadx(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `q` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._q = x
         x, lmax = convertArgsToLists(x)
         [obj.setQ(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -269,8 +284,8 @@ class Biquadx(PyoObject):
 
         :Args:
 
-            x : int
-                New `type` attribute. 
+            x: int
+                New `type` attribute.
                 0. lowpass
                 1. highpass
                 2. bandpass
@@ -278,6 +293,7 @@ class Biquadx(PyoObject):
                 4. allpass
 
         """
+        pyoArgsAssert(self, "i", x)
         self._type = x
         x, lmax = convertArgsToLists(x)
         [obj.setType(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -288,49 +304,52 @@ class Biquadx(PyoObject):
 
         :Args:
 
-            x : int
-                New `stages` attribute. 
+            x: int
+                New `stages` attribute.
 
         """
+        pyoArgsAssert(self, "i", x)
         self._stages = x
         x, lmax = convertArgsToLists(x)
         [obj.setStages(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
-        self._map_list = [SLMapFreq(self._freq), SLMapQ(self._q), SLMapMul(self._mul)]
+        self._map_list = [SLMapFreq(self._freq), SLMapQ(self._q),
+                          SLMap(0, 4, 'lin', 'type', self._type, res="int", dataOnly=True),
+                          SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def freq(self):
-        """float or PyoObject. Cutoff or center frequency of the filter.""" 
+        """float or PyoObject. Cutoff or center frequency of the filter."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
     def q(self):
-        """float or PyoObject. Q of the filter.""" 
+        """float or PyoObject. Q of the filter."""
         return self._q
     @q.setter
     def q(self, x): self.setQ(x)
 
     @property
     def type(self):
-        """int. Filter type.""" 
+        """int. Filter type."""
         return self._type
     @type.setter
     def type(self, x): self.setType(x)
 
     @property
     def stages(self):
-        """int. The number of filtering stages.""" 
+        """int. The number of filtering stages."""
         return self._stages
     @stages.setter
     def stages(self, x): self.setStages(x)
@@ -340,14 +359,14 @@ class Biquada(PyoObject):
     A general purpose biquadratic digital filter (floating-point arguments).
 
     A digital biquad filter is a second-order recursive linear filter, containing
-    two poles and two zeros. Biquadi is a "Direct Form 1" implementation of a Biquad 
+    two poles and two zeros. Biquadi is a "Direct Form 1" implementation of a Biquad
     filter:
 
     y[n] = ( b0*x[n] + b1*x[n-1] + b2*x[n-2] - a1*y[n-1] - a2*y[n-2] ) / a0
 
     This object is directly controlled via the six coefficients, as floating-point
-    values or audio stream, of the filter. There is no clipping of the values given as 
-    coefficients, so, unless you know what you do, it is recommended to use the Biquad 
+    values or audio stream, of the filter. There is no clipping of the values given as
+    coefficients, so, unless you know what you do, it is recommended to use the Biquad
     object, which is controlled with frequency, Q and type arguments.
 
     The default values of the object give a lowpass filter with a 1000 Hz cutoff frequency.
@@ -356,19 +375,19 @@ class Biquada(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        b0 : float or PyoObject, optional
+        b0: float or PyoObject, optional
             Amplitude of the current sample. Defaults to 0.005066.
-        b1 : float or PyoObject, optional
+        b1: float or PyoObject, optional
             Amplitude of the first input sample delayed. Defaults to 0.010132.
-        b2 : float or PyoObject, optional
+        b2: float or PyoObject, optional
             Amplitude of the second input sample delayed. Defaults to 0.005066.
-        a0 : float or PyoObject, optional
+        a0: float or PyoObject, optional
             Overall gain coefficient. Defaults to 1.070997.
-        a1 : float or PyoObject, optional
+        a1: float or PyoObject, optional
             Amplitude of the first output sample delayed. Defaults to -1.979735.
-        a2 : float or PyoObject, optional
+        a2: float or PyoObject, optional
             Amplitude of the second output sample delayed. Defaults to 0.929003.
 
     >>> s = Server().boot()
@@ -379,6 +398,7 @@ class Biquada(PyoObject):
 
     """
     def __init__(self, input, b0=0.005066, b1=0.010132, b2=0.005066, a0=1.070997, a1=-1.979735, a2=0.929003, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOOOOOO", input, b0, b1, b2, a0, a1, a2, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._b0 = Sig(b0)
@@ -390,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):
         """
@@ -397,12 +418,13 @@ class Biquada(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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)
 
@@ -412,10 +434,11 @@ class Biquada(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `b0` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._b0.value = x
 
     def setB1(self, x):
@@ -424,10 +447,11 @@ class Biquada(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `b1` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._b1.value = x
 
     def setB2(self, x):
@@ -436,10 +460,11 @@ class Biquada(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `b2` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._b2.value = x
 
     def setA0(self, x):
@@ -448,10 +473,11 @@ class Biquada(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `a0` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._a0.value = x
 
     def setA1(self, x):
@@ -460,10 +486,11 @@ class Biquada(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `a1` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._a1.value = x
 
     def setA2(self, x):
@@ -472,31 +499,32 @@ class Biquada(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `a2` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._a2.value = x
 
     def setCoeffs(self, *args, **kwds):
         """
         Replace all filter coefficients.
-    
+
         :Args:
-    
-            b0 : float or PyoObject, optional
+
+            b0: float or PyoObject, optional
                 New `b0` attribute.
-            b1 : float or PyoObject, optional
+            b1: float or PyoObject, optional
                 New `b1` attribute.
-            b2 : float or PyoObject, optional
+            b2: float or PyoObject, optional
                 New `b2` attribute.
-            a0 : float or PyoObject, optional
+            a0: float or PyoObject, optional
                 New `a0` attribute.
-            a1 : float or PyoObject, optional
+            a1: float or PyoObject, optional
                 New `a1` attribute.
-            a2 : float or PyoObject, optional
+            a2: float or PyoObject, optional
                 New `a2` attribute.
-    
+
         """
         for i, val in enumerate(args):
             attr = getattr(self, ["_b0", "_b1", "_b2", "_a0", "_a1", "_a2"][i])
@@ -512,81 +540,81 @@ class Biquada(PyoObject):
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def b0(self):
-        """float or PyoObject. `b0` coefficient.""" 
+        """float or PyoObject. `b0` coefficient."""
         return self._b0
     @b0.setter
     def b0(self, x): self.setB0(x)
 
     @property
     def b1(self):
-        """float or PyoObject. `b1` coefficient.""" 
+        """float or PyoObject. `b1` coefficient."""
         return self._b1
     @b1.setter
     def b1(self, x): self.setB1(x)
 
     @property
     def b2(self):
-        """float or PyoObject. `b2` coefficient.""" 
+        """float or PyoObject. `b2` coefficient."""
         return self._b2
     @b2.setter
     def b2(self, x): self.setB2(x)
 
     @property
     def a0(self):
-        """float or PyoObject. `a0` coefficient.""" 
+        """float or PyoObject. `a0` coefficient."""
         return self._a0
     @a0.setter
     def a0(self, x): self.setA0(x)
 
     @property
     def a1(self):
-        """float or PyoObject. `a1` coefficient.""" 
+        """float or PyoObject. `a1` coefficient."""
         return self._a1
     @a1.setter
     def a1(self, x): self.setA1(x)
 
     @property
     def a2(self):
-        """float or PyoObject. `a2` coefficient.""" 
+        """float or PyoObject. `a2` coefficient."""
         return self._a2
     @a2.setter
     def a2(self, x): self.setA2(x)
 
 class EQ(PyoObject):
     """
-    Equalizer filter. 
-    
-    EQ is a biquadratic digital filter designed for equalization. It 
-    provides peak/notch and lowshelf/highshelf filters for building 
+    Equalizer filter.
+
+    EQ is a biquadratic digital filter designed for equalization. It
+    provides peak/notch and lowshelf/highshelf filters for building
     parametric equalizers.
-    
+
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
-    
-        input : PyoObject
+
+        input: PyoObject
             Input signal to process.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Cutoff or center frequency of the filter. Defaults to 1000.
-        q : float or PyoObject, optional
-            Q of the filter, defined as freq/bandwidth. 
+        q: float or PyoObject, optional
+            Q of the filter, defined as freq/bandwidth.
             Should be between 1 and 500. Defaults to 1.
-        boost : float or PyoObject, optional
-            Gain, expressed in dB, to add or remove at the center frequency. 
+        boost: float or PyoObject, optional
+            Gain, expressed in dB, to add or remove at the center frequency.
             Default to -3.
-        type : int, optional
+        type: int, optional
             Filter type. Three possible values :
                 0. peak/notch (default)
                 1. lowshelf
                 2. highshelf
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> amp = Fader(1, 1, mul=.15).play()
@@ -597,6 +625,7 @@ class EQ(PyoObject):
 
     """
     def __init__(self, input, freq=1000, q=1, boost=-3.0, type=0, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOiOO", input, freq, q, boost, type, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._freq = freq
@@ -606,32 +635,35 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setFreq(self, x):
         """
         Replace the `freq` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `freq` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -639,13 +671,14 @@ class EQ(PyoObject):
     def setQ(self, x):
         """
         Replace the `q` attribute. Should be between 1 and 500.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `q` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._q = x
         x, lmax = convertArgsToLists(x)
         [obj.setQ(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -653,13 +686,14 @@ class EQ(PyoObject):
     def setBoost(self, x):
         """
         Replace the `boost` attribute, expressed in dB.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `boost` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._boost = x
         x, lmax = convertArgsToLists(x)
         [obj.setBoost(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -667,57 +701,59 @@ class EQ(PyoObject):
     def setType(self, x):
         """
         Replace the `type` attribute.
-        
+
         :Args:
 
-            x : int
-                New `type` attribute. 
+            x: int
+                New `type` attribute.
                 0. peak
                 1. lowshelf
                 2. highshelf
 
         """
+        pyoArgsAssert(self, "i", x)
         self._type = x
         x, lmax = convertArgsToLists(x)
         [obj.setType(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
-        self._map_list = [SLMapFreq(self._freq), SLMapQ(self._q), 
-                          SLMap(-40.0, 40.0, "lin", "boost", self._boost), 
+        self._map_list = [SLMapFreq(self._freq), SLMapQ(self._q),
+                          SLMap(-40.0, 40.0, "lin", "boost", self._boost),
+                          SLMap(0, 2, 'lin', 'type', self._type, res="int", dataOnly=True),
                           SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def freq(self):
-        """float or PyoObject. Cutoff or center frequency of the filter.""" 
+        """float or PyoObject. Cutoff or center frequency of the filter."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
     def q(self):
-        """float or PyoObject. Q of the filter.""" 
+        """float or PyoObject. Q of the filter."""
         return self._q
     @q.setter
     def q(self, x): self.setQ(x)
 
     @property
     def boost(self):
-        """float or PyoObject. Boost factor of the filter.""" 
+        """float or PyoObject. Boost factor of the filter."""
         return self._boost
     @boost.setter
     def boost(self, x): self.setBoost(x)
 
     @property
     def type(self):
-        """int. Filter type.""" 
+        """int. Filter type."""
         return self._type
     @type.setter
     def type(self, x): self.setType(x)
@@ -725,16 +761,16 @@ class EQ(PyoObject):
 class Tone(PyoObject):
     """
     A first-order recursive low-pass filter with variable frequency response.
- 
+
     :Parent: :py:class:`PyoObject`
-   
+
     :Args:
-    
-        input : PyoObject
+
+        input: PyoObject
             Input signal to process.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Cutoff frequency of the filter in hertz. Default to 1000.
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> n = Noise(.3)
@@ -743,38 +779,42 @@ class Tone(PyoObject):
 
     """
     def __init__(self, input, freq=1000, mul=1, add=0):
+        pyoArgsAssert(self, "oOOO", input, freq, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._freq = freq
         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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
-        
+
     def setFreq(self, x):
         """
         Replace the `freq` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `freq` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -782,17 +822,17 @@ class Tone(PyoObject):
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMapFreq(self._freq), SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
-      
+
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def freq(self):
-        """float or PyoObject. Cutoff frequency of the filter.""" 
+        """float or PyoObject. Cutoff frequency of the filter."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
@@ -800,16 +840,16 @@ class Tone(PyoObject):
 class Atone(PyoObject):
     """
     A first-order recursive high-pass filter with variable frequency response.
- 
+
     :Parent: :py:class:`PyoObject`
-   
+
     :Args:
-    
-        input : PyoObject
+
+        input: PyoObject
             Input signal to process.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Cutoff frequency of the filter in hertz. Default to 1000.
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> n = Noise(.3)
@@ -818,38 +858,42 @@ class Atone(PyoObject):
 
     """
     def __init__(self, input, freq=1000, mul=1, add=0):
+        pyoArgsAssert(self, "oOOO", input, freq, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._freq = freq
         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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
-        
+
     def setFreq(self, x):
         """
         Replace the `freq` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `freq` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -857,17 +901,17 @@ class Atone(PyoObject):
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMapFreq(self._freq), SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
-      
+
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def freq(self):
-        """float or PyoObject. Cutoff frequency of the filter.""" 
+        """float or PyoObject. Cutoff frequency of the filter."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
@@ -875,22 +919,22 @@ class Atone(PyoObject):
 class Port(PyoObject):
     """
     Exponential portamento.
-    
-    Perform an exponential portamento on an audio signal with 
+
+    Perform an exponential portamento on an audio signal with
     different rising and falling times.
-    
+
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        risetime : float or PyoObject, optional
+        risetime: float or PyoObject, optional
             Time to reach upward value in seconds. Defaults to 0.05.
-        falltime : float or PyoObject, optional
+        falltime: float or PyoObject, optional
             Time to reach downward value in seconds. Defaults to 0.05.
-        init : float, optional
-            Initial state of the internal memory. Available at intialization 
+        init: float, optional
+            Initial state of the internal memory. Available at intialization
             time only. Defaults to 0.
 
     >>> from random import uniform
@@ -902,9 +946,10 @@ class Port(PyoObject):
     >>> def new_freq():
     ...     x.value = uniform(400, 800)
     >>> pat = Pattern(function=new_freq, time=1).play()
-    
+
     """
     def __init__(self, input, risetime=0.05, falltime=0.05, init=0, mul=1, add=0):
+        pyoArgsAssert(self, "oOOnOO", input, risetime, falltime, init, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._risetime = risetime
@@ -912,32 +957,35 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setRiseTime(self, x):
         """
         Replace the `risetime` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `risetime` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._risetime = x
         x, lmax = convertArgsToLists(x)
         [obj.setRiseTime(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -945,32 +993,33 @@ class Port(PyoObject):
     def setFallTime(self, x):
         """
         Replace the `falltime` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `falltime` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._falltime = x
         x, lmax = convertArgsToLists(x)
         [obj.setFallTime(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.001, 10., 'lin', 'risetime', self._risetime),
-                          SLMap(0.001, 10., 'lin', 'falltime', self._falltime)]
+        self._map_list = [SLMap(0.001, 10., 'log', 'risetime', self._risetime),
+                          SLMap(0.001, 10., 'log', 'falltime', self._falltime)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def risetime(self):
-        """float or PyoObject. Time to reach upward value in seconds.""" 
+        """float or PyoObject. Time to reach upward value in seconds."""
         return self._risetime
     @risetime.setter
     def risetime(self, x): self.setRiseTime(x)
@@ -985,14 +1034,14 @@ class Port(PyoObject):
 class DCBlock(PyoObject):
     """
     Implements the DC blocking filter.
- 
+
     :Parent: :py:class:`PyoObject`
-   
+
     :Args:
-    
-        input : PyoObject
+
+        input: PyoObject
             Input signal to process.
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> n = Noise(.01)
@@ -1001,30 +1050,33 @@ class DCBlock(PyoObject):
 
     """
     def __init__(self, input, mul=1, add=0):
+        pyoArgsAssert(self, "oOO", input, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -1032,31 +1084,31 @@ class DCBlock(PyoObject):
 class BandSplit(PyoObject):
     """
     Splits an input signal into multiple frequency bands.
-    
-    The input signal will be separated into `num` bands between `min` 
-    and `max` frequencies using second-order bandpass filters. Each 
-    band will then be assigned to an independent audio stream. 
+
+    The input signal will be separated into `num` bands between `min`
+    and `max` frequencies using second-order bandpass filters. Each
+    band will then be assigned to an independent audio stream.
     Useful for multiband processing.
 
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
-    
-        input : PyoObject
+
+        input: PyoObject
             Input signal to process.
-        num : int, optional
-            Number of frequency bands created. Available at initialization 
+        num: int, optional
+            Number of frequency bands created. Available at initialization
             time only. Defaults to 6.
-        min : float, optional
-            Lowest frequency. Available at initialization time only. 
+        min: float, optional
+            Lowest frequency. Available at initialization time only.
             Defaults to 20.
-        max : float, optional
-            Highest frequency. Available at initialization time only. 
+        max: float, optional
+            Highest frequency. Available at initialization time only.
             Defaults to 20000.
-        q : float or PyoObject, optional
-            Q of the filters, defined as center frequency / bandwidth. 
+        q: float or PyoObject, optional
+            Q of the filters, defined as center frequency / bandwidth.
             Should be between 1 and 500. Defaults to 1.
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> lfos = Sine(freq=[.3,.4,.5,.6,.7,.8], mul=.5, add=.5)
@@ -1065,6 +1117,7 @@ class BandSplit(PyoObject):
 
     """
     def __init__(self, input, num=6, min=20, max=20000, q=1, mul=1, add=0):
+        pyoArgsAssert(self, "oINNOOO", input, num, min, max, q, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._num = num
@@ -1080,32 +1133,35 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setQ(self, x):
         """
         Replace the `q` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `q` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._q = x
         x, lmax = convertArgsToLists(x)
         [obj.setQ(wrap(x,i)) for i, obj in enumerate(self._base_players)]
@@ -1116,42 +1172,42 @@ class BandSplit(PyoObject):
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
-    def q(self): 
+    def q(self):
         """float or PyoObject. Q of the filters."""
         return self._q
     @q.setter
-    def q(self, x): self.setQ(x) 
+    def q(self, x): self.setQ(x)
 
 class FourBand(PyoObject):
     """
     Splits an input signal into four frequency bands.
 
-    The input signal will be separated into 4 bands around `freqs` 
-    arguments using fourth-order Linkwitz-Riley lowpass and highpass 
-    filters. Each band will then be assigned to an independent audio 
-    stream. The sum of the four bands reproduces the same signal as 
+    The input signal will be separated into 4 bands around `freqs`
+    arguments using fourth-order Linkwitz-Riley lowpass and highpass
+    filters. Each band will then be assigned to an independent audio
+    stream. The sum of the four bands reproduces the same signal as
     the `input`. Useful for multiband processing.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        freq1 : float or PyoObject, optional
+        freq1: float or PyoObject, optional
             First crossover frequency. First band will contain signal
             from 0 Hz to `freq1` Hz. Defaults to 150.
-        freq2 : float or PyoObject, optional
+        freq2: float or PyoObject, optional
             Second crossover frequency. Second band will contain signal
             from `freq1` Hz to `freq2`. `freq2` is the lower limit of the
             third band signal. Defaults to 500.
-        freq3 : float or PyoObject, optional
+        freq3: float or PyoObject, optional
             Third crossover frequency. It's the upper limit of the third
             band signal and fourth band will contain signal from `freq3`
             to sr/2. Defaults to 2000.
@@ -1164,6 +1220,7 @@ class FourBand(PyoObject):
 
     """
     def __init__(self, input, freq1=150, freq2=500, freq3=2000, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOOO", input, freq1, freq2, freq3, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._freq1 = freq1
@@ -1178,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):
         """
@@ -1185,12 +1243,13 @@ class FourBand(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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)
 
@@ -1200,10 +1259,11 @@ class FourBand(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `freq1` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq1 = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq1(wrap(x,i)) for i, obj in enumerate(self._base_players)]
@@ -1214,10 +1274,11 @@ class FourBand(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `freq2` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq2 = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq2(wrap(x,i)) for i, obj in enumerate(self._base_players)]
@@ -1228,10 +1289,11 @@ class FourBand(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `freq3` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq3 = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq3(wrap(x,i)) for i, obj in enumerate(self._base_players)]
@@ -1245,63 +1307,63 @@ class FourBand(PyoObject):
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
-    def freq1(self): 
+    def freq1(self):
         """float or PyoObject. First crossover frequency."""
         return self._freq1
     @freq1.setter
-    def freq1(self, x): self.setFreq1(x) 
+    def freq1(self, x): self.setFreq1(x)
 
     @property
-    def freq2(self): 
+    def freq2(self):
         """float or PyoObject. Second crossover frequency."""
         return self._freq2
     @freq2.setter
-    def freq2(self, x): self.setFreq2(x) 
+    def freq2(self, x): self.setFreq2(x)
 
     @property
-    def freq3(self): 
+    def freq3(self):
         """float or PyoObject. Third crossover frequency."""
         return self._freq3
     @freq3.setter
-    def freq3(self, x): self.setFreq3(x) 
+    def freq3(self, x): self.setFreq3(x)
 
 class Hilbert(PyoObject):
     """
     Hilbert transform.
-    
-    Hilbert is an IIR filter based implementation of a broad-band 90 degree 
-    phase difference network. The outputs of hilbert have an identical 
-    frequency response to the input (i.e. they sound the same), but the two 
-    outputs have a constant phase difference of 90 degrees, plus or minus some 
-    small amount of error, throughout the entire frequency range. The outputs 
+
+    Hilbert is an IIR filter based implementation of a broad-band 90 degree
+    phase difference network. The outputs of hilbert have an identical
+    frequency response to the input (i.e. they sound the same), but the two
+    outputs have a constant phase difference of 90 degrees, plus or minus some
+    small amount of error, throughout the entire frequency range. The outputs
     are in quadrature.
 
-    Hilbert is useful in the implementation of many digital signal processing 
-    techniques that require a signal in phase quadrature. The real part corresponds 
-    to the cosine output of hilbert, while the imaginary part corresponds to the 
-    sine output. The two outputs have a constant phase difference throughout the 
+    Hilbert is useful in the implementation of many digital signal processing
+    techniques that require a signal in phase quadrature. The real part corresponds
+    to the cosine output of hilbert, while the imaginary part corresponds to the
+    sine output. The two outputs have a constant phase difference throughout the
     audio range that corresponds to the phase relationship between cosine and sine waves.
-    
+
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
-    
-        input : PyoObject
+
+        input: PyoObject
             Input signal to process.
-    
+
     .. note::
-    
-        Real and imaginary parts are two separated set of streams. 
+
+        Real and imaginary parts are two separated set of streams.
         The user should call :
-        
-        Hilbert['real'] to retrieve the real part.
-        Hilbert['imag'] to retrieve the imaginary part.
+
+        |  Hilbert['real'] to retrieve the real part.
+        |  Hilbert['imag'] to retrieve the imaginary part.
 
     >>> s = Server().boot()
     >>> s.start()
@@ -1316,6 +1378,7 @@ class Hilbert(PyoObject):
 
     """
     def __init__(self, input, mul=1, add=0):
+        pyoArgsAssert(self, "oOO", input, mul, add)
         PyoObject.__init__(self, mul, add)
         self._real_dummy = []
         self._imag_dummy = []
@@ -1329,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':
@@ -1341,47 +1405,48 @@ class Hilbert(PyoObject):
     def get(self, identifier="real", all=False):
         """
         Return the first sample of the current buffer as a float.
-        
+
         Can be used to convert audio stream to usable Python data.
-        
+
         "real" or "imag" must be given to `identifier` to specify
         which stream to get value from.
-        
+
         :Args:
 
-            identifier : string {"real", "imag"}
+            identifier: string {"real", "imag"}
                 Address string parameter identifying audio stream.
                 Defaults to "real".
-            all : boolean, optional
+            all: boolean, optional
                 If True, the first value of each object's stream
                 will be returned as a list. Otherwise, only the value
                 of the first object's stream will be returned as a float.
                 Defaults to False.
-                 
+
         """
         if not all:
             return self.__getitem__(identifier)[0]._getStream().getValue()
         else:
             return [obj._getStream().getValue() for obj in self.__getitem__(identifier).getBaseObjects()]
- 
+
     def setInput(self, x, fadetime=0.05):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -1389,7 +1454,7 @@ class Hilbert(PyoObject):
 class Allpass(PyoObject):
     """
     Delay line based allpass filter.
-    
+
     Allpass is based on the combination of feedforward and feedback comb
     filter. This kind of filter is often used in simple digital reverb
     implementations.
@@ -1398,15 +1463,15 @@ class Allpass(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        delay : float or PyoObject, optional
+        delay: float or PyoObject, optional
             Delay time in seconds. Defaults to 0.01.
-        feedback : float or PyoObject, optional
+        feedback: float or PyoObject, optional
             Amount of output signal sent back into the delay line.
             Defaults to 0.
-        maxdelay : float, optional
-            Maximum delay length in seconds. Available only at initialization. 
+        maxdelay: float, optional
+            Maximum delay length in seconds. Available only at initialization.
             Defaults to 1.
 
     >>> # SIMPLE REVERB
@@ -1421,9 +1486,10 @@ class Allpass(PyoObject):
     >>> c2 = Tone(b2, 3000, mul=0.2).out()
     >>> c3 = Tone(b3, 1500, mul=0.2).out()
     >>> c4 = Tone(b4, 500, mul=0.2).out()
-    
+
     """
     def __init__(self, input, delay=0.01, feedback=0, maxdelay=1, mul=1, add=0):
+        pyoArgsAssert(self, "oOOnOO", input, delay, feedback, maxdelay, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._delay = delay
@@ -1432,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):
         """
@@ -1439,12 +1506,13 @@ class Allpass(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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)
 
@@ -1454,10 +1522,11 @@ class Allpass(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `delay` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._delay = x
         x, lmax = convertArgsToLists(x)
         [obj.setDelay(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1468,60 +1537,61 @@ class Allpass(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `feedback` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._feedback = x
         x, lmax = convertArgsToLists(x)
         [obj.setFeedback(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.001, self._maxdelay, 'log', 'delay',  self._delay),
+        self._map_list = [SLMap(0.001, self._maxdelay, 'log', 'delay', self._delay),
                           SLMap(0., 1., 'lin', 'feedback', self._feedback),
                           SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def delay(self):
-        """float or PyoObject. Delay time in seconds.""" 
+        """float or PyoObject. Delay time in seconds."""
         return self._delay
     @delay.setter
     def delay(self, x): self.setDelay(x)
 
     @property
     def feedback(self):
-        """float or PyoObject. Amount of output signal sent back into the delay line.""" 
+        """float or PyoObject. Amount of output signal sent back into the delay line."""
         return self._feedback
     @feedback.setter
     def feedback(self, x): self.setFeedback(x)
 
 class Allpass2(PyoObject):
     """
-    Second-order phase shifter allpass. 
-    
+    Second-order phase shifter allpass.
+
     This kind of filter is used in phaser implementation. The signal
     of this filter, when added to original sound, creates a notch in
     the spectrum at frequencies that are in phase opposition.
-    
+
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
-    
-        input : PyoObject
+
+        input: PyoObject
             Input signal to process.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Center frequency of the filter. Defaults to 1000.
-        bw : float or PyoObject, optional
+        bw: float or PyoObject, optional
             Bandwidth of the filter in Hertz. Defaults to 100.
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> # 3 STAGES PHASER
@@ -1535,6 +1605,7 @@ class Allpass2(PyoObject):
 
     """
     def __init__(self, input, freq=1000, bw=100, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOO", input, freq, bw, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._freq = freq
@@ -1542,32 +1613,35 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setFreq(self, x):
         """
         Replace the `freq` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `freq` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1575,46 +1649,47 @@ class Allpass2(PyoObject):
     def setBw(self, x):
         """
         Replace the `bw` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `bw` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._bw = x
         x, lmax = convertArgsToLists(x)
         [obj.setBw(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
-        self._map_list = [SLMapFreq(self._freq), SLMap(10, 1000, "lin", "bw", self._bw), 
+        self._map_list = [SLMapFreq(self._freq), SLMap(10, 1000, "lin", "bw", self._bw),
                           SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def input(self):
-        """PyoObject. Input signal to filter.""" 
+        """PyoObject. Input signal to filter."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def freq(self):
-        """float or PyoObject. Center frequency of the filter.""" 
+        """float or PyoObject. Center frequency of the filter."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
     def bw(self):
-        """float or PyoObject. Bandwidth of the filter.""" 
+        """float or PyoObject. Bandwidth of the filter."""
         return self._bw
     @bw.setter
     def bw(self, x): self.setBw(x)
 
 class Phaser(PyoObject):
     """
-    Multi-stages second-order phase shifter allpass filters. 
+    Multi-stages second-order phase shifter allpass filters.
 
     Phaser implements `num` number of second-order allpass filters.
 
@@ -1622,21 +1697,21 @@ class Phaser(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Center frequency of the first notch. Defaults to 1000.
-        spread : float or PyoObject, optional
+        spread: float or PyoObject, optional
             Spreading factor for upper notch frequencies. Defaults to 1.1.
-        q : float or PyoObject, optional
+        q: float or PyoObject, optional
             Q of the filter as center frequency / bandwidth. Defaults to 10.
-        feedback : float or PyoObject, optional
+        feedback: float or PyoObject, optional
             Amount of output signal which is fed back into the input of the
             allpass chain. Defaults to 0.
-        num : int, optional
+        num: int, optional
             The number of allpass stages in series. Defines the number of
             notches in the spectrum. Defaults to 8.
-            
+
             Available at initialization only.
 
     >>> s = Server().boot()
@@ -1649,16 +1724,18 @@ class Phaser(PyoObject):
 
     """
     def __init__(self, input, freq=1000, spread=1.1, q=10, feedback=0, num=8, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOOiOO", input, freq, spread, q, feedback, num, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._freq = freq
         self._spread = spread
         self._q = q
         self._feedback = feedback
-        self._num= num
+        self._num = num
         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):
         """
@@ -1666,12 +1743,13 @@ class Phaser(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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)
 
@@ -1681,10 +1759,11 @@ class Phaser(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `freq` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1695,10 +1774,11 @@ class Phaser(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `spread` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._spread = x
         x, lmax = convertArgsToLists(x)
         [obj.setSpread(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1709,10 +1789,11 @@ class Phaser(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `q` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._q = x
         x, lmax = convertArgsToLists(x)
         [obj.setQ(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1723,99 +1804,100 @@ class Phaser(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `feedback` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._feedback = x
         x, lmax = convertArgsToLists(x)
         [obj.setFeedback(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(20, 2000, "log", "freq", self._freq), 
+        self._map_list = [SLMap(20, 2000, "log", "freq", self._freq),
                           SLMap(0.5, 2, "lin", "spread", self._spread),
-                          SLMap(0.5, 100, "log", "q", self._q), 
+                          SLMap(0.5, 100, "log", "q", self._q),
                           SLMap(0, 1, "lin", "feedback", self._feedback),
                           SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def freq(self):
-        """float or PyoObject. Center frequency of the first notch.""" 
+        """float or PyoObject. Center frequency of the first notch."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
     def spread(self):
-        """float or PyoObject. Spreading factor for upper notch frequencies.""" 
+        """float or PyoObject. Spreading factor for upper notch frequencies."""
         return self._spread
     @spread.setter
     def spread(self, x): self.setSpread(x)
 
     @property
     def q(self):
-        """float or PyoObject. Q factor of the filter.""" 
+        """float or PyoObject. Q factor of the filter."""
         return self._q
     @q.setter
     def q(self, x): self.setQ(x)
 
     @property
     def feedback(self):
-        """float or PyoObject. Feedback factor of the filter.""" 
+        """float or PyoObject. Feedback factor of the filter."""
         return self._feedback
     @feedback.setter
     def feedback(self, x): self.setFeedback(x)
 
 class Vocoder(PyoObject):
     """
-    Applies the spectral envelope of a first sound to the spectrum of a second sound. 
+    Applies the spectral envelope of a first sound to the spectrum of a second sound.
 
-    The vocoder is an analysis/synthesis system, historically used to reproduce 
-    human speech. In the encoder, the first input (spectral envelope) is passed 
-    through a multiband filter, each band is passed through an envelope follower, 
-    and the control signals from the envelope followers are communicated to the 
-    decoder. The decoder applies these (amplitude) control signals to corresponding 
+    The vocoder is an analysis/synthesis system, historically used to reproduce
+    human speech. In the encoder, the first input (spectral envelope) is passed
+    through a multiband filter, each band is passed through an envelope follower,
+    and the control signals from the envelope followers are communicated to the
+    decoder. The decoder applies these (amplitude) control signals to corresponding
     filters modifying the second source (exciter).
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Spectral envelope. Gives the spectral properties of the bank of filters.
             For best results, this signal must have a dynamic spectrum, both for
             amplitudes and frequencies.
-        input2 : PyoObject
+        input2: PyoObject
             Exciter. Spectrum to filter. For best results, this signal must have a
             broadband spectrum with few amplitude variations.
-        freq : float or PyoObject, optional
-            Center frequency of the first band. This is the base frequency used to 
+        freq: float or PyoObject, optional
+            Center frequency of the first band. This is the base frequency used to
             compute the upper bands. Defaults to 60.
-        spread : float or PyoObject, optional
-            Spreading factor for upper band frequencies. Each band is 
+        spread: float or PyoObject, optional
+            Spreading factor for upper band frequencies. Each band is
             `freq * pow(order, spread)`, where order is the harmonic rank of the band.
             Defaults to 1.25.
-        q : float or PyoObject, optional
+        q: float or PyoObject, optional
             Q of the filters as `center frequency / bandwidth`. Higher values imply
             more resonance around the center frequency. Defaults to 20.
-        slope : float or PyoObject, optional
+        slope: float or PyoObject, optional
             Time response of the envelope follower. Lower values mean smoother changes,
             while higher values mean a better time accuracy. Defaults to 0.5.
-        stages : int, optional
-            The number of bands in the filter bank. Defines the number of notches in 
+        stages: int, optional
+            The number of bands in the filter bank. Defines the number of notches in
             the spectrum. Defaults to 24.
 
     .. note::
 
-        Altough parameters can be audio signals, values are sampled only four times 
+        Altough parameters can be audio signals, values are sampled only four times
         per buffer size. To avoid artefacts, it is recommended to keep variations
         at low rate (< 20 Hz).
 
@@ -1828,6 +1910,7 @@ class Vocoder(PyoObject):
 
     """
     def __init__(self, input, input2, freq=60, spread=1.25, q=20, slope=0.5, stages=24, mul=1, add=0):
+        pyoArgsAssert(self, "ooOOOOiOO", input, input2, freq, spread, q, slope, stages, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._input2 = input2
@@ -1840,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):
         """
@@ -1847,12 +1931,13 @@ class Vocoder(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 The spectral envelope.
-            fadetime : float, optional
+            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)
 
@@ -1862,12 +1947,13 @@ class Vocoder(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 The exciter.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Defaults to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input2 = x
         self._in_fader2.setInput(x, fadetime)
 
@@ -1877,10 +1963,11 @@ class Vocoder(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `freq` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1891,10 +1978,11 @@ class Vocoder(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `spread` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._spread = x
         x, lmax = convertArgsToLists(x)
         [obj.setSpread(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1905,10 +1993,11 @@ class Vocoder(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `q` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._q = x
         x, lmax = convertArgsToLists(x)
         [obj.setQ(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1919,10 +2008,11 @@ class Vocoder(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `slope` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._slope = x
         x, lmax = convertArgsToLists(x)
         [obj.setSlope(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1933,67 +2023,69 @@ class Vocoder(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 New `stages` attribute.
 
         """
+        pyoArgsAssert(self, "i", x)
         self._stages = x
         x, lmax = convertArgsToLists(x)
         [obj.setStages(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(10, 1000, "log", "freq", self._freq), 
+        self._map_list = [SLMap(10, 1000, "log", "freq", self._freq),
                           SLMap(0.25, 2, "lin", "spread", self._spread),
-                          SLMap(0.5, 200, "log", "q", self._q), 
+                          SLMap(0.5, 200, "log", "q", self._q),
                           SLMap(0, 1, "lin", "slope", self._slope),
+                          SLMap(2, 64, 'lin', 'stages', self._stages, res="int", dataOnly=True),
                           SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def input(self):
-        """PyoObject. The spectral envelope.""" 
+        """PyoObject. The spectral envelope."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def input2(self):
-        """PyoObject. The exciter.""" 
+        """PyoObject. The exciter."""
         return self._input2
     @input2.setter
     def input2(self, x): self.setInput2(x)
 
     @property
     def freq(self):
-        """float or PyoObject. Center frequency of the first band.""" 
+        """float or PyoObject. Center frequency of the first band."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
     def spread(self):
-        """float or PyoObject. Spreading factor for upper band frequencies.""" 
+        """float or PyoObject. Spreading factor for upper band frequencies."""
         return self._spread
     @spread.setter
     def spread(self, x): self.setSpread(x)
 
     @property
     def q(self):
-        """float or PyoObject. Q factor of the filters.""" 
+        """float or PyoObject. Q factor of the filters."""
         return self._q
     @q.setter
     def q(self, x): self.setQ(x)
 
     @property
     def slope(self):
-        """float or PyoObject. Time response of the envelope follower.""" 
+        """float or PyoObject. Time response of the envelope follower."""
         return self._slope
     @slope.setter
     def slope(self, x): self.setSlope(x)
 
     @property
     def stages(self):
-        """int. The number of bands in the filter bank.""" 
+        """int. The number of bands in the filter bank."""
         return self._stages
     @stages.setter
     def stages(self, x): self.setStages(x)
@@ -2001,9 +2093,9 @@ class Vocoder(PyoObject):
 class IRWinSinc(PyoObject):
     """
     Windowed-sinc filter using circular convolution.
-    
-    IRWinSinc uses circular convolution to implement standard filters like 
-    lowpass, highpass, bandreject and bandpass with very flat passband 
+
+    IRWinSinc uses circular convolution to implement standard filters like
+    lowpass, highpass, bandreject and bandpass with very flat passband
     response and sharp roll-off. User can defined the length, in samples,
     of the impulse response, also known as the filter kernel.
 
@@ -2011,32 +2103,32 @@ class IRWinSinc(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Frequency cutoff for lowpass and highpass and center frequency for
             bandjrect and bandpass filters, expressed in Hz. Defaults to 1000.
-        bw : float or PyoObject, optional
+        bw: float or PyoObject, optional
             Bandwidth, expressed in Hertz, for bandreject and bandpass filters.
             Defaults to 500.
-        type : int, optional
+        type: int, optional
             Filter type. Four possible values :
                 0. lowpass (default)
                 1. highpass
                 2. bandreject
                 3. bandpass
-        order : int {even number}, optional
-            Length, in samples, of the filter kernel used for convolution. Available 
+        order: int {even number}, optional
+            Length, in samples, of the filter kernel used for convolution. Available
             at initialization time only. Defaults to 256.
-            
-            This value must be even. Higher is the order and sharper is the roll-off 
-            of the filter, but it is also more expensive to compute. 
+
+            This value must be even. Higher is the order and sharper is the roll-off
+            of the filter, but it is also more expensive to compute.
 
     .. note::
 
-        Convolution is very expensive to compute, so the length of the impulse 
+        Convolution is very expensive to compute, so the length of the impulse
         response (the `order` parameter) must be kept very short to run in real time.
-        
+
         Note that although `freq` and `bw` can be PyoObjects, the impulse response of
         the filter is only updated once per buffer size.
 
@@ -2049,6 +2141,7 @@ class IRWinSinc(PyoObject):
 
     """
     def __init__(self, input, freq=1000, bw=500, type=0, order=256, mul=1, add=0):
+        pyoArgsAssert(self, "oOOiiOO", input, freq, bw, type, order, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._freq = freq
@@ -2056,11 +2149,12 @@ class IRWinSinc(PyoObject):
         self._type = type
         if (order % 2) != 0:
             order += 1
-            print "order argument of IRWinSinc must be even, set to %i" % order
+            print("order argument of IRWinSinc must be even, set to %i" % order)
         self._order = order
         self._in_fader = InputFader(input)
-        in_fader, freq, bw, type, order, mul, add, lmax = convertArgsToLists(self._in_fader, freq, bw, type, order, mul, add)                     
+        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):
         """
@@ -2068,12 +2162,13 @@ class IRWinSinc(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
@@ -2083,10 +2178,11 @@ class IRWinSinc(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `freq` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2097,10 +2193,11 @@ class IRWinSinc(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `bw` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._bw = x
         x, lmax = convertArgsToLists(x)
         [obj.setBandwidth(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2111,47 +2208,49 @@ class IRWinSinc(PyoObject):
 
         :Args:
 
-            x : int
-                New `type` attribute. 
+            x: int
+                New `type` attribute.
                 0. lowpass
                 1. highpass
                 2. bandreject
                 3. bandpass
 
         """
+        pyoArgsAssert(self, "i", x)
         self._type = x
         x, lmax = convertArgsToLists(x)
         [obj.setType(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMapFreq(self._freq),
-                          SLMap(20., 10000., "log", "bw", self._bw)]
+                          SLMap(20., 10000., "log", "bw", self._bw),
+                          SLMap(0, 3, 'lin', 'type', self._type, res="int", dataOnly=True)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def freq(self):
-        """float or PyoObject. Cutoff or Center frequency of the filter.""" 
+        """float or PyoObject. Cutoff or Center frequency of the filter."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
     def bw(self):
-        """float or PyoObject. Bandwidth for bandreject and bandpass filters.""" 
+        """float or PyoObject. Bandwidth for bandreject and bandpass filters."""
         return self._bw
     @bw.setter
     def bw(self, x): self.setBw(x)
 
     @property
     def type(self):
-        """int. Filter type {0 = lowpass, 1 = highpass, 2 = bandreject, 3 = bandpass}.""" 
+        """int. Filter type {0 = lowpass, 1 = highpass, 2 = bandreject, 3 = bandpass}."""
         return self._type
     @type.setter
     def type(self, x): self.setType(x)
@@ -2162,8 +2261,8 @@ class IRAverage(PyoObject):
 
     IRAverage uses circular convolution to implement an average filter. This
     filter is designed to reduce the noise in the input signal while keeping
-    as much as possible the step response of the original signal. User can 
-    defined the length, in samples, of the impulse response, also known as 
+    as much as possible the step response of the original signal. User can
+    defined the length, in samples, of the impulse response, also known as
     the filter kernel. This controls the ratio of removed noise vs the fidelity
     of the original step response.
 
@@ -2171,19 +2270,19 @@ class IRAverage(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        order : int {even number}, optional
-            Length, in samples, of the filter kernel used for convolution. Available 
-            at initialization time only. Defaults to 256. 
-            
-            This value must be even. A high order will reduced more noise and will 
-            have a higher damping effect on the step response, but it is also more 
-            expensive to compute. 
+        order: int {even number}, optional
+            Length, in samples, of the filter kernel used for convolution. Available
+            at initialization time only. Defaults to 256.
+
+            This value must be even. A high order will reduced more noise and will
+            have a higher damping effect on the step response, but it is also more
+            expensive to compute.
 
     .. note::
 
-        Convolution is very expensive to compute, so the length of the impulse 
+        Convolution is very expensive to compute, so the length of the impulse
         response (the `order` parameter) must be kept very short to run in real time.
 
     >>> s = Server().boot()
@@ -2194,15 +2293,17 @@ class IRAverage(PyoObject):
 
     """
     def __init__(self, input, order=256, mul=1, add=0):
+        pyoArgsAssert(self, "oiOO", input, order, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         if (order % 2) != 0:
             order += 1
-            print "order argument of IRAverage must be even, set to %i" % order
+            print("order argument of IRAverage must be even, set to %i" % order)
         self._order = order
         self._in_fader = InputFader(input)
-        in_fader, order, mul, add, lmax = convertArgsToLists(self._in_fader, order, mul, add)                     
+        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):
         """
@@ -2210,18 +2311,19 @@ class IRAverage(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -2230,40 +2332,40 @@ class IRPulse(PyoObject):
     """
     Comb-like filter using circular convolution.
 
-    IRPulse uses circular convolution to implement standard comb-like 
-    filters consisting of an harmonic series with fundamental `freq` and 
-    a comb filter with the first notch at `bw` frequency. The `type` 
-    parameter defines variations of this pattern. User can defined the length, 
+    IRPulse uses circular convolution to implement standard comb-like
+    filters consisting of an harmonic series with fundamental `freq` and
+    a comb filter with the first notch at `bw` frequency. The `type`
+    parameter defines variations of this pattern. User can defined the length,
     in samples, of the impulse response, also known as the filter kernel.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        freq : float or PyoObject, optional
-            Fundamental frequency of the spikes in the filter's spectrum, expressed 
+        freq: float or PyoObject, optional
+            Fundamental frequency of the spikes in the filter's spectrum, expressed
             in Hertz. Defaults to 500.
-        bw : float or PyoObject, optional
+        bw: float or PyoObject, optional
             Frequency, expressed in Hertz, of the first notch in the comb filtering.
             Defaults to 2500.
-        type : int, optional
+        type: int, optional
             Filter type. Four possible values :
                 0. Pulse & comb (default)
                 1. Pulse & comb & lowpass
                 2. Pulse (odd harmonics) & comb
                 3. Pulse (odd harmonics) & comb & lowpass
-        order : int {even number}, optional
-            Length, in samples, of the filter kernel used for convolution. Available 
+        order: int {even number}, optional
+            Length, in samples, of the filter kernel used for convolution. Available
             at initialization time only. Defaults to 256.
-            
-            This value must be even. Higher is the order and sharper is the roll-off 
-            of the filter, but it is also more expensive to compute. 
+
+            This value must be even. Higher is the order and sharper is the roll-off
+            of the filter, but it is also more expensive to compute.
 
     .. note::
 
-        Convolution is very expensive to compute, so the length of the impulse 
+        Convolution is very expensive to compute, so the length of the impulse
         response (the `order` parameter) must be kept very short to run in real time.
 
         Note that although `freq` and `bw` can be PyoObjects, the impulse response of
@@ -2276,6 +2378,7 @@ class IRPulse(PyoObject):
 
     """
     def __init__(self, input, freq=500, bw=2500, type=0, order=256, mul=1, add=0):
+        pyoArgsAssert(self, "oOOiiOO", input, freq, bw, type, order, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._freq = freq
@@ -2283,11 +2386,12 @@ class IRPulse(PyoObject):
         self._type = type
         if (order % 2) != 0:
             order += 1
-            print "order argument of IRPulse must be even, set to %i" % order
+            print("order argument of IRPulse must be even, set to %i" % order)
         self._order = order
         self._in_fader = InputFader(input)
-        in_fader, freq, bw, type, order, mul, add, lmax = convertArgsToLists(self._in_fader, freq, bw, type, order, mul, add)                     
+        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):
         """
@@ -2295,12 +2399,13 @@ class IRPulse(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
@@ -2310,10 +2415,11 @@ class IRPulse(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `freq` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2324,10 +2430,11 @@ class IRPulse(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `bw` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._bw = x
         x, lmax = convertArgsToLists(x)
         [obj.setBandwidth(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2338,7 +2445,7 @@ class IRPulse(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 New `type` attribute. Filter type. Four possible values:
                     0. Pulse & comb (default)
                     1. Pulse & comb & lowpass
@@ -2346,39 +2453,41 @@ class IRPulse(PyoObject):
                     3. Pulse (odd harmonics) & comb & lowpass
 
         """
+        pyoArgsAssert(self, "i", x)
         self._type = x
         x, lmax = convertArgsToLists(x)
         [obj.setType(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMapFreq(self._freq),
-                          SLMap(20., 10000., "log", "bw", self._bw)]
+                          SLMap(20., 10000., "log", "bw", self._bw),
+                          SLMap(0, 3, 'lin', 'type', self._type, res="int", dataOnly=True)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def freq(self):
-        """float or PyoObject. Cutoff or Center frequency of the filter.""" 
+        """float or PyoObject. Cutoff or Center frequency of the filter."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
     def bw(self):
-        """float or PyoObject. Bandwidth for bandreject and bandpass filters.""" 
+        """float or PyoObject. Bandwidth for bandreject and bandpass filters."""
         return self._bw
     @bw.setter
     def bw(self, x): self.setBw(x)
 
     @property
     def type(self):
-        """int. Filter type {0 = pulse, 1 = pulse_lp, 2 = pulse_odd, 3 = pulse_odd_lp}.""" 
+        """int. Filter type {0 = pulse, 1 = pulse_lp, 2 = pulse_odd, 3 = pulse_odd_lp}."""
         return self._type
     @type.setter
     def type(self, x): self.setType(x)
@@ -2387,8 +2496,8 @@ class IRFM(PyoObject):
     """
     Filters a signal with a frequency modulation spectrum using circular convolution.
 
-    IRFM uses circular convolution to implement filtering with a frequency 
-    modulation spectrum. User can defined the length, in samples, of the 
+    IRFM uses circular convolution to implement filtering with a frequency
+    modulation spectrum. User can defined the length, in samples, of the
     impulse response, also known as the filter kernel. The higher the `order`,
     the narrower the bandwidth around each of the FM components.
 
@@ -2396,29 +2505,29 @@ class IRFM(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        carrier : float or PyoObject, optional
+        carrier: float or PyoObject, optional
             Carrier frequency in cycles per second. Defaults to 1000.
-        ratio : float or PyoObject, optional
-            A factor that, when multiplied by the `carrier` parameter, 
+        ratio: float or PyoObject, optional
+            A factor that, when multiplied by the `carrier` parameter,
             gives the modulator frequency. Defaults to 0.5.
-        index : float or PyoObject, optional
+        index: float or PyoObject, optional
             The modulation index. This value multiplied by the modulator
             frequency gives the modulator amplitude. Defaults to 3.
-        order : int {even number}, optional
-            Length, in samples, of the filter kernel used for convolution. 
+        order: int {even number}, optional
+            Length, in samples, of the filter kernel used for convolution.
             Available at initialization time only. Defaults to 256.
-            
-            This value must be even. Higher is the order and sharper is the 
+
+            This value must be even. Higher is the order and sharper is the
             roll-off of the filter, but it is also more expensive to compute.
 
     .. note::
 
-        Convolution is very expensive to compute, so the length of the impulse 
+        Convolution is very expensive to compute, so the length of the impulse
         response (the `order` parameter) must be kept very short to run in real time.
 
-        Note that although `carrier`, `ratio` and `index` can be PyoObjects, the 
+        Note that although `carrier`, `ratio` and `index` can be PyoObjects, the
         impulse response of the filter is only updated once per buffer size.
 
     >>> s = Server().boot()
@@ -2429,6 +2538,7 @@ class IRFM(PyoObject):
 
     """
     def __init__(self, input, carrier=1000, ratio=0.5, index=3, order=256, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOiOO", input, carrier, ratio, index, order, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._carrier = carrier
@@ -2436,11 +2546,12 @@ class IRFM(PyoObject):
         self._index = index
         if (order % 2) != 0:
             order += 1
-            print "order argument of IRFM must be even, set to %i" % order
+            print("order argument of IRFM must be even, set to %i" % order)
         self._order = order
         self._in_fader = InputFader(input)
-        in_fader, carrier, ratio, index, order, mul, add, lmax = convertArgsToLists(self._in_fader, carrier, ratio, index, order, mul, add)                     
+        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):
         """
@@ -2448,12 +2559,13 @@ class IRFM(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
@@ -2463,10 +2575,11 @@ class IRFM(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `carrier` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._carrier = x
         x, lmax = convertArgsToLists(x)
         [obj.setCarrier(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2477,10 +2590,11 @@ class IRFM(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `ratio` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._ratio = x
         x, lmax = convertArgsToLists(x)
         [obj.setRatio(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2491,10 +2605,11 @@ class IRFM(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `index` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._index = x
         x, lmax = convertArgsToLists(x)
         [obj.setIndex(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2507,58 +2622,58 @@ class IRFM(PyoObject):
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def carrier(self):
-        """float or PyoObject. Carrier frequency in Hz.""" 
+        """float or PyoObject. Carrier frequency in Hz."""
         return self._carrier
     @carrier.setter
     def carrier(self, x): self.setCarrier(x)
 
     @property
     def ratio(self):
-        """float or PyoObject. Modulator/carrier ratio.""" 
+        """float or PyoObject. Modulator/carrier ratio."""
         return self._ratio
     @ratio.setter
     def ratio(self, x): self.setRatio(x)
 
     @property
     def index(self):
-        """float or PyoObject. Modulation index.""" 
+        """float or PyoObject. Modulation index."""
         return self._index
     @index.setter
     def index(self, x): self.setIndex(x)
 
 class SVF(PyoObject):
     """
-    Fourth-order state variable filter allowing continuous change of the filter type. 
-    
+    Fourth-order state variable filter allowing continuous change of the filter type.
+
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
-    
-        input : PyoObject
+
+        input: PyoObject
             Input signal to process.
-        freq : float or PyoObject, optional
-            Cutoff or center frequency of the filter. Defaults to 1000. 
-            
-            Because this filter becomes unstable at higher frequencies, 
+        freq: float or PyoObject, optional
+            Cutoff or center frequency of the filter. Defaults to 1000.
+
+            Because this filter becomes unstable at higher frequencies,
             the `freq` parameter is limited to one-sixth of the sampling rate.
-        q : float or PyoObject, optional
-            Q of the filter, defined (for bandpass filters) as freq/bandwidth. 
+        q: float or PyoObject, optional
+            Q of the filter, defined (for bandpass filters) as freq/bandwidth.
             Should be between 0.5 and 50. Defaults to 1.
-        type : float or PyoObject, optional
-            This value, in the range 0 to 1, controls the filter type crossfade 
+        type: float or PyoObject, optional
+            This value, in the range 0 to 1, controls the filter type crossfade
             on the continuum lowpass-bandpass-highpass.
 
             - 0.0 = lowpass (default)
             - 0.5 = bandpass
             - 1.0 = highpass
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> a = Noise(.2)
@@ -2569,6 +2684,7 @@ class SVF(PyoObject):
 
     """
     def __init__(self, input, freq=1000, q=1, type=0, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOOO", input, freq, q, type, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._freq = freq
@@ -2577,33 +2693,36 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setFreq(self, x):
         """
         Replace the `freq` attribute. Limited in the upper bound to
         one-sixth of the sampling rate.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `freq` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2611,13 +2730,14 @@ class SVF(PyoObject):
     def setQ(self, x):
         """
         Replace the `q` attribute. Should be between 0.5 and 50.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `q` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._q = x
         x, lmax = convertArgsToLists(x)
         [obj.setQ(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2625,22 +2745,23 @@ class SVF(PyoObject):
     def setType(self, x):
         """
         Replace the `type` attribute. Must be in the range 0 to 1.
-        
-        This value allows the filter type to sweep from a lowpass (0) 
-        to a bandpass (0.5) and then, from the bandpass to a highpass (1). 
-        
+
+        This value allows the filter type to sweep from a lowpass (0)
+        to a bandpass (0.5) and then, from the bandpass to a highpass (1).
+
         :Args:
 
-            x : float or PyoObject
-                New `type` attribute. 
+            x: float or PyoObject
+                New `type` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._type = x
         x, lmax = convertArgsToLists(x)
         [obj.setType(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(20, 7350, "log", "freq", self._freq), 
+        self._map_list = [SLMap(20, 7350, "log", "freq", self._freq),
                           SLMap(0.5, 10, "log", "q", self._q),
                           SLMap(0, 1, "lin", "type", self._type),
                           SLMapMul(self._mul)]
@@ -2648,28 +2769,28 @@ class SVF(PyoObject):
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def freq(self):
-        """float or PyoObject. Cutoff or center frequency of the filter.""" 
+        """float or PyoObject. Cutoff or center frequency of the filter."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
     def q(self):
-        """float or PyoObject. Q of the filter.""" 
+        """float or PyoObject. Q of the filter."""
         return self._q
     @q.setter
     def q(self, x): self.setQ(x)
 
     @property
     def type(self):
-        """float or PyoObject. Crossfade between filter types.""" 
+        """float or PyoObject. Crossfade between filter types."""
         return self._type
     @type.setter
     def type(self, x): self.setType(x)
@@ -2677,22 +2798,22 @@ class SVF(PyoObject):
 class Average(PyoObject):
     """
     Moving average filter.
-    
+
     As the name implies, the moving average filter operates by averaging a number
     of points from the input signal to produce each point in the output signal.
     In spite of its simplicity, the moving average filter is optimal for
     a common task: reducing random noise while retaining a sharp step response.
 
     :Parent: :py:class:`PyoObject`
-   
+
     :Args:
-    
-        input : PyoObject
+
+        input: PyoObject
             Input signal to process.
-        size : int, optional
-            Filter kernel size, which is the number of samples used in the 
+        size: int, optional
+            Filter kernel size, which is the number of samples used in the
             moving average. Default to 10.
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> a = Noise(.025)
@@ -2701,82 +2822,87 @@ class Average(PyoObject):
 
     """
     def __init__(self, input, size=10, mul=1, add=0):
+        pyoArgsAssert(self, "oiOO", input, size, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._size = size
         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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
-        
+
     def setSize(self, x):
         """
         Replace the `size` attribute.
-        
+
         :Args:
 
-            x : int
+            x: int
                 New `size` attribute.
 
         """
+        pyoArgsAssert(self, "i", x)
         self._size = x
         x, lmax = convertArgsToLists(x)
         [obj.setSize(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
-        self._map_list = [SLMapMul(self._mul)]
+        self._map_list = [SLMap(2, 256, 'lin', 'size', self._size, res="int", dataOnly=True),
+                          SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
-      
+
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def size(self):
-        """int. Filter kernel size in samples.""" 
+        """int. Filter kernel size in samples."""
         return self._size
     @size.setter
     def size(self, x): self.setSize(x)
 
 class Reson(PyoObject):
     """
-    A second-order resonant bandpass filter. 
-    
+    A second-order resonant bandpass filter.
+
     Reson implements a classic resonant bandpass filter, as described in:
-        
+
     Dodge, C., Jerse, T., "Computer Music, Synthesis, Composition and Performance".
-    
+
     Reson uses less CPU than the equivalent filter with a Biquad object.
-    
+
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
-    
-        input : PyoObject
+
+        input: PyoObject
             Input signal to process.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Center frequency of the filter. Defaults to 1000.
-        q : float or PyoObject, optional
-            Q of the filter, defined as freq/bandwidth. 
+        q: float or PyoObject, optional
+            Q of the filter, defined as freq/bandwidth.
             Should be between 1 and 500. Defaults to 1.
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> a = Noise(mul=.7)
@@ -2785,6 +2911,7 @@ class Reson(PyoObject):
 
     """
     def __init__(self, input, freq=1000, q=1, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOO", input, freq, q, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._freq = freq
@@ -2792,32 +2919,35 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setFreq(self, x):
         """
         Replace the `freq` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `freq` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2825,13 +2955,14 @@ class Reson(PyoObject):
     def setQ(self, x):
         """
         Replace the `q` attribute. Should be between 1 and 500.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `q` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._q = x
         x, lmax = convertArgsToLists(x)
         [obj.setQ(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2842,50 +2973,50 @@ class Reson(PyoObject):
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def freq(self):
-        """float or PyoObject. Center frequency of the filter.""" 
+        """float or PyoObject. Center frequency of the filter."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
     def q(self):
-        """float or PyoObject. Q of the filter.""" 
+        """float or PyoObject. Q of the filter."""
         return self._q
     @q.setter
     def q(self, x): self.setQ(x)
 
 class Resonx(PyoObject):
     """
-    A multi-stages second-order resonant bandpass filter. 
-    
+    A multi-stages second-order resonant bandpass filter.
+
     Resonx implements a stack of the classic resonant bandpass filter, as described in:
-        
+
     Dodge, C., Jerse, T., "Computer Music, Synthesis, Composition and Performance".
-    
+
     Resonx is equivalent to a filter consisting of more layers of Reson
     with the same arguments, serially connected. It is faster than using
-    a large number of instances of the Reson object, it uses less memory 
+    a large number of instances of the Reson object, it uses less memory
     and allows filters with sharper cutoff.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Center frequency of the filter. Defaults to 1000.
-        q : float or PyoObject, optional
-            Q of the filter, defined as freq/bandwidth. 
+        q: float or PyoObject, optional
+            Q of the filter, defined as freq/bandwidth.
             Should be between 1 and 500. Defaults to 1.
-        stages : int, optional
+        stages: int, optional
             The number of filtering stages in the filter stack. Defaults to 4.
 
     >>> s = Server().boot()
@@ -2896,6 +3027,7 @@ class Resonx(PyoObject):
 
     """
     def __init__(self, input, freq=1000, q=1, stages=4, mul=1, add=0):
+        pyoArgsAssert(self, "oOOiOO", input, freq, q, stages, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._freq = freq
@@ -2904,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):
         """
@@ -2911,12 +3044,13 @@ class Resonx(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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)
 
@@ -2926,10 +3060,11 @@ class Resonx(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `freq` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2940,10 +3075,11 @@ class Resonx(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `q` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._q = x
         x, lmax = convertArgsToLists(x)
         [obj.setQ(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2954,10 +3090,11 @@ class Resonx(PyoObject):
 
         :Args:
 
-            x : int
-                New `stages` attribute. 
+            x: int
+                New `stages` attribute.
 
         """
+        pyoArgsAssert(self, "i", x)
         self._stages = x
         x, lmax = convertArgsToLists(x)
         [obj.setStages(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2968,28 +3105,28 @@ class Resonx(PyoObject):
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def freq(self):
-        """float or PyoObject. Center frequency of the filter.""" 
+        """float or PyoObject. Center frequency of the filter."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
     def q(self):
-        """float or PyoObject. Q of the filter.""" 
+        """float or PyoObject. Q of the filter."""
         return self._q
     @q.setter
     def q(self, x): self.setQ(x)
 
     @property
     def stages(self):
-        """int. The number of filtering stages.""" 
+        """int. The number of filtering stages."""
         return self._stages
     @stages.setter
     def stages(self, x): self.setStages(x)
@@ -2997,20 +3134,20 @@ class Resonx(PyoObject):
 class ButLP(PyoObject):
     """
     A second-order Butterworth lowpass filter.
-    
+
     ButLP implements a second-order IIR Butterworth lowpass filter,
-    which has a maximally flat passband and a very good precision and 
+    which has a maximally flat passband and a very good precision and
     stopband attenuation.
- 
+
     :Parent: :py:class:`PyoObject`
-   
+
     :Args:
-    
-        input : PyoObject
+
+        input: PyoObject
             Input signal to process.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Cutoff frequency of the filter in hertz. Default to 1000.
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> n = Noise(.3)
@@ -3019,38 +3156,42 @@ class ButLP(PyoObject):
 
     """
     def __init__(self, input, freq=1000, mul=1, add=0):
+        pyoArgsAssert(self, "oOOO", input, freq, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._freq = freq
         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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
-        
+
     def setFreq(self, x):
         """
         Replace the `freq` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `freq` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -3058,17 +3199,17 @@ class ButLP(PyoObject):
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMapFreq(self._freq), SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
-      
+
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def freq(self):
-        """float or PyoObject. Cutoff frequency of the filter.""" 
+        """float or PyoObject. Cutoff frequency of the filter."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
@@ -3076,20 +3217,20 @@ class ButLP(PyoObject):
 class ButHP(PyoObject):
     """
     A second-order Butterworth highpass filter.
-    
+
     ButHP implements a second-order IIR Butterworth highpass filter,
-    which has a maximally flat passband and a very good precision and 
+    which has a maximally flat passband and a very good precision and
     stopband attenuation.
- 
+
     :Parent: :py:class:`PyoObject`
-   
+
     :Args:
-    
-        input : PyoObject
+
+        input: PyoObject
             Input signal to process.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Cutoff frequency of the filter in hertz. Default to 1000.
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> n = Noise(.2)
@@ -3098,38 +3239,42 @@ class ButHP(PyoObject):
 
     """
     def __init__(self, input, freq=1000, mul=1, add=0):
+        pyoArgsAssert(self, "oOOO", input, freq, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._freq = freq
         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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
-        
+
     def setFreq(self, x):
         """
         Replace the `freq` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `freq` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -3137,17 +3282,17 @@ class ButHP(PyoObject):
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMapFreq(self._freq), SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
-      
+
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def freq(self):
-        """float or PyoObject. Cutoff frequency of the filter.""" 
+        """float or PyoObject. Cutoff frequency of the filter."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
@@ -3155,23 +3300,23 @@ class ButHP(PyoObject):
 class ButBP(PyoObject):
     """
     A second-order Butterworth bandpass filter.
-    
+
     ButBP implements a second-order IIR Butterworth bandpass filter,
-    which has a maximally flat passband and a very good precision and 
+    which has a maximally flat passband and a very good precision and
     stopband attenuation.
-    
+
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
-    
-        input : PyoObject
+
+        input: PyoObject
             Input signal to process.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Center frequency of the filter. Defaults to 1000.
-        q : float or PyoObject, optional
-            Q of the filter, defined as freq/bandwidth. 
+        q: float or PyoObject, optional
+            Q of the filter, defined as freq/bandwidth.
             Should be between 1 and 500. Defaults to 1.
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> a = Noise(mul=.7)
@@ -3180,6 +3325,7 @@ class ButBP(PyoObject):
 
     """
     def __init__(self, input, freq=1000, q=1, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOO", input, freq, q, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._freq = freq
@@ -3187,32 +3333,35 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setFreq(self, x):
         """
         Replace the `freq` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `freq` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -3220,39 +3369,40 @@ class ButBP(PyoObject):
     def setQ(self, x):
         """
         Replace the `q` attribute. Should be between 1 and 500.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `q` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._q = x
         x, lmax = convertArgsToLists(x)
         [obj.setQ(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
-        self._map_list = [SLMapFreq(self._freq), 
+        self._map_list = [SLMapFreq(self._freq),
                           SLMap(1, 100, "log", "q", self._q), SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def freq(self):
-        """float or PyoObject. Center frequency of the filter.""" 
+        """float or PyoObject. Center frequency of the filter."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
     def q(self):
-        """float or PyoObject. Q of the filter.""" 
+        """float or PyoObject. Q of the filter."""
         return self._q
     @q.setter
     def q(self, x): self.setQ(x)
@@ -3260,23 +3410,23 @@ class ButBP(PyoObject):
 class ButBR(PyoObject):
     """
     A second-order Butterworth band-reject filter.
-    
+
     ButBR implements a second-order IIR Butterworth band-reject filter,
-    which has a maximally flat passband and a very good precision and 
+    which has a maximally flat passband and a very good precision and
     stopband attenuation.
-    
+
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
-    
-        input : PyoObject
+
+        input: PyoObject
             Input signal to process.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Center frequency of the filter. Defaults to 1000.
-        q : float or PyoObject, optional
-            Q of the filter, defined as freq/bandwidth. 
+        q: float or PyoObject, optional
+            Q of the filter, defined as freq/bandwidth.
             Should be between 1 and 500. Defaults to 1.
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> a = Noise(mul=.2)
@@ -3285,6 +3435,7 @@ class ButBR(PyoObject):
 
     """
     def __init__(self, input, freq=1000, q=1, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOO", input, freq, q, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._freq = freq
@@ -3292,32 +3443,35 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setFreq(self, x):
         """
         Replace the `freq` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `freq` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -3325,39 +3479,262 @@ class ButBR(PyoObject):
     def setQ(self, x):
         """
         Replace the `q` attribute. Should be between 1 and 500.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `q` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._q = x
         x, lmax = convertArgsToLists(x)
         [obj.setQ(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
-        self._map_list = [SLMapFreq(self._freq), 
+        self._map_list = [SLMapFreq(self._freq),
                           SLMap(1, 100, "log", "q", self._q), SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def freq(self):
-        """float or PyoObject. Center frequency of the filter.""" 
+        """float or PyoObject. Center frequency of the filter."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
     def q(self):
-        """float or PyoObject. Q of the filter.""" 
+        """float or PyoObject. Q of the filter."""
         return self._q
     @q.setter
     def q(self, x): self.setQ(x)
+
+class MoogLP(PyoObject):
+    """
+    A fourth-order resonant lowpass filter.
+
+    Digital approximation of the Moog VCF, giving a decay of 24dB/oct.
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        input: PyoObject
+            Input signal to process.
+        freq: float or PyoObject, optional
+            Cutoff frequency of the filter. Defaults to 1000.
+        res: float or PyoObject, optional
+            Amount of Resonance of the filter, usually between 0 (no resonance)
+            and 1 (medium resonance). Self-oscillation occurs when the
+            resonance is >= 1. Can go up to 10. Defaults to 0.
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> ph = Phasor(40)
+    >>> sqr = Round(ph, add=-0.5)
+    >>> lfo = Sine(freq=[.4, .5], mul=2000, add=2500)
+    >>> fil = MoogLP(sqr, freq=lfo, res=1.25).out()
+
+    """
+    def __init__(self, input, freq=1000, res=0, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOO", input, freq, res, mul, add)
+        PyoObject.__init__(self, mul, add)
+        self._input = input
+        self._freq = freq
+        self._res = res
+        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):
+        """
+        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 setFreq(self, x):
+        """
+        Replace the `freq` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                New `freq` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._freq = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def setRes(self, x):
+        """
+        Replace the `res` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                New `res` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._res = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setRes(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def ctrl(self, map_list=None, title=None, wxnoserver=False):
+        self._map_list = [SLMapFreq(self._freq),
+                          SLMap(0.,1., "lin", "res", self._res),
+                          SLMapMul(self._mul)]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
+    @property
+    def input(self):
+        """PyoObject. Input signal to process."""
+        return self._input
+    @input.setter
+    def input(self, x): self.setInput(x)
+
+    @property
+    def freq(self):
+        """float or PyoObject. Cutoff frequency of the filter."""
+        return self._freq
+    @freq.setter
+    def freq(self, x): self.setFreq(x)
+
+    @property
+    def res(self):
+        """float or PyoObject. Amount of resonance of the filter."""
+        return self._res
+    @res.setter
+    def res(self, x): self.setRes(x)
+
+class ComplexRes(PyoObject):
+    """
+    Complex one-pole resonator filter.
+
+    ComplexRes implements a resonator derived from a complex
+    multiplication, which is very similar to a digital filter.
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        input: PyoObject
+            Input signal to process.
+        freq: float or PyoObject, optional
+            Center frequency of the filter. Defaults to 1000.
+        decay: float or PyoObject, optional
+            Decay time, in seconds, for the filter's response.
+            Defaults to 0.25.
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> env = HannTable()
+    >>> trigs = Metro(.2, poly=4).play()
+    >>> amp = TrigEnv(trigs, table=env, dur=0.005, mul=2)
+    >>> im = Noise(mul=amp)
+    >>> res = ComplexRes(im, freq=[950,530,780,1490], decay=1).out()
+
+    """
+    def __init__(self, input, freq=1000, decay=.25, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOO", input, freq, decay, mul, add)
+        PyoObject.__init__(self, mul, add)
+        self._input = input
+        self._freq = freq
+        self._decay = decay
+        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):
+        """
+        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 setFreq(self, x):
+        """
+        Replace the `freq` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                New `freq` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._freq = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def setDecay(self, x):
+        """
+        Replace the `decay` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                New `decay` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._decay = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setDecay(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def ctrl(self, map_list=None, title=None, wxnoserver=False):
+        self._map_list = [SLMapFreq(self._freq), SLMap(0.0001, 10, "log", "decay", self._decay),
+                          SLMapMul(self._mul)]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
+    @property
+    def input(self):
+        """PyoObject. Input signal to filter."""
+        return self._input
+    @input.setter
+    def input(self, x): self.setInput(x)
+
+    @property
+    def freq(self):
+        """float or PyoObject. Center frequency of the filter."""
+        return self._freq
+    @freq.setter
+    def freq(self, x): self.setFreq(x)
+
+    @property
+    def decay(self):
+        """float or PyoObject. Decay time of the filter's response."""
+        return self._decay
+    @decay.setter
+    def decay(self, x): self.setDecay(x)
diff --git a/pyolib/fourier.py b/pyolib/fourier.py
index d48b223..1798209 100644
--- a/pyolib/fourier.py
+++ b/pyolib/fourier.py
@@ -1,37 +1,38 @@
 """
 Fast Fourier Transform.
 
-A Fast Fourier Transform (FFT) is an efficient algorithm to compute 
+A Fast Fourier Transform (FFT) is an efficient algorithm to compute
 the discrete Fourier transform (DFT) and its inverse (IFFT).
 
-The objects below can be used to perform sound processing in the 
+The objects below can be used to perform sound processing in the
 spectral domain.
 
 """
 
+from __future__ import division
+from __future__ import absolute_import
 """
-Copyright 2011 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+You should have received a copy of the GNU Lesser General Public
+License along with pyo.  If not, see <http://www.gnu.org/licenses/>.
 """
-from _core import *
-from _maps import *
-from _widgets import createSpectrumWindow
-from pattern import Pattern
+
+from ._core import *
+from ._maps import *
 
 class FFT(PyoObject):
     """
@@ -39,29 +40,29 @@ class FFT(PyoObject):
 
     FFT analyses an input signal and converts it into the spectral
     domain. Three audio signals are sent out of the object, the
-    `real` part, from bin 0 (DC) to bin size/2 (Nyquist), the 
-    `imaginary` part, from bin 0 to bin size/2-1, and the bin 
-    number, an increasing count from 0 to size-1. `real` and 
-    `imaginary` buffer's left samples  up to size-1 are filled 
-    with zeros. See notes below for an example of how to retrieve 
+    `real` part, from bin 0 (DC) to bin size/2 (Nyquist), the
+    `imaginary` part, from bin 0 to bin size/2-1, and the bin
+    number, an increasing count from 0 to size-1. `real` and
+    `imaginary` buffer's left samples  up to size-1 are filled
+    with zeros. See notes below for an example of how to retrieve
     each signal component.
-    
+
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
-    
-        input : PyoObject
+
+        input: PyoObject
             Input signal to process.
-        size : int {pow-of-two > 4}, optional
+        size: int {pow-of-two > 4}, optional
             FFT size. Must be a power of two greater than 4.
             The FFT size is the number of samples used in each
             analysis frame. Defaults to 1024.
-        overlaps : int, optional
+        overlaps: int, optional
             The number of overlaped analysis block. Must be a
             positive integer. More overlaps can greatly improved
             sound quality synthesis but it is also more CPU
             expensive. Defaults to 4.
-        wintype : int, optional
+        wintype: int, optional
             Shape of the envelope used to filter each input frame.
             Possible shapes are :
                 0. rectangular (no windowing)
@@ -75,18 +76,18 @@ class FFT(PyoObject):
                 8. Sine (half-sine window)
 
     .. note::
-    
-        FFT has no `out` method. Signal must be converted back to time domain, 
+
+        FFT has no `out` method. Signal must be converted back to time domain,
         with IFFT, before being sent to output.
 
         FFT has no `mul` and `add` attributes.
-        
-        Real, imaginary and bin_number parts are three separated set 
+
+        Real, imaginary and bin_number parts are three separated set
         of audio streams. The user should call :
-        
-        FFT['real'] to retrieve the real part.
-        FFT['imag'] to retrieve the imaginary part.
-        FFT['bin'] to retrieve the bin number part.
+
+        |  FFT['real'] to retrieve the real part.
+        |  FFT['imag'] to retrieve the imaginary part.
+        |  FFT['bin'] to retrieve the bin number part.
 
     >>> s = Server().boot()
     >>> s.start()
@@ -100,6 +101,7 @@ class FFT(PyoObject):
 
     """
     def __init__(self, input, size=1024, overlaps=4, wintype=2):
+        pyoArgsAssert(self, "oiIi", input, size, overlaps, wintype)
         PyoObject.__init__(self)
         self._real_dummy = []
         self._imag_dummy = []
@@ -113,7 +115,7 @@ class FFT(PyoObject):
         self._base_players = []
         for j in range(overlaps):
             for i in range(lmax):
-                hopsize = wrap(size,i) * j / overlaps
+                hopsize = wrap(size,i) * j // overlaps
                 self._base_players.append(FFTMain_base(wrap(in_fader,i), wrap(size,i), hopsize, wrap(wintype,i)))
         self._real_objs = []
         self._imag_objs = []
@@ -122,7 +124,8 @@ 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)
 
@@ -140,44 +143,45 @@ class FFT(PyoObject):
     def get(self, identifier="real", all=False):
         """
         Return the first sample of the current buffer as a float.
-        
+
         Can be used to convert audio stream to usable Python data.
-        
+
         "real", "imag" or "bin" must be given to `identifier` to specify
         which stream to get value from.
-        
+
         :Args:
 
-            identifier : string {"real", "imag", "bin"}
+            identifier: string {"real", "imag", "bin"}
                 Address string parameter identifying audio stream.
                 Defaults to "real".
-            all : boolean, optional
+            all: boolean, optional
                 If True, the first value of each object's stream
                 will be returned as a list. Otherwise, only the value
                 of the first object's stream will be returned as a float.
                 Defaults to False.
-                 
+
         """
         if not all:
             return self.__getitem__(identifier)[0]._getStream().getValue()
         else:
             return [obj._getStream().getValue() for obj in self.__getitem__(identifier).getBaseObjects()]
- 
+
     def setInput(self, x, fadetime=0.05):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
-                    
+
     def play(self, dur=0, delay=0):
         dur, delay, lmax = convertArgsToLists(dur, delay)
         self._base_players = [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_players)]
@@ -185,7 +189,7 @@ class FFT(PyoObject):
         self._imag_objs = [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._imag_objs)]
         self._bin_objs = [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._bin_objs)]
         return self
-    
+
     def stop(self):
         [obj.stop() for obj in self._base_players]
         [obj.stop() for obj in self._real_objs]
@@ -199,38 +203,40 @@ class FFT(PyoObject):
     def setSize(self, x):
         """
         Replace the `size` attribute.
-        
+
         :Args:
 
-            x : int
+            x: int
                 new `size` attribute.
-        
+
         """
+        pyoArgsAssert(self, "i", x)
         self._size = x
         x, lmax = convertArgsToLists(x)
-        poly = len(self._base_players) / self._overlaps
+        poly = len(self._base_players) // self._overlaps
         for j in range(self._overlaps):
             for i in range(poly):
-                hopsize = wrap(x,i) * j / self._overlaps
+                hopsize = wrap(x,i) * j // self._overlaps
                 self._base_players[j*poly+i].setSize(wrap(x,i), hopsize)
 
     def setWinType(self, x):
         """
         Replace the `wintype` attribute.
-        
+
         :Args:
 
-            x : int
+            x: int
                 new `wintype` attribute.
-        
+
         """
+        pyoArgsAssert(self, "i", x)
         self._wintype = x
         x, lmax = convertArgsToLists(x)
         [obj.setWinType(wrap(x,i)) for i, obj in enumerate(self._base_players)]
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -253,33 +259,33 @@ class IFFT(PyoObject):
     """
     Inverse Fast Fourier Transform.
 
-    IFFT takes a signal in the spectral domain and converts it to a 
-    real audio signal using an inverse fast fourier transform. 
+    IFFT takes a signal in the spectral domain and converts it to a
+    real audio signal using an inverse fast fourier transform.
     IFFT takes two signals in input, the `real` and `imaginary` parts
     of an FFT analysis and returns the corresponding real signal.
     These signals must correspond to `real` and `imaginary` parts
     from an FFT object.
 
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
-    
-        inreal : PyoObject
+
+        inreal: PyoObject
             Input `real` signal.
-        inimag : PyoObject
+        inimag: PyoObject
             Input `imaginary` signal.
-        size : int {pow-of-two > 4}, optional
+        size: int {pow-of-two > 4}, optional
             FFT size. Must be a power of two greater than 4.
             The FFT size is the number of samples used in each
-            analysis frame. This value must match the `size` 
+            analysis frame. This value must match the `size`
             attribute of the former FFT object. Defaults to 1024.
-        overlaps : int, optional
+        overlaps: int, optional
             The number of overlaped analysis block. Must be a
             positive integer. More overlaps can greatly improved
             sound quality synthesis but it is also more CPU
-            expensive. This value must match the `overlaps` 
+            expensive. This value must match the `overlaps`
             atribute of the former FFT object. Defaults to 4.
-        wintype : int, optional
+        wintype: int, optional
             Shape of the envelope used to filter each output frame.
             Possible shapes are :
                 0. rectangular (no windowing)
@@ -293,7 +299,7 @@ class IFFT(PyoObject):
                 8. Sine (half-sine window)
 
     .. note::
-    
+
         The number of streams in `inreal` and `inimag` attributes
         must be egal to the output of the former FFT object. In
         most case, it will be `channels of processed sound` * `overlaps`.
@@ -302,7 +308,7 @@ class IFFT(PyoObject):
         signal from the overlapped streams. It is left to the user
         to call the mix(channels of the processed sound) method on
         an IFFT object.
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> a = Noise(.25).mix(2)
@@ -315,6 +321,7 @@ class IFFT(PyoObject):
 
     """
     def __init__(self, inreal, inimag, size=1024, overlaps=4, wintype=2, mul=1, add=0):
+        pyoArgsAssert(self, "ooiIiOO", inreal, inimag, size, overlaps, wintype, mul, add)
         PyoObject.__init__(self, mul, add)
         self._inreal = inreal
         self._inimag = inimag
@@ -325,71 +332,76 @@ class IFFT(PyoObject):
         self._in_fader2 = InputFader(inimag)
         in_fader, in_fader2, size, wintype, mul, add, lmax = convertArgsToLists(self._in_fader, self._in_fader2, size, wintype, mul, add)
         self._base_objs = []
-        ratio = lmax / overlaps
+        ratio = lmax // overlaps
         for i in range(lmax):
-            hopsize = wrap(size,i) * ((i/ratio)%overlaps) / overlaps
+            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)
-        
+
     def setInReal(self, x, fadetime=0.05):
         """
         Replace the `inreal` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New input `real` signal.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._inreal = x
         self._in_fader.setInput(x, fadetime)
 
     def setInImag(self, x, fadetime=0.05):
         """
         Replace the `inimag` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New input `imag` signal.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._inimag = x
         self._in_fader2.setInput(x, fadetime)
 
     def setSize(self, x):
         """
         Replace the `size` attribute.
-        
+
         :Args:
 
-            x : int
+            x: int
                 new `size` attribute.
-        
+
         """
+        pyoArgsAssert(self, "i", x)
         self._size = x
         x, lmax = convertArgsToLists(x)
-        ratio = len(self._base_objs) / self._overlaps
+        ratio = len(self._base_objs) // self._overlaps
         for i, obj in enumerate(self._base_objs):
-            hopsize = wrap(x,i) * ((i/ratio)%self._overlaps) / self._overlaps
+            hopsize = wrap(x,i) * ((i // ratio) % self._overlaps) // self._overlaps
             self._base_objs[i].setSize(wrap(x,i), hopsize)
 
     def setWinType(self, x):
         """
         Replace the `wintype` attribute.
-        
+
         :Args:
 
-            x : int
+            x: int
                 new `wintype` attribute.
-        
+
         """
+        pyoArgsAssert(self, "i", x)
         self._wintype = x
         x, lmax = convertArgsToLists(x)
         [obj.setWinType(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -397,17 +409,17 @@ class IFFT(PyoObject):
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
-      
+
     @property
     def inreal(self):
-        """PyoObject. Real input signal.""" 
+        """PyoObject. Real input signal."""
         return self._inreal
     @inreal.setter
     def inreal(self, x): self.setInReal(x)
 
     @property
     def inimag(self):
-        """PyoObject. Imaginary input signal.""" 
+        """PyoObject. Imaginary input signal."""
         return self._inimag
     @inimag.setter
     def inimag(self, x): self.setInImag(x)
@@ -430,31 +442,31 @@ class CarToPol(PyoObject):
     """
     Performs the cartesian to polar conversion.
 
-    The Cartesian system locates points on a plane by measuring the  horizontal and 
-    vertical distances from an arbitrary origin to a point.  These are usually denoted 
+    The Cartesian system locates points on a plane by measuring the  horizontal and
+    vertical distances from an arbitrary origin to a point.  These are usually denoted
     as a pair of values (X,Y).
 
-    The Polar system locates the point by measuring the straight line distance, usually 
-    denoted by R, from the origin to the point and the angle of an imaginary line from 
+    The Polar system locates the point by measuring the straight line distance, usually
+    denoted by R, from the origin to the point and the angle of an imaginary line from
     the origin to the point measured counterclockwise from the positive X axis.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        inreal : PyoObject
+        inreal: PyoObject
             Real input signal.
-        inimag : PyoObject
+        inimag: PyoObject
             Imaginary input signal.
 
     .. note::
-    
+
         Polar coordinates can be retrieve by calling :
-        
-        CarToPol['mag'] to retrieve the magnitude part.
-        CarToPol['ang'] to retrieve the angle part.
 
-        CarToPol has no `out` method. Signal must be converted back to time domain, 
+        |  CarToPol['mag'] to retrieve the magnitude part.
+        |  CarToPol['ang'] to retrieve the angle part.
+
+        CarToPol has no `out` method. Signal must be converted back to time domain,
         with IFFT, before being sent to output.
 
     >>> s = Server().boot()
@@ -475,6 +487,7 @@ class CarToPol(PyoObject):
 
     """
     def __init__(self, inreal, inimag, mul=1, add=0):
+        pyoArgsAssert(self, "ooOO", inreal, inimag, mul, add)
         PyoObject.__init__(self, mul, add)
         self._mag_dummy = []
         self._ang_dummy = []
@@ -487,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)
@@ -510,10 +524,10 @@ class CarToPol(PyoObject):
 
         :Args:
 
-            identifier : string {"mag", "ang"}
+            identifier: string {"mag", "ang"}
                 Address string parameter identifying audio stream.
                 Defaults to "mag".
-            all : boolean, optional
+            all: boolean, optional
                 If True, the first value of each object's stream
                 will be returned as a list. Otherwise, only the value
                 of the first object's stream will be returned as a float.
@@ -531,12 +545,13 @@ class CarToPol(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._inreal = x
         self._in_fader.setInput(x, fadetime)
 
@@ -546,25 +561,26 @@ class CarToPol(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._inimag = x
         self._in_fader2.setInput(x, fadetime)
 
     @property
     def inreal(self):
-        """PyoObject. Real input signal.""" 
+        """PyoObject. Real input signal."""
         return self._inreal
     @inreal.setter
     def inreal(self, x): self.setInReal(x)
 
     @property
     def inimag(self):
-        """PyoObject. Imaginary input signal.""" 
+        """PyoObject. Imaginary input signal."""
         return self._inimag
     @inimag.setter
     def inimag(self, x): self.setInImag(x)
@@ -573,31 +589,31 @@ class PolToCar(PyoObject):
     """
     Performs the polar to cartesian conversion.
 
-    The Polar system locates the point by measuring the straight line distance, usually 
-    denoted by R, from the origin to the point and the angle of an imaginary line from 
+    The Polar system locates the point by measuring the straight line distance, usually
+    denoted by R, from the origin to the point and the angle of an imaginary line from
     the origin to the point measured counterclockwise from the positive X axis.
 
-    The Cartesian system locates points on a plane by measuring the  horizontal and 
-    vertical distances from an arbitrary origin to a point.  These are usually denoted 
+    The Cartesian system locates points on a plane by measuring the  horizontal and
+    vertical distances from an arbitrary origin to a point.  These are usually denoted
     as a pair of values (X,Y).
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        inmag : PyoObject
+        inmag: PyoObject
             Magintude input signal.
-        inang : PyoObject
+        inang: PyoObject
             Angle input signal.
 
     .. note::
 
         Cartesians coordinates can be retrieve by calling :
-        
-        PolToCar['real'] to retrieve the real part.
-        CarToPol['imag'] to retrieve the imaginary part.
 
-        PolToCar has no `out` method. Signal must be converted back to time domain, 
+        |  PolToCar['real'] to retrieve the real part.
+        |  CarToPol['imag'] to retrieve the imaginary part.
+
+        PolToCar has no `out` method. Signal must be converted back to time domain,
         with IFFT, before being sent to output.
 
     >>> s = Server().boot()
@@ -618,6 +634,7 @@ class PolToCar(PyoObject):
 
     """
     def __init__(self, inmag, inang, mul=1, add=0):
+        pyoArgsAssert(self, "ooOO", inmag, inang, mul, add)
         PyoObject.__init__(self, mul, add)
         self._real_dummy = []
         self._imag_dummy = []
@@ -630,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)
@@ -653,10 +671,10 @@ class PolToCar(PyoObject):
 
         :Args:
 
-            identifier : string {"real", "imag"}
+            identifier: string {"real", "imag"}
                 Address string parameter identifying audio stream.
                 Defaults to "mag".
-            all : boolean, optional
+            all: boolean, optional
                 If True, the first value of each object's stream
                 will be returned as a list. Otherwise, only the value
                 of the first object's stream will be returned as a float.
@@ -674,12 +692,13 @@ class PolToCar(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._inmag = x
         self._in_fader.setInput(x, fadetime)
 
@@ -689,25 +708,26 @@ class PolToCar(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._inang = x
         self._in_fader2.setInput(x, fadetime)
 
     @property
     def inmag(self):
-        """PyoObject. Magnitude input signal.""" 
+        """PyoObject. Magnitude input signal."""
         return self._inmag
     @inmag.setter
     def inmag(self, x): self.setInMag(x)
 
     @property
     def inang(self):
-        """PyoObject. Angle input signal.""" 
+        """PyoObject. Angle input signal."""
         return self._inang
     @inang.setter
     def inang(self, x): self.setInAng(x)
@@ -716,32 +736,32 @@ class FrameDelta(PyoObject):
     """
     Computes the phase differences between successive frames.
 
-    The difference between the phase values of successive FFT frames for a given bin 
-    determines the exact frequency of the energy centered in that bin. This is often 
-    known as the phase difference (and sometimes also referred to as phase derivative 
+    The difference between the phase values of successive FFT frames for a given bin
+    determines the exact frequency of the energy centered in that bin. This is often
+    known as the phase difference (and sometimes also referred to as phase derivative
     or instantaneous frequency if it's been subjected to a few additional calculations).
 
-    In order to reconstruct a plausible playback of re-ordered FFT frames, we need to 
-    calculate the phase difference between successive frames and use it to construct a 
-    `running phase` (by simply summing the successive differences with FrameAccum) for 
+    In order to reconstruct a plausible playback of re-ordered FFT frames, we need to
+    calculate the phase difference between successive frames and use it to construct a
+    `running phase` (by simply summing the successive differences with FrameAccum) for
     the output FFT frames.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Phase input signal, usually from an FFT analysis.
-        framesize : int, optional
+        framesize: int, optional
             Frame size in samples. Usually the same as the FFT size.
             Defaults to 1024.
-        overlaps : int, optional
+        overlaps: int, optional
             Number of overlaps in incomming signal. Usually the same
             as the FFT overlaps. Defaults to 4.
 
     .. note::
 
-        FrameDelta has no `out` method. Signal must be converted back to time domain, 
+        FrameDelta has no `out` method. Signal must be converted back to time domain,
         with IFFT, before being sent to output.
 
     >>> s = Server().boot()
@@ -766,13 +786,14 @@ class FrameDelta(PyoObject):
 
     """
     def __init__(self, input, framesize=1024, overlaps=4, mul=1, add=0):
+        pyoArgsAssert(self, "oiiOO", input, framesize, overlaps, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._framesize = framesize
         self._overlaps = overlaps
         self._in_fader = InputFader(input)
         in_fader, framesize, overlaps, mul, add, lmax = convertArgsToLists(self._in_fader, framesize, overlaps, mul, add)
-        num_of_mains = len(self._in_fader) / self._overlaps
+        num_of_mains = len(self._in_fader) // self._overlaps
         self._base_players = []
         for j in range(num_of_mains):
             objs_list = []
@@ -783,8 +804,9 @@ class FrameDelta(PyoObject):
         self._base_objs = []
         for i in range(lmax):
             base_player = i % num_of_mains
-            overlap = 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)
@@ -795,12 +817,13 @@ class FrameDelta(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
@@ -810,24 +833,25 @@ class FrameDelta(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 new `framesize` attribute.
 
         """
+        pyoArgsAssert(self, "i", x)
         self._framesize = x
         x, lmax = convertArgsToLists(x)
         [obj.setFrameSize(wrap(x,i)) for i, obj in enumerate(self._base_players)]
 
     @property
     def input(self):
-        """PyoObject. Phase input signal.""" 
+        """PyoObject. Phase input signal."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def framesize(self):
-        """PyoObject. Frame size in samples.""" 
+        """PyoObject. Frame size in samples."""
         return self._framesize
     @framesize.setter
     def framesize(self, x): self.setFrameSize(x)
@@ -836,32 +860,32 @@ class FrameAccum(PyoObject):
     """
     Accumulates the phase differences between successive frames.
 
-    The difference between the phase values of successive FFT frames for a given bin 
-    determines the exact frequency of the energy centered in that bin. This is often 
-    known as the phase difference (and sometimes also referred to as phase derivative 
+    The difference between the phase values of successive FFT frames for a given bin
+    determines the exact frequency of the energy centered in that bin. This is often
+    known as the phase difference (and sometimes also referred to as phase derivative
     or instantaneous frequency if it's been subjected to a few additional calculations).
 
-    In order to reconstruct a plausible playback of re-ordered FFT frames, we need to 
-    calculate the phase difference between successive frames, with FrameDelta, and use 
-    it to construct a `running phase` (by simply summing the successive differences) for 
+    In order to reconstruct a plausible playback of re-ordered FFT frames, we need to
+    calculate the phase difference between successive frames, with FrameDelta, and use
+    it to construct a `running phase` (by simply summing the successive differences) for
     the output FFT frames.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Phase input signal.
-        framesize : int, optional
+        framesize: int, optional
             Frame size in samples. Usually same as the FFT size.
             Defaults to 1024.
-        overlaps : int, optional
+        overlaps: int, optional
             Number of overlaps in incomming signal. Usually the same
             as the FFT overlaps. Defaults to 4.
 
     .. note::
 
-        FrameAccum has no `out` method. Signal must be converted back to time domain, 
+        FrameAccum has no `out` method. Signal must be converted back to time domain,
         with IFFT, before being sent to output.
 
     >>> s = Server().boot()
@@ -886,13 +910,14 @@ class FrameAccum(PyoObject):
 
     """
     def __init__(self, input, framesize=1024, overlaps=4, mul=1, add=0):
+        pyoArgsAssert(self, "oiiOO", input, framesize, overlaps, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._framesize = framesize
         self._overlaps = overlaps
         self._in_fader = InputFader(input)
         in_fader, framesize, overlaps, mul, add, lmax = convertArgsToLists(self._in_fader, framesize, overlaps, mul, add)
-        num_of_mains = len(self._in_fader) / self._overlaps
+        num_of_mains = len(self._in_fader) // self._overlaps
         self._base_players = []
         for j in range(num_of_mains):
             objs_list = []
@@ -903,8 +928,9 @@ class FrameAccum(PyoObject):
         self._base_objs = []
         for i in range(lmax):
             base_player = i % num_of_mains
-            overlap = 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)
@@ -915,12 +941,13 @@ class FrameAccum(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
@@ -930,24 +957,25 @@ class FrameAccum(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 new `framesize` attribute.
 
         """
+        pyoArgsAssert(self, "i", x)
         self._framesize = x
         x, lmax = convertArgsToLists(x)
         [obj.setFrameSize(wrap(x,i)) for i, obj in enumerate(self._base_players)]
 
     @property
     def input(self):
-        """PyoObject. Phase input signal.""" 
+        """PyoObject. Phase input signal."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def framesize(self):
-        """PyoObject. Frame size in samples.""" 
+        """PyoObject. Frame size in samples."""
         return self._framesize
     @framesize.setter
     def framesize(self, x): self.setFrameSize(x)
@@ -963,29 +991,29 @@ class Vectral(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Magnitude input signal, usually from an FFT analysis.
-        framesize : int, optional
+        framesize: int, optional
             Frame size in samples. Usually the same as the FFT size.
             Defaults to 1024.
-        overlaps : int, optional
+        overlaps: int, optional
             Number of overlaps in incomming signal. Usually the same
             as the FFT overlaps. Defaults to 4.
-        up : float or PyoObject, optional
+        up: float or PyoObject, optional
             Filter coefficient for increasing bins, between 0 and 1.
             Lower values results in a longer ramp time for bin magnitude.
             Defaults to 1.
-        down : float or PyoObject, optional
+        down: float or PyoObject, optional
             Filter coefficient for decreasing bins, between 0 and 1.
             Lower values results in a longer decay time for bin magnitude.
             Defaults to 0.7
-        damp : float or PyoObject, optional
+        damp: float or PyoObject, optional
             High frequencies damping factor, between 0 and 1. Lower values
             mean more damping. Defaults to 0.9.
 
     .. note::
 
-        Vectral has no `out` method. Signal must be converted back to time domain, 
+        Vectral has no `out` method. Signal must be converted back to time domain,
         with IFFT, before being sent to output.
 
     >>> s = Server().boot()
@@ -1001,6 +1029,7 @@ class Vectral(PyoObject):
 
     """
     def __init__(self, input, framesize=1024, overlaps=4, up=1.0, down=0.7, damp=0.9, mul=1, add=0):
+        pyoArgsAssert(self, "oiiOOOOO", input, framesize, overlaps, up, down, damp, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._framesize = framesize
@@ -1010,7 +1039,7 @@ class Vectral(PyoObject):
         self._damp = damp
         self._in_fader = InputFader(input)
         in_fader, framesize, overlaps, up, down, damp, mul, add, lmax = convertArgsToLists(self._in_fader, framesize, overlaps, up, down, damp, mul, add)
-        num_of_mains = len(self._in_fader) / self._overlaps
+        num_of_mains = len(self._in_fader) // self._overlaps
         self._base_players = []
         for j in range(num_of_mains):
             objs_list = []
@@ -1021,8 +1050,9 @@ class Vectral(PyoObject):
         self._base_objs = []
         for i in range(lmax):
             base_player = i % num_of_mains
-            overlap = 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)
@@ -1033,12 +1063,13 @@ class Vectral(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
@@ -1048,10 +1079,11 @@ class Vectral(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 new `framesize` attribute.
 
         """
+        pyoArgsAssert(self, "i", x)
         self._framesize = x
         x, lmax = convertArgsToLists(x)
         [obj.setFrameSize(wrap(x,i)) for i, obj in enumerate(self._base_players)]
@@ -1062,10 +1094,11 @@ class Vectral(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `up` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._up = x
         x, lmax = convertArgsToLists(x)
         [obj.setUp(wrap(x,i)) for i, obj in enumerate(self._base_players)]
@@ -1076,10 +1109,11 @@ class Vectral(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `down` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._down = x
         x, lmax = convertArgsToLists(x)
         [obj.setDown(wrap(x,i)) for i, obj in enumerate(self._base_players)]
@@ -1090,10 +1124,11 @@ class Vectral(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `damp` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._damp = x
         x, lmax = convertArgsToLists(x)
         [obj.setDamp(wrap(x,i)) for i, obj in enumerate(self._base_players)]
@@ -1107,68 +1142,68 @@ class Vectral(PyoObject):
 
     @property
     def input(self):
-        """PyoObject. Magnitude input signal.""" 
+        """PyoObject. Magnitude input signal."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def framesize(self):
-        """int. Frame size in samples.""" 
+        """int. Frame size in samples."""
         return self._framesize
     @framesize.setter
     def framesize(self, x): self.setFrameSize(x)
 
     @property
     def up(self):
-        """float or PyoObject. Filter coefficient for increasing bins.""" 
+        """float or PyoObject. Filter coefficient for increasing bins."""
         return self._up
     @up.setter
     def up(self, x): self.setUp(x)
 
     @property
     def down(self):
-        """float or PyoObject. Filter coefficient for decreasing bins.""" 
+        """float or PyoObject. Filter coefficient for decreasing bins."""
         return self._down
     @down.setter
     def down(self, x): self.setDown(x)
 
     @property
     def damp(self):
-        """float or PyoObject. High frequencies damping factor.""" 
+        """float or PyoObject. High frequencies damping factor."""
         return self._damp
     @damp.setter
     def damp(self, x): self.setDamp(x)
-    
+
 class CvlVerb(PyoObject):
     """
     Convolution based reverb.
 
-    CvlVerb implements convolution based on a uniformly partitioned overlap-save 
-    algorithm. This object can be used to convolve an input signal with an 
+    CvlVerb implements convolution based on a uniformly partitioned overlap-save
+    algorithm. This object can be used to convolve an input signal with an
     impulse response soundfile to simulate real acoustic spaces.
-    
+
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
-    
-        input : PyoObject
+
+        input: PyoObject
             Input signal to process.
-        impulse : string, optional
-            Path to the impulse response soundfile. The file must have the same 
+        impulse: string, optional
+            Path to the impulse response soundfile. The file must have the same
             sampling rate as the server to get the proper convolution. Available at
-            initialization time only. Defaults to 'IRMediumHallStereo.wav', located 
+            initialization time only. Defaults to 'IRMediumHallStereo.wav', located
             in pyolib SNDS_PATH folder.
-        size : int {pow-of-two}, optional
+        size: int {pow-of-two}, optional
             The size in samples of each partition of the impulse file. Small size means
             smaller latency but more computation time. If not a power-of-2, the object
             will find the next power-of-2 greater and use that as the actual partition size.
             This value must also be greater or equal than the server's buffer size.
             Available at initialization time only. Defaults to 1024.
-        bal : float or PyoObject, optional
-            Balance between wet and dry signal, between 0 and 1. 0 means no 
+        bal: float or PyoObject, optional
+            Balance between wet and dry signal, between 0 and 1. 0 means no
             reverb. Defaults to 0.25.
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> sf = SfPlayer(SNDS_PATH+"/transparent.aif", loop=True, mul=0.5)
@@ -1176,6 +1211,7 @@ class CvlVerb(PyoObject):
 
     """
     def __init__(self, input, impulse=SNDS_PATH+"/IRMediumHallStereo.wav", bal=0.25, size=1024, mul=1, add=0):
+        pyoArgsAssert(self, "osOiOO", input, impulse, bal, size, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._impulse = impulse
@@ -1188,20 +1224,22 @@ class CvlVerb(PyoObject):
         for file in impulse:
             _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._base_objs.extend([CvlVerb_base(wrap(in_fader,i), stringencode(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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
@@ -1211,10 +1249,11 @@ class CvlVerb(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `bal` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._bal = x
         x, lmax = convertArgsToLists(x)
         [obj.setBal(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1226,421 +1265,14 @@ class CvlVerb(PyoObject):
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def bal(self):
-        """float or PyoObject. Wet / dry balance.""" 
+        """float or PyoObject. Wet / dry balance."""
         return self._bal
     @bal.setter
     def bal(self, x): self.setBal(x)
-
-class Spectrum(PyoObject):
-    """
-    Spectrum analyzer and display.
-
-    Spectrum measures the magnitude of an input signal versus frequency
-    within a user defined range. It can show both magnitude and frequency
-    on linear or logarithmic scale.
-    
-    :Parent: :py:class:`PyoObject`
-    
-    :Args:
-    
-        input : PyoObject
-            Input signal to process.
-        size : int {pow-of-two > 4}, optional
-            FFT size. Must be a power of two greater than 4.
-            The FFT size is the number of samples used in each
-            analysis frame. Defaults to 1024.
-        wintype : int, optional
-            Shape of the envelope used to filter each input frame.
-            Possible shapes are :
-                0. rectangular (no windowing)
-                1. Hamming
-                2. Hanning
-                3. Bartlett (triangular)
-                4. Blackman 3-term
-                5. Blackman-Harris 4-term
-                6. Blackman-Harris 7-term
-                7. Tuckey (alpha = 0.66)
-                8. Sine (half-sine window)
-        function : python callable, optional
-            If set, this function will be called with magnitudes (as
-            list of lists, one list per channel). Useful if someone
-            wants to save the analysis data into a text file.
-            Defaults to None.
-
-    .. note::
-    
-        Spectrum has no `out` method.
-        Spectrum has no `mul` and `add` attributes.
-
-    >>> s = Server().boot()
-    >>> s.start()
-    >>> a = SuperSaw(freq=[500,750], detune=0.6, bal=0.7, mul=0.5).out()
-    >>> spec = Spectrum(a, size=1024)
-
-    """
-    def __init__(self, input, size=1024, wintype=2, function=None):
-        PyoObject.__init__(self)
-        self.points = None
-        self.viewFrame = None
-        self._input = input
-        self._size = size
-        self._wintype = wintype
-        self._function = function
-        self._fscaling = 0
-        self._mscaling = 1
-        self._lowbound = 0
-        self._highbound = 0.5
-        self._width = 500
-        self._height = 400
-        self._gain = 1
-        self._in_fader = InputFader(input)
-        in_fader, size, wintype, lmax = convertArgsToLists(self._in_fader, size, wintype)
-        self._base_objs = [Spectrum_base(wrap(in_fader,i), wrap(size,i), wrap(wintype,i)) for i in range(lmax)]
-        if function == None:
-            self.view()
-        self._timer = Pattern(self.refreshView, 0.05).play()
- 
-    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. Default to 0.05.
-
-        """
-        self._input = x
-        self._in_fader.setInput(x, fadetime)
-
-    def setSize(self, x):
-        """
-        Replace the `size` attribute.
-        
-        :Args:
-
-            x : int
-                new `size` attribute.
-        
-        """
-        self._size = x
-        x, lmax = convertArgsToLists(x)
-        [obj.setSize(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
-
-    def setWinType(self, x):
-        """
-        Replace the `wintype` attribute.
-        
-        :Args:
-
-            x : int
-                new `wintype` attribute.
-        
-        """
-        self._wintype = x
-        x, lmax = convertArgsToLists(x)
-        [obj.setWinType(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
-
-    def setFunction(self, function):
-        """
-        Sets the function to be called to retrieve the analysis data.
-        
-        :Args:
-            
-            function : python callable
-                The function called by the internal timer to retrieve the
-                analysis data. The function must be created with one argument
-                and will receive the data as a list of lists (one list per channel).
-
-        """
-        self._function = function
-
-    def poll(self, active):
-        """
-        Turns on and off the analysis polling.
-        
-        :Args:
-            
-            active : boolean
-                If True, starts the analysis polling, False to stop it.
-                defaults to True.
-
-        """
-        if active:
-            self._timer.play()
-        else:
-            self._timer.stop()
-
-    def polltime(self, time):
-        """
-        Sets the polling time in seconds.
-        
-        :Args:
-            
-            time : float
-                Adjusts the frequency of the internal timer used to
-                retrieve the current analysis frame. defaults to 0.05.
-        
-        """
-        self._timer.time = time
-
-    def setLowbound(self, x):
-        """
-        Sets the lower frequency, as multiplier of sr, returned by the analysis.
-        
-        Returns the real low frequency en Hz.
-        
-        :Args:
-
-            x : float {0 <= x <= 0.5}
-                new `lowbound` attribute.
-        
-        """
-        self._lowbound = x
-        x, lmax = convertArgsToLists(x)
-        tmp = [obj.setLowbound(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
-        return tmp[0]
-
-    def setHighbound(self, x):
-        """
-        Sets the higher frequency, as multiplier of sr, returned by the analysis.
-        
-        Returns the real high frequency en Hz.
-        
-        :Args:
-
-            x : float {0 <= x <= 0.5}
-                new `highbound` attribute.
-        
-        """
-        self._highbound = x
-        x, lmax = convertArgsToLists(x)
-        tmp = [obj.setHighbound(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
-        return tmp[0]
-
-    def getLowfreq(self):
-        """
-        Returns the current lower frequency, in Hz, used by the analysis.
-        
-        """
-
-        return self._base_objs[0].getLowfreq()
-
-    def getHighfreq(self):
-        """
-        Returns the current higher frequency, in Hz, used by the analysis.
-        
-        """
-        return self._base_objs[0].getHighfreq()
-
-    def setWidth(self, x):
-        """
-        Sets the width, in pixels, of the current display.
-        
-        Used internally to build the list of points to draw.
-        
-        :Args:
-
-            x : int
-                new `width` attribute.
-        
-        """
-        self._width = x
-        x, lmax = convertArgsToLists(x)
-        [obj.setWidth(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
-
-    def setHeight(self, x):
-        """
-        Sets the height, in pixels, of the current display.
-        
-        Used internally to build the list of points to draw.
-        
-        :Args:
-
-            x : int
-                new `height` attribute.
-        
-        """
-        self._height = x
-        x, lmax = convertArgsToLists(x)
-        [obj.setHeight(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
-
-    def setFscaling(self, x):
-        """
-        Sets the frequency display to linear or logarithmic.
-        
-        :Args:
-
-            x : boolean
-                If True, the frequency display is logarithmic. False turns
-                it back to linear. Defaults to False.
-        
-        """
-        self._fscaling = x
-        x, lmax = convertArgsToLists(x)
-        [obj.setFscaling(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
-        if self.viewFrame != None:
-            self.viewFrame.setFscaling(self._fscaling)
-
-    def setMscaling(self, x):
-        """
-        Sets the magnitude display to linear or logarithmic.
-        
-        :Args:
-
-            x : boolean
-                If True, the magnitude display is logarithmic (which means in dB). 
-                False turns it back to linear. Defaults to True.
-        
-        """
-        self._mscaling = x
-        x, lmax = convertArgsToLists(x)
-        [obj.setMscaling(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
-        if self.viewFrame != None:
-            self.viewFrame.setMscaling(self._mscaling)
-
-    def getFscaling(self):
-        """
-        Returns the scaling of the frequency display.
-        
-        Returns True for logarithmic or False for linear.
-
-        """
-        return self._fscaling
-
-    def getMscaling(self):
-        """
-        Returns the scaling of the magnitude display.
-        
-        Returns True for logarithmic or False for linear.
-
-        """
-        return self._mscaling
-
-    def setGain(self, x):
-        """
-        Set the gain of the anaysis data. For drawing purpose.
-        
-        :Args:
-
-            x : float
-                new `gain` attribute, as linear values.
-        
-        """
-        self._gain = x
-        x, lmax = convertArgsToLists(x)
-        [obj.setGain(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
-
-    def view(self, title="Spectrum", wxnoserver=False):
-        """
-        Opens a window showing the result of the analysis.
-        
-        :Args:
-        
-            title : string, optional
-                Window title. Defaults to "Spectrum". 
-            wxnoserver : boolean, optional
-                With wxPython graphical toolkit, if True, tells the 
-                interpreter that there will be no server window.
-                
-        If `wxnoserver` is set to True, the interpreter will not wait for 
-        the server GUI before showing the controller window. 
-        
-        """
-        createSpectrumWindow(self, title, wxnoserver)
-
-    def _setViewFrame(self, frame):
-        self.viewFrame = frame
-        
-    def refreshView(self):
-        """
-        Updates the graphical display of the spectrum.
-        
-        Called automatically by the internal timer.
-
-        """
-        self.points = [obj.display() for obj in self._base_objs]
-        if self._function != None:
-            self._function(self.points)
-        if self.viewFrame != None:
-            self.viewFrame.update(self.points)
-
-
-    @property
-    def input(self):
-        """PyoObject. Input signal to process.""" 
-        return self._input
-    @input.setter
-    def input(self, x): self.setInput(x)
-
-    @property
-    def size(self):
-        """int. FFT size."""
-        return self._size
-    @size.setter
-    def size(self, x): self.setSize(x)
-
-    @property
-    def wintype(self):
-        """int. Windowing method."""
-        return self._wintype
-    @wintype.setter
-    def wintype(self, x): self.setWinType(x)
-
-    @property
-    def gain(self):
-        """float. Sets the gain of the analysis data."""
-        return self._gain
-    @gain.setter
-    def gain(self, x): self.setGain(x)
-
-    @property
-    def lowbound(self):
-        """float. Lowest frequency (multiplier of sr) to output."""
-        return self._lowbound
-    @lowbound.setter
-    def lowbound(self, x): self.setLowbound(x)
-
-    @property
-    def highbound(self):
-        """float. Highest frequency (multiplier of sr) to output."""
-        return self._highbound
-    @highbound.setter
-    def highbound(self, x): self.setHighbound(x)
-
-    @property
-    def width(self):
-        """int. Width, in pixels, of the current display."""
-        return self._width
-    @width.setter
-    def width(self, x): self.setWidth(x)
-
-    @property
-    def height(self):
-        """int. Height, in pixels, of the current display."""
-        return self._height
-    @height.setter
-    def height(self, x): self.setHeight(x)
-
-    @property
-    def fscaling(self):
-        """boolean. Scaling of the frequency display."""
-        return self._fscaling
-    @fscaling.setter
-    def fscaling(self, x): self.setFscaling(x)
-
-    @property
-    def mscaling(self):
-        """boolean. Scaling of the magnitude display."""
-        return self._mscaling
-    @mscaling.setter
-    def mscaling(self, x): self.setMscaling(x)
diff --git a/pyolib/generators.py b/pyolib/generators.py
index a24bb1e..1df8932 100644
--- a/pyolib/generators.py
+++ b/pyolib/generators.py
@@ -6,27 +6,28 @@ processing chain or as parameter's modifiers.
 
 """
 
+from __future__ import absolute_import
 """
-Copyright 2010 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+You should have received a copy of the GNU Lesser General Public
+License along with pyo.  If not, see <http://www.gnu.org/licenses/>.
 """
-from _core import *
-from _maps import *
+from ._core import *
+from ._maps import *
 
 ######################################################################
 ### Sources
@@ -34,57 +35,61 @@ from _maps import *
 class Sine(PyoObject):
     """
     A simple sine wave oscillator.
-    
+
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
-    
-        freq : float or PyoObject, optional
+
+        freq: float or PyoObject, optional
             Frequency in cycles per second. Defaults to 1000.
-        phase : float or PyoObject, optional
+        phase: float or PyoObject, optional
             Phase of sampling, expressed as a fraction of a cycle (0 to 1).
             Defaults to 0.
 
-    .. seealso:: 
-        
+    .. seealso::
+
         :py:class:`Osc`, :py:class:`Phasor`
 
     >>> s = Server().boot()
     >>> s.start()
     >>> sine = Sine(freq=[400,500], mul=.2).out()
-    
+
     """
     def __init__(self, freq=1000, phase=0, mul=1, add=0):
+        pyoArgsAssert(self, "OOOO", freq, phase, mul, add)
         PyoObject.__init__(self, mul, add)
         self._freq = freq
         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):
         """
         Replace the `freq` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `freq` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
-        
+
     def setPhase(self, x):
         """
         Replace the `phase` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `phase` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._phase = x
         x, lmax = convertArgsToLists(x)
         [obj.setPhase(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -96,29 +101,130 @@ class Sine(PyoObject):
         """
         [obj.reset() for i, obj in enumerate(self._base_objs)]
 
-
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMapFreq(self._freq), SLMapPhase(self._phase), SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
-        
+
     @property
     def freq(self):
-        """float or PyoObject. Frequency in cycles per second.""" 
+        """float or PyoObject. Frequency in cycles per second."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
     def phase(self):
-        """float or PyoObject. Phase of sampling.""" 
+        """float or PyoObject. Phase of sampling."""
         return self._phase
     @phase.setter
     def phase(self, x): self.setPhase(x)
 
+class FastSine(PyoObject):
+    """
+    A fast sine wave approximation using the formula of a parabola.
+
+    This object implements two sin approximations that are even faster
+    than a linearly interpolated table lookup. With `quality` set to 1,
+    the approximation is more accurate but also more expensive on the CPU
+    (still cheaper than a Sine object). With `quality` = 0, the algorithm
+    gives a worse approximation of the sin function but it is very fast
+    (and well suitable for generating LFO).
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        freq: float or PyoObject, optional
+            Frequency in cycles per second. Defaults to 1000.
+        initphase: float, optional
+            Initial phase of the oscillator, between 0 and 1. Available
+            at initialization time only. Defaults to 0.
+        quality: int, optional
+            Sets the approximation quality. 1 is more accurate but also
+            more expensive on the CPU. 0 is a cheaper algorithm but is
+            very fast. Defaults to 1.
+
+    .. seealso::
+
+        :py:class:`Sine`
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> lfo = FastSine(freq=[4,5], quality=0, mul=0.02, add=1)
+    >>> syn = FastSine(freq=500*lfo, quality=1, mul=0.4).out()
+
+    """
+    def __init__(self, freq=1000, initphase=0.0, quality=1, mul=1, add=0):
+        pyoArgsAssert(self, "OniOO", freq, initphase, quality, mul, add)
+        PyoObject.__init__(self, mul, add)
+        self._freq = freq
+        self._initphase = initphase
+        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):
+        """
+        Replace the `freq` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                new `freq` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._freq = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def setQuality(self, x):
+        """
+        Replace the `quality` attribute.
+
+        :Args:
+
+            x: int {0 or 1}
+                new `quality` attribute.
+
+        """
+        pyoArgsAssert(self, "i", x)
+        self._quality = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setQuality(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)]
+
+    def ctrl(self, map_list=None, title=None, wxnoserver=False):
+        self._map_list = [SLMapFreq(self._freq),
+                          SLMap(0, 1, "lin", "quality", self._quality, res="int", dataOnly=True),
+                          SLMapMul(self._mul)]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
+    @property
+    def freq(self):
+        """float or PyoObject. Frequency in cycles per second."""
+        return self._freq
+    @freq.setter
+    def freq(self, x): self.setFreq(x)
+
+    @property
+    def quality(self):
+        """int. Quality of the sin approximation."""
+        return self._quality
+    @quality.setter
+    def quality(self, x): self.setQuality(x)
+
 class SineLoop(PyoObject):
     """
     A simple sine wave oscillator with feedback.
-    
+
     The oscillator output, multiplied by `feedback`, is added to the position
     increment and can be used to control the brightness of the oscillator.
 
@@ -126,14 +232,14 @@ class SineLoop(PyoObject):
 
     :Args:
 
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Frequency in cycles per second. Defaults to 1000.
-        feedback : float or PyoObject, optional
-            Amount of the output signal added to position increment, between 0 and 1. 
+        feedback: float or PyoObject, optional
+            Amount of the output signal added to position increment, between 0 and 1.
             Controls the brightness. Defaults to 0.
 
-    .. seealso:: 
-        
+    .. seealso::
+
         :py:class:`Sine`, :py:class:`OscLoop`
 
     >>> s = Server().boot()
@@ -143,11 +249,13 @@ class SineLoop(PyoObject):
 
     """
     def __init__(self, freq=1000, feedback=0, mul=1, add=0):
+        pyoArgsAssert(self, "OOOO", freq, feedback, mul, add)
         PyoObject.__init__(self, mul, add)
         self._freq = freq
         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):
         """
@@ -155,10 +263,11 @@ class SineLoop(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `freq` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -169,10 +278,11 @@ class SineLoop(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `feedback` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._feedback = x
         x, lmax = convertArgsToLists(x)
         [obj.setFeedback(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -183,14 +293,14 @@ class SineLoop(PyoObject):
 
     @property
     def freq(self):
-        """float or PyoObject. Frequency in cycles per second.""" 
+        """float or PyoObject. Frequency in cycles per second."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
     def feedback(self):
-        """float or PyoObject. Brightness control.""" 
+        """float or PyoObject. Brightness control."""
         return self._feedback
     @feedback.setter
     def feedback(self, x): self.setFeedback(x)
@@ -198,60 +308,64 @@ class SineLoop(PyoObject):
 class Phasor(PyoObject):
     """
     A simple phase incrementor.
-    
+
     Output is a periodic ramp from 0 to 1.
- 
+
     :Parent: :py:class:`PyoObject`
-   
+
     :Args:
-    
-        freq : float or PyoObject, optional
+
+        freq: float or PyoObject, optional
             Frequency in cycles per second. Defaults to 100.
-        phase : float or PyoObject, optional
-            Phase of sampling, expressed as a fraction of a cycle (0 to 1). 
+        phase: float or PyoObject, optional
+            Phase of sampling, expressed as a fraction of a cycle (0 to 1).
             Defaults to 0.
 
-    .. seealso:: 
-        
+    .. seealso::
+
         :py:class:`Osc`, :py:class:`Sine`
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> f = Phasor(freq=[1, 1.5], mul=1000, add=500)
     >>> sine = Sine(freq=f, mul=.2).out()
-    
+
     """
     def __init__(self, freq=100, phase=0, mul=1, add=0):
+        pyoArgsAssert(self, "OOOO", freq, phase, mul, add)
         PyoObject.__init__(self, mul, add)
         self._freq = freq
         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):
         """
         Replace the `freq` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `freq` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
-        
+
     def setPhase(self, x):
         """
         Replace the `phase` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `phase` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._phase = x
         x, lmax = convertArgsToLists(x)
         [obj.setPhase(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -263,21 +377,20 @@ class Phasor(PyoObject):
         """
         [obj.reset() for i, obj in enumerate(self._base_objs)]
 
-
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMapFreq(self._freq), SLMapPhase(self._phase), SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
-        
+
     @property
     def freq(self):
-        """float or PyoObject. Frequency in cycles per second.""" 
+        """float or PyoObject. Frequency in cycles per second."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
     def phase(self):
-        """float or PyoObject. Phase of sampling.""" 
+        """float or PyoObject. Phase of sampling."""
         return self._phase
     @phase.setter
     def phase(self, x): self.setPhase(x)
@@ -289,25 +402,27 @@ class Input(PyoObject):
     :Parent: :py:class:`PyoObject`
 
     :Args:
-    
-        chnl : int, optional
+
+        chnl: int, optional
             Input channel to read from. Defaults to 0.
 
     .. note::
-    
-        Requires that the Server's duplex mode is set to 1. 
-    
+
+        Requires that the Server's duplex mode is set to 1.
+
     >>> s = Server(duplex=1).boot()
     >>> s.start()
     >>> a = Input(chnl=0, mul=.7)
     >>> b = Delay(a, delay=.25, feedback=.5, mul=.5).out()
-    
+
     """
     def __init__(self, chnl=0, mul=1, add=0):
+        pyoArgsAssert(self, "iOO", chnl, mul, add)
         PyoObject.__init__(self, mul, add)
         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)]
@@ -316,19 +431,21 @@ class Input(PyoObject):
 class Noise(PyoObject):
     """
     A white noise generator.
-        
+
     :Parent: :py:class:`PyoObject`
 
     >>> s = Server().boot()
     >>> s.start()
     >>> a = Noise(.1).mix(2).out()
-        
+
     """
     def __init__(self, mul=1, add=0):
+        pyoArgsAssert(self, "OO", mul, add)
         PyoObject.__init__(self, mul, add)
         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):
         """
@@ -336,11 +453,12 @@ class Noise(PyoObject):
 
         :Args:
 
-            x : int, {0, 1}
+            x: int, {0, 1}
                 0 uses the system rand() method to generate number. Used as default.
                 1 uses a simple linear congruential generator, cheaper than rand().
 
         """
+        pyoArgsAssert(self, "i", x)
         self._type = x
         x, lmax = convertArgsToLists(x)
         [obj.setType(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -351,7 +469,7 @@ class Noise(PyoObject):
 
     @property
     def type(self):
-        """int {0, 1}. Sets the generation algorithm.""" 
+        """int {0, 1}. Sets the generation algorithm."""
         return self._type
     @type.setter
     def type(self, x): self.setType(x)
@@ -365,7 +483,7 @@ class PinkNoise(PyoObject):
     This is an approximation to a -10dB/decade filter using a weighted sum
     of first order filters. It is accurate to within +/-0.05dB above 9.2Hz
     (44100Hz sampling rate).
-    
+
     :Parent: :py:class:`PyoObject`
 
     >>> s = Server().boot()
@@ -374,9 +492,11 @@ class PinkNoise(PyoObject):
 
     """
     def __init__(self, mul=1, add=0):
+        pyoArgsAssert(self, "OO", mul, add)
         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)]
@@ -386,9 +506,9 @@ class BrownNoise(PyoObject):
     """
     A brown noise generator.
 
-    The spectrum of a brown noise has a power density which decreases 6 dB 
+    The spectrum of a brown noise has a power density which decreases 6 dB
     per octave with increasing frequency (density proportional to 1/f^2).
-    
+
     :Parent: :py:class:`PyoObject`
 
     >>> s = Server().boot()
@@ -397,9 +517,11 @@ class BrownNoise(PyoObject):
 
     """
     def __init__(self, mul=1, add=0):
+        pyoArgsAssert(self, "OO", mul, add)
         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)]
@@ -408,19 +530,19 @@ class BrownNoise(PyoObject):
 class FM(PyoObject):
     """
     A simple frequency modulation generator.
-    
+
     Implements frequency modulation synthesis based on Chowning's algorithm.
-    
+
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
-    
-        carrier : float or PyoObject, optional
+
+        carrier: float or PyoObject, optional
             Carrier frequency in cycles per second. Defaults to 100.
-        ratio : float or PyoObject, optional
-            A factor that, when multiplied by the `carrier` parameter, 
+        ratio: float or PyoObject, optional
+            A factor that, when multiplied by the `carrier` parameter,
             gives the modulator frequency. Defaults to 0.5.
-        index : float or PyoObject, optional
+        index: float or PyoObject, optional
             The modulation index. This value multiplied by the modulator
             frequency gives the modulator amplitude. Defaults to 5.
 
@@ -430,40 +552,44 @@ class FM(PyoObject):
     >>> m = Metro(4).play()
     >>> tr = TrigEnv(m, table=ind, dur=4)
     >>> f = FM(carrier=[251,250], ratio=[.2498,.2503], index=tr, mul=.2).out()
-    
+
     """
     def __init__(self, carrier=100, ratio=0.5, index=5, mul=1, add=0):
+        pyoArgsAssert(self, "OOOOO", carrier, ratio, index, mul, add)
         PyoObject.__init__(self, mul, add)
         self._carrier = carrier
         self._ratio = ratio
         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):
         """
         Replace the `carrier` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `carrier` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._carrier = x
         x, lmax = convertArgsToLists(x)
         [obj.setCarrier(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
-        
+
     def setRatio(self, x):
         """
         Replace the `ratio` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `ratio` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._ratio = x
         x, lmax = convertArgsToLists(x)
         [obj.setRatio(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -471,13 +597,14 @@ class FM(PyoObject):
     def setIndex(self, x):
         """
         Replace the `index` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `index` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._index = x
         x, lmax = convertArgsToLists(x)
         [obj.setIndex(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -488,24 +615,24 @@ class FM(PyoObject):
                           SLMap(0, 20, "lin", "index", self._index),
                           SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
-        
+
     @property
     def carrier(self):
-        """float or PyoObject. Carrier frequency in cycles per second.""" 
+        """float or PyoObject. Carrier frequency in cycles per second."""
         return self._carrier
     @carrier.setter
     def carrier(self, x): self.setCarrier(x)
 
     @property
     def ratio(self):
-        """float or PyoObject. Modulator/Carrier ratio.""" 
+        """float or PyoObject. Modulator/Carrier ratio."""
         return self._ratio
     @ratio.setter
     def ratio(self, x): self.setRatio(x)
 
     @property
     def index(self):
-        """float or PyoObject. Modulation index.""" 
+        """float or PyoObject. Modulation index."""
         return self._index
     @index.setter
     def index(self, x): self.setIndex(x)
@@ -521,20 +648,20 @@ class CrossFM(PyoObject):
 
     :Args:
 
-        carrier : float or PyoObject, optional
+        carrier: float or PyoObject, optional
             Carrier frequency in cycles per second. Defaults to 100.
-        ratio : float or PyoObject, optional
-            A factor that, when multiplied by the `carrier` parameter, 
+        ratio: float or PyoObject, optional
+            A factor that, when multiplied by the `carrier` parameter,
             gives the modulator frequency. Defaults to 0.5.
-        ind1 : float or PyoObject, optional
+        ind1: float or PyoObject, optional
             The carrier index. This value multiplied by the carrier
             frequency gives the carrier amplitude for modulating the
-            modulation oscillator frequency. 
+            modulation oscillator frequency.
             Defaults to 2.
-        ind1 : float or PyoObject, optional
+        ind1: float or PyoObject, optional
             The modulation index. This value multiplied by the modulation
-            frequency gives the modulation amplitude for modulating the 
-            carrier oscillator frequency. 
+            frequency gives the modulation amplitude for modulating the
+            carrier oscillator frequency.
             Defaults to 2.
 
     >>> s = Server().boot()
@@ -546,6 +673,7 @@ class CrossFM(PyoObject):
 
     """
     def __init__(self, carrier=100, ratio=0.5, ind1=2, ind2=2, mul=1, add=0):
+        pyoArgsAssert(self, "OOOOOO", carrier, ratio, ind1, ind2, mul, add)
         PyoObject.__init__(self, mul, add)
         self._carrier = carrier
         self._ratio = ratio
@@ -553,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):
         """
@@ -560,10 +689,11 @@ class CrossFM(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `carrier` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._carrier = x
         x, lmax = convertArgsToLists(x)
         [obj.setCarrier(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -574,10 +704,11 @@ class CrossFM(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `ratio` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._ratio = x
         x, lmax = convertArgsToLists(x)
         [obj.setRatio(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -588,10 +719,11 @@ class CrossFM(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `ind1` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._ind1 = x
         x, lmax = convertArgsToLists(x)
         [obj.setInd1(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -602,10 +734,11 @@ class CrossFM(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `ind2` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._ind2 = x
         x, lmax = convertArgsToLists(x)
         [obj.setInd2(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -620,28 +753,28 @@ class CrossFM(PyoObject):
 
     @property
     def carrier(self):
-        """float or PyoObject. Carrier frequency in cycles per second.""" 
+        """float or PyoObject. Carrier frequency in cycles per second."""
         return self._carrier
     @carrier.setter
     def carrier(self, x): self.setCarrier(x)
 
     @property
     def ratio(self):
-        """float or PyoObject. Modulator/Carrier ratio.""" 
+        """float or PyoObject. Modulator/Carrier ratio."""
         return self._ratio
     @ratio.setter
     def ratio(self, x): self.setRatio(x)
 
     @property
     def ind1(self):
-        """float or PyoObject. Carrier index.""" 
+        """float or PyoObject. Carrier index."""
         return self._ind1
     @ind1.setter
     def ind1(self, x): self.setInd1(x)
 
     @property
     def ind2(self):
-        """float or PyoObject. Modulation index.""" 
+        """float or PyoObject. Modulation index."""
         return self._ind2
     @ind2.setter
     def ind2(self, x): self.setInd2(x)
@@ -650,16 +783,16 @@ class Blit(PyoObject):
     """
     Band limited impulse train synthesis.
 
-    Impulse train generator with control over the number of harmonics 
+    Impulse train generator with control over the number of harmonics
     in the spectrum, which gives oscillators with very low aliasing.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Frequency in cycles per second. Defaults to 100.
-        harms : float or PyoObject, optional
+        harms: float or PyoObject, optional
             Number of harmonics in the generated spectrum. Defaults to 40.
 
     >>> s = Server().boot()
@@ -670,11 +803,13 @@ class Blit(PyoObject):
 
     """
     def __init__(self, freq=100, harms=40, mul=1, add=0):
+        pyoArgsAssert(self, "OOOO", freq, harms, mul, add)
         PyoObject.__init__(self, mul, add)
         self._freq = freq
         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):
         """
@@ -682,10 +817,11 @@ class Blit(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `freq` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -696,10 +832,11 @@ class Blit(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `harms` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._harms = x
         x, lmax = convertArgsToLists(x)
         [obj.setHarms(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -712,14 +849,14 @@ class Blit(PyoObject):
 
     @property
     def freq(self):
-        """float or PyoObject. Frequency in cycles per second.""" 
+        """float or PyoObject. Frequency in cycles per second."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
     def harms(self):
-        """float or PyoObject. Number of harmonics.""" 
+        """float or PyoObject. Number of harmonics."""
         return self._harms
     @harms.setter
     def harms(self, x): self.setHarms(x)
@@ -728,33 +865,33 @@ class Rossler(PyoObject):
     """
     Chaotic attractor for the Rossler system.
 
-    The Rossler attractor is a system of three non-linear ordinary differential 
-    equations. These differential equations define a continuous-time dynamical 
-    system that exhibits chaotic dynamics associated with the fractal properties 
+    The Rossler attractor is a system of three non-linear ordinary differential
+    equations. These differential equations define a continuous-time dynamical
+    system that exhibits chaotic dynamics associated with the fractal properties
     of the attractor.
-    
+
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        pitch : float or PyoObject, optional
-            Controls the speed, in the range 0 -> 1, of the variations. With values 
-            below 0.2, this object can be used as a low frequency oscillator (LFO) 
-            and above 0.2, it will generate a broad spectrum noise with harmonic peaks. 
+        pitch: float or PyoObject, optional
+            Controls the speed, in the range 0 -> 1, of the variations. With values
+            below 0.2, this object can be used as a low frequency oscillator (LFO)
+            and above 0.2, it will generate a broad spectrum noise with harmonic peaks.
             Defaults to 0.25.
-        chaos : float or PyoObject, optional
-            Controls the chaotic behavior, in the range 0 -> 1, of the oscillator. 
+        chaos: float or PyoObject, optional
+            Controls the chaotic behavior, in the range 0 -> 1, of the oscillator.
             0 means nearly periodic while 1 is totally chaotic. Defaults to 0.5.
         stereo, boolean, optional
-            If True, 2 streams will be generated, one with the X variable signal of 
+            If True, 2 streams will be generated, one with the X variable signal of
             the algorithm and a second composed of the Y variable signal of the algorithm.
-            These two signal are strongly related in their frequency spectrum but 
+            These two signal are strongly related in their frequency spectrum but
             the Y signal is out-of-phase by approximatly 180 degrees. Useful to create
             alternating LFOs. Available at initialization only. Defaults to False.
 
-    .. seealso:: 
-        
-        :py:class:`Lorenz`
+    .. seealso::
+
+        :py:class:`Lorenz`, :py:class:`ChenLee`
 
     >>> s = Server().boot()
     >>> s.start()
@@ -763,6 +900,7 @@ class Rossler(PyoObject):
 
     """
     def __init__(self, pitch=0.25, chaos=0.5, stereo=False, mul=1, add=0):
+        pyoArgsAssert(self, "OObOO", pitch, chaos, stereo, mul, add)
         PyoObject.__init__(self, mul, add)
         self._pitch = pitch
         self._chaos = chaos
@@ -774,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):
         """
@@ -781,10 +920,11 @@ class Rossler(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `pitch` attribute. {0. -> 1.}
 
         """
+        pyoArgsAssert(self, "O", x)
         self._pitch = x
         x, lmax = convertArgsToLists(x)
         if self._stereo:
@@ -798,10 +938,11 @@ class Rossler(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `chaos` attribute. {0. -> 1.}
 
         """
+        pyoArgsAssert(self, "O", x)
         self._chaos = x
         x, lmax = convertArgsToLists(x)
         if self._stereo:
@@ -810,20 +951,20 @@ class Rossler(PyoObject):
             [obj.setChaos(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", "pitch", self._pitch), 
+        self._map_list = [SLMap(0., 1., "lin", "pitch", self._pitch),
                           SLMap(0., 1., "lin", "chaos", self._chaos), SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def pitch(self):
-        """float or PyoObject. Speed of the variations.""" 
+        """float or PyoObject. Speed of the variations."""
         return self._pitch
     @pitch.setter
     def pitch(self, x): self.setPitch(x)
 
     @property
     def chaos(self):
-        """float or PyoObject. Chaotic behavior.""" 
+        """float or PyoObject. Chaotic behavior."""
         return self._chaos
     @chaos.setter
     def chaos(self, x): self.setChaos(x)
@@ -832,33 +973,33 @@ class Lorenz(PyoObject):
     """
     Chaotic attractor for the Lorenz system.
 
-    The Lorenz attractor is a system of three non-linear ordinary differential 
-    equations. These differential equations define a continuous-time dynamical 
-    system that exhibits chaotic dynamics associated with the fractal properties 
+    The Lorenz attractor is a system of three non-linear ordinary differential
+    equations. These differential equations define a continuous-time dynamical
+    system that exhibits chaotic dynamics associated with the fractal properties
     of the attractor.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        pitch : float or PyoObject, optional
-            Controls the speed, in the range 0 -> 1, of the variations. With values 
-            below 0.2, this object can be used as a low frequency oscillator (LFO) 
-            and above 0.2, it will generate a broad spectrum noise with harmonic peaks. 
+        pitch: float or PyoObject, optional
+            Controls the speed, in the range 0 -> 1, of the variations. With values
+            below 0.2, this object can be used as a low frequency oscillator (LFO)
+            and above 0.2, it will generate a broad spectrum noise with harmonic peaks.
             Defaults to 0.25.
-        chaos : float or PyoObject, optional
-            Controls the chaotic behavior, in the range 0 -> 1, of the oscillator. 
+        chaos: float or PyoObject, optional
+            Controls the chaotic behavior, in the range 0 -> 1, of the oscillator.
             0 means nearly periodic while 1 is totally chaotic. Defaults to 0.5
         stereo, boolean, optional
-            If True, 2 streams will be generated, one with the X variable signal of 
+            If True, 2 streams will be generated, one with the X variable signal of
             the algorithm and a second composed of the Y variable signal of the algorithm.
-            These two signal are strongly related in their frequency spectrum but 
+            These two signal are strongly related in their frequency spectrum but
             the Y signal is out-of-phase by approximatly 180 degrees. Useful to create
             alternating LFOs. Available at initialization only. Defaults to False.
 
-    .. seealso:: 
-        
-        :py:class:`Rossler`
+    .. seealso::
+
+        :py:class:`Rossler`, :py:class:`ChenLee`
 
     >>> s = Server().boot()
     >>> s.start()
@@ -867,6 +1008,7 @@ class Lorenz(PyoObject):
 
     """
     def __init__(self, pitch=0.25, chaos=0.5, stereo=False, mul=1, add=0):
+        pyoArgsAssert(self, "OObOO", pitch, chaos, stereo, mul, add)
         PyoObject.__init__(self, mul, add)
         self._pitch = pitch
         self._chaos = chaos
@@ -878,6 +1020,115 @@ 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):
+        """
+        Replace the `pitch` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                new `pitch` attribute. {0. -> 1.}
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._pitch = x
+        x, lmax = convertArgsToLists(x)
+        if self._stereo:
+            [obj.setPitch(wrap(x,i)) for i, obj in enumerate(self._base_objs) if (i % 2) == 0]
+        else:
+            [obj.setPitch(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def setChaos(self, x):
+        """
+        Replace the `chaos` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                new `chaos` attribute. {0. -> 1.}
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._chaos = x
+        x, lmax = convertArgsToLists(x)
+        if self._stereo:
+            [obj.setChaos(wrap(x,i)) for i, obj in enumerate(self._base_objs) if (i % 2) == 0]
+        else:
+            [obj.setChaos(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", "pitch", self._pitch),
+                          SLMap(0., 1., "lin", "chaos", self._chaos), SLMapMul(self._mul)]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
+    @property
+    def pitch(self):
+        """float or PyoObject. Speed of the variations."""
+        return self._pitch
+    @pitch.setter
+    def pitch(self, x): self.setPitch(x)
+
+    @property
+    def chaos(self):
+        """float or PyoObject. Chaotic behavior."""
+        return self._chaos
+    @chaos.setter
+    def chaos(self, x): self.setChaos(x)
+
+class ChenLee(PyoObject):
+    """
+    Chaotic attractor for the Chen-Lee system.
+
+    The ChenLee attractor is a system of three non-linear ordinary differential
+    equations. These differential equations define a continuous-time dynamical
+    system that exhibits chaotic dynamics associated with the fractal properties
+    of the attractor.
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        pitch: float or PyoObject, optional
+            Controls the speed, in the range 0 -> 1, of the variations. With values
+            below 0.2, this object can be used as a low frequency oscillator (LFO)
+            and above 0.2, it will generate a broad spectrum noise with harmonic peaks.
+            Defaults to 0.25.
+        chaos: float or PyoObject, optional
+            Controls the chaotic behavior, in the range 0 -> 1, of the oscillator.
+            0 means nearly periodic while 1 is totally chaotic. Defaults to 0.5
+        stereo, boolean, optional
+            If True, 2 streams will be generated, one with the X variable signal of
+            the algorithm and a second composed of the Y variable signal of the algorithm.
+            These two signal are strongly related in their frequency spectrum but
+            the Y signal is slightly out-of-phase. Useful to create alternating LFOs.
+            Available at initialization only. Defaults to False.
+
+    .. seealso::
+
+        :py:class:`Rossler`, :py:class:`Lorenz`
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> a = ChenLee(pitch=.001, chaos=0.2, stereo=True, mul=.5, add=.5)
+    >>> b = ChenLee(pitch=1, chaos=a, mul=0.5).out()
+
+    """
+    def __init__(self, pitch=0.25, chaos=0.5, stereo=False, mul=1, add=0):
+        pyoArgsAssert(self, "OObOO", pitch, chaos, stereo, mul, add)
+        PyoObject.__init__(self, mul, add)
+        self._pitch = pitch
+        self._chaos = chaos
+        self._stereo = stereo
+        pitch, chaos, mul, add, lmax = convertArgsToLists(pitch, chaos, mul, add)
+        self._base_objs = []
+        self._alt_objs = []
+        for i in range(lmax):
+            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):
         """
@@ -885,10 +1136,11 @@ class Lorenz(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `pitch` attribute. {0. -> 1.}
 
         """
+        pyoArgsAssert(self, "O", x)
         self._pitch = x
         x, lmax = convertArgsToLists(x)
         if self._stereo:
@@ -902,10 +1154,11 @@ class Lorenz(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `chaos` attribute. {0. -> 1.}
 
         """
+        pyoArgsAssert(self, "O", x)
         self._chaos = x
         x, lmax = convertArgsToLists(x)
         if self._stereo:
@@ -914,20 +1167,20 @@ class Lorenz(PyoObject):
             [obj.setChaos(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", "pitch", self._pitch), 
+        self._map_list = [SLMap(0., 1., "lin", "pitch", self._pitch),
                           SLMap(0., 1., "lin", "chaos", self._chaos), SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def pitch(self):
-        """float or PyoObject. Speed of the variations.""" 
+        """float or PyoObject. Speed of the variations."""
         return self._pitch
     @pitch.setter
     def pitch(self, x): self.setPitch(x)
 
     @property
     def chaos(self):
-        """float or PyoObject. Chaotic behavior.""" 
+        """float or PyoObject. Chaotic behavior."""
         return self._chaos
     @chaos.setter
     def chaos(self, x): self.setChaos(x)
@@ -940,12 +1193,13 @@ class LFO(PyoObject):
 
     :Args:
 
-        freq : float or PyoObject, optional
-            Oscillator frequency in cycles per second. Defaults to 100.
-        sharp : float or PyoObject, optional
+        freq: float or PyoObject, optional
+            Oscillator frequency in cycles per second. The frequency is
+            internally clamped between 0.00001 and sr/4. Defaults to 100.
+        sharp: float or PyoObject, optional
             Sharpness factor between 0 and 1. Sharper waveform results
             in more harmonics in the spectrum. Defaults to 0.5.
-        type : int, optional
+        type: int, optional
             Waveform type. eight possible values :
                 0. Saw up (default)
                 1. Saw down
@@ -965,12 +1219,14 @@ class LFO(PyoObject):
 
     """
     def __init__(self, freq=100, sharp=0.5, type=0, mul=1, add=0):
+        pyoArgsAssert(self, "OOiOO", freq, sharp, type, mul, add)
         PyoObject.__init__(self, mul, add)
         self._freq = freq
         self._sharp = sharp
         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):
         """
@@ -978,10 +1234,11 @@ class LFO(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `freq` attribute, in cycles per seconds.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -992,10 +1249,11 @@ class LFO(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `sharp` attribute, in the range 0 -> 1.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._sharp = x
         x, lmax = convertArgsToLists(x)
         [obj.setSharp(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1006,7 +1264,7 @@ class LFO(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 New `type` attribute. Choices are :
                     0. Saw up
                     1. Saw down
@@ -1016,13 +1274,13 @@ class LFO(PyoObject):
                     5. Bipolar pulse
                     6. Sample and hold
                     7. Modulated Sine
-            
+
 
         """
-        if x >= 0 and x < 8:
-            self._type = x
-            x, lmax = convertArgsToLists(x)
-            [obj.setType(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+        pyoArgsAssert(self, "i", x)
+        self._type = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setType(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     def reset(self):
         """
@@ -1031,28 +1289,30 @@ class LFO(PyoObject):
         """
         [obj.reset() for i, obj in enumerate(self._base_objs)]
 
-
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
-        self._map_list = [SLMapFreq(self._freq), SLMap(0., 1., "lin", "sharp", self._sharp), SLMapMul(self._mul)]
+        self._map_list = [SLMap(0.1, self.getSamplingRate()*0.25, "log", "freq", self._freq),
+                          SLMap(0., 1., "lin", "sharp", self._sharp),
+                          SLMap(0, 7, "lin", "type", self._type, "int", dataOnly=True),
+                          SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def freq(self):
-        """float or PyoObject. Oscillator frequency in cycles per second.""" 
+        """float or PyoObject. Oscillator frequency in cycles per second."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
     def sharp(self):
-        """float or PyoObject. Sharpness factor {0 -> 1}.""" 
+        """float or PyoObject. Sharpness factor {0 -> 1}."""
         return self._sharp
     @sharp.setter
     def sharp(self, x): self.setSharp(x)
 
     @property
     def type(self):
-        """int. Waveform type.""" 
+        """int. Waveform type."""
         return self._type
     @type.setter
     def type(self, x): self.setType(x)
@@ -1060,77 +1320,81 @@ class LFO(PyoObject):
 class SumOsc(PyoObject):
     """
     Discrete summation formulae to produce complex spectra.
-    
+
     This object implements a discrete summation formulae taken from
-    the paper 'The synthesis of complex audio spectra by means of 
+    the paper 'The synthesis of complex audio spectra by means of
     discrete summation formulae' by James A. Moorer. The formulae
     used is of this form:
-        
+
     (sin(theta) - a * sin(theta - beta)) / (1 + a**2 - 2 * a * cos(beta))
-       
-    where 'theta' and 'beta' are periodic functions and 'a' is 
-    the modulation index, providing control over the damping of 
+
+    where 'theta' and 'beta' are periodic functions and 'a' is
+    the modulation index, providing control over the damping of
     the partials.
-    
+
     The resulting sound is related to the family of modulation
     techniques but this formulae express 'one-sided' spectra,
     useful to avoid aliasing from the negative frequencies.
 
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
-    
-        freq : float or PyoObject, optional
+
+        freq: float or PyoObject, optional
             Base frequency in cycles per second. Defaults to 100.
-        ratio : float or PyoObject, optional
-            A factor used to stretch or compress the partial serie by 
-            manipulating the frequency of the modulation oscillator. 
+        ratio: float or PyoObject, optional
+            A factor used to stretch or compress the partial serie by
+            manipulating the frequency of the modulation oscillator.
             Integer ratios give harmonic spectra. Defaults to 0.5.
-        index : float or PyoObject, optional
-            Damping of successive partials, between 0 and 1. With a 
+        index: float or PyoObject, optional
+            Damping of successive partials, between 0 and 1. With a
             value of 0.5, each partial is 6dB lower than the previous
-            partial. Defaults to 5.
-        
+            partial. Defaults to 0.5.
+
     >>> s = Server().boot()
     >>> s.start()
     >>> ind = LinTable([(0,.3), (20,.85), (300,.7), (1000,.5), (8191,.3)])
     >>> m = Metro(4).play()
     >>> tr = TrigEnv(m, table=ind, dur=4)
     >>> f = SumOsc(freq=[301,300], ratio=[.2498,.2503], index=tr, mul=.2).out()
-    
+
     """
     def __init__(self, freq=100, ratio=0.5, index=0.5, mul=1, add=0):
+        pyoArgsAssert(self, "OOOOO", freq, ratio, index, mul, add)
         PyoObject.__init__(self, mul, add)
         self._freq = freq
         self._ratio = ratio
         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):
         """
         Replace the `freq` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `freq` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
-        
+
     def setRatio(self, x):
         """
         Replace the `ratio` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `ratio` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._ratio = x
         x, lmax = convertArgsToLists(x)
         [obj.setRatio(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1138,13 +1402,14 @@ class SumOsc(PyoObject):
     def setIndex(self, x):
         """
         Replace the `index` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `index` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._index = x
         x, lmax = convertArgsToLists(x)
         [obj.setIndex(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1155,24 +1420,24 @@ class SumOsc(PyoObject):
                           SLMap(0, 1, "lin", "index", self._index),
                           SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
-        
+
     @property
     def freq(self):
-        """float or PyoObject. Base frequency in cycles per second.""" 
+        """float or PyoObject. Base frequency in cycles per second."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
     def ratio(self):
-        """float or PyoObject. Base/modulator frequency ratio.""" 
+        """float or PyoObject. Base/modulator frequency ratio."""
         return self._ratio
     @ratio.setter
     def ratio(self, x): self.setRatio(x)
 
     @property
     def index(self):
-        """float or PyoObject. Index, high frequency damping.""" 
+        """float or PyoObject. Index, high frequency damping."""
         return self._index
     @index.setter
     def index(self, x): self.setIndex(x)
@@ -1180,70 +1445,74 @@ class SumOsc(PyoObject):
 class SuperSaw(PyoObject):
     """
     Roland JP-8000 Supersaw emulator.
-    
+
     This object implements an emulation of the Roland JP-8000 Supersaw algorithm.
-    The shape of the waveform is produced from 7 sawtooth oscillators detuned 
+    The shape of the waveform is produced from 7 sawtooth oscillators detuned
     against each other over a period of time. It allows control over the depth
     of the detuning and the balance between central and sideband oscillators.
- 
+
     :Parent: :py:class:`PyoObject`
-   
+
     :Args:
-    
-        freq : float or PyoObject, optional
+
+        freq: float or PyoObject, optional
             Frequency in cycles per second. Defaults to 100.
-        detune : float or PyoObject, optional
+        detune: float or PyoObject, optional
             Depth of the detuning, between 0 and 1. 0 means all oscillators are
             tuned to the same frequency and 1 means sideband oscillators are at
-            maximum detuning regarding the central frequency. Defaults to 0.5. 
-        bal : float or PyoObject, optional
-            Balance between central oscillator and sideband oscillators. A value 
+            maximum detuning regarding the central frequency. Defaults to 0.5.
+        bal: float or PyoObject, optional
+            Balance between central oscillator and sideband oscillators. A value
             of 0 outputs only the central oscillator while a value of 1 gives a
             mix of all oscillators with the central one lower than the sidebands.
             Defaults to 0.7.
 
-    .. seealso:: 
-        
+    .. seealso::
+
         :py:class:`Phasor`, :py:class:`SineLoop`
 
     >>> s = Server().boot()
     >>> s.start()
     >>> lfd = Sine([.4,.3], mul=.2, add=.5)
     >>> a = SuperSaw(freq=[49,50], detune=lfd, bal=0.7, mul=0.2).out()
-    
+
     """
     def __init__(self, freq=100, detune=0.5, bal=0.7, mul=1, add=0):
+        pyoArgsAssert(self, "OOOOO", freq, detune, bal, mul, add)
         PyoObject.__init__(self, mul, add)
         self._freq = freq
         self._detune = detune
         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):
         """
         Replace the `freq` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `freq` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
-        
+
     def setDetune(self, x):
         """
         Replace the `detune` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `detune` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._detune = x
         x, lmax = convertArgsToLists(x)
         [obj.setDetune(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1251,40 +1520,41 @@ class SuperSaw(PyoObject):
     def setBal(self, x):
         """
         Replace the `bal` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `bal` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._bal = x
         x, lmax = convertArgsToLists(x)
         [obj.setBal(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
-        self._map_list = [SLMapFreq(self._freq), 
-                          SLMap(0, 1, "lin", "detune", self._detune), 
+        self._map_list = [SLMapFreq(self._freq),
+                          SLMap(0, 1, "lin", "detune", self._detune),
                           SLMap(0, 1, "lin", "bal", self._bal), SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
-        
+
     @property
     def freq(self):
-        """float or PyoObject. Frequency in cycles per second.""" 
+        """float or PyoObject. Frequency in cycles per second."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
     def detune(self):
-        """float or PyoObject. Depth of the detuning.""" 
+        """float or PyoObject. Depth of the detuning."""
         return self._detune
     @detune.setter
     def detune(self, x): self.setDetune(x)
 
     @property
     def bal(self):
-        """float or PyoObject. Balance between central and sideband oscillators.""" 
+        """float or PyoObject. Balance between central and sideband oscillators."""
         return self._bal
     @bal.setter
     def bal(self, x): self.setBal(x)
@@ -1292,62 +1562,66 @@ class SuperSaw(PyoObject):
 class RCOsc(PyoObject):
     """
     Waveform aproximation of a RC circuit.
-    
+
     A RC circuit is a capacitor and a resistor in series, giving a logarithmic
     growth followed by an exponential decay.
- 
+
     :Parent: :py:class:`PyoObject`
-   
+
     :Args:
-    
-        freq : float or PyoObject, optional
+
+        freq: float or PyoObject, optional
             Frequency in cycles per second. Defaults to 100.
-        sharp : float or PyoObject, optional
+        sharp: float or PyoObject, optional
             Slope of the attack and decay of the waveform, between 0 and 1.
             A value of 0 gives a triangular waveform and 1 gives almost a
             square wave. Defaults to 0.25.
 
-    .. seealso:: 
-        
+    .. seealso::
+
         :py:class:`Osc`, :py:class:`LFO`, :py:class:`SineLoop`, :py:class:`SumOsc`
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> fr = RCOsc(freq=[.48,.5], sharp=.2, mul=300, add=600)
     >>> a = RCOsc(freq=fr, sharp=.1, mul=.2).out()
-    
+
     """
     def __init__(self, freq=100, sharp=0.25, mul=1, add=0):
+        pyoArgsAssert(self, "OOOO", freq, sharp, mul, add)
         PyoObject.__init__(self, mul, add)
         self._freq = freq
         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):
         """
         Replace the `freq` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `freq` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
-        
+
     def setSharp(self, x):
         """
         Replace the `sharp` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `sharp` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._sharp = x
         x, lmax = convertArgsToLists(x)
         [obj.setSharp(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1362,17 +1636,17 @@ class RCOsc(PyoObject):
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMapFreq(self._freq), SLMap(0,1,"lin","sharp",self._sharp), SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
-        
+
     @property
     def freq(self):
-        """float or PyoObject. Frequency in cycles per second.""" 
+        """float or PyoObject. Frequency in cycles per second."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
     def sharp(self):
-        """float or PyoObject. Sharpness of the waveform.""" 
+        """float or PyoObject. Sharpness of the waveform."""
         return self._sharp
     @sharp.setter
     def sharp(self, x): self.setSharp(x)
diff --git a/pyolib/listener.py b/pyolib/listener.py
new file mode 100644
index 0000000..5a1a09d
--- /dev/null
+++ b/pyolib/listener.py
@@ -0,0 +1,293 @@
+from __future__ import absolute_import
+from ._core import *
+import time
+import threading
+
+class MidiListener(threading.Thread):
+    """
+    Self-contained midi listener thread.
+
+    This object allows to setup a Midi server that is independent
+    of the audio server (mainly to be able to receive 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.
+
+    :Parent: threading.Thread
+
+    :Args:
+
+        function: Python function (can't be a list)
+            Function that will be called when a new midi event is available.
+            This function is called with the incoming midi data as
+            arguments. The signature of the function must be:
+
+            def myfunc(status, data1, data2)
+
+        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. 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::
+
+        This object is available only if pyo is built with portmidi support
+        (see withPortmidi function).
+
+    >>> s = Server()
+    >>> s.deactivateMidi()
+    >>> s.boot()
+    >>> def midicall(status, data1, data2):
+    ...     print(status, data1, data2)
+    >>> listen = MidiListener(midicall, 5)
+    >>> listen.start()
+
+    """
+    def __init__(self, function, mididev=-1, reportdevice=False):
+        threading.Thread.__init__(self)
+        self.daemon = True
+        self._function = WeakMethod(function)
+        self._mididev = mididev
+        if type(mididev) is not list:
+            mididev = [mididev]
+        self._reportdevice = reportdevice
+        self._listener = MidiListener_base(self._function, mididev, self._reportdevice)
+
+    def run(self):
+        """
+        Starts the process. The thread runs as daemon, so no need to stop it.
+
+        """
+        self._listener.play()
+        while True:
+            try:
+                time.sleep(0.001)
+            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.
+
+    Use the `sendx` method to send sysex 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()
+    >>> s.deactivateMidi()
+    >>> s.boot()
+    >>> 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 sendx(self, msg, timestamp=0, device=-1):
+        """
+        Send a MIDI system exclusive message to the selected midi output device.
+
+        Arguments can be list of values to generate multiple events
+        in one call.
+
+        :Args:
+
+            msg: str
+                A valid system exclusive message as a string. The first byte
+                must be 0xf0 and the last one must be 0xf7.
+            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.
+
+        """
+        msg, timestamp, device, lmax = convertArgsToLists(msg, timestamp, device)
+        [self._dispatcher.sendx(wrap(msg,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):
+    """
+    Self-contained OSC listener thread.
+
+    This object allows to setup an OSC server that is independent
+    of the audio server (mainly to be able to receive OSC data even
+    when the audio server is stopped).
+
+    :Parent: threadind.Thread
+
+    :Args:
+
+        function: Python function (can't be a list)
+            Function that will be called when a new OSC event is available.
+            This function is called with the incoming address and values as
+            arguments. The signature of the function must be:
+
+            def myfunc(address, *args)
+
+        port: int, optional
+            The OSC port on which the values are received. Defaults to 9000.
+
+    >>> s = Server().boot()
+    >>> def call(address, *args):
+    ...     print(address, args)
+    >>> listen = OscListener(call, 9901)
+    >>> listen.start()
+
+    """
+    def __init__(self, function, port=9000):
+        threading.Thread.__init__(self)
+        self.daemon = True
+        self._function = WeakMethod(function)
+        self._port = port
+        self._listener = OscListener_base(self._oscrecv, self._port)
+
+    def _oscrecv(self, address, *args):
+        with OscListenerLock:
+            self._function(address, *args)
+
+    def run(self):
+        """
+        Starts the process. The thread runs as daemon, so no need to stop it.
+
+        """
+        while True:
+            self._listener.get()
+            try:
+                time.sleep(0.001)
+            except:
+                pass
diff --git a/pyolib/matrix.py b/pyolib/matrix.py
index 1fea8c5..bdcda56 100644
--- a/pyolib/matrix.py
+++ b/pyolib/matrix.py
@@ -1,25 +1,25 @@
+from __future__ import absolute_import
 """
-Copyright 2010 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+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/>.
 """
-from _core import *
-from _maps import *
+from ._core import *
+from ._maps import *
 
 ######################################################################
 ### Matrix
@@ -28,7 +28,7 @@ class NewMatrix(PyoMatrixObject):
     """
     Create a new matrix ready for recording.
 
-    Optionally, the matrix can be filled with the contents of the 
+    Optionally, the matrix can be filled with the contents of the
     `init` parameter.
 
     See :py:class:`MatrixRec` to write samples in the matrix.
@@ -37,15 +37,15 @@ class NewMatrix(PyoMatrixObject):
 
     :Args:
 
-        width : int
+        width: int
             Desired matrix width in samples.
-        height : int
+        height: int
             Desired matrix height in samples.
-        init : list of list of floats, optional
+        init: list of list of floats, optional
             Initial matrix. Defaults to None.
 
-    .. seealso:: 
-        
+    .. seealso::
+
         :py:class:`MatrixRec`
 
     >>> s = Server().boot()
@@ -61,31 +61,33 @@ class NewMatrix(PyoMatrixObject):
 
     """
     def __init__(self, width, height, init=None):
+        pyoArgsAssert(self, "IIL", width, height, init)
         PyoMatrixObject.__init__(self)
         self._size = (width, height)
-        if init == None:
+        if init is None:
             self._base_objs = [NewMatrix_base(width, height)]
         else:
             self._base_objs = [NewMatrix_base(width, height, init)]
-            
+
     def replace(self, x):
         """
         Replaces the actual matrix.
-        
+
         :Args:
-        
-            x : list of list of floats
+
+            x: list of list of floats
                 New matrix. Must be of the same size as the actual matrix.
 
         """
+        pyoArgsAssert(self, "l", x)
         [obj.setMatrix(x) for obj in self._base_objs]
         self.refreshView()
 
     def getRate(self):
         """
-        Returns the frequency (cycle per second) to give to an 
+        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()
 
@@ -95,13 +97,14 @@ class NewMatrix(PyoMatrixObject):
 
         :Args:
 
-            freq : float
+            freq: float
                 Frequency of sinusoids used to created the terrain.
                 Defaults to 1.
-            phase : float
+            phase: float
                 Phase deviation between rows of the terrain. Should be in
                 the range 0 -> 1. Defaults to 0.0625.
 
         """
+        pyoArgsAssert(self, "NN", freq, phase)
         [obj.genSineTerrain(freq, phase) for obj in self._base_objs]
         self.refreshView()
diff --git a/pyolib/matrixprocess.py b/pyolib/matrixprocess.py
index 3fa4037..0c02422 100644
--- a/pyolib/matrixprocess.py
+++ b/pyolib/matrixprocess.py
@@ -7,28 +7,28 @@ are done by giving row and column positions.
 
 """
 
+from __future__ import absolute_import
 """
-Copyright 2010 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+You should have received a copy of the GNU Lesser General Public
+License along with pyo.  If not, see <http://www.gnu.org/licenses/>.
 """
-from _core import *
-from _maps import *
-from types import SliceType
+from ._core import *
+from ._maps import *
 
 class MatrixRec(PyoObject):
     """
@@ -37,24 +37,24 @@ class MatrixRec(PyoObject):
     See :py:class:`NewMatrix` to create an empty matrix.
 
     The play method is not called at the object creation time. It starts
-    the recording into the matrix, row after row, until the matrix is full. 
-    Calling the play method again restarts the recording and overwrites 
-    previously recorded samples. The stop method stops the recording. 
+    the recording into the matrix, row after row, until the matrix is full.
+    Calling the play method again restarts the recording and overwrites
+    previously recorded samples. The stop method stops the recording.
     Otherwise, the default behaviour is to record through the end of the matrix.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Audio signal to write in the matrix.
-        matrix : PyoMatrixObject
+        matrix: PyoMatrixObject
             The matrix where to write samples.
-        fadetime : float, optional
-            Fade time at the beginning and the end of the recording 
+        fadetime: float, optional
+            Fade time at the beginning and the end of the recording
             in seconds. Defaults to 0.
-        delay : int, optional
-            Delay time, in samples, before the recording begins. 
+        delay: int, optional
+            Delay time, in samples, before the recording begins.
             Available at initialization time only. Defaults to 0.
 
     .. note::
@@ -63,12 +63,12 @@ class MatrixRec(PyoObject):
 
         MatrixRec has no `mul` and `add` attributes.
 
-        MatrixRec will sends a trigger signal at the end of the recording. 
+        MatrixRec will send a trigger signal at the end of the recording.
         User can retreive the trigger streams by calling obj['trig']. See
         `TableRec` documentation for an example.
 
-    .. seealso:: 
-        
+    .. seealso::
+
         :py:class:`NewMatrix`
 
     >>> s = Server().boot()
@@ -87,6 +87,7 @@ class MatrixRec(PyoObject):
 
     """
     def __init__(self, input, matrix, fadetime=0, delay=0):
+        pyoArgsAssert(self, "omni", input, matrix, fadetime, delay)
         PyoObject.__init__(self)
         self._input = input
         self._matrix = matrix
@@ -100,42 +101,44 @@ class MatrixRec(PyoObject):
 
     def setMul(self, x):
         pass
-        
+
     def setAdd(self, x):
-        pass    
+        pass
 
     def setInput(self, x, fadetime=0.05):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setMatrix(self, x):
         """
         Replace the `matrix` attribute.
-        
+
         :Args:
 
-            x : NewMatrix
+            x: NewMatrix
                 new `matrix` attribute.
-        
+
         """
+        pyoArgsAssert(self, "m", x)
         self._matrix = x
         x, lmax = convertArgsToLists(x)
         [obj.setMatrix(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     @property
     def input(self):
-        """PyoObject. Audio signal to record in the matrix.""" 
+        """PyoObject. Audio signal to record in the matrix."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -153,16 +156,16 @@ class MatrixRecLoop(PyoObject):
 
     See :py:class:`NewMatrix` to create an empty matrix.
 
-    MatrixRecLoop records samples into the matrix, row after row, until 
-    the matrix is full and then loop back to the beginning. 
+    MatrixRecLoop records samples into the matrix, row after row, until
+    the matrix is full and then loop back to the beginning.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Audio signal to write in the matrix.
-        matrix : PyoMatrixObject
+        matrix: PyoMatrixObject
             The matrix where to write samples.
 
     .. note::
@@ -171,12 +174,12 @@ class MatrixRecLoop(PyoObject):
 
         MatrixRecLoop has no `mul` and `add` attributes.
 
-        MatrixRecLoop will sends a trigger signal when reaching the end 
-        of the matrix. User can retreive the trigger streams by calling 
+        MatrixRecLoop will send a trigger signal when reaching the end
+        of the matrix. User can retreive the trigger streams by calling
         obj['trig']. See `TableRec` documentation for an example.
 
-    .. seealso:: 
-        
+    .. seealso::
+
         :py:class:`NewMatrix`
 
     >>> s = Server().boot()
@@ -194,6 +197,7 @@ class MatrixRecLoop(PyoObject):
 
     """
     def __init__(self, input, matrix):
+        pyoArgsAssert(self, "om", input, matrix)
         PyoObject.__init__(self)
         self._input = input
         self._matrix = matrix
@@ -201,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)
@@ -209,7 +214,7 @@ class MatrixRecLoop(PyoObject):
         pass
 
     def setAdd(self, x):
-        pass    
+        pass
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -217,12 +222,13 @@ class MatrixRecLoop(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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)
 
@@ -232,17 +238,18 @@ class MatrixRecLoop(PyoObject):
 
         :Args:
 
-            x : NewMatrix
+            x: NewMatrix
                 new `matrix` attribute.
 
         """
+        pyoArgsAssert(self, "m", x)
         self._matrix = x
         x, lmax = convertArgsToLists(x)
         [obj.setMatrix(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     @property
     def input(self):
-        """PyoObject. Audio signal to record in the matrix.""" 
+        """PyoObject. Audio signal to record in the matrix."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -262,11 +269,11 @@ class MatrixPointer(PyoObject):
 
     :Args:
 
-        matrix : PyoMatrixObject
+        matrix: PyoMatrixObject
             Matrix containing the waveform samples.
-        x : PyoObject
+        x: PyoObject
             Normalized X position in the matrix between 0 and 1.
-        y : PyoObject
+        y: PyoObject
             Normalized Y position in the matrix between 0 and 1.
 
     >>> s = Server().boot()
@@ -285,23 +292,26 @@ class MatrixPointer(PyoObject):
 
     """
     def __init__(self, matrix, x, y, mul=1, add=0):
+        pyoArgsAssert(self, "mooOO", matrix, x, y, mul, add)
         PyoObject.__init__(self, mul, add)
         self._matrix = matrix
         self._x = x
         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):
         """
         Replace the `matrix` attribute.
-        
+
         :Args:
 
-            x : PyoTableObject
+            x: PyoTableObject
                 new `matrix` attribute.
-        
+
         """
+        pyoArgsAssert(self, "m", x)
         self._matrix = x
         x, lmax = convertArgsToLists(x)
         [obj.setMatrix(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -309,13 +319,14 @@ class MatrixPointer(PyoObject):
     def setX(self, x):
         """
         Replace the `x` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 new `x` attribute.
-        
+
         """
+        pyoArgsAssert(self, "o", x)
         self._x = x
         x, lmax = convertArgsToLists(x)
         [obj.setX(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -323,13 +334,14 @@ class MatrixPointer(PyoObject):
     def setY(self, x):
         """
         Replace the `y` attribute.
-        
+
         :Args:
 
-            y : PyoObject
+            y: PyoObject
                 new `y` attribute.
-        
+
         """
+        pyoArgsAssert(self, "o", x)
         self._y = x
         x, lmax = convertArgsToLists(x)
         [obj.setY(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -340,21 +352,21 @@ class MatrixPointer(PyoObject):
 
     @property
     def matrix(self):
-        """PyoMatrixObject. Matrix containing the samples.""" 
+        """PyoMatrixObject. Matrix containing the samples."""
         return self._matrix
     @matrix.setter
     def matrix(self, x): self.setMatrix(x)
 
     @property
     def x(self):
-        """PyoObject. Normalized X position in the matrix.""" 
+        """PyoObject. Normalized X position in the matrix."""
         return self._x
     @x.setter
     def x(self, x): self.setX(x)
 
     @property
     def y(self):
-        """PyoObject. Normalized Y position in the matrix.""" 
+        """PyoObject. Normalized Y position in the matrix."""
         return self._y
     @y.setter
     def y(self, x): self.setY(x)
@@ -363,21 +375,21 @@ class MatrixMorph(PyoObject):
     """
     Morphs between multiple PyoMatrixObjects.
 
-    Uses an index into a list of PyoMatrixObjects to morph between adjacent 
-    matrices in the list. The resulting morphed function is written into the 
-    `matrix` object at the beginning of each buffer size. The matrices in the 
+    Uses an index into a list of PyoMatrixObjects to morph between adjacent
+    matrices in the list. The resulting morphed function is written into the
+    `matrix` object at the beginning of each buffer size. The matrices in the
     list and the resulting matrix must be equal in size.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
-            Morphing index between 0 and 1. 0 is the first matrix in the list 
+        input: PyoObject
+            Morphing index between 0 and 1. 0 is the first matrix in the list
             and 1 is the last.
-        matrix : NewMatrix
+        matrix: NewMatrix
             The matrix where to write morphed function.
-        sources : list of PyoMatrixObject
+        sources: list of PyoMatrixObject
             List of matrices to interpolate from.
 
     .. note::
@@ -401,6 +413,7 @@ class MatrixMorph(PyoObject):
 
     """
     def __init__(self, input, matrix, sources):
+        pyoArgsAssert(self, "oml", input, matrix, sources)
         PyoObject.__init__(self)
         self._input = input
         self._matrix = matrix
@@ -409,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)
@@ -417,7 +431,7 @@ class MatrixMorph(PyoObject):
         pass
 
     def setAdd(self, x):
-        pass    
+        pass
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -425,12 +439,13 @@ class MatrixMorph(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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)
 
@@ -440,10 +455,11 @@ class MatrixMorph(PyoObject):
 
         :Args:
 
-            x : NewMatrix
+            x: NewMatrix
                 new `matrix` attribute.
 
         """
+        pyoArgsAssert(self, "m", x)
         self._matrix = x
         x, lmax = convertArgsToLists(x)
         [obj.setMatrix(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -454,17 +470,18 @@ class MatrixMorph(PyoObject):
 
         :Args:
 
-            x : list of PyoMatrixObject
+            x: list of PyoMatrixObject
                 new `sources` attribute.
 
         """
+        pyoArgsAssert(self, "l", x)
         self._sources = x
         self._base_sources = [source[0] for source in x]
         [obj.setSources(self._base_sources) for i, obj in enumerate(self._base_objs)]
 
     @property
     def input(self):
-        """PyoObject. Morphing index between 0 and 1.""" 
+        """PyoObject. Morphing index between 0 and 1."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
diff --git a/pyolib/midi.py b/pyolib/midi.py
index e305ba4..b39b8a9 100644
--- a/pyolib/midi.py
+++ b/pyolib/midi.py
@@ -8,59 +8,60 @@ used as controls and can't be sent to the output soundcard.
 
 """
 
+from __future__ import absolute_import
 """
-Copyright 2010 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+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 sys
-from _core import *
-from _maps import *
+from ._core import *
+from ._maps import *
 
 ######################################################################
 ### MIDI
-######################################################################                                       
+######################################################################
 class Midictl(PyoObject):
     """
     Get the current value of a Midi controller.
-    
-    Get the current value of a controller and optionally map it 
+
+    Get the current value of a controller and optionally map it
     inside a specified range.
 
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
-    
-        ctlnumber : int
+
+        ctlnumber: int
             Controller number.
-        minscale : float, optional
+        minscale: float, optional
             Low range value for mapping. Defaults to 0.
-        maxscale : float, optional
+        maxscale: float, optional
             High range value for mapping. Defaults to 1.
-        init : float, optional
+        init: float, optional
             Initial value. Defaults to 0.
-        channel : int, optional
+        channel: int, optional
             Midi channel. 0 means all channels. Defaults to 0.
 
     .. note::
 
-        The out() method is bypassed. Midictl's signal can not be sent 
+        The out() method is bypassed. Midictl's signal can not be sent
         to audio outs.
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> m = Midictl(ctlnumber=[107,102], minscale=250, maxscale=1000)
@@ -68,9 +69,10 @@ class Midictl(PyoObject):
     >>> a = Sine(freq=p, mul=.3).out()
     >>> a1 = Sine(freq=p*1.25, mul=.3).out()
     >>> a2 = Sine(freq=p*1.5, mul=.3).out()
-        
+
     """
     def __init__(self, ctlnumber, minscale=0, maxscale=1, init=0, channel=0, mul=1, add=0):
+        pyoArgsAssert(self, "innniOO", ctlnumber, minscale, maxscale, init, channel, mul, add)
         PyoObject.__init__(self, mul, add)
         self._ctlnumber = ctlnumber
         self._minscale = minscale
@@ -78,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)
@@ -88,10 +91,11 @@ class Midictl(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 new `ctlnumber` attribute.
 
         """
+        pyoArgsAssert(self, "i", x)
         self._ctlnumber = x
         x, lmax = convertArgsToLists(x)
         [obj.setCtlNumber(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -102,10 +106,11 @@ class Midictl(PyoObject):
 
         :Args:
 
-            x : int
+            x: float
                 new `minscale` attribute.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._minscale = x
         x, lmax = convertArgsToLists(x)
         [obj.setMinScale(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -116,10 +121,11 @@ class Midictl(PyoObject):
 
         :Args:
 
-            x : int
+            x: float
                 new `maxscale` attribute.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._maxscale = x
         x, lmax = convertArgsToLists(x)
         [obj.setMaxScale(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -130,10 +136,11 @@ class Midictl(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 new `channel` attribute.
 
         """
+        pyoArgsAssert(self, "i", x)
         self._channel = x
         x, lmax = convertArgsToLists(x)
         [obj.setChannel(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -144,84 +151,87 @@ class Midictl(PyoObject):
 
         :Args:
 
-            x : float
+            x: float
                 new current value.
 
         """
+        pyoArgsAssert(self, "n", x)
         x, lmax = convertArgsToLists(x)
         [obj.setValue(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     def setInterpolation(self, x):
         """
-        Activate/Deactivate interpolation. Activated by default.
-
-        :Args:
-
-            x : boolean
-                True activates the interpolation, False deactivates it.
+        Deprecated method. If needed, use Port or SigTo to interpolate between values.
 
         """
-        x, lmax = convertArgsToLists(x)
-        [obj.setInterpolation(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+        print("setInterpolation() is deprecated. If needed, use Port or SigTo to interpolate between values.")
+
+    def ctrl(self, map_list=None, title=None, wxnoserver=False):
+        self._map_list = [SLMap(0, 127, 'lin', 'ctlnumber', self._ctlnumber, res="int", dataOnly=True),
+                         SLMap(-1.0, 0.0, 'lin', 'minscale', self._minscale, dataOnly=True),
+                         SLMap(0.0, 1.0, 'lin', 'maxscale', self._maxscale, dataOnly=True),
+                         SLMap(0, 16, 'lin', 'channel', self._channel, res="int", dataOnly=True)
+                         ]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
-    def ctlnumber(self): 
+    def ctlnumber(self):
         """int. Controller number."""
         return self._ctlnumber
     @ctlnumber.setter
-    def ctlnumber(self, x): 
-        self.setCtlNumber(x)   
+    def ctlnumber(self, x):
+        self.setCtlNumber(x)
 
     @property
-    def minscale(self): 
+    def minscale(self):
         """float. Minimum value for scaling."""
         return self._minscale
     @minscale.setter
-    def minscale(self, x): 
-        self.setMinScale(x)   
+    def minscale(self, x):
+        self.setMinScale(x)
 
     @property
-    def maxscale(self): 
+    def maxscale(self):
         """float. Maximum value for scaling."""
         return self._maxscale
     @maxscale.setter
-    def maxscale(self, x): 
-        self.setMaxScale(x)   
+    def maxscale(self, x):
+        self.setMaxScale(x)
 
     @property
-    def channel(self): 
+    def channel(self):
         """int. Midi channel. 0 means all channels."""
         return self._channel
     @channel.setter
-    def channel(self, x): 
-        self.setChannel(x)   
+    def channel(self, x):
+        self.setChannel(x)
 
 class CtlScan(PyoObject):
     """
     Scan the Midi controller's number in input.
-    
+
     Scan the Midi controller's number in input and send it to
     a standard python `function`. Useful to implement a MidiLearn
     algorithm.
 
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
-    
-        function : Python function
+
+        function: Python function (can't be a list)
             Function to be called. The function must be declared
-            with an argument for the controller number in input. Ex.: 
-                
+            with an argument for the controller number in input. Ex.:
+
             def ctl_scan(ctlnum):
-                print ctlnum
-                    
-        toprint : boolean, optional
-            If True, controller number and value will be print to 
+                print(ctlnum)
+
+        toprint: boolean, optional
+            If True, controller number and value will be printed to
             the console.
 
     .. note::
 
-        The out() method is bypassed. CtlScan's signal can not be sent 
+        The out() method is bypassed. CtlScan's signal can not be sent
         to audio outs.
 
     >>> s = Server()
@@ -229,18 +239,17 @@ class CtlScan(PyoObject):
     >>> s.boot()
     >>> s.start()
     >>> def ctl_scan(ctlnum):
-    ...     print ctlnum
+    ...     print(ctlnum)
     >>> a = CtlScan(ctl_scan)
-        
+
     """
     def __init__(self, function, toprint=True):
+        pyoArgsAssert(self, "CB", function, toprint)
         PyoObject.__init__(self)
-        if not callable(function):
-            print >> sys.stderr, 'TypeError: "function" argument of %s must be callable.\n' % self.__class__.__name__
-            exit()
-        self._function = function
+        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)
@@ -257,19 +266,26 @@ class CtlScan(PyoObject):
     def setDiv(self, x):
         pass
 
+    def reset(self):
+        """
+        Resets the scanner.
+
+        """
+        [obj.reset() for obj in self._base_objs]
+
     def setFunction(self, x):
         """
         Replace the `function` attribute.
 
         :Args:
 
-            x : Python function
+            x: Python function
                 new `function` attribute.
 
         """
-        self._function = x
-        x, lmax = convertArgsToLists(x)
-        [obj.setFunction(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+        pyoArgsAssert(self, "C", x)
+        self._function = WeakMethod(x)
+        [obj.setFunction(self._function) for i, obj in enumerate(self._base_objs)]
 
     def setToprint(self, x):
         """
@@ -277,56 +293,57 @@ class CtlScan(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 new `toprint` attribute.
 
         """
+        pyoArgsAssert(self, "b", x)
         self._toprint = x
         x, lmax = convertArgsToLists(x)
         [obj.setToprint(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     @property
-    def function(self): 
+    def function(self):
         """Python function. Function to be called."""
         return self._function
     @function.setter
-    def function(self, x): 
-        self.setFunction(x)   
+    def function(self, x):
+        self.setFunction(x)
     @property
-    def toprint(self): 
-        """boolean. If True, print values to the console."""
+    def toprint(self):
+        """boolean. If True, prints values to the console."""
         return self._toprint
     @toprint.setter
-    def toprint(self, x): 
-        self.setToprint(x)   
+    def toprint(self, x):
+        self.setToprint(x)
 
 class CtlScan2(PyoObject):
     """
     Scan the Midi channel and controller number in input.
 
-    Scan the Midi channel and controller number in input and send them 
-    to a standard python `function`. Useful to implement a MidiLearn 
+    Scan the Midi channel and controller number in input and send them
+    to a standard python `function`. Useful to implement a MidiLearn
     algorithm.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        function : Python function
+        function: Python function (can't be a list)
             Function to be called. The function must be declared
-            with two arguments, one for the controller number and 
-            one for the midi channel. Ex.: 
+            with two arguments, one for the controller number and
+            one for the midi channel. Ex.:
 
             def ctl_scan(ctlnum, midichnl):
-                print ctlnum, midichnl
+                print(ctlnum, midichnl)
 
-        toprint : boolean, optional
-            If True, controller number and value will be print to 
+        toprint: boolean, optional
+            If True, controller number and value will be printed to
             the console.
 
     .. note::
 
-        The out() method is bypassed. CtlScan2's signal can not be sent 
+        The out() method is bypassed. CtlScan2's signal can not be sent
         to audio outs.
 
     >>> s = Server()
@@ -334,18 +351,17 @@ class CtlScan2(PyoObject):
     >>> s.boot()
     >>> s.start()
     >>> def ctl_scan(ctlnum, midichnl):
-    ...     print ctlnum, midichnl
+    ...     print(ctlnum, midichnl)
     >>> a = CtlScan2(ctl_scan)
 
     """
     def __init__(self, function, toprint=True):
+        pyoArgsAssert(self, "CB", function, toprint)
         PyoObject.__init__(self)
-        if not callable(function):
-            print >> sys.stderr, 'TypeError: "function" argument of %s must be callable.\n' % self.__class__.__name__
-            exit()
-        self._function = function
+        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)
@@ -362,19 +378,26 @@ class CtlScan2(PyoObject):
     def setDiv(self, x):
         pass
 
+    def reset(self):
+        """
+        Resets the scanner.
+
+        """
+        [obj.reset() for obj in self._base_objs]
+
     def setFunction(self, x):
         """
         Replace the `function` attribute.
 
         :Args:
 
-            x : Python function
+            x: Python function
                 new `function` attribute.
 
         """
-        self._function = x
-        x, lmax = convertArgsToLists(x)
-        [obj.setFunction(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+        pyoArgsAssert(self, "C", x)
+        self._function = WeakMethod(x)
+        [obj.setFunction(self._function) for i, obj in enumerate(self._base_objs)]
 
     def setToprint(self, x):
         """
@@ -382,74 +405,81 @@ class CtlScan2(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 new `toprint` attribute.
 
         """
+        pyoArgsAssert(self, "b", x)
         self._toprint = x
         x, lmax = convertArgsToLists(x)
         [obj.setToprint(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     @property
-    def function(self): 
+    def function(self):
         """Python function. Function to be called."""
         return self._function
     @function.setter
-    def function(self, x): 
-        self.setFunction(x)   
+    def function(self, x):
+        self.setFunction(x)
     @property
-    def toprint(self): 
-        """boolean. If True, print values to the console."""
+    def toprint(self):
+        """boolean. If True, prints values to the console."""
         return self._toprint
     @toprint.setter
-    def toprint(self, x): 
-        self.setToprint(x)   
+    def toprint(self, x):
+        self.setToprint(x)
 
 class Notein(PyoObject):
     """
     Generates Midi note messages.
-    
-    From a Midi device, takes the notes in the range defined with 
-    `first` and `last` parameters, and outputs up to `poly` 
-    noteon - noteoff streams in the `scale` format (Midi, hertz 
+
+    From a Midi device, takes the notes in the range defined with
+    `first` and `last` parameters, and outputs up to `poly`
+    noteon - noteoff streams in the `scale` format (Midi, hertz
     or transpo).
-    
+
     :Parent: :py:class:`PyoObject`
 
     :Args:
-    
-        poly : int, optional
+
+        poly: int, optional
             Number of streams of polyphony generated. Defaults to 10.
-        scale : int, optional
-            Pitch output format. 
+        scale: int, optional
+            Pitch output format.
                 0. Midi
                 1. Hertz
-                2. transpo 
+                2. transpo
+
+            In the transpo mode, the default central key (the key where
+            there is no transposition) is (`first` + `last`) / 2.
 
-            In the transpo mode, the default central key (the key where 
-            there is no transposition) is (`first` + `last`) / 2. 
-            
             The central key can be changed with the setCentralKey method.
-        first : int, optional
+        first: int, optional
             Lowest Midi value. Defaults to 0.
-        last : int, optional
+        last: int, optional
             Highest Midi value. Defaults to 127.
-        channel : int, optional
+        channel: int, optional
             Midi channel. 0 means all channels. Defaults to 0.
 
     .. note::
-    
-        Pitch and velocity are two separated set of streams. 
+
+        Pitch and velocity are two separated set of streams.
         The user should call :
-        
-        Notein['pitch'] to retrieve pitch streams.
-        Notein['velocity'] to retrieve velocity streams.    
+
+        |  Notein['pitch'] to retrieve pitch streams.
+        |  Notein['velocity'] to retrieve velocity streams.
 
         Velocity is automatically scaled between 0 and 1.
-        
-        The out() method is bypassed. Notein's signal can not be sent 
+
+        Notein also outputs trigger streams on noteon and noteoff.
+        These streams can be retrieved with :
+
+        |  Notein['trigon'] to retrieve noteon trigger streams.
+        |  Notein['trigoff'] to retrieve noteoff trigger streams.
+
+        The out() method is bypassed. Notein's signal can not be sent
         to audio outs.
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> notes = Notein(poly=10, scale=1, mul=.5)
@@ -457,12 +487,15 @@ class Notein(PyoObject):
     >>> b = Sine(freq=notes['pitch'], mul=p).out()
     >>> c = Sine(freq=notes['pitch'] * 0.997, mul=p).out()
     >>> d = Sine(freq=notes['pitch'] * 1.005, mul=p).out()
-    
+
     """
     def __init__(self, poly=10, scale=0, first=0, last=127, channel=0, mul=1, add=0):
+        pyoArgsAssert(self, "IIIIIOO", poly, scale, first, last, channel, mul, add)
         PyoObject.__init__(self, mul, add)
         self._pitch_dummy = []
         self._velocity_dummy = []
+        self._trigon_dummy = []
+        self._trigoff_dummy = []
         self._poly = poly
         self._scale = scale
         self._first = first
@@ -471,17 +504,69 @@ class Notein(PyoObject):
         mul, add, lmax = convertArgsToLists(mul, add)
         self._base_handler = MidiNote_base(self._poly, self._scale, self._first, self._last, self._channel)
         self._base_objs = []
+        self._trig_objs = []
         for i in range(lmax * poly):
             self._base_objs.append(Notein_base(self._base_handler, i, 0, 1, 0))
             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':
             self._pitch_dummy.append(Dummy([self._base_objs[i*2] for i in range(self._poly)]))
             return self._pitch_dummy[-1]
-        if str == 'velocity':
+        elif str == 'velocity':
             self._velocity_dummy.append(Dummy([self._base_objs[i*2+1] for i in range(self._poly)]))
             return self._velocity_dummy[-1]
+        elif str == 'trigon':
+            self._trigon_dummy.append(Dummy([self._trig_objs[i*2] for i in range(self._poly)]))
+            return self._trigon_dummy[-1]
+        elif str == 'trigoff':
+            self._trigoff_dummy.append(Dummy([self._trig_objs[i*2+1] for i in range(self._poly)]))
+            return self._trigoff_dummy[-1]
+
+    def setScale(self, x):
+        """
+        Replace the `scale` attribute.
+
+        :Args:
+
+            x: int
+                new `scale` attribute. 0 = midi, 1 = hertz, 2 = transpo.
+
+        """
+        pyoArgsAssert(self, "I", x)
+        self._scale = x
+        self._base_handler.setScale(x)
+
+    def setFirst(self, x):
+        """
+        Replace the `first` attribute.
+
+        :Args:
+
+            x: int
+                new `first` attribute, between 0 and 127.
+
+        """
+        pyoArgsAssert(self, "I", x)
+        self._first = x
+        self._base_handler.setFirst(x)
+
+    def setLast(self, x):
+        """
+        Replace the `last` attribute.
+
+        :Args:
+
+            x: int
+                new `last` attribute, between 0 and 127.
+
+        """
+        pyoArgsAssert(self, "I", x)
+        self._last = x
+        self._base_handler.setLast(x)
 
     def setChannel(self, x):
         """
@@ -489,71 +574,74 @@ class Notein(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 new `channel` attribute.
 
         """
+        pyoArgsAssert(self, "I", x)
         self._channel = x
         self._base_handler.setChannel(x)
 
     def setCentralKey(self, x):
         """
         Set the midi key where there is no transposition.
-        
+
         Used for transpo conversion. This value must be greater than or
         equal to `first` and lower than or equal to `last`.
 
         :Args:
 
-            x : int
+            x: int
                 new centralkey value.
 
         """
+        pyoArgsAssert(self, "I", x)
         self._base_handler.setCentralKey(x)
 
     def setStealing(self, x):
         """
         Activates the stealing mode if True. Defaults to False.
-        
+
         In stealing mode, a new note will overwrite the oldest one
         according to the polyphony. In non-stealing mode, if the
         polyphony is already full, the new notes will be ignored.
 
         :Args:
 
-            x : boolean
+            x: boolean
                 True for stealing mode, False for non-stealing.
 
         """
+        pyoArgsAssert(self, "B", x)
         self._base_handler.setStealing(x)
 
     def get(self, identifier="pitch", all=False):
         """
         Return the first sample of the current buffer as a float.
-        
+
         Can be used to convert audio stream to usable Python data.
-        
+
         "pitch" or "velocity" must be given to `identifier` to specify
         which stream to get value from.
-        
+
         :Args:
 
-            identifier : string {"pitch", "velocity"}
+            identifier: string {"pitch", "velocity"}
                 Address string parameter identifying audio stream.
                 Defaults to "pitch".
-            all : boolean, optional
+            all: boolean, optional
                 If True, the first value of each object's stream
-                will be returned as a list. 
-                
-                Otherwise, only the value of the first object's 
+                will be returned as a list.
+
+                Otherwise, only the value of the first object's
                 stream will be returned as a float.
-                 
+
         """
         if not all:
             return self.__getitem__(identifier)[0]._getStream().getValue()
         else:
             return [obj._getStream().getValue() for obj in self.__getitem__(identifier).getBaseObjects()]
-                        
+
     def play(self, dur=0, delay=0):
         self._base_handler.play()
         return PyoObject.play(self, dur, delay)
@@ -565,41 +653,70 @@ class Notein(PyoObject):
         self._base_handler.stop()
         return PyoObject.stop(self)
 
+    def ctrl(self, map_list=None, title=None, wxnoserver=False):
+        self._map_list = [SLMap(0, 2, 'lin', 'scale', self._scale, res="int", dataOnly=True),
+                         SLMap(0, 127, 'lin', 'first', self._first, res="int", dataOnly=True),
+                         SLMap(0, 127, 'lin', 'last', self._last, res="int", dataOnly=True),
+                         SLMap(0, 16, 'lin', 'channel', self._channel, res="int", dataOnly=True)
+                         ]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
     @property
-    def channel(self): 
+    def scale(self):
+        """int. Output format. 0 = midi, 1 = hertz, 2 = transpo."""
+        return self._scale
+    @scale.setter
+    def scale(self, x): self.setScale(x)
+
+    @property
+    def first(self):
+        """int. Lowest midi value."""
+        return self._first
+    @first.setter
+    def first(self, x): self.setFirst(x)
+
+    @property
+    def last(self):
+        """int. Highest midi value."""
+        return self._last
+    @last.setter
+    def last(self, x): self.setLast(x)
+
+    @property
+    def channel(self):
         """int. Midi channel. 0 means all channels."""
         return self._channel
     @channel.setter
-    def channel(self, x): 
-        self.setChannel(x)   
+    def channel(self, x):
+        self.setChannel(x)
 
 class Bendin(PyoObject):
     """
     Get the current value of the pitch bend controller.
 
-    Get the current value of the pitch bend controller and optionally 
+    Get the current value of the pitch bend controller and optionally
     maps it inside a specified range.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        brange : float, optional
+        brange: float, optional
             Bipolar range of the pitch bend in semitones. Defaults to 2.
             -brange <= value < brange.
-        scale : int, optional
+        scale: int, optional
             Output format. Defaults to 0.
                 0. Midi
                 1. transpo.
-                
-            The transpo mode is useful if you want to transpose values that 
+
+            The transpo mode is useful if you want to transpose values that
             are in a frequency (Hz) format.
-        channel : int, optional
+        channel: int, optional
             Midi channel. 0 means all channels. Defaults to 0.
 
     .. note::
 
-        The out() method is bypassed. Bendin's signal can not be sent 
+        The out() method is bypassed. Bendin's signal can not be sent
         to audio outs.
 
     >>> s = Server().boot()
@@ -613,12 +730,14 @@ class Bendin(PyoObject):
 
     """
     def __init__(self, brange=2, scale=0, channel=0, mul=1, add=0):
+        pyoArgsAssert(self, "niiOO", brange, scale, channel, mul, add)
         PyoObject.__init__(self, mul, add)
         self._brange = brange
         self._scale = scale
         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)
@@ -629,10 +748,11 @@ class Bendin(PyoObject):
 
         :Args:
 
-            x : int
+            x: float
                 new `brange` attribute.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._brange = x
         x, lmax = convertArgsToLists(x)
         [obj.setBrange(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -643,10 +763,11 @@ class Bendin(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 new `scale` attribute.
 
         """
+        pyoArgsAssert(self, "i", x)
         self._scale = x
         x, lmax = convertArgsToLists(x)
         [obj.setScale(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -657,58 +778,73 @@ class Bendin(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 new `channel` attribute.
 
         """
+        pyoArgsAssert(self, "i", x)
         self._channel = x
         x, lmax = convertArgsToLists(x)
         [obj.setChannel(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
+    def setInterpolation(self, x):
+        """
+        Deprecated method. If needed, use Port or SigTo to interpolate between values.
+
+        """
+        print("setInterpolation() is deprecated. If needed, use Port or SigTo to interpolate between values.")
+
+    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),
+                         SLMap(0, 16, 'lin', 'channel', self._channel, res="int", dataOnly=True)
+                         ]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
     @property
-    def brange(self): 
+    def brange(self):
         """float. Bipolar range of the pitch bend in semitones."""
         return self._brange
     @brange.setter
-    def brange(self, x): self.setBrange(x)   
+    def brange(self, x): self.setBrange(x)
 
     @property
-    def scale(self): 
+    def scale(self):
         """int. Output format. 0 = Midi, 1 = transpo."""
         return self._scale
     @scale.setter
-    def scale(self, x): self.setScale(x)   
+    def scale(self, x): self.setScale(x)
 
     @property
-    def channel(self): 
+    def channel(self):
         """int. Midi channel. 0 means all channels."""
         return self._channel
     @channel.setter
-    def channel(self, x): self.setChannel(x)   
+    def channel(self, x): self.setChannel(x)
 
 class Touchin(PyoObject):
     """
     Get the current value of an after-touch Midi controller.
 
-    Get the current value of an after-touch Midi controller and optionally 
+    Get the current value of an after-touch Midi controller and optionally
     maps it inside a specified range.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        minscale : float, optional
+        minscale: float, optional
             Low range value for mapping. Defaults to 0.
-        maxscale : float, optional
+        maxscale: float, optional
             High range value for mapping. Defaults to 1.
-        init : float, optional
+        init: float, optional
             Initial value. Defaults to 0.
-        channel : int, optional
+        channel: int, optional
             Midi channel. 0 means all channels. Defaults to 0.
 
     .. note::
 
-        The out() method is bypassed. Touchin's signal can not be sent 
+        The out() method is bypassed. Touchin's signal can not be sent
         to audio outs.
 
     >>> s = Server().boot()
@@ -722,12 +858,14 @@ class Touchin(PyoObject):
 
     """
     def __init__(self, minscale=0, maxscale=1, init=0, channel=0, mul=1, add=0):
+        pyoArgsAssert(self, "nnniOO", minscale, maxscale, init, channel, mul, add)
         PyoObject.__init__(self, mul, add)
         self._minscale = minscale
         self._maxscale = maxscale
         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)
@@ -738,10 +876,11 @@ class Touchin(PyoObject):
 
         :Args:
 
-            x : int
+            x: float
                 new `minscale` attribute.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._minscale = x
         x, lmax = convertArgsToLists(x)
         [obj.setMinScale(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -752,10 +891,11 @@ class Touchin(PyoObject):
 
         :Args:
 
-            x : int
+            x: float
                 new `maxscale` attribute.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._maxscale = x
         x, lmax = convertArgsToLists(x)
         [obj.setMaxScale(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -766,37 +906,52 @@ class Touchin(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 new `channel` attribute.
 
         """
+        pyoArgsAssert(self, "i", x)
         self._channel = x
         x, lmax = convertArgsToLists(x)
         [obj.setChannel(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
+    def setInterpolation(self, x):
+        """
+        Deprecated method. If needed, use Port or SigTo to interpolate between values.
+
+        """
+        print("setInterpolation() is deprecated. If needed, use Port or SigTo to interpolate between values.")
+
+    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),
+                         SLMap(0, 16, 'lin', 'channel', self._channel, res="int", dataOnly=True)
+                         ]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
     @property
-    def minscale(self): 
+    def minscale(self):
         """float. Minimum value for scaling."""
         return self._minscale
     @minscale.setter
-    def minscale(self, x): 
-        self.setMinScale(x)   
+    def minscale(self, x):
+        self.setMinScale(x)
 
     @property
-    def maxscale(self): 
+    def maxscale(self):
         """float. Maximum value for scaling."""
         return self._maxscale
     @maxscale.setter
     def maxscale(self, x):
-        self.setMaxScale(x)   
+        self.setMaxScale(x)
 
     @property
-    def channel(self): 
+    def channel(self):
         """int. Midi channel. 0 means all channels."""
         return self._channel
     @channel.setter
-    def channel(self, x): 
-        self.setChannel(x)   
+    def channel(self, x):
+        self.setChannel(x)
 
 class Programin(PyoObject):
     """
@@ -808,12 +963,12 @@ class Programin(PyoObject):
 
     :Args:
 
-        channel : int, optional
+        channel: int, optional
             Midi channel. 0 means all channels. Defaults to 0.
 
     .. note::
 
-        The out() method is bypassed. Programin's signal can not be sent 
+        The out() method is bypassed. Programin's signal can not be sent
         to audio outs.
 
     >>> s = Server().boot()
@@ -827,10 +982,12 @@ class Programin(PyoObject):
 
     """
     def __init__(self, channel=0, mul=1, add=0):
+        pyoArgsAssert(self, "iOO", channel, mul, add)
         PyoObject.__init__(self, mul, add)
         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)
@@ -841,27 +998,32 @@ class Programin(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 new `channel` attribute.
 
         """
+        pyoArgsAssert(self, "i", x)
         self._channel = x
         x, lmax = convertArgsToLists(x)
         [obj.setChannel(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, 16, 'lin', 'channel', self._channel, res="int", dataOnly=True)]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
     @property
-    def channel(self): 
+    def channel(self):
         """int. Midi channel. 0 means all channels."""
         return self._channel
     @channel.setter
-    def channel(self, x): 
-        self.setChannel(x)   
+    def channel(self, x):
+        self.setChannel(x)
 
 class MidiAdsr(PyoObject):
     """
     Midi triggered ADSR envelope generator.
 
-    Calculates the classical ADSR envelope using linear segments. 
+    Calculates the classical ADSR envelope using linear segments.
     The envelope starts when it receives a positive value in input,
     this value is used as the peak amplitude of the envelope. The
     `sustain` parameter is a fraction of the peak value and sets
@@ -872,24 +1034,27 @@ class MidiAdsr(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal used to trigger the envelope. A positive value
             sets the peak amplitude and starts the envelope. A 0 starts
             the release part of the envelope.
-        attack : float, optional
+        attack: float, optional
             Duration of the attack phase in seconds. Defaults to 0.01.
-        decay : float, optional
+        decay: float, optional
             Duration of the decay phase in seconds. Defaults to 0.05.
-        sustain : float, optional
+        sustain: float, optional
             Amplitude of the sustain phase, as a fraction of the peak
             amplitude at the start of the envelope. Defaults to 0.7.
-        release : float, optional
+        release: float, optional
             Duration of the release phase in seconds. Defaults to 0.1.
 
     .. note::
 
         The out() method is bypassed. MidiAdsr's signal can not be sent to audio outs.
 
+        As of version 0.8.0, exponential or logarithmic envelopes can be created
+        with the exponent factor (see setExp() method).
+
     >>> s = Server().boot()
     >>> s.start()
     >>> mid = Notein(scale=1)
@@ -899,15 +1064,18 @@ class MidiAdsr(PyoObject):
 
     """
     def __init__(self, input, attack=0.01, decay=0.05, sustain=0.7, release=0.1, mul=1, add=0):
+        pyoArgsAssert(self, "onnnnOO", input, attack, decay, sustain, release, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._attack = attack
         self._decay = decay
         self._sustain = sustain
         self._release = release
+        self._exp = 1.0;
         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)
@@ -918,12 +1086,13 @@ class MidiAdsr(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal used to trigger the envelope.
-            fadetime : float, optional
+            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)
 
@@ -933,10 +1102,11 @@ class MidiAdsr(PyoObject):
 
         :Args:
 
-            x : float
+            x: float
                 new `attack` attribute.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._attack = x
         x, lmax = convertArgsToLists(x)
         [obj.setAttack(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -947,10 +1117,11 @@ class MidiAdsr(PyoObject):
 
         :Args:
 
-            x : float
+            x: float
                 new `decay` attribute.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._decay = x
         x, lmax = convertArgsToLists(x)
         [obj.setDecay(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -961,10 +1132,11 @@ class MidiAdsr(PyoObject):
 
         :Args:
 
-            x : float
+            x: float
                 new `sustain` attribute.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._sustain = x
         x, lmax = convertArgsToLists(x)
         [obj.setSustain(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -975,79 +1147,118 @@ class MidiAdsr(PyoObject):
 
         :Args:
 
-            x : float
+            x: float
                 new `sustain` attribute.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._release = x
         x, lmax = convertArgsToLists(x)
         [obj.setRelease(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
+    def setExp(self, x):
+        """
+        Sets an exponent factor to create exponential or logarithmic envelopes.
+
+        The default value is 1.0, which means linear segments. A value
+        higher than 1.0 will produce exponential segments while a value
+        between 0 and 1 will produce logarithmic segments. Must be > 0.0.
+
+        :Args:
+
+            x: float
+                new `exp` attribute.
+
+        """
+        pyoArgsAssert(self, "n", x)
+        self._exp = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setExp(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, 1.0, 'lin', 'attack', self._attack, dataOnly=True),
+                          SLMap(0.0, 1.0, 'lin', 'decay', self._decay, dataOnly=True),
+                          SLMap(0.0, 1.0, 'lin', 'sustain', self._sustain, dataOnly=True),
+                          SLMap(0.0, 1.0, 'lin', 'release', self._release, dataOnly=True),
+                          SLMap(0.1, 10.0, 'log', 'exp', self._exp, dataOnly=True),
+                         ]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
     @property
     def attack(self):
-        """float. Duration of the attack phase in seconds.""" 
+        """float. Duration of the attack phase in seconds."""
         return self._attack
     @attack.setter
     def attack(self, x): self.setAttack(x)
 
     @property
     def decay(self):
-        """float. Duration of the decay phase in seconds.""" 
+        """float. Duration of the decay phase in seconds."""
         return self._decay
     @decay.setter
     def decay(self, x): self.setDecay(x)
 
     @property
     def sustain(self):
-        """float. Amplitude of the sustain phase, as fraction of the peak amplitude.""" 
+        """float. Amplitude of the sustain phase, as fraction of the peak amplitude."""
         return self._sustain
     @sustain.setter
     def sustain(self, x): self.setSustain(x)
 
     @property
     def release(self):
-        """float. Duration of the release phase in seconds.""" 
+        """float. Duration of the release phase in seconds."""
         return self._release
     @release.setter
     def release(self, x): self.setRelease(x)
 
+    @property
+    def exp(self):
+        """float. Exponent factor of the envelope."""
+        return self._exp
+    @exp.setter
+    def exp(self, x): self.setExp(x)
+
 class MidiDelAdsr(PyoObject):
     """
     Midi triggered ADSR envelope generator with pre-delay.
 
-    Calculates the classical ADSR envelope using linear segments. 
-    The envelope starts after `delay` seconds when it receives a 
-    positive value in input, this value is used as the peak amplitude 
-    of the envelope. The `sustain` parameter is a fraction of the 
-    peak value and sets the real sustain value. A 0 in input (note off) 
+    Calculates the classical ADSR envelope using linear segments.
+    The envelope starts after `delay` seconds when it receives a
+    positive value in input, this value is used as the peak amplitude
+    of the envelope. The `sustain` parameter is a fraction of the
+    peak value and sets the real sustain value. A 0 in input (note off)
     starts the release part of the envelope.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal used to trigger the envelope. A positive value
             sets the peak amplitude and starts the envelope. A 0 starts
             the release part of the envelope.
-        delay : float, optional
-            Duration of the delay phase, before calling the envelope 
+        delay: float, optional
+            Duration of the delay phase, before calling the envelope
             in seconds. Defaults to 0.
-        attack : float, optional
+        attack: float, optional
             Duration of the attack phase in seconds. Defaults to 0.01.
-        decay : float, optional
+        decay: float, optional
             Duration of the decay phase in seconds. Defaults to 0.05.
-        sustain : float, optional
+        sustain: float, optional
             Amplitude of the sustain phase, as a fraction of the peak
             amplitude at the start of the envelope. Defaults to 0.7.
-        release : float, optional
+        release: float, optional
             Duration of the release phase in seconds. Defaults to 0.1.
 
     .. note::
 
-        The out() method is bypassed. MidiDelAdsr's signal can not be sent 
+        The out() method is bypassed. MidiDelAdsr's signal can not be sent
         to audio outs.
 
+        As of version 0.8.0, exponential or logarithmic envelopes can be created
+        with the exponent factor (see setExp() method).
+
     >>> s = Server().boot()
     >>> s.start()
     >>> mid = Notein(scale=1)
@@ -1057,6 +1268,7 @@ class MidiDelAdsr(PyoObject):
 
     """
     def __init__(self, input, delay=0, attack=0.01, decay=0.05, sustain=0.7, release=0.1, mul=1, add=0):
+        pyoArgsAssert(self, "onnnnnOO", input, delay, attack, decay, sustain, release, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._delay = delay
@@ -1064,9 +1276,11 @@ class MidiDelAdsr(PyoObject):
         self._decay = decay
         self._sustain = sustain
         self._release = release
+        self._exp = 1.0;
         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)
@@ -1077,12 +1291,13 @@ class MidiDelAdsr(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal used to trigger the envelope.
-            fadetime : float, optional
+            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)
 
@@ -1092,10 +1307,11 @@ class MidiDelAdsr(PyoObject):
 
         :Args:
 
-            x : float
+            x: float
                 new `delay` attribute.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._delay = x
         x, lmax = convertArgsToLists(x)
         [obj.setDelay(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1106,10 +1322,11 @@ class MidiDelAdsr(PyoObject):
 
         :Args:
 
-            x : float
+            x: float
                 new `attack` attribute.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._attack = x
         x, lmax = convertArgsToLists(x)
         [obj.setAttack(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1120,10 +1337,11 @@ class MidiDelAdsr(PyoObject):
 
         :Args:
 
-            x : float
+            x: float
                 new `decay` attribute.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._decay = x
         x, lmax = convertArgsToLists(x)
         [obj.setDecay(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1134,10 +1352,11 @@ class MidiDelAdsr(PyoObject):
 
         :Args:
 
-            x : float
+            x: float
                 new `sustain` attribute.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._sustain = x
         x, lmax = convertArgsToLists(x)
         [obj.setSustain(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1148,45 +1367,159 @@ class MidiDelAdsr(PyoObject):
 
         :Args:
 
-            x : float
+            x: float
                 new `sustain` attribute.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._release = x
         x, lmax = convertArgsToLists(x)
         [obj.setRelease(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
+    def setExp(self, x):
+        """
+        Sets an exponent factor to create exponential or logarithmic envelope.
+
+        The default value is 1.0, which means linear segments. A value
+        higher than 1.0 will produce exponential segments while a value
+        between 0 and 1 will produce logarithmic segments. Must be > 0.0.
+
+        :Args:
+
+            x: float
+                new `exp` attribute.
+
+        """
+        pyoArgsAssert(self, "n", x)
+        self._exp = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setExp(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, 1.0, 'lin', 'delay', self._delay, dataOnly=True),
+                          SLMap(0.0, 1.0, 'lin', 'attack', self._attack, dataOnly=True),
+                          SLMap(0.0, 1.0, 'lin', 'decay', self._decay, dataOnly=True),
+                          SLMap(0.0, 1.0, 'lin', 'sustain', self._sustain, dataOnly=True),
+                          SLMap(0.0, 1.0, 'lin', 'release', self._release, dataOnly=True),
+                          SLMap(0.1, 10.0, 'log', 'exp', self._exp, dataOnly=True),
+                         ]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
     @property
     def delay(self):
-        """float. Duration of the delay phase in seconds.""" 
+        """float. Duration of the delay phase in seconds."""
         return self._delay
     @delay.setter
     def delay(self, x): self.setDelay(x)
 
     @property
     def attack(self):
-        """float. Duration of the attack phase in seconds.""" 
+        """float. Duration of the attack phase in seconds."""
         return self._attack
     @attack.setter
     def attack(self, x): self.setAttack(x)
 
     @property
     def decay(self):
-        """float. Duration of the decay phase in seconds.""" 
+        """float. Duration of the decay phase in seconds."""
         return self._decay
     @decay.setter
     def decay(self, x): self.setDecay(x)
 
     @property
     def sustain(self):
-        """float. Amplitude of the sustain phase, as fraction of the peak amplitude.""" 
+        """float. Amplitude of the sustain phase, as fraction of the peak amplitude."""
         return self._sustain
     @sustain.setter
     def sustain(self, x): self.setSustain(x)
 
     @property
     def release(self):
-        """float. Duration of the release phase in seconds.""" 
+        """float. Duration of the release phase in seconds."""
         return self._release
     @release.setter
     def release(self, x): self.setRelease(x)
+
+    @property
+    def exp(self):
+        """float. Exponent factor of the envelope."""
+        return self._exp
+    @exp.setter
+    def exp(self, x): self.setExp(x)
+
+class RawMidi(PyoObject):
+    """
+    Raw Midi handler.
+
+    This object calls a python function for each raw midi data
+    (status, data1, data2) event for further processing in Python.
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        function: Python function (can't be a list)
+            Function to be called. The function must be declared
+            with three arguments, one for the status byte and two
+            for the data bytes. Ex.:
+
+            def event(status, data1, data2):
+                print(status, data1, data2)
+
+    .. note::
+
+        The out() method is bypassed. RawMidi's signal can not be sent
+        to audio outs.
+
+    >>> s = Server()
+    >>> s.setMidiInputDevice(99) # opens all devices
+    >>> s.boot()
+    >>> s.start()
+    >>> def event(status, data1, data2):
+    ...     print(status, data1, data2)
+    >>> a = RawMidi(event)
+
+    """
+    def __init__(self, function):
+        pyoArgsAssert(self, "C", function)
+        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)
+
+    def setMul(self, x):
+        pass
+
+    def setAdd(self, x):
+        pass
+
+    def setSub(self, x):
+        pass
+
+    def setDiv(self, x):
+        pass
+
+    def setFunction(self, x):
+        """
+        Replace the `function` attribute.
+
+        :Args:
+
+            x: Python function
+                new `function` attribute.
+
+        """
+        pyoArgsAssert(self, "C", x)
+        self._function = WeakMethod(x)
+        [obj.setFunction(self._function) for i, obj in enumerate(self._base_objs)]
+
+    @property
+    def function(self):
+        """Python function. Function to be called."""
+        return self._function
+    @function.setter
+    def function(self, x):
+        self.setFunction(x)
diff --git a/pyolib/opensndctrl.py b/pyolib/opensndctrl.py
index 2c27ba0..770ab1c 100644
--- a/pyolib/opensndctrl.py
+++ b/pyolib/opensndctrl.py
@@ -1,40 +1,52 @@
+from __future__ import print_function
+from __future__ import absolute_import
 """
 Objects to manage values on an Open Sound Control port.
 
 OscSend takes the first value of each buffersize and send it on an
 OSC port.
 
-OscReceive creates and returns audio streams from the value in its 
+OscReceive creates and returns audio streams from the value in its
 input port.
 
 The audio streams of these objects are essentially intended to be
 controls and can't be sent to the output soundcard.
 
+These objects are available only if pyo is built with OSC (Open Sound
+Control) support.
+
 """
 
 """
-Copyright 2010 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+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 sys
-from _core import *
-from _maps import *
-from types import IntType, ListType
+from ._core import *
+from ._maps import *
+
+def assertOSCSupport(obj):
+    if not withOSC():
+        raise Exception("Pyo built without OSC support! '%s' objects is not available." % obj.__class__.__name__)
+
+### TODO - Know bugs:
+### OscListReceive.setValue(address, value) make the program segfault on quit (python 2.7 and 3.5).
+### OscSend/OscReceive don't work with unicode on python 2.7 (ok on python 3.5)
+###
 
 ######################################################################
 ### Open Sound Control
@@ -43,45 +55,48 @@ class OscSend(PyoObject):
     """
     Sends values over a network via the Open Sound Control protocol.
 
-    Uses the OSC protocol to share values to other softwares or other 
-    computers. Only the first value of each input buffersize will be 
+    Uses the OSC protocol to share values to other softwares or other
+    computers. Only the first value of each input buffersize will be
     sent on the OSC port.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal.
-        port : int
-            Port on which values are sent. Receiver should listen on the 
+        port: int
+            Port on which values are sent. Receiver should listen on the
             same port.
-        address : string
-            Address used on the port to identify values. Address is in 
+        address: string
+            Address used on the port to identify values. Address is in
             the form of a Unix path (ex.: '/pitch').
-        host : string, optional
-            IP address of the target computer. The default, '127.0.0.1', 
+        host: string, optional
+            IP address of the target computer. The default, '127.0.0.1',
             is the localhost.
 
     .. note::
 
-        The out() method is bypassed. OscSend's signal can not be sent 
+        The out() method is bypassed. OscSend's signal can not be sent
         to audio outs.
-        
+
         OscSend has no `mul` and `add` attributes.
 
     >>> s = Server().boot()
     >>> s.start()
     >>> a = Sine(freq=[1,1.5], mul=[100,.1], add=[600, .1])
     >>> b = OscSend(a, port=10001, address=['/pitch','/amp'])
-    
+
     """
     def __init__(self, input, port, address, host="127.0.0.1"):
+        assertOSCSupport(self)
+        pyoArgsAssert(self, "oiss", input, port, address, host)
         PyoObject.__init__(self)
         self._input = input
         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):
         """
@@ -89,76 +104,78 @@ class OscSend(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 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    
+        pass
 
     def setBufferRate(self, x):
         """
         Sets how many buffers to wait before sending a new value.
-        
+
         :Args:
 
-            x : int
+            x: int
                 Changes the data output frequency in multiples of the buffer size.
                 Should be greater or equal to 1.
 
         """
+        pyoArgsAssert(self, "I", x)
         [obj.setBufferRate(x) for obj in self._base_objs]
 
     @property
     def input(self):
-        """PyoObject. Input signal.""" 
+        """PyoObject. Input signal."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
-         
+
 class OscReceive(PyoObject):
     """
     Receives values over a network via the Open Sound Control protocol.
 
-    Uses the OSC protocol to receive values from other softwares or 
-    other computers. Get a value at the beginning of each buffersize 
+    Uses the OSC protocol to receive values from other softwares or
+    other computers. Get a value at the beginning of each buffersize
     and fill its buffer with it.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        port : int
-            Port on which values are received. Sender should output on 
-            the same port. 
-            
-            Unlike OscSend object, there can be only one port per OscReceive 
-            object. 
-            
+        port: int
+            Port on which values are received. Sender should output on
+            the same port.
+
+            Unlike OscSend object, there can be only one port per OscReceive
+            object.
+
             Available at initialization time only.
-        address : string
-            Address used on the port to identify values. Address is in 
+        address: string
+            Address used on the port to identify values. Address is in
             the form of a Unix path (ex.: '/pitch').
 
     .. note::
 
-        Audio streams are accessed with the `address` string parameter. 
+        Audio streams are accessed with the `address` string parameter.
         The user should call :
 
         OscReceive['/pitch'] to retreive stream named '/pitch'.
 
-        The out() method is bypassed. OscReceive's signal can not be sent 
+        The out() method is bypassed. OscReceive's signal can not be sent
         to audio outs.
 
     >>> s = Server().boot()
@@ -169,22 +186,22 @@ class OscReceive(PyoObject):
     """
 
     def __init__(self, port, address, mul=1, add=0):
+        assertOSCSupport(self)
+        pyoArgsAssert(self, "IsOO", port, address, mul, add)
         PyoObject.__init__(self, mul, add)
-        if type(port) != IntType:
-            print >> sys.stderr, 'TypeError: "port" argument of %s must be an integer.\n' % self.__class__.__name__
-            exit()
         address, mul, add, lmax = convertArgsToLists(address, mul, add)
         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) == type(''):
+        if type(i) in [bytes_t, unicode_t]:
             return self._base_objs[self._address.index(i)]
         elif i < len(self._base_objs):
             return self._base_objs[i]
         else:
-            print "'i' too large!"
+            print("'i' too large!")
 
     def getAddresses(self):
         """
@@ -199,14 +216,15 @@ class OscReceive(PyoObject):
 
         :Args:
 
-            path : string or list of strings
+            path: string or list of strings
                 New path(s) to receive from.
-            mul : float or PyoObject
+            mul: float or PyoObject
                 Multiplication factor. Defaults to 1.
-            add : float or PyoObject
+            add: float or PyoObject
                 Addition factor. Defaults to 0.
 
         """
+        pyoArgsAssert(self, "sOO", path, mul, add)
         path, lmax = convertArgsToLists(path)
         mul, add, lmax2 = convertArgsToLists(mul, add)
         for i, p in enumerate(path):
@@ -221,10 +239,11 @@ class OscReceive(PyoObject):
 
         :Args:
 
-            path : string or list of strings
+            path: string or list of strings
                 Path(s) to remove.
 
         """
+        pyoArgsAssert(self, "s", path)
         path, lmax = convertArgsToLists(path)
         self._mainReceiver.delAddress(path)
         indexes = [self._address.index(p) for p in path]
@@ -238,31 +257,33 @@ class OscReceive(PyoObject):
 
         :Args:
 
-            x : boolean
+            x: boolean
                 True activates the interpolation, False deactivates it.
-        
+
         """
+        pyoArgsAssert(self, "B", x)
         [obj.setInterpolation(x) for obj in self._base_objs]
 
     def setValue(self, path, value):
         """
         Sets value for a given address.
-        
+
         :Args:
-        
-            path : string
+
+            path: string
                 Address to which the value should be attributed.
-            value : float
+            value: float
                 Value to attribute to the given address.
 
         """
+        pyoArgsAssert(self, "sn", path, value)
         path, value, lmax = convertArgsToLists(path, value)
         for i in range(lmax):
             p = wrap(path,i)
             if p in self._address:
                 self._mainReceiver.setValue(p, wrap(value,i))
             else:
-                print 'Error: OscReceive.setValue, Illegal address "%s"' % p 
+                print('Error: OscReceive.setValue, Illegal address "%s"' % p)
 
     def get(self, identifier=None, all=False):
         """
@@ -275,11 +296,11 @@ class OscReceive(PyoObject):
 
         :Args:
 
-            identifier : string
+            identifier: string
                 Address string parameter identifying audio stream.
-                Defaults to None, useful when `all` is True to 
+                Defaults to None, useful when `all` is True to
                 retreive all streams values.
-            all : boolean, optional
+            all: boolean, optional
                 If True, the first value of each object's stream
                 will be returned as a list. Otherwise, only the value
                 of the first object's stream will be returned as a float.
@@ -290,7 +311,7 @@ class OscReceive(PyoObject):
             return self._base_objs[self._address.index(identifier)]._getStream().getValue()
         else:
             return [obj._getStream().getValue() for obj in self._base_objs]
-             
+
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
 
@@ -298,7 +319,7 @@ class OscDataSend(PyoObject):
     """
     Sends data values over a network via the Open Sound Control protocol.
 
-    Uses the OSC protocol to share values to other softwares or other 
+    Uses the OSC protocol to share values to other softwares or other
     computers. Values are sent on the form of a list containing `types`
     elements.
 
@@ -306,25 +327,31 @@ class OscDataSend(PyoObject):
 
     :Args:
 
-        types : str
+        types: str
             String specifying the types sequence of the message to be sent.
             Possible values are:
-                - integer : "i"
-                - long integer : "h"
-                - float : "f"
-                - double : "d"
-                - string : "s"
-                
+                - "i": integer
+                - "h": long integer
+                - "f": float
+                - "d": double
+                - "s" ; string
+                - "b": blob (list of chars)
+                - "m": MIDI packet (list of 4 bytes: [midi port, status, data1, data2])
+                - "c": char
+                - "T": True
+                - "F": False
+                - "N": None (nil)
+
             The string "ssfi" indicates that the value to send will be a list
             containing two strings followed by a float and an integer.
-        port : int
-            Port on which values are sent. Receiver should listen on the 
+        port: int
+            Port on which values are sent. Receiver should listen on the
             same port.
-        address : string
-            Address used on the port to identify values. Address is in 
+        address: string
+            Address used on the port to identify values. Address is in
             the form of a Unix path (ex.: '/pitch').
-        host : string, optional
-            IP address of the target computer. The default, '127.0.0.1', 
+        host: string, optional
+            IP address of the target computer. The default, '127.0.0.1',
             is the localhost.
 
     .. note::
@@ -335,23 +362,35 @@ class OscDataSend(PyoObject):
 
     >>> s = Server().boot()
     >>> s.start()
-    >>> a = OscDataSend("fissif", 9900, "/data/test")
     >>> def pp(address, *args):
-    ...     print address
-    ...     print args
-    >>> b = OscDataReceive(9900, "/data/test", pp)
+    ...     print(address)
+    ...     print(args)
+    >>> r = OscDataReceive(9900, "/data/test", pp)
+    >>> # Send various types
+    >>> a = OscDataSend("fissif", 9900, "/data/test")
     >>> msg = [3.14159, 1, "Hello", "world!", 2, 6.18]
     >>> a.send(msg)
+    >>> # Send a blob
+    >>> b = OscDataSend("b", 9900, "/data/test")
+    >>> msg = [[chr(i) for i in range(10)]]
+    >>> b.send(msg)
+    >>> # Send a MIDI noteon on port 0
+    >>> c = OscDataSend("m", 9900, "/data/test")
+    >>> msg = [[0, 144, 60, 100]]
+    >>> c.send(msg)
 
     """
-    def __init__(self, types, port, address, host="127.0.0.1"):    
+    def __init__(self, types, port, address, host="127.0.0.1"):
+        assertOSCSupport(self)
+        pyoArgsAssert(self, "siss", types, port, address, host)
         PyoObject.__init__(self)
         types, port, address, host, lmax = convertArgsToLists(types, port, address, host)
         self._base_objs = [OscDataSend_base(wrap(types,i), wrap(port,i), wrap(address,i), wrap(host,i)) for i in range(lmax)]
         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)
 
@@ -359,14 +398,14 @@ class OscDataSend(PyoObject):
         pass
 
     def setAdd(self, x):
-        pass    
+        pass
 
     def getAddresses(self):
         """
         Returns the addresses managed by the object.
 
         """
-        return self._addresses.keys()
+        return list(self._addresses.keys())
 
     def addAddress(self, types, port, address, host="127.0.0.1"):
         """
@@ -374,28 +413,35 @@ class OscDataSend(PyoObject):
 
         :Args:
 
-            types : str
+            types: str
                 String specifying the types sequence of the message to be sent.
                 Possible values are:
-                    - integer : "i"
-                    - long integer : "h"
-                    - float : "f"
-                    - double : "d"
-                    - string : "s"
+                - "i": integer
+                - "h": long integer
+                - "f": float
+                - "d": double
+                - "s" ; string
+                - "b": blob (list of chars)
+                - "m": MIDI packet (list of 4 bytes: [midi port, status, data1, data2])
+                - "c": char
+                - "T": True
+                - "F": False
+                - "N": None (nil)
 
                 The string "ssfi" indicates that the value to send will be a list
                 containing two strings followed by a float and an integer.
-            port : int
-                Port on which values are sent. Receiver should listen on the 
+            port: int
+                Port on which values are sent. Receiver should listen on the
                 same port.
-            address : string
-                Address used on the port to identify values. Address is in 
+            address: string
+                Address used on the port to identify values. Address is in
                 the form of a Unix path (ex.: '/pitch').
-            host : string, optional
-                IP address of the target computer. The default, '127.0.0.1', 
+            host: string, optional
+                IP address of the target computer. The default, '127.0.0.1',
                 is the localhost.
 
         """
+        pyoArgsAssert(self, "siss", types, port, address, host)
         types, port, address, host, lmax = convertArgsToLists(types, port, address, host)
         objs = [OscDataSend_base(wrap(types,i), wrap(port,i), wrap(address,i), wrap(host,i)) for i in range(lmax)]
         self._base_objs.extend(objs)
@@ -408,60 +454,64 @@ class OscDataSend(PyoObject):
 
         :Args:
 
-            path : string or list of strings
+            path: string or list of strings
                 Path(s) to remove.
 
         """
+        pyoArgsAssert(self, "s", path)
         path, lmax = convertArgsToLists(path)
         for p in path:
-            self._base_objs.remove(self._addresses[p])
-            del self._addresses[p]
+            if p in self._addresses:
+                self._base_objs.remove(self._addresses[p])
+                del self._addresses[p]
 
     def send(self, msg, address=None):
         """
         Method used to send `msg` values as a list.
-        
+
         :Args:
-        
-            msg : list
+
+            msg: list
                 List of values to send. Types of values in list
                 must be of the kind defined of `types` argument
                 given at the object's initialization.
-            address : string, optional
+            address: string, optional
                 Address destination to send values. If None, values
                 will be sent to all addresses managed by the object.
-        
+
         """
-        if address == None:
+        if address is None:
+            pyoArgsAssert(self, "l", msg)
             [obj.send(msg) for obj in self._base_objs]
         else:
+            pyoArgsAssert(self, "lS", msg, address)
             self._addresses[address].send(msg)
 
 class OscDataReceive(PyoObject):
     """
     Receives data values over a network via the Open Sound Control protocol.
 
-    Uses the OSC protocol to receive data values from other softwares or 
+    Uses the OSC protocol to receive data values from other softwares or
     other computers. When a message is received, the function given at the
-    argument `function` is called with the current address destination in 
+    argument `function` is called with the current address destination in
     argument followed by a tuple of values.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        port : int
-            Port on which values are received. Sender should output on 
-            the same port. Unlike OscDataSend object, there can be only 
-            one port per OscDataReceive object. Available at initialization 
+        port: int
+            Port on which values are received. Sender should output on
+            the same port. Unlike OscDataSend object, there can be only
+            one port per OscDataReceive object. Available at initialization
             time only.
-        address : string
-            Address used on the port to identify values. Address is in 
+        address: string
+            Address used on the port to identify values. Address is in
             the form of a Unix path (ex.: "/pitch"). There can be as many
             addresses as needed on a single port.
-        function : callable
+        function: callable (can't be a list)
             This function will be called whenever a message with a known
-            address is received. there can be only one function per 
+            address is received. there can be only one function per
             OscDataReceive object. Available at initialization time only.
 
     .. note::
@@ -477,33 +527,39 @@ class OscDataReceive(PyoObject):
 
     >>> s = Server().boot()
     >>> s.start()
-    >>> a = OscDataSend("fissif", 9900, "/data/test")
     >>> def pp(address, *args):
-    ...     print address
-    ...     print args
-    >>> b = OscDataReceive(9900, "/data/test", pp)
+    ...     print(address)
+    ...     print(args)
+    >>> r = OscDataReceive(9900, "/data/test", pp)
+    >>> # Send various types
+    >>> a = OscDataSend("fissif", 9900, "/data/test")
     >>> msg = [3.14159, 1, "Hello", "world!", 2, 6.18]
     >>> a.send(msg)
+    >>> # Send a blob
+    >>> b = OscDataSend("b", 9900, "/data/test")
+    >>> msg = [[chr(i) for i in range(10)]]
+    >>> b.send(msg)
+    >>> # Send a MIDI noteon on port 0
+    >>> c = OscDataSend("m", 9900, "/data/test")
+    >>> msg = [[0, 144, 60, 100]]
+    >>> c.send(msg)
 
     """
 
     def __init__(self, port, address, function):
+        assertOSCSupport(self)
+        pyoArgsAssert(self, "IsC", port, address, function)
         PyoObject.__init__(self)
-        if type(port) != IntType:
-            print >> sys.stderr, 'TypeError: "port" argument of %s must be an integer.\n' % self.__class__.__name__
-            exit()
         self._port = port
-        if not callable(function):
-            print >> sys.stderr, 'TypeError: "function" argument of %s must be callable.\n' % self.__class__.__name__
-            exit()
-        self._function = function
+        self._function = WeakMethod(function)
         self._address, lmax = convertArgsToLists(address)
         # self._address is linked with list at C level
-        self._base_objs = [OscDataReceive_base(port, self._address, function)]
+        self._base_objs = [OscDataReceive_base(port, self._address, self._function)]
+        self.play()
 
     def setMul(self, x):
         pass
-        
+
     def setAdd(self, x):
         pass
 
@@ -513,23 +569,25 @@ class OscDataReceive(PyoObject):
     def getAddresses(self):
         """
         Returns the addresses managed by the object.
-        
+
         """
         return self._address
 
     def addAddress(self, path):
         """
         Adds new address(es) to the object's handler.
-        
+
         :Args:
-        
-            path : string or list of strings
+
+            path: string or list of strings
                 New path(s) to receive from.
 
         """
+        pyoArgsAssert(self, "s", path)
         path, lmax = convertArgsToLists(path)
         for p in path:
             if p not in self._address:
+                self._address.append(p)
                 self._base_objs[0].addAddress(p)
 
     def delAddress(self, path):
@@ -538,20 +596,23 @@ class OscDataReceive(PyoObject):
 
         :Args:
 
-            path : string or list of strings
+            path: string or list of strings
                 Path(s) to remove.
 
         """
+        pyoArgsAssert(self, "s", path)
         path, lmax = convertArgsToLists(path)
         for p in path:
-            index = self._address.index(p)
-            self._base_objs[0].delAddress(index)
+            if p in self._address:
+                index = self._address.index(p)
+                self._base_objs[0].delAddress(index)
+                self._address.remove(p)
 
 class OscListReceive(PyoObject):
     """
     Receives list of values over a network via the Open Sound Control protocol.
 
-    Uses the OSC protocol to receive list of floating-point values from other 
+    Uses the OSC protocol to receive list of floating-point values from other
     softwares or other computers. The list are converted into audio streams.
     Get values at the beginning of each buffersize and fill buffers with them.
 
@@ -559,28 +620,28 @@ class OscListReceive(PyoObject):
 
     :Args:
 
-        port : int
-            Port on which values are received. Sender should output on 
-            the same port. Unlike OscSend object, there can be only one 
-            port per OscListReceive object. Available at initialization time 
+        port: int
+            Port on which values are received. Sender should output on
+            the same port. Unlike OscSend object, there can be only one
+            port per OscListReceive object. Available at initialization time
             only.
-        address : string
-            Address used on the port to identify values. Address is in 
+        address: string
+            Address used on the port to identify values. Address is in
             the form of a Unix path (ex.: '/pitch').
-        num : int, optional
+        num: int, optional
             Length of the lists in input. The object will generate `num` audio
             streams per given address. Available at initialization time only.
-            This value can't be a list. That means all addresses managed by an 
+            This value can't be a list. That means all addresses managed by an
             OscListReceive object are of the same length. Defaults to 8.
 
     .. note::
 
-        Audio streams are accessed with the `address` string parameter. 
+        Audio streams are accessed with the `address` string parameter.
         The user should call :
 
         OscReceive['/pitch'] to retreive list of streams named '/pitch'.
 
-        The out() method is bypassed. OscReceive's signal can not be sent 
+        The out() method is bypassed. OscReceive's signal can not be sent
         to audio outs.
 
     >>> s = Server().boot()
@@ -592,29 +653,26 @@ class OscListReceive(PyoObject):
     """
 
     def __init__(self, port, address, num=8, mul=1, add=0):
+        assertOSCSupport(self)
+        pyoArgsAssert(self, "IsIOO", port, address, num, mul, add)
         PyoObject.__init__(self, mul, add)
-        if type(port) != IntType:
-            print >> sys.stderr, 'TypeError: "port" argument of %s must be an integer.\n' % self.__class__.__name__
-            exit()
-        if type(num) != IntType:
-            print >> sys.stderr, 'TypeError: "num" argument of %s must be an integer.\n' % self.__class__.__name__
-            exit()
         self._num = num
         self._op_duplicate = self._num
         address, mul, add, lmax = convertArgsToLists(address, mul, add)
         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) == type(''):
+        if type(i) in [bytes_t, unicode_t]:
             first = self._address.index(i) * self._num
             return self._base_objs[first:first+self._num]
         elif i < len(self._base_objs):
             first = i * self._num
             return self._base_objs[first:first+self._num]
         else:
-            print "'i' too large!"
+            print("'i' too large!")
 
     def getAddresses(self):
         """
@@ -629,14 +687,15 @@ class OscListReceive(PyoObject):
 
         :Args:
 
-            path : string or list of strings
+            path: string or list of strings
                 New path(s) to receive from.
-            mul : float or PyoObject
+            mul: float or PyoObject
                 Multiplication factor. Defaults to 1.
-            add : float or PyoObject
+            add: float or PyoObject
                 Addition factor. Defaults to 0.
 
         """
+        pyoArgsAssert(self, "sOO", path, mul, add)
         path, lmax = convertArgsToLists(path)
         mul, add, lmax2 = convertArgsToLists(mul, add)
         for i, p in enumerate(path):
@@ -651,17 +710,18 @@ class OscListReceive(PyoObject):
 
         :Args:
 
-            path : string or list of strings
+            path: string or list of strings
                 Path(s) to remove.
 
         """
+        pyoArgsAssert(self, "s", path)
         path, lmax = convertArgsToLists(path)
         self._mainReceiver.delAddress(path)
-        indexes = [self._address.index(p) for p in path]
+        indexes = [self._address.index(p) for p in path if p in self._address]
         for ind in reversed(indexes):
             self._address.pop(ind)
             first = ind * self._num
-            for i in reversed(range(first, first+self._num)):
+            for i in reversed(list(range(first, first+self._num))):
                 obj = self._base_objs.pop(i)
 
     def setInterpolation(self, x):
@@ -670,38 +730,40 @@ class OscListReceive(PyoObject):
 
         :Args:
 
-            x : boolean
+            x: boolean
                 True activates the interpolation, False deactivates it.
 
         """
+        pyoArgsAssert(self, "B", x)
         [obj.setInterpolation(x) for obj in self._base_objs]
 
     def setValue(self, path, value):
         """
         Sets value for a given address.
-        
+
         :Args:
-        
-            path : string
+
+            path: string
                 Address to which the value should be attributed.
-            value : list of floats
+            value: list of floats
                 List of values to attribute to the given address.
 
         """
+        pyoArgsAssert(self, "sl", path, value)
         path, lmax = convertArgsToLists(path)
         for i in range(lmax):
             p = wrap(path,i)
             if p in self._address:
-                if type(value[0]) == ListType:
+                if type(value[0]) == list:
                     val = wrap(value,i)
                 else:
                     val = value
                 if len(val) == self._num:
                     self._mainReceiver.setValue(p, val)
                 else:
-                    print 'Error: OscListReceive.setValue, value must be of the same length as the `num` attribute.'
+                    print('Error: OscListReceive.setValue, value must be of the same length as the `num` attribute.')
             else:
-                print 'Error: OscListReceive.setValue, Illegal address "%s"' % p 
+                print('Error: OscListReceive.setValue, Illegal address "%s"' % p)
 
     def get(self, identifier=None, all=False):
         """
@@ -714,14 +776,14 @@ class OscListReceive(PyoObject):
 
         :Args:
 
-            identifier : string
+            identifier: string
                 Address string parameter identifying audio stream.
-                Defaults to None, useful when `all` is True to 
+                Defaults to None, useful when `all` is True to
                 retreive all streams values.
-            all : boolean, optional
+            all: boolean, optional
                 If True, the first list of values of each object's stream
-                will be returned as a list of lists. Otherwise, only the 
-                the list of the object's identifier will be returned as a 
+                will be returned as a list of lists. Otherwise, only the
+                the list of the object's identifier will be returned as a
                 list of floats. Defaults to False.
 
         """
diff --git a/pyolib/pan.py b/pyolib/pan.py
index 54b16d7..ab68e2d 100644
--- a/pyolib/pan.py
+++ b/pyolib/pan.py
@@ -1,32 +1,34 @@
+from __future__ import division
+from __future__ import print_function
+from __future__ import absolute_import
 """
-Set of objects to manage audio voice routing and spread of a sound 
+Set of objects to manage audio voice routing and spread of a sound
 signal into a new stereo or multi-channel sound field.
- 
+
 """
 
 """
-Copyright 2010 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+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 sys, random
-from _core import *
-from _maps import *
-from types import SliceType, IntType
+from ._core import *
+from ._maps import *
 
 class Pan(PyoObject):
     """
@@ -36,15 +38,16 @@ class Pan(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        outs : int, optional
-            Number of channels on the panning circle. Defaults to 2.
-        pan : float or PyoObject
-            Position of the sound on the panning circle, between 0 and 1. 
+        outs: int, optional
+            Number of channels on the panning circle. Available at
+            initialization time only. Defaults to 2.
+        pan: float or PyoObject
+            Position of the sound on the panning circle, between 0 and 1.
             Defaults to 0.5.
-        spread : float or PyoObject
-            Amount of sound leaking to the surrounding channels, 
+        spread: float or PyoObject
+            Amount of sound leaking to the surrounding channels,
             between 0 and 1. Defaults to 0.5.
 
     >>> s = Server(nchnls=2).boot()
@@ -52,9 +55,10 @@ class Pan(PyoObject):
     >>> a = Noise(mul=.2)
     >>> lfo = Sine(freq=1, mul=.5, add=.5)
     >>> p = Pan(a, outs=2, pan=lfo).out()
-    
-    """ 
+
+    """
     def __init__(self, input, outs=2, pan=0.5, spread=0.5, mul=1, add=0):
+        pyoArgsAssert(self, "oIOOOO", input, outs, pan, spread, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._pan = pan
@@ -67,32 +71,35 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     def setPan(self, x):
         """
         Replace the `pan` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            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)]
@@ -100,13 +107,14 @@ class Pan(PyoObject):
     def setSpread(self, x):
         """
         Replace the `spread` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `spread` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._spread = x
         x, lmax = convertArgsToLists(x)
         [obj.setSpread(wrap(x,i)) for i, obj in enumerate(self._base_players)]
@@ -123,17 +131,17 @@ class Pan(PyoObject):
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
- 
+
     @property
     def pan(self):
         """float or PyoObject. Position of the sound on the panning circle."""
         return self._pan
     @pan.setter
-    def pan(self, x): self.setPan(x) 
+    def pan(self, x): self.setPan(x)
 
     @property
     def spread(self):
-        """float or PyoObject. Amount of sound leaking to the surrounding channels.""" 
+        """float or PyoObject. Amount of sound leaking to the surrounding channels."""
         return self._spread
     @spread.setter
     def spread(self, x): self.setSpread(x)
@@ -146,12 +154,13 @@ class SPan(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        outs : int, optional
-            Number of channels on the panning circle. Defaults to 2.
-        pan : float or PyoObject
-            Position of the sound on the panning circle, between 0 and 1. 
+        outs: int, optional
+            Number of channels on the panning circle. Available at
+            initialization time only. Defaults to 2.
+        pan: float or PyoObject
+            Position of the sound on the panning circle, between 0 and 1.
             Defaults to 0.5.
 
     >>> s = Server(nchnls=2).boot()
@@ -162,6 +171,7 @@ class SPan(PyoObject):
 
     """
     def __init__(self, input, outs=2, pan=0.5, mul=1, add=0):
+        pyoArgsAssert(self, "oIOOO", input, outs, pan, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._outs = outs
@@ -173,32 +183,35 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     def setPan(self, x):
         """
         Replace the `pan` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            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)]
@@ -208,14 +221,14 @@ class SPan(PyoObject):
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
-    def input(self): 
+    def input(self):
         """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
-    def pan(self): 
+    def pan(self):
         """float or PyoObject. Position of the sound on the panning circle."""
         return self._pan
     @pan.setter
@@ -235,12 +248,13 @@ class Switch(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        outs : int, optional
-            Number of outputs. Defaults to 2.
-        voice : float or PyoObject
-            Voice position pointer, between 0 and (outs-1) / len(input). 
+        outs: int, optional
+            Number of outputs. Available at initialization time only.
+            Defaults to 2.
+        voice: float or PyoObject
+            Voice position pointer, between 0 and (outs-1) / len(input).
             Defaults to 0.
 
     >>> s = Server(nchnls=2).boot()
@@ -254,6 +268,7 @@ class Switch(PyoObject):
 
     """
     def __init__(self, input, outs=2, voice=0., mul=1, add=0):
+        pyoArgsAssert(self, "oIOOO", input, outs, voice, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._outs = outs
@@ -265,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):
         """
@@ -272,12 +288,13 @@ class Switch(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
@@ -287,10 +304,11 @@ class Switch(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `voice` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._voice = x
         x, lmax = convertArgsToLists(x)
         [obj.setVoice(wrap(x,i)) for i, obj in enumerate(self._base_players)]
@@ -300,14 +318,14 @@ class Switch(PyoObject):
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
-    def input(self): 
+    def input(self):
         """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
-    def voice(self): 
+    def voice(self):
         """float or PyoObject. Voice position pointer."""
         return self._voice
     @voice.setter
@@ -317,17 +335,17 @@ class Selector(PyoObject):
     """
     Audio selector.
 
-    Selector takes multiple PyoObjects in input and interpolates between 
+    Selector takes multiple PyoObjects in input and interpolates between
     them to generate a single output.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        inputs : list of PyoObject
+        inputs: list of PyoObject
             Audio objects to interpolate from.
-        voice : float or PyoObject, optional
-            Voice position pointer, between 0 and len(inputs)-1. 
+        voice: float or PyoObject, optional
+            Voice position pointer, between 0 and len(inputs)-1.
             Defaults to 0.
 
     >>> s = Server().boot()
@@ -340,17 +358,19 @@ class Selector(PyoObject):
 
     """
     def __init__(self, inputs, voice=0., mul=1, add=0):
+        pyoArgsAssert(self, "lOOO", inputs, voice, mul, add)
         PyoObject.__init__(self, mul, add)
         self._inputs = inputs
         self._voice = voice
+        self._mode = 0
         voice, mul, add, self._lmax = convertArgsToLists(voice, mul, add)
         self._length = 1
         for obj in self._inputs:
             try:
                 if len(obj) > self._length: self._length = len(obj)
             except:
-                pass    
-        self._base_objs = []        
+                pass
+        self._base_objs = []
         for i in range(self._lmax):
             for j in range(self._length):
                 choice = []
@@ -358,62 +378,83 @@ class Selector(PyoObject):
                     try:
                         choice.append(obj[j%len(obj)])
                     except:
-                        choice.append(obj)            
+                        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):
         """
         Replace the `inputs` attribute.
-        
+
         :Args:
 
-            x : list of PyoObject
+            x: list of PyoObject
                 new `inputs` attribute.
-        
+
         """
+        pyoArgsAssert(self, "l", x)
         self._inputs = x
-        for i in range(self._lmax):           
+        for i in range(self._lmax):
             for j in range(self._length):
                 choice = []
                 for obj in self._inputs:
                     try:
                         choice.append(obj[j%len(obj)])
                     except:
-                        choice.append(obj) 
+                        choice.append(obj)
                 self._base_objs[i+j*self._lmax].setInputs(choice)
 
     def setVoice(self, x):
         """
         Replace the `voice` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `voice` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._voice = x
         x, lmax = convertArgsToLists(x)
         for i, obj in enumerate(self._base_objs):
-            obj.setVoice(wrap(x, i/self._length))
+            obj.setVoice(wrap(x, i // self._length))
+
+    def setMode(self, x):
+        """
+        Change the algorithm used to interpolate between inputs.
+
+        if inputs are phase correlated you should use a linear fade. 
+
+        :Args:
+
+            x: int {0, 1}
+                If 0 (the default) the equal power law is used to
+                interpolate bewtween sources. If 1, linear fade is
+                used instead.
+
+        """
+        pyoArgsAssert(self, "i", x)
+        self._mode = x
+        [obj.setMode(x) for obj in self._base_objs]
 
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMap(0, len(self._inputs)-1, "lin", "voice", self._voice), SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
-    def inputs(self): 
+    def inputs(self):
         """List of PyoObjects. Audio objects to interpolate from."""
         return self._inputs
     @inputs.setter
-    def inputs(self, x): 
+    def inputs(self, x):
         self.setInputs(x)
     @property
-    def voice(self): 
+    def voice(self):
         """float or PyoObject. Voice position pointer."""
         return self._voice
     @voice.setter
-    def voice(self, x): 
+    def voice(self, x):
         self.setVoice(x)
 
 class VoiceManager(PyoObject):
@@ -425,7 +466,7 @@ class VoiceManager(PyoObject):
     the same position in the list of triggers given at the argument `triggers`.
 
     Usually, the trigger enabling the voice number will come from the process
-    started with the object output. So, it's common to leave the `triggers` 
+    started with the object output. So, it's common to leave the `triggers`
     argument to None and set the list of triggers afterward with the `setTriggers`
     method. The maximum number of voices generated by the object is the length
     of the trigger list.
@@ -436,12 +477,12 @@ class VoiceManager(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Trigger stream asking for new voice numbers.
-        triggers : PyoObject or list of PyoObject, optional
+        triggers: PyoObject or list of PyoObject, optional
             List of mono PyoObject sending triggers. Can be a multi-streams
-            PyoObject but not a mix of both. 
-            
+            PyoObject but not a mix of both.
+
             Ordering in the list corresponds to voice numbers. Defaults to None.
 
     >>> s = Server().boot()
@@ -454,16 +495,17 @@ class VoiceManager(PyoObject):
     >>> amp = TrigEnv(sel, table=env, dur=.5, mul=.25)
     >>> synth1 = SineLoop(pit, feedback=.07, mul=amp).out()
     >>> vm.setTriggers(amp["trig"])
-    
+
     """
     def __init__(self, input, triggers=None, mul=1, add=0):
+        #pyoArgsAssert(self, "ooOO", input, triggers, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._triggers = triggers
         self._in_fader = InputFader(input)
         in_fader, mul, add, lmax = convertArgsToLists(self._in_fader, mul, add)
-        if triggers != None:
-            if type(triggers) == ListType:
+        if triggers is not None:
+            if type(triggers) == list:
                 try:
                     t_streams = [obj[0] for obj in triggers]
                 except TypeError:
@@ -475,35 +517,38 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setTriggers(self, x):
         """
         Replace the `triggers` attribute.
-        
+
         :Args:
 
-            x : PyoObject or list of PyoObject 
+            x: PyoObject or list of PyoObject
                 New `triggers` attribute.
 
         """
+        #pyoArgsAssert(self, "o", x)
         self._triggers = x
-        if x != None:
-            if type(x) == ListType:
+        if x is not None:
+            if type(x) == list:
                 try:
                     t_streams = [obj[0] for obj in x]
                 except TypeError:
@@ -516,38 +561,38 @@ class VoiceManager(PyoObject):
 
     @property
     def input(self):
-        """PyoObject. Trigger stream asking for new voice numbers.""" 
+        """PyoObject. Trigger stream asking for new voice numbers."""
         return self._input
     @input.setter
-    def input(self, x): 
+    def input(self, x):
         self.setInput(x)
     @property
-    def triggers(self): 
+    def triggers(self):
         """list of PyoObject. Trigger streams enabling voices."""
         return self._triggers
     @triggers.setter
-    def triggers(self, x): 
+    def triggers(self, x):
         self.setTriggers(x)
 
 class Mixer(PyoObject):
     """
     Audio mixer.
 
-    Mixer mixes multiple inputs to an arbitrary number of outputs 
-    with independant amplitude values per mixing channel and a 
+    Mixer mixes multiple inputs to an arbitrary number of outputs
+    with independant amplitude values per mixing channel and a
     user defined portamento applied on amplitude changes.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        outs : int, optional
+        outs: int, optional
             Number of outputs of the mixer. Available at initialization
             time only. Defaults to 2.
-        chnls : int, optional
+        chnls: int, optional
             Number of channels per output. Available at initialization
             time only. Defaults to 1.
-        time : float, optional
+        time: float, optional
             Duration, in seconds, of a portamento applied on
             a new amplitude value for a mixing channel.
             Defaults to 0.025.
@@ -574,13 +619,8 @@ class Mixer(PyoObject):
 
     """
     def __init__(self, outs=2, chnls=1, time=0.025, mul=1, add=0):
+        pyoArgsAssert(self, "IInOO", outs, chnls, time, mul, add)
         PyoObject.__init__(self, mul, add)
-        if type(outs) != IntType:
-            print >> sys.stderr, 'TypeError: "outs" argument of %s must be an integer.\n' % self.__class__.__name__
-            exit()
-        if type(chnls) != IntType:
-            print >> sys.stderr, 'TypeError: "chnls" argument of %s must be an integer.\n' % self.__class__.__name__
-            exit()
         self._outs = outs
         self._chnls = chnls
         self._time = time
@@ -588,14 +628,15 @@ 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) == SliceType:
-            return [self._base_objs[j*self._chnls+i] for j in range(x.start or 0, x.stop or sys.maxint, x.step or 1) for i in range(self._chnls)]
+        if type(x) == slice:
+            return [self._base_objs[j*self._chnls+i] for j in range(x.start or 0, x.stop or sys.maxsize, x.step or 1) for i in range(self._chnls)]
         elif x < len(self._base_objs):
             return [self._base_objs[x*self._chnls+i] for i in range(self._chnls)]
         else:
-            print "'x' too large!"         
+            print("'x' too large!")
 
     def setTime(self, x):
         """
@@ -603,10 +644,11 @@ class Mixer(PyoObject):
 
         :Args:
 
-            x : float
+            x: float
                 New portamento duration.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._time = x
         x, lmax = convertArgsToLists(x)
         [obj.setTime(wrap(x,i)) for i, obj in enumerate(self._base_players)]
@@ -619,19 +661,20 @@ class Mixer(PyoObject):
 
         :Args:
 
-            voice : int or string
-                Key in the mixer dictionary for this input. If None, a unique key 
+            voice: int or string
+                Key in the mixer dictionary for this input. If None, a unique key
                 between 0 and 32767 will be automatically generated.
-            input : PyoObject
+            input: PyoObject
                 Audio object to add to the mixer.
 
         """
-        if voice == None:
+        pyoArgsAssert(self, "o", input)
+        if voice is None:
             voice = random.randint(0, 32767)
-            while self._inputs.has_key(voice):
+            while voice in self._inputs:
                 voice = random.randint(0, 32767)
-        if self._inputs.has_key(voice):
-            print >> sys.stderr, "Mixer has already a key named %s" % voice
+        if voice in self._inputs:
+            print("Mixer has already a key named %s" % voice, file=sys.stderr)
             return
         self._inputs[voice] = input
         input, lmax = convertArgsToLists(input)
@@ -644,11 +687,11 @@ class Mixer(PyoObject):
 
         :Args:
 
-            voice : int or string
+            voice: int or string
                 Key in the mixer dictionary assigned to the input to remove.
 
         """
-        if self._inputs.has_key(voice):
+        if voice in self._inputs:
             del self._inputs[voice]
             [obj.delInput(str(voice)) for i, obj in enumerate(self._base_players)]
 
@@ -658,21 +701,21 @@ class Mixer(PyoObject):
 
         :Args:
 
-            vin : int or string
+            vin: int or string
                 Key in the mixer dictionary of the desired input.
-            vout : int
+            vout: int
                 Ouput channel where to send the signal.
-            amp : float
+            amp: float
                 Amplitude value for this mixing channel.
 
         """
-        if self._inputs.has_key(vin) and vout < self._outs:
+        if vin in self._inputs and vout < self._outs:
             [obj.setAmp(str(vin), vout, amp) for i, obj in enumerate(self._base_players)]
 
     def getChannels(self):
         """
         Returns the Mixer's channels dictionary.
-        
+
         """
         return self._inputs
 
@@ -681,15 +724,16 @@ class Mixer(PyoObject):
         Returns the list of current keys in the Mixer's channels dictionary.
 
         """
-        return self._inputs.keys()
-        
+        return list(self._inputs.keys())
+
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
-        self._map_list = [SLMapMul(self._mul)]
+        self._map_list = [SLMap(0, 10, 'lin', 'time', self._time, dataOnly=True),
+                          SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def time(self):
-        """float. Portamento.""" 
+        """float. Portamento."""
         return self._time
     @time.setter
     def time(self, x): self.setTime(x)
diff --git a/pyolib/pattern.py b/pyolib/pattern.py
index 851ad20..c164ff6 100644
--- a/pyolib/pattern.py
+++ b/pyolib/pattern.py
@@ -1,55 +1,67 @@
 """
-Set of objects that call Python functions from triggers or number counts. 
+Set of objects that call Python functions from triggers or number counts.
 Useful for event sequencing.
 
 """
 
+from __future__ import absolute_import
 """
-Copyright 2010 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+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 sys
-from _core import *
-from _maps import *
-from types import ListType, TupleType
+from ._core import *
+from ._maps import *
 
 class Pattern(PyoObject):
     """
     Periodically calls a Python function.
 
-    The play() method starts the pattern timer and is not called 
+    The play() method starts the pattern timer and is not called
     at the object creation time.
-            
+
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
 
-        function : Python function
+        function: Python function
             Python function to be called periodically.
-        time : float or PyoObject, optional
+        time: float or PyoObject, optional
             Time, in seconds, between each call. Default to 1.
+        arg: anything, optional
+            Argument sent to the function's call. If None, the function
+            will be called without argument. Defaults to None.
 
     .. note::
 
         The out() method is bypassed. Pattern doesn't return signal.
-        
+
         Pattern has no `mul` and `add` attributes.
 
+        If `arg` is None, the function must be defined without argument:
+
+        >>> def tocall():
+        >>>     # function's body
+
+        If `arg` is not None, the function must be defined with one argument:
+
+        >>> def tocall(arg):
+        >>>     print(arg)
+
     >>> s = Server().boot()
     >>> s.start()
     >>> t = HarmTable([1,0,.33,0,.2,0,.143,0,.111])
@@ -59,22 +71,16 @@ class Pattern(PyoObject):
     ...     a.freq = [f, f+1]
     >>> p = Pattern(pat, .125)
     >>> p.play()
-    
+
     """
-    def __init__(self, function, time=1):
+    def __init__(self, function, time=1, arg=None):
+        pyoArgsAssert(self, "cO", function, time)
         PyoObject.__init__(self)
-        if type(function) == ListType or type(function) == TupleType:
-            if not callable(function[0]):
-                print >> sys.stderr, 'TypeError: "function" argument of %s must be callable.\n' % self.__class__.__name__
-                exit()
-        else:
-            if not callable(function):
-                print >> sys.stderr, 'TypeError: "function" argument of %s must be callable.\n' % self.__class__.__name__
-                exit()
-        self._function = function
+        self._function = getWeakMethodRef(function)
         self._time = time
-        function, time, lmax = convertArgsToLists(function, time)
-        self._base_objs = [Pattern_base(wrap(function,i), wrap(time,i)) for i in range(lmax)]
+        self._arg = arg
+        function, time, arg, lmax = convertArgsToLists(function, time, arg)
+        self._base_objs = [Pattern_base(WeakMethod(wrap(function,i)), wrap(time,i), wrap(arg,i)) for i in range(lmax)]
 
     def setFunction(self, x):
         """
@@ -82,31 +88,47 @@ class Pattern(PyoObject):
 
         :Args:
 
-            x : Python function
+            x: Python function
                 new `function` attribute.
 
         """
-        self._function = x
+        pyoArgsAssert(self, "c", x)
+        self._function = getWeakMethodRef(x)
         x, lmax = convertArgsToLists(x)
-        [obj.setFunction(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+        [obj.setFunction(WeakMethod(wrap(x,i))) for i, obj in enumerate(self._base_objs)]
 
     def setTime(self, x):
         """
         Replace the `time` attribute.
-        
+
         :Args:
-        
-            x : float or PyoObject
+
+            x: float or PyoObject
                 New `time` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._time = x
         x, lmax = convertArgsToLists(x)
         [obj.setTime(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
+    def setArg(self, x):
+        """
+        Replace the `arg` attribute.
+
+        :Args:
+
+            x: Anything
+                new `arg` attribute.
+
+        """
+        self._arg = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setArg(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
     def out(self, x=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
-        
+
     def setMul(self, x):
         pass
 
@@ -122,54 +144,61 @@ class Pattern(PyoObject):
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMap(0.125, 4., 'lin', 'time', self._time)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
-         
+
     @property
     def function(self):
-        """Python function. Function to be called.""" 
+        """Python function. Function to be called."""
         return self._function
     @function.setter
-    def function(self, x): 
-        self.setFunction(x)   
+    def function(self, x):
+        self.setFunction(x)
     @property
     def time(self):
-        """float or PyoObject. Time, in seconds, between each call.""" 
+        """float or PyoObject. Time, in seconds, between each call."""
         return self._time
     @time.setter
     def time(self, x): self.setTime(x)
+    @property
+    def arg(self):
+        """Anything. Callable's argument."""
+        return self._arg
+    @arg.setter
+    def arg(self, x):
+        self.setArg(x)
 
 class Score(PyoObject):
     """
     Calls functions by incrementation of a preformatted name.
-    
+
     Score takes audio stream containning integers in input and calls
-    a function whose name is the concatenation of `fname` and the changing 
+    a function whose name is the concatenation of `fname` and the changing
     integer.
-    
-    Can be used to sequence events, first by creating functions p0, p1, 
-    p2, etc. and then, by passing a counter to a Score object with "p" 
+
+    Can be used to sequence events, first by creating functions p0, p1,
+    p2, etc. and then, by passing a counter to a Score object with "p"
     as `fname` argument. Functions are called without parameters.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Audio signal. Must contains integer numbers. Integer must change
             before calling its function again.
-        fname : string, optional
+        fname: string, optional
             Name of the functions to be called. Defaults to "event_", meaning
             that the object will call the function "event_0", "event_1", "event_2",
             and so on... Available at initialization time only.
-    
+
     .. note::
 
-        The out() method is bypassed. Score's signal can not be sent 
+        The out() method is bypassed. Score's signal can not be sent
         to audio outs.
 
         Score has no `mul` and `add` attributes.
 
     .. seealso:: :py:class:`Pattern`, :py:class:`TrigFunc`
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> a = SineLoop(freq=[200,300,400,500], feedback=0.05, mul=.1).out()
@@ -182,70 +211,83 @@ class Score(PyoObject):
     >>> m = Metro(1).play()
     >>> c = Counter(m, min=0, max=3)
     >>> sc = Score(c)
-    
+
     """
     def __init__(self, input, fname="event_"):
+        pyoArgsAssert(self, "os", input, fname)
         PyoObject.__init__(self)
         self._input = input
         self._fname = fname
         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)
 
     def setMul(self, x):
         pass
-        
+
     def setAdd(self, x):
-        pass    
+        pass
 
     def setInput(self, x, fadetime=0.05):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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)
 
     @property
-    def input(self): 
+    def input(self):
         """PyoObject. Audio signal sending integer numbers."""
         return self._input
     @input.setter
-    def input(self, x): 
+    def input(self, x):
         self.setInput(x)
 
 class CallAfter(PyoObject):
     """
     Calls a Python function after a given time.
-        
+
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
 
-        function : Python function
+        function: Python function
             Python callable execute after `time` seconds.
-        time : float, optional
+        time: float, optional
             Time, in seconds, before the call. Default to 1.
-        arg : any Python object, optional
+        arg: any Python object, optional
             Argument sent to the called function. Default to None.
-  
+
     .. note::
 
         The out() method is bypassed. CallAfter doesn't return signal.
-        
+
         CallAfter has no `mul` and `add` attributes.
-        
-        The object is not deleted after the call. The User must delete it himself.
+
+        If `arg` is None, the function must be defined without argument:
+
+        >>> def tocall():
+        >>>     # function's body
+
+        If `arg` is not None, the function must be defined with one argument:
+
+        >>> def tocall(arg):
+        >>>     print(arg)
+
+        The object is not deleted after the call. The user must delete it himself.
 
     >>> s = Server().boot()
     >>> s.start()
@@ -258,22 +300,16 @@ class CallAfter(PyoObject):
 
     """
     def __init__(self, function, time=1, arg=None):
+        pyoArgsAssert(self, "cn", function, time)
         PyoObject.__init__(self)
-        if type(function) == ListType or type(function) == TupleType:
-            if not callable(function[0]):
-                print >> sys.stderr, 'TypeError: "function" argument of %s must be callable.\n' % self.__class__.__name__
-                exit()
-        else:
-            if not callable(function):
-                print >> sys.stderr, 'TypeError: "function" argument of %s must be callable.\n' % self.__class__.__name__
-                exit()
-        self._function = function
+        self._function = getWeakMethodRef(function)
         function, time, arg, lmax = convertArgsToLists(function, time, arg)
-        self._base_objs = [CallAfter_base(wrap(function,i), wrap(time,i), wrap(arg,i)) for i in range(lmax)]
+        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)
-        
+
     def setMul(self, x):
         pass
 
diff --git a/pyolib/phasevoc.py b/pyolib/phasevoc.py
index bb4f5e5..0bc1774 100644
--- a/pyolib/phasevoc.py
+++ b/pyolib/phasevoc.py
@@ -1,67 +1,68 @@
 """
 Phase vocoder.
 
-The phase vocoder is a digital signal processing technique of potentially 
-great musical significance. It can be used to perform very high fidelity 
+The phase vocoder is a digital signal processing technique of potentially
+great musical significance. It can be used to perform very high fidelity
 time scaling, pitch transposition, and myriad other modifications of sounds.
 
 """
 
+from __future__ import absolute_import
 """
-Copyright 2011 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+You should have received a copy of the GNU Lesser General Public
+License along with pyo.  If not, see <http://www.gnu.org/licenses/>.
 """
-from _core import *
-from _maps import *
-from _widgets import createSpectrumWindow
-from pattern import Pattern
+from ._core import *
+from ._maps import *
+from ._widgets import createSpectrumWindow
+from .pattern import Pattern
 
 class PVAnal(PyoPVObject):
     """
     Phase Vocoder analysis object.
 
     PVAnal takes an input sound and performs the phase vocoder
-    analysis on it. This results in two streams, one for the bin's 
-    magnitudes and the other for the bin's true frequencies. These 
-    two streams are used by the PVxxx object family to transform 
+    analysis on it. This results in two streams, one for the bin's
+    magnitudes and the other for the bin's true frequencies. These
+    two streams are used by the PVxxx object family to transform
     the input signal using spectral domain algorithms. The last
     object in the phase vocoder chain must be a PVSynth to perform
     the spectral to time domain conversion.
-    
+
     :Parent: :py:class:`PyoPVObject`
-    
+
     :Args:
-    
-        input : PyoObject
+
+        input: PyoObject
             Input signal to process.
-        size : int {pow-of-two > 4}, optional
+        size: int {pow-of-two > 4}, optional
             FFT size. Must be a power of two greater than 4.
             Defaults to 1024.
 
             The FFT size is the number of samples used in each
-            analysis frame. 
-        overlaps : int, optional
+            analysis frame.
+        overlaps: int, optional
             The number of overlaped analysis block. Must be a
             power of two. Defaults to 4.
-            
-            More overlaps can greatly improved sound quality 
+
+            More overlaps can greatly improved sound quality
             synthesis but it is also more CPU expensive.
-        wintype : int, optional
+        wintype: int, optional
             Shape of the envelope used to filter each input frame.
             Possible shapes are:
                 0. rectangular (no windowing)
@@ -82,6 +83,7 @@ class PVAnal(PyoPVObject):
 
     """
     def __init__(self, input, size=1024, overlaps=4, wintype=2):
+        pyoArgsAssert(self, "oiii", input, size, overlaps, wintype)
         PyoPVObject.__init__(self)
         self._input = input
         self._size = size
@@ -90,32 +92,35 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     def setSize(self, x):
         """
         Replace the `size` attribute.
-        
+
         :Args:
 
-            x : int
+            x: int
                 new `size` attribute.
-        
+
         """
+        pyoArgsAssert(self, "i", x)
         self._size = x
         x, lmax = convertArgsToLists(x)
         [obj.setSize(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -123,13 +128,14 @@ class PVAnal(PyoPVObject):
     def setOverlaps(self, x):
         """
         Replace the `overlaps` attribute.
-        
+
         :Args:
 
-            x : int
+            x: int
                 new `overlaps` attribute.
-        
+
         """
+        pyoArgsAssert(self, "i", x)
         self._overlaps = x
         x, lmax = convertArgsToLists(x)
         [obj.setOverlaps(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -137,12 +143,12 @@ class PVAnal(PyoPVObject):
     def setWinType(self, x):
         """
         Replace the `wintype` attribute.
-        
+
         :Args:
 
-            x : int
+            x: int
                 new `wintype` attribute.
-        
+
         """
         self._wintype = x
         x, lmax = convertArgsToLists(x)
@@ -150,7 +156,7 @@ class PVAnal(PyoPVObject):
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -184,15 +190,15 @@ class PVSynth(PyoObject):
     the spectral to time domain conversion on it. This step
     converts phase vocoder magnitude and true frequency's
     streams back to a real signal.
-    
+
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
-    
-        input : PyoPVObject
+
+        input: PyoPVObject
             Phase vocoder streaming object to process.
-        wintype : int, optional
-            Shape of the envelope used to filter each input frame. 
+        wintype: int, optional
+            Shape of the envelope used to filter each input frame.
             Possible shapes are:
                 0. rectangular (no windowing)
                 1. Hamming
@@ -212,22 +218,25 @@ class PVSynth(PyoObject):
 
     """
     def __init__(self, input, wintype=2, mul=1, add=0):
+        pyoArgsAssert(self, "piOO", input, wintype, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoPVObject
+            x: PyoPVObject
                 New signal to process.
 
         """
+        pyoArgsAssert(self, "p", x)
         self._input = x
         x, lmax = convertArgsToLists(x)
         [obj.setInput(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -235,13 +244,14 @@ class PVSynth(PyoObject):
     def setWinType(self, x):
         """
         Replace the `wintype` attribute.
-        
+
         :Args:
 
-            x : int
+            x: int
                 new `wintype` attribute.
-        
+
         """
+        pyoArgsAssert(self, "i", x)
         self._wintype = x
         x, lmax = convertArgsToLists(x)
         [obj.setWinType(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -252,7 +262,7 @@ class PVSynth(PyoObject):
 
     @property
     def input(self):
-        """PyoPVObject. Input signal to process.""" 
+        """PyoPVObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -269,37 +279,38 @@ class PVAddSynth(PyoObject):
     Phase Vocoder additive synthesis object.
 
     PVAddSynth takes a PyoPVObject as its input and resynthesize
-    the real signal using the magnitude and true frequency's 
-    streams to control amplitude and frequency envelopes of an 
+    the real signal using the magnitude and true frequency's
+    streams to control amplitude and frequency envelopes of an
     oscillator bank.
 
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
-    
-        input : PyoPVObject
+
+        input: PyoPVObject
             Phase vocoder streaming object to process.
-        pitch : float or PyoObject, optional
+        pitch: float or PyoObject, optional
             Transposition factor. Defaults to 1.
-        num : int, optional
+        num: int, optional
             Number of oscillators used to synthesize the
             output sound. Defaults to 100.
-        first : int, optional
-            The first bin to synthesize, starting from 0. 
+        first: int, optional
+            The first bin to synthesize, starting from 0.
             Defaults to 0.
-        inc : int, optional
-            Starting from bin `first`, resynthesize bins 
-            `inc` apart. Defaults to 1. 
-            
+        inc: int, optional
+            Starting from bin `first`, resynthesize bins
+            `inc` apart. Defaults to 1.
+
 
     >>> s = Server().boot()
     >>> s.start()
     >>> a = SfPlayer(SNDS_PATH+"/transparent.aif", loop=True, mul=0.7)
-    >>> pva = PVAnal(a, size=1024, overlaps=4, pitch=2)
-    >>> pvs = PVAddSynth(pva, pitch=1.25, num=100, first=0, inc=2)
+    >>> pva = PVAnal(a, size=1024, overlaps=4, wintype=2)
+    >>> pvs = PVAddSynth(pva, pitch=1.25, num=100, first=0, inc=2).out()
 
     """
     def __init__(self, input, pitch=1, num=100, first=0, inc=1, mul=1, add=0):
+        pyoArgsAssert(self, "pOiiiOO", input, pitch, num, first, inc, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._pitch = pitch
@@ -308,17 +319,19 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoPVObject
+            x: PyoPVObject
                 New signal to process.
 
         """
+        pyoArgsAssert(self, "p", x)
         self._input = x
         x, lmax = convertArgsToLists(x)
         [obj.setInput(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -326,13 +339,14 @@ class PVAddSynth(PyoObject):
     def setPitch(self, x):
         """
         Replace the `pitch` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            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_objs)]
@@ -340,13 +354,14 @@ class PVAddSynth(PyoObject):
     def setNum(self, x):
         """
         Replace the `num` attribute.
-        
+
         :Args:
 
-            x : int
+            x: int
                 new `num` attribute.
-        
+
         """
+        pyoArgsAssert(self, "i", x)
         self._num = x
         x, lmax = convertArgsToLists(x)
         [obj.setNum(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -354,13 +369,14 @@ class PVAddSynth(PyoObject):
     def setFirst(self, x):
         """
         Replace the `first` attribute.
-        
+
         :Args:
 
-            x : int
+            x: int
                 new `first` attribute.
-        
+
         """
+        pyoArgsAssert(self, "i", x)
         self._first = x
         x, lmax = convertArgsToLists(x)
         [obj.setFirst(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -368,13 +384,14 @@ class PVAddSynth(PyoObject):
     def setInc(self, x):
         """
         Replace the `inc` attribute.
-        
+
         :Args:
 
-            x : int
+            x: int
                 new `inc` attribute.
-        
+
         """
+        pyoArgsAssert(self, "i", x)
         self._inc = x
         x, lmax = convertArgsToLists(x)
         [obj.setInc(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -386,7 +403,7 @@ class PVAddSynth(PyoObject):
 
     @property
     def input(self):
-        """PyoPVObject. Input signal to process.""" 
+        """PyoPVObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -422,14 +439,14 @@ class PVAddSynth(PyoObject):
 class PVTranspose(PyoPVObject):
     """
     Transpose the frequency components of a pv stream.
-    
+
     :Parent: :py:class:`PyoPVObject`
-    
+
     :Args:
-    
-        input : PyoPVObject
+
+        input: PyoPVObject
             Phase vocoder streaming object to process.
-        transpo : float or PyoObject, optional
+        transpo: float or PyoObject, optional
             Transposition factor. Defaults to 1.
 
     >>> s = Server().boot()
@@ -442,22 +459,25 @@ class PVTranspose(PyoPVObject):
 
     """
     def __init__(self, input, transpo=1):
+        pyoArgsAssert(self, "pO", input, transpo)
         PyoPVObject.__init__(self)
         self._input = input
         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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoPVObject
+            x: PyoPVObject
                 New signal to process.
 
         """
+        pyoArgsAssert(self, "p", x)
         self._input = x
         x, lmax = convertArgsToLists(x)
         [obj.setInput(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -465,13 +485,14 @@ class PVTranspose(PyoPVObject):
     def setTranspo(self, x):
         """
         Replace the `transpo` attribute.
-        
+
         :Args:
 
-            x : int
+            x: int
                 new `transpo` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._transpo = x
         x, lmax = convertArgsToLists(x)
         [obj.setTranspo(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -482,7 +503,7 @@ class PVTranspose(PyoPVObject):
 
     @property
     def input(self):
-        """PyoPVObject. Input signal to process.""" 
+        """PyoPVObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -502,13 +523,13 @@ class PVVerb(PyoPVObject):
 
     :Args:
 
-        input : PyoPVObject
+        input: PyoPVObject
             Phase vocoder streaming object to process.
-        revtime : float or PyoObject, optional
-            Reverberation factor, between 0 and 1. 
+        revtime: float or PyoObject, optional
+            Reverberation factor, between 0 and 1.
             Defaults to 0.75.
-        damp : float or PyoObject, optional
-            High frequency damping factor, between 0 and 1. 
+        damp: float or PyoObject, optional
+            High frequency damping factor, between 0 and 1.
             1 means no damping and 0 is the most damping.
             Defaults to 0.75.
 
@@ -523,23 +544,26 @@ class PVVerb(PyoPVObject):
 
     """
     def __init__(self, input, revtime=0.75, damp=0.75):
+        pyoArgsAssert(self, "pOO", input, revtime, damp)
         PyoPVObject.__init__(self)
         self._input = input
         self._revtime = revtime
         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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoPVObject
+            x: PyoPVObject
                 New signal to process.
 
         """
+        pyoArgsAssert(self, "p", x)
         self._input = x
         x, lmax = convertArgsToLists(x)
         [obj.setInput(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -547,13 +571,14 @@ class PVVerb(PyoPVObject):
     def setRevtime(self, x):
         """
         Replace the `revtime` attribute.
-        
+
         :Args:
 
-            x : int
+            x: int
                 new `revtime` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._revtime = x
         x, lmax = convertArgsToLists(x)
         [obj.setRevtime(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -561,13 +586,14 @@ class PVVerb(PyoPVObject):
     def setDamp(self, x):
         """
         Replace the `damp` attribute.
-        
+
         :Args:
 
-            x : int
+            x: int
                 new `damp` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._damp = x
         x, lmax = convertArgsToLists(x)
         [obj.setDamp(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -579,7 +605,7 @@ class PVVerb(PyoPVObject):
 
     @property
     def input(self):
-        """PyoPVObject. Input signal to process.""" 
+        """PyoPVObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -590,7 +616,7 @@ class PVVerb(PyoPVObject):
         return self._revtime
     @revtime.setter
     def revtime(self, x): self.setRevtime(x)
-    
+
     @property
     def damp(self):
         """float or PyoObject. High frequency damping factor."""
@@ -606,13 +632,18 @@ class PVGate(PyoPVObject):
 
     :Args:
 
-        input : PyoPVObject
+        input: PyoPVObject
             Phase vocoder streaming object to process.
-        thresh : float or PyoObject, optional
+        thresh: float or PyoObject, optional
             Threshold factor in dB. Bins below that threshold
             will be scaled by `damp` factor. Defaults to -20.
-        damp : float or PyoObject, optional
+        damp: float or PyoObject, optional
             Damping factor for low amplitude bins. Defaults to 0.
+        inverse: boolean, optional
+            If True, the damping factor will be applied to the bins
+            with amplitude above the given threshold. If False, the
+            damping factor is applied to bins with amplitude below
+            the given threshold. Defaults to False.
 
     >>> s = Server().boot()
     >>> s.start()
@@ -622,24 +653,28 @@ class PVGate(PyoPVObject):
     >>> pvs = PVSynth(pvg).mix(2).out()
 
     """
-    def __init__(self, input, thresh=-20, damp=0.):
+    def __init__(self, input, thresh=-20, damp=0., inverse=False):
+        pyoArgsAssert(self, "pOOb", input, thresh, damp, inverse)
         PyoPVObject.__init__(self)
         self._input = input
         self._thresh = thresh
         self._damp = damp
-        input, thresh, damp, lmax = convertArgsToLists(self._input, thresh, damp)
-        self._base_objs = [PVGate_base(wrap(input,i), wrap(thresh,i), wrap(damp,i)) for i in range(lmax)]
- 
+        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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoPVObject
+            x: PyoPVObject
                 New signal to process.
 
         """
+        pyoArgsAssert(self, "p", x)
         self._input = x
         x, lmax = convertArgsToLists(x)
         [obj.setInput(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -647,13 +682,14 @@ class PVGate(PyoPVObject):
     def setThresh(self, x):
         """
         Replace the `thresh` attribute.
-        
+
         :Args:
 
-            x : int
+            x: int
                 new `thresh` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._thresh = x
         x, lmax = convertArgsToLists(x)
         [obj.setThresh(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -661,17 +697,33 @@ class PVGate(PyoPVObject):
     def setDamp(self, x):
         """
         Replace the `damp` attribute.
-        
+
         :Args:
 
-            x : int
+            x: int
                 new `damp` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._damp = x
         x, lmax = convertArgsToLists(x)
         [obj.setDamp(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
+    def setInverse(self, x):
+        """
+        Replace the `inverse` attribute.
+
+        :Args:
+
+            x: boolean
+                new `inverse` attribute.
+
+        """
+        pyoArgsAssert(self, "b", x)
+        self._inverse = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setInverse(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(-120, 18, "lin", "thresh", self._thresh),
                           SLMap(0, 2, "lin", "damp", self._damp)]
@@ -679,7 +731,7 @@ class PVGate(PyoPVObject):
 
     @property
     def input(self):
-        """PyoPVObject. Input signal to process.""" 
+        """PyoPVObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -690,7 +742,7 @@ class PVGate(PyoPVObject):
         return self._thresh
     @thresh.setter
     def thresh(self, x): self.setThresh(x)
-    
+
     @property
     def damp(self):
         """float or PyoObject. Damping factor for low amplitude bins."""
@@ -698,30 +750,37 @@ class PVGate(PyoPVObject):
     @damp.setter
     def damp(self, x): self.setDamp(x)
 
+    @property
+    def inverse(self):
+        """boolean. If True, the gate is applied to high amplitude bins."""
+        return self._inverse
+    @inverse.setter
+    def inverse(self, x): self.setInverse(x)
+
 class PVCross(PyoPVObject):
     """
     Performs cross-synthesis between two phase vocoder streaming object.
-    
+
     The amplitudes from `input` and `input2` (scaled by `fade` argument)
     are applied to the frequencies of `input`.
 
     :Parent: :py:class:`PyoPVObject`
-    
+
     :Args:
-    
-        input : PyoPVObject
+
+        input: PyoPVObject
             Phase vocoder streaming object to process. Frequencies from
             this pv stream are used to compute the output signal.
-        input2 : PyoPVObject
+        input2: PyoPVObject
             Phase vocoder streaming object which gives the second set of
             magnitudes. Frequencies from this pv stream are not used.
-        fade : float or PyoObject, optional
-            Scaling factor for the output amplitudes, between 0 and 1. 
-            0 means amplitudes from `input` and 1 means amplitudes from `input2`. 
+        fade: float or PyoObject, optional
+            Scaling factor for the output amplitudes, between 0 and 1.
+            0 means amplitudes from `input` and 1 means amplitudes from `input2`.
             Defaults to 1.
 
     .. note::
-        
+
         The two input pv stream must have the same size and overlaps. It is
         the responsibility of the user to be sure they are consistent. To change
         the size (or the overlaps) of the phase vocoder process, one must
@@ -746,23 +805,26 @@ class PVCross(PyoPVObject):
 
     """
     def __init__(self, input, input2, fade=1):
+        pyoArgsAssert(self, "ppO", input, input2, fade)
         PyoPVObject.__init__(self)
         self._input = input
         self._input2 = input2
         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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoPVObject
+            x: PyoPVObject
                 New signal to process.
 
         """
+        pyoArgsAssert(self, "p", x)
         self._input = x
         x, lmax = convertArgsToLists(x)
         [obj.setInput(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -770,13 +832,14 @@ class PVCross(PyoPVObject):
     def setInput2(self, x):
         """
         Replace the `input2` attribute.
-        
+
         :Args:
 
-            x : PyoPVObject
+            x: PyoPVObject
                 New signal to process.
 
         """
+        pyoArgsAssert(self, "p", x)
         self._input2 = x
         x, lmax = convertArgsToLists(x)
         [obj.setInput2(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -784,13 +847,14 @@ class PVCross(PyoPVObject):
     def setFade(self, x):
         """
         Replace the `fade` attribute.
-        
+
         :Args:
 
-            x : int
+            x: float or PyoObject
                 new `fade` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._fade = x
         x, lmax = convertArgsToLists(x)
         [obj.setFade(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -801,14 +865,14 @@ class PVCross(PyoPVObject):
 
     @property
     def input(self):
-        """PyoPVObject. Input signal to process.""" 
+        """PyoPVObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def input2(self):
-        """PyoPVObject. Second set of amplitudes.""" 
+        """PyoPVObject. Second set of amplitudes."""
         return self._input2
     @input2.setter
     def input2(self, x): self.setInput2(x)
@@ -825,18 +889,18 @@ class PVMult(PyoPVObject):
     Multiply magnitudes from two phase vocoder streaming object.
 
     :Parent: :py:class:`PyoPVObject`
-    
+
     :Args:
-    
-        input : PyoPVObject
+
+        input: PyoPVObject
             Phase vocoder streaming object to process. Frequencies from
             this pv stream are used to compute the output signal.
-        input2 : PyoPVObject
+        input2: PyoPVObject
             Phase vocoder streaming object which gives the second set of
             magnitudes. Frequencies from this pv stream are not used.
 
     .. note::
-        
+
         The two input pv stream must have the same size and overlaps. It is
         the responsibility of the user to be sure they are consistent. To change
         the size (or the overlaps) of the phase vocoder process, one must
@@ -861,22 +925,25 @@ class PVMult(PyoPVObject):
 
     """
     def __init__(self, input, input2):
+        pyoArgsAssert(self, "pp", input, input2)
         PyoPVObject.__init__(self)
         self._input = input
         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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoPVObject
+            x: PyoPVObject
                 New signal to process.
 
         """
+        pyoArgsAssert(self, "p", x)
         self._input = x
         x, lmax = convertArgsToLists(x)
         [obj.setInput(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -884,27 +951,28 @@ class PVMult(PyoPVObject):
     def setInput2(self, x):
         """
         Replace the `input2` attribute.
-        
+
         :Args:
 
-            x : PyoPVObject
+            x: PyoPVObject
                 New signal to process.
 
         """
+        pyoArgsAssert(self, "p", x)
         self._input2 = x
         x, lmax = convertArgsToLists(x)
         [obj.setInput2(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     @property
     def input(self):
-        """PyoPVObject. Input signal to process.""" 
+        """PyoPVObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def input2(self):
-        """PyoPVObject. Second set of magnitudes.""" 
+        """PyoPVObject. Second set of magnitudes."""
         return self._input2
     @input2.setter
     def input2(self, x): self.setInput2(x)
@@ -912,27 +980,27 @@ class PVMult(PyoPVObject):
 class PVMorph(PyoPVObject):
     """
     Performs spectral morphing between two phase vocoder streaming object.
-    
-    According to `fade` argument, the amplitudes from `input` and `input2` 
+
+    According to `fade` argument, the amplitudes from `input` and `input2`
     are interpolated linearly while the frequencies are interpolated
     exponentially.
 
     :Parent: :py:class:`PyoPVObject`
-    
+
     :Args:
-    
-        input : PyoPVObject
+
+        input: PyoPVObject
             Phase vocoder streaming object which gives the first set of
             magnitudes and frequencies.
-        input2 : PyoPVObject
+        input2: PyoPVObject
             Phase vocoder streaming object which gives the second set of
             magnitudes and frequencies.
-        fade : float or PyoObject, optional
-            Scaling factor for the output amplitudes and frequencies, 
+        fade: float or PyoObject, optional
+            Scaling factor for the output amplitudes and frequencies,
             between 0 and 1. 0 is `input` and 1 in `input2`. Defaults to 0.5.
 
     .. note::
-        
+
         The two input pv stream must have the same size and overlaps. It is
         the responsibility of the user to be sure they are consistent. To change
         the size (or the overlaps) of the phase vocoder process, one must
@@ -957,23 +1025,26 @@ class PVMorph(PyoPVObject):
 
     """
     def __init__(self, input, input2, fade=0.5):
+        pyoArgsAssert(self, "ppO", input, input2, fade)
         PyoPVObject.__init__(self)
         self._input = input
         self._input2 = input2
         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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoPVObject
+            x: PyoPVObject
                 New signal to process.
 
         """
+        pyoArgsAssert(self, "p", x)
         self._input = x
         x, lmax = convertArgsToLists(x)
         [obj.setInput(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -981,13 +1052,14 @@ class PVMorph(PyoPVObject):
     def setInput2(self, x):
         """
         Replace the `input2` attribute.
-        
+
         :Args:
 
-            x : PyoPVObject
+            x: PyoPVObject
                 New signal to process.
 
         """
+        pyoArgsAssert(self, "p", x)
         self._input2 = x
         x, lmax = convertArgsToLists(x)
         [obj.setInput2(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -995,13 +1067,14 @@ class PVMorph(PyoPVObject):
     def setFade(self, x):
         """
         Replace the `fade` attribute.
-        
+
         :Args:
 
-            x : int
+            x: float or PyoObject
                 new `fade` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._fade = x
         x, lmax = convertArgsToLists(x)
         [obj.setFade(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1012,14 +1085,14 @@ class PVMorph(PyoPVObject):
 
     @property
     def input(self):
-        """PyoPVObject. First input signal.""" 
+        """PyoPVObject. First input signal."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def input2(self):
-        """PyoPVObject. Second input signal.""" 
+        """PyoPVObject. Second input signal."""
         return self._input2
     @input2.setter
     def input2(self, x): self.setInput2(x)
@@ -1034,28 +1107,28 @@ class PVMorph(PyoPVObject):
 class PVFilter(PyoPVObject):
     """
     Spectral filter.
-    
+
     PVFilter filters frequency components of a pv stream
     according to the shape drawn in the table given in
     argument.
-    
+
     :Parent: :py:class:`PyoPVObject`
-    
+
     :Args:
-    
-        input : PyoPVObject
+
+        input: PyoPVObject
             Phase vocoder streaming object to process.
-        table : PyoTableObject
-            Table containing the filter shape. If the 
+        table: PyoTableObject
+            Table containing the filter shape. If the
             table length is smaller than fftsize/2,
             remaining bins will be set to 0.
-        gain : float or PyoObject, optional
-            Gain of the filter applied to the input spectrum. 
+        gain: float or PyoObject, optional
+            Gain of the filter applied to the input spectrum.
             Defaults to 1.
-        mode : int, optional
+        mode: int, optional
             Table scanning mode. Defaults to 0.
-            
-            If 0, bin indexes outside table size are set to 0. 
+
+            If 0, bin indexes outside table size are set to 0.
             If 1, bin indexes are scaled over table length.
 
     >>> s = Server().boot()
@@ -1068,6 +1141,7 @@ class PVFilter(PyoPVObject):
 
     """
     def __init__(self, input, table, gain=1, mode=0):
+        pyoArgsAssert(self, "ptOi", input, table, gain, mode)
         PyoPVObject.__init__(self)
         self._input = input
         self._table = table
@@ -1075,17 +1149,19 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoPVObject
+            x: PyoPVObject
                 New signal to process.
 
         """
+        pyoArgsAssert(self, "p", x)
         self._input = x
         x, lmax = convertArgsToLists(x)
         [obj.setInput(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1093,13 +1169,14 @@ class PVFilter(PyoPVObject):
     def setTable(self, x):
         """
         Replace the `table` attribute.
-        
+
         :Args:
 
-            x : PyoTableObject
+            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)]
@@ -1107,13 +1184,14 @@ class PVFilter(PyoPVObject):
     def setGain(self, x):
         """
         Replace the `gain` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `gain` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._gain = x
         x, lmax = convertArgsToLists(x)
         [obj.setGain(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1121,13 +1199,14 @@ class PVFilter(PyoPVObject):
     def setMode(self, x):
         """
         Replace the `mode` attribute.
-        
+
         :Args:
 
-            x : int
+            x: int
                 new `mode` attribute.
-        
+
         """
+        pyoArgsAssert(self, "i", x)
         self._mode = x
         x, lmax = convertArgsToLists(x)
         [obj.setMode(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1138,14 +1217,14 @@ class PVFilter(PyoPVObject):
 
     @property
     def input(self):
-        """PyoPVObject. Input signal to process.""" 
+        """PyoPVObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def table(self):
-        """PyoTableObject. Table containing the filter shape.""" 
+        """PyoTableObject. Table containing the filter shape."""
         return self._table
     @table.setter
     def table(self, x): self.setTable(x)
@@ -1167,35 +1246,35 @@ class PVFilter(PyoPVObject):
 class PVDelay(PyoPVObject):
     """
     Spectral delays.
-    
+
     PVDelay applies different delay times and feedbacks for
-    each bin of a phase vocoder analysis. Delay times and 
+    each bin of a phase vocoder analysis. Delay times and
     feedbacks are specified with PyoTableObjects.
-    
+
     :Parent: :py:class:`PyoPVObject`
-    
+
     :Args:
-    
-        input : PyoPVObject
+
+        input: PyoPVObject
             Phase vocoder streaming object to process.
-        deltable : PyoTableObject
+        deltable: PyoTableObject
             Table containing delay times, as integer multipliers
-            of the FFT hopsize (fftsize / overlaps). 
-            
+            of the FFT hopsize (fftsize / overlaps).
+
             If the table length is smaller than fftsize/2,
             remaining bins will be set to 0.
-        feedtable : PyoTableObject
-            Table containing feedback values, between -1 and 1. 
-            
+        feedtable: PyoTableObject
+            Table containing feedback values, between -1 and 1.
+
             If the table length is smaller than fftsize/2,
             remaining bins will be set to 0.
-        maxdelay : float, optional
-            Maximum delay time in seconds. Available at initialization 
+        maxdelay: float, optional
+            Maximum delay time in seconds. Available at initialization
             time only. Defaults to 1.0.
-        mode : int, optional
+        mode: int, optional
             Tables scanning mode. Defaults to 0.
-            
-            If 0, bin indexes outside table size are set to 0. 
+
+            If 0, bin indexes outside table size are set to 0.
             If 1, bin indexes are scaled over table length.
 
     >>> s = Server().boot()
@@ -1215,6 +1294,7 @@ class PVDelay(PyoPVObject):
 
     """
     def __init__(self, input, deltable, feedtable, maxdelay=1.0, mode=0):
+        pyoArgsAssert(self, "pttni", input, deltable, feedtable, maxdelay, mode)
         PyoPVObject.__init__(self)
         self._input = input
         self._deltable = deltable
@@ -1223,17 +1303,19 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoPVObject
+            x: PyoPVObject
                 New signal to process.
 
         """
+        pyoArgsAssert(self, "p", x)
         self._input = x
         x, lmax = convertArgsToLists(x)
         [obj.setInput(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1241,13 +1323,14 @@ class PVDelay(PyoPVObject):
     def setDeltable(self, x):
         """
         Replace the `deltable` attribute.
-        
+
         :Args:
 
-            x : PyoTableObject
+            x: PyoTableObject
                 new `deltable` attribute.
-        
+
         """
+        pyoArgsAssert(self, "t", x)
         self._deltable = x
         x, lmax = convertArgsToLists(x)
         [obj.setDeltable(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1255,13 +1338,14 @@ class PVDelay(PyoPVObject):
     def setFeedtable(self, x):
         """
         Replace the `feedtable` attribute.
-        
+
         :Args:
 
-            x : PyoTableObject
+            x: PyoTableObject
                 new `feedtable` attribute.
-        
+
         """
+        pyoArgsAssert(self, "t", x)
         self._feedtable = x
         x, lmax = convertArgsToLists(x)
         [obj.setFeedtable(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1269,27 +1353,28 @@ class PVDelay(PyoPVObject):
     def setMode(self, x):
         """
         Replace the `mode` attribute.
-        
+
         :Args:
 
-            x : int
+            x: int
                 new `mode` attribute.
-        
+
         """
+        pyoArgsAssert(self, "i", x)
         self._mode = x
         x, lmax = convertArgsToLists(x)
         [obj.setMode(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     @property
     def input(self):
-        """PyoPVObject. Input signal to process.""" 
+        """PyoPVObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def deltable(self):
-        """PyoTableObject. Table containing the delay times.""" 
+        """PyoTableObject. Table containing the delay times."""
         return self._deltable
     @deltable.setter
     def deltable(self, x): self.setDeltable(x)
@@ -1311,28 +1396,28 @@ class PVDelay(PyoPVObject):
 class PVBuffer(PyoPVObject):
     """
     Phase vocoder buffer and playback with transposition.
-    
+
     PVBuffer keeps `length` seconds of pv analysis in memory
     and gives control on playback position and transposition.
-    
+
     :Parent: :py:class:`PyoPVObject`
-    
+
     :Args:
-    
-        input : PyoPVObject
+
+        input: PyoPVObject
             Phase vocoder streaming object to process.
-        index : PyoObject
-            Playback position, as audio stream, normalized 
-            between 0 and 1. 
-        pitch : float or PyoObject, optional
+        index: PyoObject
+            Playback position, as audio stream, normalized
+            between 0 and 1.
+        pitch: float or PyoObject, optional
             Transposition factor. Defaults to 1.
-        length : float, optional
-            Memory length in seconds. Available at initialization 
+        length: float, optional
+            Memory length in seconds. Available at initialization
             time only. Defaults to 1.0.
 
     .. note::
-        
-        The play() method can be called to start a new recording of 
+
+        The play() method can be called to start a new recording of
         the current pv input.
 
     >>> s = Server().boot()
@@ -1347,6 +1432,7 @@ class PVBuffer(PyoPVObject):
 
     """
     def __init__(self, input, index, pitch=1.0, length=1.0):
+        pyoArgsAssert(self, "poOn", input, index, pitch, length)
         PyoPVObject.__init__(self)
         self._input = input
         self._index = index
@@ -1354,17 +1440,19 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoPVObject
+            x: PyoPVObject
                 New signal to process.
 
         """
+        pyoArgsAssert(self, "p", x)
         self._input = x
         x, lmax = convertArgsToLists(x)
         [obj.setInput(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1372,13 +1460,14 @@ class PVBuffer(PyoPVObject):
     def setIndex(self, x):
         """
         Replace the `index` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 new `index` attribute.
-        
+
         """
+        pyoArgsAssert(self, "o", x)
         self._index = x
         x, lmax = convertArgsToLists(x)
         [obj.setIndex(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1386,13 +1475,14 @@ class PVBuffer(PyoPVObject):
     def setPitch(self, x):
         """
         Replace the `pitch` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            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_objs)]
@@ -1403,14 +1493,14 @@ class PVBuffer(PyoPVObject):
 
     @property
     def input(self):
-        """PyoPVObject. Input signal to process.""" 
+        """PyoPVObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def index(self):
-        """PyoObject. Reader's normalized position.""" 
+        """PyoObject. Reader's normalized position."""
         return self._index
     @index.setter
     def index(self, x): self.setIndex(x)
@@ -1425,17 +1515,17 @@ class PVBuffer(PyoPVObject):
 class PVShift(PyoPVObject):
     """
     Spectral domain frequency shifter.
-    
+
     PVShift linearly moves the analysis bins by the amount, in Hertz,
-    specified by the the `shift` argument. 
-    
+    specified by the the `shift` argument.
+
     :Parent: :py:class:`PyoPVObject`
-    
+
     :Args:
-    
-        input : PyoPVObject
+
+        input: PyoPVObject
             Phase vocoder streaming object to process.
-        shift : float or PyoObject, optional
+        shift: float or PyoObject, optional
             Frequency shift factor. Defaults to 0.
 
     >>> s = Server().boot()
@@ -1447,22 +1537,25 @@ class PVShift(PyoPVObject):
 
     """
     def __init__(self, input, shift=0):
+        pyoArgsAssert(self, "pO", input, shift)
         PyoPVObject.__init__(self)
         self._input = input
         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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoPVObject
+            x: PyoPVObject
                 New signal to process.
 
         """
+        pyoArgsAssert(self, "p", x)
         self._input = x
         x, lmax = convertArgsToLists(x)
         [obj.setInput(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1470,13 +1563,14 @@ class PVShift(PyoPVObject):
     def setShift(self, x):
         """
         Replace the `shift` attribute.
-        
+
         :Args:
 
-            x : int
+            x: float or PyoObject
                 new `shift` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._shift = x
         x, lmax = convertArgsToLists(x)
         [obj.setShift(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1487,7 +1581,7 @@ class PVShift(PyoPVObject):
 
     @property
     def input(self):
-        """PyoPVObject. Input signal to process.""" 
+        """PyoPVObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -1502,15 +1596,15 @@ class PVShift(PyoPVObject):
 class PVAmpMod(PyoPVObject):
     """
     Performs frequency independent amplitude modulations.
-    
-    PVAmpMod modulates the magnitude of each bin of a pv 
-    stream with an independent oscillator. `basefreq` and 
-    `spread` are used to derive the frequency of each 
+
+    PVAmpMod modulates the magnitude of each bin of a pv
+    stream with an independent oscillator. `basefreq` and
+    `spread` are used to derive the frequency of each
     modulating oscillator.
-    
+
     Internally, the following operations are applied to
     derive oscillator frequencies (`i` is the bin number):
-        
+
         spread = spread * 0.001 + 1.0
 
         f_i = basefreq * pow(spread, i)
@@ -1519,14 +1613,24 @@ class PVAmpMod(PyoPVObject):
 
     :Args:
 
-        input : PyoPVObject
+        input: PyoPVObject
             Phase vocoder streaming object to process.
-        basefreq : float or PyoObject, optional
-            Base modulation frequency, in Hertz. 
+        basefreq: float or PyoObject, optional
+            Base modulation frequency, in Hertz.
             Defaults to 1.
-        spread : float or PyoObject, optional
+        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()
@@ -1536,24 +1640,28 @@ class PVAmpMod(PyoPVObject):
     >>> pvs = PVSynth(pvm).out()
 
     """
-    def __init__(self, input, basefreq=1, spread=0):
+    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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoPVObject
+            x: PyoPVObject
                 New signal to process.
 
         """
+        pyoArgsAssert(self, "p", x)
         self._input = x
         x, lmax = convertArgsToLists(x)
         [obj.setInput(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1561,13 +1669,14 @@ class PVAmpMod(PyoPVObject):
     def setBasefreq(self, x):
         """
         Replace the `basefreq` attribute.
-        
+
         :Args:
 
-            x : int
+            x: float or PyoObject
                 new `basefreq` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._basefreq = x
         x, lmax = convertArgsToLists(x)
         [obj.setBasefreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1575,24 +1684,48 @@ class PVAmpMod(PyoPVObject):
     def setSpread(self, x):
         """
         Replace the `spread` attribute.
-        
+
         :Args:
 
-            x : int
+            x: float or PyoObject
                 new `spread` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._spread = x
         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.
 
         """
         [obj.reset() for obj in self._base_objs]
-        
+
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMap(0.1, 20, "log", "basefreq", self._basefreq),
                           SLMap(-1, 1, "lin", "spread", self._spread)]
@@ -1600,7 +1733,7 @@ class PVAmpMod(PyoPVObject):
 
     @property
     def input(self):
-        """PyoPVObject. Input signal to process.""" 
+        """PyoPVObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -1611,7 +1744,7 @@ class PVAmpMod(PyoPVObject):
         return self._basefreq
     @basefreq.setter
     def basefreq(self, x): self.setBasefreq(x)
-    
+
     @property
     def spread(self):
         """float or PyoObject. Modulator's frequency spreading factor."""
@@ -1619,18 +1752,25 @@ 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.
-    
-    PVFreqMod modulates the frequency of each bin of a pv 
-    stream with an independent oscillator. `basefreq` and 
-    `spread` are used to derive the frequency of each 
+
+    PVFreqMod modulates the frequency of each bin of a pv
+    stream with an independent oscillator. `basefreq` and
+    `spread` are used to derive the frequency of each
     modulating oscillator.
-    
+
     Internally, the following operations are applied to
     derive oscillator frequencies (`i` is the bin number):
-        
+
         spread = spread * 0.001 + 1.0
 
         f_i = basefreq * pow(spread, i)
@@ -1639,17 +1779,27 @@ class PVFreqMod(PyoPVObject):
 
     :Args:
 
-        input : PyoPVObject
+        input: PyoPVObject
             Phase vocoder streaming object to process.
-        basefreq : float or PyoObject, optional
-            Base modulation frequency, in Hertz. 
+        basefreq: float or PyoObject, optional
+            Base modulation frequency, in Hertz.
             Defaults to 1.
-        spread : float or PyoObject, optional
+        spread: float or PyoObject, optional
             Spreading factor for oscillator frequencies, between
             -1 and 1. 0 means every oscillator has the same frequency.
-        depth : float or PyoObject, optional
-            Amplitude of the modulating oscillators, between 0 and 1. 
+        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()
@@ -1659,25 +1809,29 @@ class PVFreqMod(PyoPVObject):
     >>> pvs = PVSynth(pvm).out()
 
     """
-    def __init__(self, input, basefreq=1, spread=0, depth=0.1):
+    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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoPVObject
+            x: PyoPVObject
                 New signal to process.
 
         """
+        pyoArgsAssert(self, "p", x)
         self._input = x
         x, lmax = convertArgsToLists(x)
         [obj.setInput(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1685,13 +1839,14 @@ class PVFreqMod(PyoPVObject):
     def setBasefreq(self, x):
         """
         Replace the `basefreq` attribute.
-        
+
         :Args:
 
-            x : int
+            x: float or PyoObject
                 new `basefreq` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._basefreq = x
         x, lmax = convertArgsToLists(x)
         [obj.setBasefreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1699,13 +1854,14 @@ class PVFreqMod(PyoPVObject):
     def setSpread(self, x):
         """
         Replace the `spread` attribute.
-        
+
         :Args:
 
-            x : int
+            x: float or PyoObject
                 new `spread` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._spread = x
         x, lmax = convertArgsToLists(x)
         [obj.setSpread(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1713,24 +1869,48 @@ class PVFreqMod(PyoPVObject):
     def setDepth(self, x):
         """
         Replace the `depth` attribute.
-        
+
         :Args:
 
-            x : int
+            x: float or PyoObject
                 new `depth` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._depth = x
         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.
 
         """
         [obj.reset() for obj in self._base_objs]
-        
+
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMap(0.1, 20, "log", "basefreq", self._basefreq),
                           SLMap(-1, 1, "lin", "spread", self._spread),
@@ -1739,7 +1919,7 @@ class PVFreqMod(PyoPVObject):
 
     @property
     def input(self):
-        """PyoPVObject. Input signal to process.""" 
+        """PyoPVObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -1750,7 +1930,7 @@ class PVFreqMod(PyoPVObject):
         return self._basefreq
     @basefreq.setter
     def basefreq(self, x): self.setBasefreq(x)
-    
+
     @property
     def spread(self):
         """float or PyoObject. Modulator's frequencies spreading factor."""
@@ -1765,25 +1945,32 @@ 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.
-    
+
     PVBufLoops keeps `length` seconds of pv analysis in memory
-    and gives control on playback position independently for 
+    and gives control on playback position independently for
     every frequency bin.
-    
+
     :Parent: :py:class:`PyoPVObject`
-    
+
     :Args:
-    
-        input : PyoPVObject
+
+        input: PyoPVObject
             Phase vocoder streaming object to process.
-        low : float or PyoObject, optional
-            Lowest bin speed factor. Defaults to 1.0. 
-        high : float or PyoObject, optional
-            Highest bin speed factor. Defaults to 1.0. 
-        mode : int, optional
+        low: float or PyoObject, optional
+            Lowest bin speed factor. Defaults to 1.0.
+        high: float or PyoObject, optional
+            Highest bin speed factor. Defaults to 1.0.
+        mode: int, optional
             Speed distribution algorithm. Available algorithms are:
                 0. linear, line between `low` and `high` (default)
                 1. exponential, exponential line between `low` and `high`
@@ -1793,13 +1980,13 @@ class PVBufLoops(PyoPVObject):
                 5. rand expon max, exponential random from `high` to `low`
                 6. rand bi-expon, bipolar exponential random between `low` and `high`
 
-        length : float, optional
-            Memory length in seconds. Available at initialization 
+        length: float, optional
+            Memory length in seconds. Available at initialization
             time only. Defaults to 1.0.
 
     .. note::
-        
-        The play() method can be called to start a new recording of 
+
+        The play() method can be called to start a new recording of
         the current pv input.
 
     >>> s = Server().boot()
@@ -1813,6 +2000,7 @@ class PVBufLoops(PyoPVObject):
 
     """
     def __init__(self, input, low=1.0, high=1.0, mode=0, length=1.0):
+        pyoArgsAssert(self, "pOOin", input, low, high, mode, length)
         PyoPVObject.__init__(self)
         self._input = input
         self._low = low
@@ -1821,17 +2009,19 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoPVObject
+            x: PyoPVObject
                 New signal to process.
 
         """
+        pyoArgsAssert(self, "p", x)
         self._input = x
         x, lmax = convertArgsToLists(x)
         [obj.setInput(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1839,13 +2029,14 @@ class PVBufLoops(PyoPVObject):
     def setLow(self, x):
         """
         Replace the `low` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `low` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._low = x
         x, lmax = convertArgsToLists(x)
         [obj.setLow(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1853,13 +2044,14 @@ class PVBufLoops(PyoPVObject):
     def setHigh(self, x):
         """
         Replace the `high` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `high` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._high = x
         x, lmax = convertArgsToLists(x)
         [obj.setHigh(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1867,13 +2059,14 @@ class PVBufLoops(PyoPVObject):
     def setMode(self, x):
         """
         Replace the `mode` attribute.
-        
+
         :Args:
 
-            x : int
+            x: int
                 new `mode` attribute.
-        
+
         """
+        pyoArgsAssert(self, "i", x)
         self._mode = x
         x, lmax = convertArgsToLists(x)
         [obj.setMode(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1881,7 +2074,7 @@ class PVBufLoops(PyoPVObject):
     def reset(self):
         """
         Reset pointer positions to 0.
-        
+
         """
         [obj.reset() for obj in self._base_objs]
 
@@ -1892,14 +2085,14 @@ class PVBufLoops(PyoPVObject):
 
     @property
     def input(self):
-        """PyoPVObject. Input signal to process.""" 
+        """PyoPVObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def low(self):
-        """float or PyoObject. Lowest bin speed factor.""" 
+        """float or PyoObject. Lowest bin speed factor."""
         return self._low
     @low.setter
     def low(self, x): self.setLow(x)
@@ -1921,26 +2114,26 @@ class PVBufLoops(PyoPVObject):
 class PVBufTabLoops(PyoPVObject):
     """
     Phase vocoder buffer with bin independent speed playback.
-    
+
     PVBufTabLoops keeps `length` seconds of pv analysis in memory
     and gives control on playback position, using a PyoTableObject,
     independently for every frequency bin.
-    
+
     :Parent: :py:class:`PyoPVObject`
-    
+
     :Args:
-    
-        input : PyoPVObject
+
+        input: PyoPVObject
             Phase vocoder streaming object to process.
-        speed : PyoTableObject
-            Table which specify the speed of bin playback readers. 
-        length : float, optional
-            Memory length in seconds. Available at initialization 
+        speed: PyoTableObject
+            Table which specify the speed of bin playback readers.
+        length: float, optional
+            Memory length in seconds. Available at initialization
             time only. Defaults to 1.0.
 
     .. note::
-        
-        The play() method can be called to start a new recording of 
+
+        The play() method can be called to start a new recording of
         the current pv input.
 
     >>> s = Server().boot()
@@ -1955,23 +2148,26 @@ class PVBufTabLoops(PyoPVObject):
 
     """
     def __init__(self, input, speed, length=1.0):
+        pyoArgsAssert(self, "ptn", input, speed, length)
         PyoPVObject.__init__(self)
         self._input = input
         self._speed = speed
         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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoPVObject
+            x: PyoPVObject
                 New signal to process.
 
         """
+        pyoArgsAssert(self, "p", x)
         self._input = x
         x, lmax = convertArgsToLists(x)
         [obj.setInput(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1979,13 +2175,14 @@ class PVBufTabLoops(PyoPVObject):
     def setSpeed(self, x):
         """
         Replace the `speed` attribute.
-        
+
         :Args:
 
-            x : PyoTableObject
+            x: PyoTableObject
                 new `speed` attribute.
-        
+
         """
+        pyoArgsAssert(self, "t", x)
         self._speed = x
         x, lmax = convertArgsToLists(x)
         [obj.setSpeed(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1993,39 +2190,39 @@ class PVBufTabLoops(PyoPVObject):
     def reset(self):
         """
         Reset pointer positions to 0.
-        
+
         """
         [obj.reset() for obj in self._base_objs]
 
     @property
     def input(self):
-        """PyoPVObject. Input signal to process.""" 
+        """PyoPVObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def speed(self):
-        """PyoTableObject. Table which specify the speed of bin playback readers.""" 
+        """PyoTableObject. Table which specify the speed of bin playback readers."""
         return self._speed
     @speed.setter
     def speed(self, x): self.setSpeed(x)
-    
+
 class PVMix(PyoPVObject):
     """
     Mix the most prominent components from two phase vocoder streaming objects.
 
     :Parent: :py:class:`PyoPVObject`
-    
+
     :Args:
-    
-        input : PyoPVObject
+
+        input: PyoPVObject
             Phase vocoder streaming object 1.
-        input2 : PyoPVObject
+        input2: PyoPVObject
             Phase vocoder streaming object 2.
 
     .. note::
-        
+
         The two input pv stream must have the same size and overlaps. It is
         the responsibility of the user to be sure they are consistent. To change
         the size (or the overlaps) of the phase vocoder process, one must
@@ -2050,22 +2247,25 @@ class PVMix(PyoPVObject):
 
     """
     def __init__(self, input, input2):
+        pyoArgsAssert(self, "pp", input, input2)
         PyoPVObject.__init__(self)
         self._input = input
         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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoPVObject
+            x: PyoPVObject
                 New signal to process.
 
         """
+        pyoArgsAssert(self, "p", x)
         self._input = x
         x, lmax = convertArgsToLists(x)
         [obj.setInput(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2073,27 +2273,28 @@ class PVMix(PyoPVObject):
     def setInput2(self, x):
         """
         Replace the `input2` attribute.
-        
+
         :Args:
 
-            x : PyoPVObject
+            x: PyoPVObject
                 New signal to process.
 
         """
+        pyoArgsAssert(self, "p", x)
         self._input2 = x
         x, lmax = convertArgsToLists(x)
         [obj.setInput2(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     @property
     def input(self):
-        """PyoPVObject. Phase vocoder streaming object 1.""" 
+        """PyoPVObject. Phase vocoder streaming object 1."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def input2(self):
-        """PyoPVObject. Phase vocoder streaming object 2.""" 
+        """PyoPVObject. Phase vocoder streaming object 2."""
         return self._input2
     @input2.setter
     def input2(self, x): self.setInput2(x)
diff --git a/pyolib/players.py b/pyolib/players.py
index 98992ad..74e3e09 100644
--- a/pyolib/players.py
+++ b/pyolib/players.py
@@ -1,66 +1,68 @@
+from __future__ import division
+from __future__ import print_function
+from __future__ import absolute_import
 """
 Play soundfiles from the disk.
 
-SfMarkerXXX objects use markers features (store in the header) from 
+SfMarkerXXX objects use markers features (store in the header) from
 an AIFF file to create more specific reading patterns.
 
 """
 """
-Copyright 2010 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+You should have received a copy of the GNU Lesser General Public
+License along with pyo.  If not, see <http://www.gnu.org/licenses/>.
 """
-from _core import *
-from _maps import *
+from ._core import *
+from ._maps import *
 import aifc
-from types import ListType
 
 class SfPlayer(PyoObject):
     """
     Soundfile player.
-    
-    Reads audio data from a file using one of several available interpolation 
+
+    Reads audio data from a file using one of several available interpolation
     types. User can alter its pitch with the `speed` attribute. The object
-    takes care of sampling rate conversion to match the Server sampling 
+    takes care of sampling rate conversion to match the Server sampling
     rate setting.
-    
+
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
-    
-        path : string
+
+        path: string
             Full path name of the sound to read.
-        speed : float or PyoObject, optional
-            Transpose the pitch of input sound by this factor. 
+        speed: float or PyoObject, optional
+            Transpose the pitch of input sound by this factor.
             Defaults to 1.
-            
-            1 is the original pitch, lower values play sound slower, and higher 
-            values play sound faster. 
-            
-            Negative values results in playing sound backward. 
-            
+
+            1 is the original pitch, lower values play sound slower, and higher
+            values play sound faster.
+
+            Negative values results in playing sound backward.
+
             Although the `speed` attribute accepts audio
             rate signal, its value is updated only once per buffer size.
-        loop : bool, optional
+        loop: bool, optional
             If set to True, sound will play in loop. Defaults to False.
-        offset : float, optional 
-            Time in seconds of input sound to be skipped, assuming speed = 1. 
+        offset: float, optional
+            Time in seconds of input sound to be skipped, assuming speed = 1.
             Defaults to 0.
-        interp : int, optional
+        interp: int, optional
             Interpolation type. Defaults to 2.
                 1. no interpolation
                 2. linear
@@ -68,21 +70,31 @@ class SfPlayer(PyoObject):
                 4. cubic
 
     .. note::
-    
-        SfPlayer will sends a trigger signal at the end of the playback if 
-        loop is off or any time it wraps around if loop is on. User can 
+
+        SfPlayer will send a trigger signal at the end of the playback if
+        loop is off or any time it wraps around if loop is on. User can
         retrieve the trigger streams by calling obj['trig']:
-        
+
         >>> sf = SfPlayer(SNDS_PATH + "/transparent.aif").out()
         >>> trig = TrigRand(sf['trig'])
-    
+
+        Note that the object will send as many trigs as there is channels
+        in the sound file. If you want to retrieve only one trig, only give
+        the first stream to the next object:
+
+        >>> def printing():
+        ...     print("one trig!")
+        >>> sf = SfPlayer("/stereo/sound/file.aif").out()
+        >>> trig = TrigFunc(sf['trig'][0], printing)
+
     >>> s = Server().boot()
     >>> s.start()
     >>> snd = SNDS_PATH + "/transparent.aif"
     >>> sf = SfPlayer(snd, speed=[.75,.8], loop=True, mul=.3).out()
-    
+
     """
     def __init__(self, path, speed=1, loop=False, offset=0, interp=2, mul=1, add=0):
+        pyoArgsAssert(self, "sObniOO", path, speed, loop, offset, interp, mul, add)
         PyoObject.__init__(self, mul, add)
         self._path = path
         self._speed = speed
@@ -94,31 +106,33 @@ class SfPlayer(PyoObject):
         self._base_objs = []
         _trig_objs_tmp = []
         for i in range(lmax):
-            _snd_size, _dur, _snd_sr, _snd_chnls, _format, _type  = sndinfo(path[0])
-            self._base_players.append(SfPlayer_base(wrap(path,i), wrap(speed,i), wrap(loop,i), wrap(offset,i), wrap(interp,i)))
+            _snd_size, _dur, _snd_sr, _snd_chnls, _format, _type = sndinfo(path[0])
+            self._base_players.append(SfPlayer_base(stringencode(wrap(path,i)), wrap(speed,i), wrap(loop,i), wrap(offset,i), wrap(interp,i)))
             for j in range(_snd_chnls):
                 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):
         """
         Sets a new sound to read.
-        
-        The number of channels of the new sound must match those 
+
+        The number of channels of the new sound must match those
         of the sound loaded at initialization time.
-        
+
         :Args:
-        
-            path : string
+
+            path: string
                 Full path of the new sound.
 
         """
-        if type(self._path) == ListType:
+        pyoArgsAssert(self, "s", path)
+        if type(self._path) == list:
             curNchnls = sndinfo(self._path[0])[3]
         else:
             curNchnls = sndinfo(self._path)[3]
-        if type(path) == ListType:
+        if type(path) == list:
             p = path[0]
         else:
             p = path
@@ -127,23 +141,23 @@ class SfPlayer(PyoObject):
         except:
             return
         if _snd_chnls != curNchnls:
-            print "Soundfile must contains exactly %d channels." % curNchnls
+            print("Soundfile must contains exactly %d channels." % curNchnls)
             return
-    
+
         self._path = path
         path, lmax = convertArgsToLists(path)
-        [obj.setSound(wrap(path,i)) for i, obj in enumerate(self._base_players)]
+        [obj.setSound(stringencode(wrap(path,i))) for i, obj in enumerate(self._base_players)]
 
     def setSound(self, path):
         """
         Sets a new sound to read.
-        
-        The number of channels of the new sound must match those 
+
+        The number of channels of the new sound must match those
         of the sound loaded at initialization time.
-        
+
         :Args:
-        
-            path : string
+
+            path: string
                 Full path of the new sound.
 
         """
@@ -152,13 +166,14 @@ class SfPlayer(PyoObject):
     def setSpeed(self, x):
         """
         Replace the `speed` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `speed` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._speed = x
         x, lmax = convertArgsToLists(x)
         [obj.setSpeed(wrap(x,i)) for i, obj in enumerate(self._base_players)]
@@ -166,13 +181,14 @@ class SfPlayer(PyoObject):
     def setLoop(self, x):
         """
         Replace the `loop` attribute.
-        
+
         :Args:
 
-            x : bool {True, False}
+            x: bool {True, False}
                 new `loop` attribute.
-        
+
         """
+        pyoArgsAssert(self, "b", x)
         self._loop = x
         x, lmax = convertArgsToLists(x)
         for i, obj in enumerate(self._base_players):
@@ -182,13 +198,14 @@ class SfPlayer(PyoObject):
     def setOffset(self, x):
         """
         Replace the `offset` attribute.
-        
+
         :Args:
 
-            x : float
+            x: float
                 new `offset` attribute.
-        
+
         """
+        pyoArgsAssert(self, "n", x)
         self._offset = x
         x, lmax = convertArgsToLists(x)
         [obj.setOffset(wrap(x,i)) for i, obj in enumerate(self._base_players)]
@@ -196,58 +213,61 @@ class SfPlayer(PyoObject):
     def setInterp(self, x):
         """
         Replace the `interp` attribute.
-        
+
         :Args:
 
-            x : int {1, 2, 3, 4}
+            x: int {1, 2, 3, 4}
                 new `interp` attribute.
-        
+
         """
+        pyoArgsAssert(self, "i", x)
         self._interp = x
         x, lmax = convertArgsToLists(x)
         [obj.setInterp(wrap(x,i)) for i, obj in enumerate(self._base_players)]
 
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
-        self._map_list = [SLMap(-2., 2., 'lin', 'speed', self._speed), SLMapMul(self._mul)]
+        self._map_list = [SLMap(-2., 2., 'lin', 'speed', self._speed),
+                          SLMap(1, 4, 'lin', 'interp', self._interp, res="int", dataOnly=True),
+                          SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
-    def path(self): 
+    def path(self):
         """string. Full path of the sound."""
         return self._path
     @path.setter
     def path(self, x): self.setPath(x)
-          
+
     @property
-    def sound(self): 
+    def sound(self):
         """string. Alias to the `path` attribute."""
         return self._path
     @sound.setter
     def sound(self, x): self.setPath(x)
-    
+
     @property
-    def speed(self): 
+    def speed(self):
         """float or PyoObject. Transposition factor."""
         return self._speed
     @speed.setter
     def speed(self, x): self.setSpeed(x)
 
     @property
-    def loop(self): 
+    def loop(self):
         """bool. Looping mode."""
         return self._loop
     @loop.setter
     def loop(self, x): self.setLoop(x)
 
     @property
-    def offset(self): 
+    def offset(self):
         """float. Time, in seconds, of the first sample to read."""
         return self._offset
     @offset.setter
     def offset(self, x): self.setOffset(x)
 
     @property
-    def interp(self): 
+    def interp(self):
         """int {1, 2, 3, 4}. Interpolation method."""
         return self._interp
     @interp.setter
@@ -256,36 +276,36 @@ class SfPlayer(PyoObject):
 class SfMarkerShuffler(PyoObject):
     """
     AIFF with markers soundfile shuffler.
-    
-    Reads audio data from a AIFF file using one of several available 
-    interpolation types. User can alter its pitch with the `speed` 
-    attribute. The object takes care of sampling rate conversion to 
-    match the Server sampling rate setting. 
-    
+
+    Reads audio data from a AIFF file using one of several available
+    interpolation types. User can alter its pitch with the `speed`
+    attribute. The object takes care of sampling rate conversion to
+    match the Server sampling rate setting.
+
     The reading pointer randomly choose a marker (from the MARK chunk
-    in the header of the AIFF file) as its starting point and reads 
-    the samples until it reaches the following marker. Then, it choose 
+    in the header of the AIFF file) as its starting point and reads
+    the samples until it reaches the following marker. Then, it choose
     another marker and reads from the new position and so on...
-    
+
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
-    
-        path : string
+
+        path: string
             Full path name of the sound to read. Can't e changed after
             initialization.
-        speed : float or PyoObject, optional
-            Transpose the pitch of input sound by this factor. 
+        speed: float or PyoObject, optional
+            Transpose the pitch of input sound by this factor.
             Defaults to 1.
-            
-            1 is the original pitch, lower values play sound slower, and higher 
-            values play sound faster. 
-            
-            Negative values results in playing sound backward. 
-            
+
+            1 is the original pitch, lower values play sound slower, and higher
+            values play sound faster.
+
+            Negative values results in playing sound backward.
+
             Although the `speed` attribute accepts audio
             rate signal, its value is updated only once per buffer size.
-        interp : int, optional
+        interp: int, optional
             Choice of the interpolation method. Defaults to 2.
                 1. no interpolation
                 2. linear
@@ -294,10 +314,13 @@ class SfMarkerShuffler(PyoObject):
 
     >>> s = Server().boot()
     >>> s.start()
-    >>> sf = SfMarkerShuffler(SNDS_PATH + "/transparent.aif", speed=[1,1], mul=.3).out()
-    
+    >>> sound = SNDS_PATH + "/transparent.aif"
+    >>> sf = SfMarkerShuffler(sound, speed=[1,1], mul=.3).out()
+    >>> sf.setRandomType("expon_min", 0.6)
+
     """
     def __init__(self, path, speed=1, interp=2, mul=1, add=0):
+        pyoArgsAssert(self, "sOiOO", path, speed, interp, mul, add)
         PyoObject.__init__(self, mul, add)
         self._speed = speed
         self._interp = interp
@@ -307,27 +330,29 @@ class SfMarkerShuffler(PyoObject):
         self._snd_size, self._dur, self._snd_sr, self._snd_chnls, _format, _type = sndinfo(path[0])
         for i in range(lmax):
             try:
-                sf = aifc.open(wrap(path,i))
+                sf = aifc.open(wrap(path,i)) # Do we need stringencode() here?
                 markerstmp = sf.getmarkers()
                 sf.close()
                 self._markers = [m[1] for m in markerstmp]
             except:
-                self._markers = []    
-            self._base_players.append(SfMarkerShuffler_base(wrap(path,i), self._markers, wrap(speed,i), wrap(interp,i)))
+                self._markers = []
+            self._base_players.append(SfMarkerShuffler_base(stringencode(wrap(path,i)), self._markers, wrap(speed,i), wrap(interp,i)))
         for i in range(lmax * self._snd_chnls):
-            j = i / 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):
         """
         Replace the `speed` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `speed` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._speed = x
         x, lmax = convertArgsToLists(x)
         [obj.setSpeed(wrap(x,i)) for i, obj in enumerate(self._base_players)]
@@ -335,37 +360,96 @@ class SfMarkerShuffler(PyoObject):
     def setInterp(self, x):
         """
         Replace the `interp` attribute.
-        
+
         :Args:
 
-            x : int {1, 2, 3, 4}
+            x: int {1, 2, 3, 4}
                 new `interp` attribute.
-        
+
         """
+        pyoArgsAssert(self, "i", x)
         self._interp = x
         x, lmax = convertArgsToLists(x)
         [obj.setInterp(wrap(x,i)) for i, obj in enumerate(self._base_players)]
 
+    def setRandomType(self, dist=0, x=0.5):
+        """
+        Set the random distribution type used to choose the markers.
+
+        :Args:
+
+            dist: int or string
+                The distribution type. Available distributions are:
+                    0. uniform (default)
+                    1. linear minimum
+                    2. linear maximum
+                    3. triangular
+                    4. exponential minimum
+                    5. exponential maximum
+                    6. double (bi)exponential
+                    7. cauchy
+                    8. weibull
+                    9. gaussian
+            x: float
+                Distribution specific parameter, if applicable, as a float
+                between 0 and 1. Defaults to 0.5.
+
+        .. note::
+
+            Depending on the distribution type, `x` parameter is applied as
+            follow (names as string, or associated number can be used as `dist`
+            parameter):
+
+            0. uniform
+                - x: not used
+            1. linear_min
+                - x: not used
+            2. linear_max
+                - x: not used
+            3. triangle
+                - x: not used
+            4. expon_min
+                - x: slope {0 = no slope -> 1 = sharp slope}
+            5. expon_max
+                - x: slope {0 = no slope -> 1 = sharp slope}
+            6. biexpon
+                - x: bandwidth {0 = huge bandwidth -> 1 = narrow bandwidth}
+            7. cauchy
+                - x: bandwidth {0 = huge bandwidth -> 1 = narroe bandwidth}
+            8. weibull
+                - x: shape {0 = expon min => linear min => 1 = gaussian}
+            9. gaussian
+                - x: bandwidth {0 = huge bandwidth -> 1 = narrow bandwidth}
+
+        """
+        dist, x, lmax = convertArgsToLists(dist, x)
+        for i, t in enumerate(dist):
+            if type(t) in [bytes_t, unicode_t]:
+                dist[i] = XNOISE_DICT.get(t, 0)
+        [obj.setRandomType(wrap(dist,i), wrap(x,i)) for i, obj in enumerate(self._base_players)]
+
     def getMarkers(self):
         """
         Returns a list of marker time values in samples.
-        
+
         """
         return self._markers
-        
+
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
-        self._map_list = [SLMap(0.01, 2., 'lin', 'speed', self._speed), SLMapMul(self._mul)]
+        self._map_list = [SLMap(0.01, 2., 'lin', 'speed', self._speed),
+                          SLMap(1, 4, 'lin', 'interp', self._interp, res="int", dataOnly=True),
+                          SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
-                    
+
     @property
-    def speed(self): 
+    def speed(self):
         """float or PyoObject. Transposition factor."""
         return self._speed
     @speed.setter
     def speed(self, x): self.setSpeed(x)
 
     @property
-    def interp(self): 
+    def interp(self):
         """int {1, 2, 3, 4}. Interpolation method."""
         return self._interp
     @interp.setter
@@ -375,36 +459,36 @@ class SfMarkerLooper(PyoObject):
     """
     AIFF with markers soundfile looper.
 
-    Reads audio data from a AIFF file using one of several available 
+    Reads audio data from a AIFF file using one of several available
     interpolation types. User can alter its pitch with the `speed`
-    attribute. The object takes care of sampling rate conversion to 
-    match the Server sampling rate setting. 
-    
+    attribute. The object takes care of sampling rate conversion to
+    match the Server sampling rate setting.
+
     The reading pointer loops a specific marker (from the MARK chunk
-    in the header of the AIFF file) until it received a new integer 
+    in the header of the AIFF file) until it received a new integer
     in the `mark` attribute.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        path : string
+        path: string
             Full path name of the sound to read.
-        speed : float or PyoObject, optional
-            Transpose the pitch of input sound by this factor. 
+        speed: float or PyoObject, optional
+            Transpose the pitch of input sound by this factor.
             Defaults to 1.
-            
-            1 is the original pitch, lower values play sound slower, and higher 
-            values play sound faster. 
-            
-            Negative values results in playing sound backward. 
-            
+
+            1 is the original pitch, lower values play sound slower, and higher
+            values play sound faster.
+
+            Negative values results in playing sound backward.
+
             Although the `speed` attribute accepts audio
             rate signal, its value is updated only once per buffer size.
-        mark : float or PyoObject, optional
-            Integer denoting the marker to loop, in the range 
+        mark: float or PyoObject, optional
+            Integer denoting the marker to loop, in the range
             0 -> len(getMarkers()). Defaults to 0.
-        interp : int, optional
+        interp: int, optional
             Choice of the interpolation method. Defaults to 2.
                 1. no interpolation
                 2. linear
@@ -419,6 +503,7 @@ class SfMarkerLooper(PyoObject):
 
     """
     def __init__(self, path, speed=1, mark=0, interp=2, mul=1, add=0):
+        pyoArgsAssert(self, "sOOiOO", path, speed, mark, interp, mul, add)
         PyoObject.__init__(self, mul, add)
         self._speed = speed
         self._mark = mark
@@ -434,11 +519,12 @@ class SfMarkerLooper(PyoObject):
                 sf.close()
                 self._markers = [m[1] for m in markerstmp]
             except:
-                self._markers = []    
-            self._base_players.append(SfMarkerLooper_base(wrap(path,i), self._markers, wrap(speed,i), wrap(mark,i), wrap(interp,i)))
+                self._markers = []
+            self._base_players.append(SfMarkerLooper_base(stringencode(wrap(path,i)), self._markers, wrap(speed,i), wrap(mark,i), wrap(interp,i)))
         for i in range(lmax * self._snd_chnls):
-            j = i / 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):
         """
@@ -446,10 +532,11 @@ class SfMarkerLooper(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `speed` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._speed = x
         x, lmax = convertArgsToLists(x)
         [obj.setSpeed(wrap(x,i)) for i, obj in enumerate(self._base_players)]
@@ -460,10 +547,11 @@ class SfMarkerLooper(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `mark` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._mark = x
         x, lmax = convertArgsToLists(x)
         [obj.setMark(wrap(x,i)) for i, obj in enumerate(self._base_players)]
@@ -474,10 +562,11 @@ class SfMarkerLooper(PyoObject):
 
         :Args:
 
-            x : int {1, 2, 3, 4}
+            x: int {1, 2, 3, 4}
                 new `interp` attribute.
 
         """
+        pyoArgsAssert(self, "i", x)
         self._interp = x
         x, lmax = convertArgsToLists(x)
         [obj.setInterp(wrap(x,i)) for i, obj in enumerate(self._base_players)]
@@ -490,27 +579,28 @@ class SfMarkerLooper(PyoObject):
         return self._markers
 
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
-        self._map_list = [SLMap(0.01, 2., 'lin', 'speed', self._speed), 
+        self._map_list = [SLMap(0.01, 2., 'lin', 'speed', self._speed),
                           SLMap(0, len(self._markers)-1, 'lin', 'mark', self._mark, 'int'),
+                          SLMap(1, 4, 'lin', 'interp', self._interp, res="int", dataOnly=True),
                           SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
-    def speed(self): 
+    def speed(self):
         """float or PyoObject. Transposition factor."""
         return self._speed
     @speed.setter
     def speed(self, x): self.setSpeed(x)
 
     @property
-    def mark(self): 
+    def mark(self):
         """float or PyoObject. Marker to loop."""
         return self._marker
     @mark.setter
     def mark(self, x): self.setMark(x)
 
     @property
-    def interp(self): 
+    def interp(self):
         """int {1, 2, 3, 4}. Interpolation method."""
         return self._interp
     @interp.setter
diff --git a/pyolib/randoms.py b/pyolib/randoms.py
index 695ee21..a864aaa 100644
--- a/pyolib/randoms.py
+++ b/pyolib/randoms.py
@@ -2,74 +2,76 @@
 Set of objects that implement different kinds of random noise generators.
 
 """
+from __future__ import absolute_import
 """
-Copyright 2010 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+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 sys
-from _core import *
-from _maps import *
-from types import StringType, ListType
+from ._core import *
+from ._maps import *
 
 class Randi(PyoObject):
     """
     Periodic pseudo-random generator with interpolation.
-    
-    Randi generates a pseudo-random number between `min` and `max` 
-    values at a frequency specified by `freq` parameter. Randi will 
+
+    Randi generates a pseudo-random number between `min` and `max`
+    values at a frequency specified by `freq` parameter. Randi will
     produce straight-line interpolation between current number and the next.
-    
+
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        min : float or PyoObject, optional
+        min: float or PyoObject, optional
             Minimum value for the random generation. Defaults to 0.
-        max : float or PyoObject, optional
+        max: float or PyoObject, optional
             Maximum value for the random generation. Defaults to 1.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Polling frequency. Defaults to 1.
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> freq = Randi(500, 3000, 4)
     >>> noze = Noise().mix(2)
     >>> a = Biquad(noze, freq=freq, q=5, type=2, mul=.5).out()
-   
+
     """
     def __init__(self, min=0., max=1., freq=1., mul=1, add=0):
+        pyoArgsAssert(self, "OOOOO", min, max, freq, mul, add)
         PyoObject.__init__(self, mul, add)
         self._min = min
         self._max = max
         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):
         """
         Replace the `min` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `min` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._min = x
         x, lmax = convertArgsToLists(x)
         [obj.setMin(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -77,13 +79,14 @@ class Randi(PyoObject):
     def setMax(self, x):
         """
         Replace the `max` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `max` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._max = x
         x, lmax = convertArgsToLists(x)
         [obj.setMax(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -91,14 +94,15 @@ class Randi(PyoObject):
     def setFreq(self, x):
         """
         Replace the `freq` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `freq` attribute.
-        
+
         """
-        self._port = x
+        pyoArgsAssert(self, "O", x)
+        self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
@@ -110,71 +114,74 @@ class Randi(PyoObject):
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
-    def min(self): 
+    def min(self):
         """float or PyoObject. Minimum value."""
         return self._min
     @min.setter
-    def min(self, x): 
+    def min(self, x):
         self.setMin(x)
     @property
-    def max(self): 
+    def max(self):
         """float or PyoObject. Maximum value."""
         return self._max
     @max.setter
-    def max(self, x): 
+    def max(self, x):
         self.setMax(x)
     @property
-    def freq(self): 
+    def freq(self):
         """float or PyoObject. Polling frequency."""
         return self._freq
     @freq.setter
-    def freq(self, x): 
+    def freq(self, x):
         self.setFreq(x)
 
 class Randh(PyoObject):
     """
     Periodic pseudo-random generator.
-    
-    Randh generates a pseudo-random number between `min` and `max` 
-    values at a frequency specified by `freq` parameter. Randh will 
+
+    Randh generates a pseudo-random number between `min` and `max`
+    values at a frequency specified by `freq` parameter. Randh will
     hold generated value until next generation.
-    
+
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        min : float or PyoObject, optional
+        min: float or PyoObject, optional
             Minimum value for the random generation. Defaults to 0.
-        max : float or PyoObject, optional
+        max: float or PyoObject, optional
             Maximum value for the random generation. Defaults to 1.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Polling frequency. Defaults to 1.
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> freq = Randh(500, 3000, 4)
     >>> noze = Noise().mix(2)
     >>> a = Biquad(noze, freq=freq, q=5, type=2, mul=.5).out()
-    
+
     """
     def __init__(self, min=0., max=1., freq=1., mul=1, add=0):
+        pyoArgsAssert(self, "OOOOO", min, max, freq, mul, add)
         PyoObject.__init__(self, mul, add)
         self._min = min
         self._max = max
         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):
         """
         Replace the `min` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `min` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._min = x
         x, lmax = convertArgsToLists(x)
         [obj.setMin(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -182,13 +189,14 @@ class Randh(PyoObject):
     def setMax(self, x):
         """
         Replace the `max` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `max` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._max = x
         x, lmax = convertArgsToLists(x)
         [obj.setMax(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -196,14 +204,15 @@ class Randh(PyoObject):
     def setFreq(self, x):
         """
         Replace the `freq` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `freq` attribute.
-        
+
         """
-        self._port = x
+        pyoArgsAssert(self, "O", x)
+        self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
@@ -215,42 +224,42 @@ class Randh(PyoObject):
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
-    def min(self): 
+    def min(self):
         """float or PyoObject. Minimum value."""
         return self._min
     @min.setter
-    def min(self, x): 
+    def min(self, x):
         self.setMin(x)
     @property
-    def max(self): 
+    def max(self):
         """float or PyoObject. Maximum value."""
         return self._max
     @max.setter
-    def max(self, x): 
+    def max(self, x):
         self.setMax(x)
     @property
-    def freq(self): 
+    def freq(self):
         """float or PyoObject. Polling frequency."""
         return self._freq
     @freq.setter
-    def freq(self, x): 
+    def freq(self, x):
         self.setFreq(x)
 
 class Choice(PyoObject):
     """
     Periodically choose a new value from a user list.
-    
+
     Choice chooses a new value from a predefined list of floats `choice`
-    at a frequency specified by `freq` parameter. Choice will 
+    at a frequency specified by `freq` parameter. Choice will
     hold choosen value until next generation.
-    
+
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        choice : list of floats or list of lists of floats
+        choice: list of floats or list of lists of floats
             Possible values for the random generation.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Polling frequency. Defaults to 1.
 
     >>> s = Server().boot()
@@ -258,49 +267,50 @@ class Choice(PyoObject):
     >>> freqs = midiToHz([60,62,64,65,67,69,71,72])
     >>> rnd = Choice(choice=freqs, freq=[3,4])
     >>> a = SineLoop(rnd, feedback=0.05, mul=.2).out()
-    
+
     """
     def __init__(self, choice, freq=1., mul=1, add=0):
+        pyoArgsAssert(self, "lOOO", choice, freq, mul, add)
         PyoObject.__init__(self, mul, add)
-        if type(choice) != ListType:
-            print >> sys.stderr, 'TypeError: "choice" argument of %s must be a list.\n' % self.__class__.__name__
-            exit()
         self._choice = choice
         self._freq = freq
         freq, mul, add, lmax = convertArgsToLists(freq, mul, add)
-        if type(choice[0]) != ListType:
+        if type(choice[0]) != list:
             self._base_objs = [Choice_base(choice, wrap(freq,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
         else:
             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):
         """
         Replace the `choice` attribute.
-        
+
         :Args:
 
-            x : list of floats or list of lists of floats
+            x: list of floats or list of lists of floats
                 new `choice` attribute.
-        
+
         """
+        pyoArgsAssert(self, "l", x)
         self._choice = x
-        if type(x[0]) != ListType:
+        if type(x[0]) != list:
             [obj.setChoice(self._choice) for i, obj in enumerate(self._base_objs)]
         else:
             [obj.setChoice(wrap(self._choice,i)) for i, obj in enumerate(self._base_objs)]
-                
+
     def setFreq(self, x):
         """
         Replace the `freq` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `freq` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -310,35 +320,35 @@ class Choice(PyoObject):
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
-    def choice(self): 
+    def choice(self):
         """list of floats or list of lists of floats. Possible choices."""
         return self._choice
     @choice.setter
-    def choice(self, x): 
+    def choice(self, x):
         self.setChoice(x)
     @property
-    def freq(self): 
+    def freq(self):
         """float or PyoObject. Polling frequency."""
         return self._freq
     @freq.setter
-    def freq(self, x): 
+    def freq(self, x):
         self.setFreq(x)
 
 class RandInt(PyoObject):
     """
     Periodic pseudo-random integer generator.
-    
-    RandInt generates a pseudo-random integer number between 0 and `max` 
-    values at a frequency specified by `freq` parameter. RandInt will 
+
+    RandInt generates a pseudo-random integer number between 0 and `max`
+    values at a frequency specified by `freq` parameter. RandInt will
     hold generated value until the next generation.
-    
+
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        max : float or PyoObject, optional
+        max: float or PyoObject, optional
             Maximum value for the random generation. Defaults to 100.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Polling frequency. Defaults to 1.
 
     >>> s = Server().boot()
@@ -346,25 +356,28 @@ class RandInt(PyoObject):
     >>> freq = RandInt(max=10, freq=5, mul=100, add=500)
     >>> jit = Randi(min=0.99, max=1.01, freq=[2.33,3.41])
     >>> a = SineLoop(freq*jit, feedback=0.03, mul=.2).out()
-    
+
     """
     def __init__(self, max=100, freq=1., mul=1, add=0):
+        pyoArgsAssert(self, "OOOO", max, freq, mul, add)
         PyoObject.__init__(self, mul, add)
         self._max = max
         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):
         """
         Replace the `max` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `max` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._max = x
         x, lmax = convertArgsToLists(x)
         [obj.setMax(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -372,13 +385,14 @@ class RandInt(PyoObject):
     def setFreq(self, x):
         """
         Replace the `freq` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `freq` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -390,35 +404,35 @@ class RandInt(PyoObject):
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
-    def max(self): 
+    def max(self):
         """float or PyoObject. Maximum value."""
         return self._max
     @max.setter
-    def max(self, x): 
+    def max(self, x):
         self.setMax(x)
     @property
-    def freq(self): 
+    def freq(self):
         """float or PyoObject. Polling frequency."""
         return self._freq
     @freq.setter
-    def freq(self, x): 
+    def freq(self, x):
         self.setFreq(x)
 
 class RandDur(PyoObject):
     """
     Recursive time varying pseudo-random generator.
 
-    RandDur generates a pseudo-random number between `min` and `max` 
-    arguments and uses that number to set the delay time before the next 
+    RandDur generates a pseudo-random number between `min` and `max`
+    arguments and uses that number to set the delay time before the next
     generation. RandDur will hold the generated value until next generation.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        min : float or PyoObject, optional
+        min: float or PyoObject, optional
             Minimum value for the random generation. Defaults to 0.
-        max : float or PyoObject, optional
+        max: float or PyoObject, optional
             Maximum value for the random generation. Defaults to 1.
 
     >>> s = Server().boot()
@@ -432,11 +446,13 @@ class RandDur(PyoObject):
 
     """
     def __init__(self, min=0., max=1., mul=1, add=0):
+        pyoArgsAssert(self, "OOOO", min, max, mul, add)
         PyoObject.__init__(self, mul, add)
         self._min = min
         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):
         """
@@ -444,10 +460,11 @@ class RandDur(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `min` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._min = x
         x, lmax = convertArgsToLists(x)
         [obj.setMin(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -458,10 +475,11 @@ class RandDur(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `max` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._max = x
         x, lmax = convertArgsToLists(x)
         [obj.setMax(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -473,18 +491,18 @@ class RandDur(PyoObject):
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
-    def min(self): 
+    def min(self):
         """float or PyoObject. Minimum value."""
         return self._min
     @min.setter
-    def min(self, x): 
+    def min(self, x):
         self.setMin(x)
     @property
-    def max(self): 
+    def max(self):
         """float or PyoObject. Maximum value."""
         return self._max
     @max.setter
-    def max(self, x): 
+    def max(self, x):
         self.setMax(x)
 
 class Xnoise(PyoObject):
@@ -498,17 +516,17 @@ class Xnoise(PyoObject):
 
     :Args:
 
-        dist : string or int, optional
+        dist: string or int, optional
             Distribution type. Defaults to 0.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Polling frequency. Defaults to 1.
-        x1 : float or PyoObject, optional
+        x1: float or PyoObject, optional
             First parameter. Defaults to 0.5.
-        x2 : float or PyoObject, optional
+        x2: float or PyoObject, optional
             Second parameter. Defaults to 0.5.
-    
+
     .. note::
-    
+
         Available distributions are:
             0. uniform
             1. linear minimum
@@ -523,50 +541,50 @@ class Xnoise(PyoObject):
             10. poisson
             11. walker (drunk)
             12. loopseg (drunk with looped segments)
-            
+
         Depending on the distribution, `x1` and `x2` parameters are applied
         as follow (names as string, or associated number can be used as `dist`
         parameter):
 
             0. uniform
-                - x1 : not used
-                - x2 : not used
+                - x1: not used
+                - x2: not used
             1. linear_min
-                - x1 : not used
-                - x2 : not used
+                - x1: not used
+                - x2: not used
             2. linear_max
-                - x1 : not used
-                - x2 : not used
+                - x1: not used
+                - x2: not used
             3. triangle
-                - x1 : not used
-                - x2 : not used
+                - x1: not used
+                - x2: not used
             4. expon_min
-                - x1 : slope {0 = no slope -> 10 = sharp slope}
-                - x2 : not used
+                - x1: slope {0 = no slope -> 10 = sharp slope}
+                - x2: not used
             5. expon_max
-                - x1 : slope {0 = no slope -> 10 = sharp slope}
-                - x2 : not used
+                - x1: slope {0 = no slope -> 10 = sharp slope}
+                - x2: not used
             6. biexpon
-                - x1 : bandwidth {0 = huge bandwidth -> 10 = narrow bandwidth}
-                - x2 : not used
+                - x1: bandwidth {0 = huge bandwidth -> 10 = narrow bandwidth}
+                - x2: not used
             7. cauchy
-                - x1 : bandwidth {0 = narrow bandwidth -> 10 = huge bandwidth}
-                - x2 : not used
+                - x1: bandwidth {0 = narrow bandwidth -> 10 = huge bandwidth}
+                - x2: not used
             8. weibull
-                - x1 : mean location {0 -> 1}
-                - x2 : shape {0.5 = linear min, 1.5 = expon min, 3.5 = gaussian}
+                - x1: mean location {0 -> 1}
+                - x2: shape {0.5 = linear min, 1.5 = expon min, 3.5 = gaussian}
             9. gaussian
-                - x1 : mean location {0 -> 1}
-                - x2 : bandwidth {0 =  narrow bandwidth -> 10 = huge bandwidth}
+                - x1: mean location {0 -> 1}
+                - x2: bandwidth {0 =  narrow bandwidth -> 10 = huge bandwidth}
             10. poisson
-                 - x1 : gravity center {0 = low values -> 10 = high values}
-                 - x2 : compress/expand range {0.1 = full compress -> 4 full expand}
+                 - x1: gravity center {0 = low values -> 10 = high values}
+                 - x2: compress/expand range {0.1 = full compress -> 4 full expand}
             11. walker
-                 - x1 : maximum value {0.1 -> 1}
-                 - x2 : maximum step {0.1 -> 1}
-            12. loopseg 
-                 - x1 : maximum value {0.1 -> 1}
-                 - x2 : maximum step {0.1 -> 1}
+                 - x1: maximum value {0.1 -> 1}
+                 - x2: maximum step {0.1 -> 1}
+            12. loopseg
+                 - x1: maximum value {0.1 -> 1}
+                 - x2: maximum step {0.1 -> 1}
 
     >>> s = Server().boot()
     >>> s.start()
@@ -577,6 +595,7 @@ class Xnoise(PyoObject):
 
     """
     def __init__(self, dist=0, freq=1., x1=0.5, x2=0.5, mul=1, add=0):
+        pyoArgsAssert(self, "OOOOO", freq, x1, x2, mul, add)
         PyoObject.__init__(self, mul, add)
         self._dist = dist
         self._freq = freq
@@ -584,8 +603,9 @@ class Xnoise(PyoObject):
         self._x2 = x2
         dist, freq, x1, x2, mul, add, lmax = convertArgsToLists(dist, freq, x1, x2, mul, add)
         for i, t in enumerate(dist):
-            if type(t) == StringType: dist[i] = XNOISE_DICT.get(t, 0)
+            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):
         """
@@ -593,14 +613,14 @@ class Xnoise(PyoObject):
 
         :Args:
 
-            x : int
+            x: string or int
                 new `dist` attribute.
 
         """
         self._dist = x
         x, lmax = convertArgsToLists(x)
         for i, t in enumerate(x):
-            if type(t) == StringType: x[i] = XNOISE_DICT.get(t, 0)
+            if type(t) in [bytes_t, unicode_t]: x[i] = XNOISE_DICT.get(t, 0)
         [obj.setType(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     def setX1(self, x):
@@ -609,10 +629,11 @@ class Xnoise(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `x1` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._x1 = x
         x, lmax = convertArgsToLists(x)
         [obj.setX1(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -623,11 +644,12 @@ class Xnoise(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `x2` attribute.
 
         """
-        self._x2= x
+        pyoArgsAssert(self, "O", x)
+        self._x2 = x
         x, lmax = convertArgsToLists(x)
         [obj.setX2(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
@@ -637,41 +659,51 @@ class Xnoise(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `freq` attribute.
 
         """
-        self._port = x
+        pyoArgsAssert(self, "O", x)
+        self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(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, 12, 'lin', 'dist', self._dist, res="int", dataOnly=True),
+                          SLMap(0.001, 200., 'log', 'freq', self._freq),
+                          SLMap(0, 1, 'lin', 'x1', self._x1),
+                          SLMap(0, 1, 'lin', 'x2', self._x2),
+                          SLMap(0, 2500, 'lin', 'mul', self._mul),
+                          SLMap(0, 2500, 'lin', 'add', self._add)]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
     @property
-    def dist(self): 
+    def dist(self):
         """string or int. Distribution type."""
         return self._dist
     @dist.setter
-    def dist(self, x): 
+    def dist(self, x):
         self.setDist(x)
     @property
-    def freq(self): 
+    def freq(self):
         """float or PyoObject. Polling frequency."""
         return self._freq
     @freq.setter
-    def freq(self, x): 
+    def freq(self, x):
         self.setFreq(x)
     @property
-    def x1(self): 
+    def x1(self):
         """float or PyoObject. First parameter."""
         return self._x1
     @x1.setter
-    def x1(self, x): 
+    def x1(self, x):
         self.setX1(x)
     @property
-    def x2(self): 
+    def x2(self):
         """float or PyoObject. Second parameter."""
         return self._x2
     @x2.setter
-    def x2(self, x): 
+    def x2(self, x):
         self.setX2(x)
 
 class XnoiseMidi(PyoObject):
@@ -680,32 +712,32 @@ class XnoiseMidi(PyoObject):
 
     XnoiseMidi implements a few of the most common noise distributions.
     Each distribution generates integer values in the range defined with
-    `mrange` parameter and output can be scaled on midi notes, hertz or 
-    transposition factor. 
+    `mrange` parameter and output can be scaled on midi notes, hertz or
+    transposition factor.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        dist : string or int, optional
+        dist: string or int, optional
             Distribution type. Defaults to 0.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Polling frequency. Defaults to 1.
-        x1 : float or PyoObject, optional
+        x1: float or PyoObject, optional
             First parameter. Defaults to 0.5.
-        x2 : float or PyoObject, optional
+        x2: float or PyoObject, optional
             Second parameter. Defaults to 0.5.
-        scale : int {0, 1, 2}, optional
-            Output format. 0 = Midi, 1 = Hertz, 2 = transposition factor. 
-            In the transposition mode, the central key (the key where there 
+        scale: int {0, 1, 2}, optional
+            Output format. 0 = Midi, 1 = Hertz, 2 = transposition factor.
+            In the transposition mode, the central key (the key where there
             is no transposition) is (`minrange` + `maxrange`) / 2. Defaults
             to 0.
-        mrange : tuple of int, optional
+        mrange: tuple of int, optional
             Minimum and maximum possible values, in Midi notes. Available
             only at initialization time. Defaults to (0, 127).
-    
+
     .. note::
-    
+
         Available distributions are:
             0. uniform
             1. linear minimum
@@ -720,50 +752,50 @@ class XnoiseMidi(PyoObject):
             10. poisson
             11. walker (drunk)
             12. loopseg (drunk with looped segments)
-            
+
         Depending on the distribution, `x1` and `x2` parameters are applied
         as follow (names as string, or associated number can be used as `dist`
         parameter):
 
             0. uniform
-                - x1 : not used
-                - x2 : not used
+                - x1: not used
+                - x2: not used
             1. linear_min
-                - x1 : not used
-                - x2 : not used
+                - x1: not used
+                - x2: not used
             2. linear_max
-                - x1 : not used
-                - x2 : not used
+                - x1: not used
+                - x2: not used
             3. triangle
-                - x1 : not used
-                - x2 : not used
+                - x1: not used
+                - x2: not used
             4. expon_min
-                - x1 : slope {0 = no slope -> 10 = sharp slope}
-                - x2 : not used
+                - x1: slope {0 = no slope -> 10 = sharp slope}
+                - x2: not used
             5. expon_max
-                - x1 : slope {0 = no slope -> 10 = sharp slope}
-                - x2 : not used
+                - x1: slope {0 = no slope -> 10 = sharp slope}
+                - x2: not used
             6. biexpon
-                - x1 : bandwidth {0 = huge bandwidth -> 10 = narrow bandwidth}
-                - x2 : not used
+                - x1: bandwidth {0 = huge bandwidth -> 10 = narrow bandwidth}
+                - x2: not used
             7. cauchy
-                - x1 : bandwidth {0 = narrow bandwidth -> 10 = huge bandwidth}
-                - x2 : not used
+                - x1: bandwidth {0 = narrow bandwidth -> 10 = huge bandwidth}
+                - x2: not used
             8. weibull
-                - x1 : mean location {0 -> 1}
-                - x2 : shape {0.5 = linear min, 1.5 = expon min, 3.5 = gaussian}
+                - x1: mean location {0 -> 1}
+                - x2: shape {0.5 = linear min, 1.5 = expon min, 3.5 = gaussian}
             9. gaussian
-                - x1 : mean location {0 -> 1}
-                - x2 : bandwidth {0 =  narrow bandwidth -> 10 = huge bandwidth}
+                - x1: mean location {0 -> 1}
+                - x2: bandwidth {0 =  narrow bandwidth -> 10 = huge bandwidth}
             10. poisson
-                 - x1 : gravity center {0 = low values -> 10 = high values}
-                 - x2 : compress/expand range {0.1 = full compress -> 4 full expand}
+                 - x1: gravity center {0 = low values -> 10 = high values}
+                 - x2: compress/expand range {0.1 = full compress -> 4 full expand}
             11. walker
-                 - x1 : maximum value {0.1 -> 1}
-                 - x2 : maximum step {0.1 -> 1}
-            12. loopseg 
-                 - x1 : maximum value {0.1 -> 1}
-                 - x2 : maximum step {0.1 -> 1}
+                 - x1: maximum value {0.1 -> 1}
+                 - x2: maximum step {0.1 -> 1}
+            12. loopseg
+                 - x1: maximum value {0.1 -> 1}
+                 - x2: maximum step {0.1 -> 1}
 
     >>> s = Server().boot()
     >>> s.start()
@@ -775,6 +807,7 @@ class XnoiseMidi(PyoObject):
 
     """
     def __init__(self, dist=0, freq=1., x1=0.5, x2=0.5, scale=0, mrange=(0,127), mul=1, add=0):
+        pyoArgsAssert(self, "OOOixOO", freq, x1, x2, scale, mrange, mul, add)
         PyoObject.__init__(self, mul, add)
         self._dist = dist
         self._freq = freq
@@ -784,8 +817,9 @@ class XnoiseMidi(PyoObject):
         self._mrange = mrange
         dist, freq, x1, x2, scale, mrange, mul, add, lmax = convertArgsToLists(dist, freq, x1, x2, scale, mrange, mul, add)
         for i, t in enumerate(dist):
-            if type(t) == StringType: dist[i] = XNOISE_DICT.get(t, 0)
+            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):
         """
@@ -793,31 +827,32 @@ class XnoiseMidi(PyoObject):
 
         :Args:
 
-            x : string or int
+            x: string or int
                 new `dist` attribute.
 
         """
         self._dist = x
         x, lmax = convertArgsToLists(x)
         for i, t in enumerate(x):
-            if type(t) == StringType: x[i] = XNOISE_DICT.get(t, 0)
+            if type(t) in [bytes_t, unicode_t]: x[i] = XNOISE_DICT.get(t, 0)
         [obj.setType(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     def setScale(self, x):
         """
         Replace the `scale` attribute.
-        
-        Possible values are: 
+
+        Possible values are:
             0. Midi notes
             1. Hertz
             2. transposition factor (centralkey is (`minrange` + `maxrange`) / 2
 
         :Args:
 
-            x : int {0, 1, 2}
+            x: int {0, 1, 2}
                 new `scale` attribute.
 
         """
+        pyoArgsAssert(self, "i", x)
         self._scale = x
         x, lmax = convertArgsToLists(x)
         [obj.setScale(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -828,12 +863,13 @@ class XnoiseMidi(PyoObject):
 
         :Args:
 
-            mini : int
+            mini: int
                 minimum output midi range.
-            maxi : int
+            maxi: int
                 maximum output midi range.
 
         """
+        pyoArgsAssert(self, "ii", mini, maxi)
         self._mrange = (mini, maxi)
         mini, maxi, lmax = convertArgsToLists(mini, maxi)
         [obj.setRange(wrap(mini,i), wrap(maxi,i)) for i, obj in enumerate(self._base_objs)]
@@ -844,10 +880,11 @@ class XnoiseMidi(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `x1` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._x1 = x
         x, lmax = convertArgsToLists(x)
         [obj.setX1(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -858,11 +895,12 @@ class XnoiseMidi(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `x2` attribute.
 
         """
-        self._x2= x
+        pyoArgsAssert(self, "O", x)
+        self._x2 = x
         x, lmax = convertArgsToLists(x)
         [obj.setX2(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
@@ -872,48 +910,57 @@ class XnoiseMidi(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `freq` attribute.
 
         """
-        self._port = x
+        pyoArgsAssert(self, "O", x)
+        self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(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, 12, 'lin', 'dist', self._dist, res="int", dataOnly=True),
+                          SLMap(0.001, 200., 'log', 'freq', self._freq),
+                          SLMap(0, 1, 'lin', 'x1', self._x1),
+                          SLMap(0, 1, 'lin', 'x2', self._x2),
+                          SLMap(0, 2, 'lin', 'scale', self._scale, res="int", dataOnly=True)]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
     @property
-    def dist(self): 
+    def dist(self):
         """string or int. Distribution type."""
         return self._dist
     @dist.setter
-    def dist(self, x): 
+    def dist(self, x):
         self.setDist(x)
     @property
-    def freq(self): 
+    def freq(self):
         """float or PyoObject. Polling frequency."""
         return self._freq
     @freq.setter
-    def freq(self, x): 
+    def freq(self, x):
         self.setFreq(x)
     @property
-    def x1(self): 
+    def x1(self):
         """float or PyoObject. First parameter."""
         return self._x1
     @x1.setter
-    def x1(self, x): 
+    def x1(self, x):
         self.setX1(x)
     @property
-    def x2(self): 
+    def x2(self):
         """float or PyoObject. Second parameter."""
         return self._x2
     @x2.setter
-    def x2(self, x): 
+    def x2(self, x):
         self.setX2(x)
     @property
-    def scale(self): 
+    def scale(self):
         """int. Output format."""
         return self._scale
     @scale.setter
-    def scale(self, x): 
+    def scale(self, x):
         self.setScale(x)
 
 class XnoiseDur(PyoObject):
@@ -922,24 +969,24 @@ class XnoiseDur(PyoObject):
 
     Xnoise implements a few of the most common noise distributions.
     Each distribution generates values in the range 0 to 1, which are
-    then rescaled between `min` and `max` arguments. The object uses 
-    the generated value to set the delay time before the next generation. 
+    then rescaled between `min` and `max` arguments. The object uses
+    the generated value to set the delay time before the next generation.
     XnoiseDur will hold the value until next generation.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        dist : string or int, optional
+        dist: string or int, optional
             Distribution type. Can be the name of the distribution as a string
             or its associated number. Defaults to 0.
-        min : float or PyoObject, optional
+        min: float or PyoObject, optional
             Minimum value for the random generation. Defaults to 0.
-        max : float or PyoObject, optional
+        max: float or PyoObject, optional
             Maximum value for the random generation. Defaults to 1.
-        x1 : float or PyoObject, optional
+        x1: float or PyoObject, optional
             First parameter. Defaults to 0.5.
-        x2 : float or PyoObject, optional
+        x2: float or PyoObject, optional
             Second parameter. Defaults to 0.5.
 
     .. note::
@@ -958,50 +1005,50 @@ class XnoiseDur(PyoObject):
             10. poisson
             11. walker (drunk)
             12. loopseg (drunk with looped segments)
-            
+
         Depending on the distribution, `x1` and `x2` parameters are applied
         as follow (names as string, or associated number can be used as `dist`
         parameter):
 
             0. uniform
-                - x1 : not used
-                - x2 : not used
+                - x1: not used
+                - x2: not used
             1. linear_min
-                - x1 : not used
-                - x2 : not used
+                - x1: not used
+                - x2: not used
             2. linear_max
-                - x1 : not used
-                - x2 : not used
+                - x1: not used
+                - x2: not used
             3. triangle
-                - x1 : not used
-                - x2 : not used
+                - x1: not used
+                - x2: not used
             4. expon_min
-                - x1 : slope {0 = no slope -> 10 = sharp slope}
-                - x2 : not used
+                - x1: slope {0 = no slope -> 10 = sharp slope}
+                - x2: not used
             5. expon_max
-                - x1 : slope {0 = no slope -> 10 = sharp slope}
-                - x2 : not used
+                - x1: slope {0 = no slope -> 10 = sharp slope}
+                - x2: not used
             6. biexpon
-                - x1 : bandwidth {0 = huge bandwidth -> 10 = narrow bandwidth}
-                - x2 : not used
+                - x1: bandwidth {0 = huge bandwidth -> 10 = narrow bandwidth}
+                - x2: not used
             7. cauchy
-                - x1 : bandwidth {0 = narrow bandwidth -> 10 = huge bandwidth}
-                - x2 : not used
+                - x1: bandwidth {0 = narrow bandwidth -> 10 = huge bandwidth}
+                - x2: not used
             8. weibull
-                - x1 : mean location {0 -> 1}
-                - x2 : shape {0.5 = linear min, 1.5 = expon min, 3.5 = gaussian}
+                - x1: mean location {0 -> 1}
+                - x2: shape {0.5 = linear min, 1.5 = expon min, 3.5 = gaussian}
             9. gaussian
-                - x1 : mean location {0 -> 1}
-                - x2 : bandwidth {0 =  narrow bandwidth -> 10 = huge bandwidth}
+                - x1: mean location {0 -> 1}
+                - x2: bandwidth {0 =  narrow bandwidth -> 10 = huge bandwidth}
             10. poisson
-                 - x1 : gravity center {0 = low values -> 10 = high values}
-                 - x2 : compress/expand range {0.1 = full compress -> 4 full expand}
+                 - x1: gravity center {0 = low values -> 10 = high values}
+                 - x2: compress/expand range {0.1 = full compress -> 4 full expand}
             11. walker
-                 - x1 : maximum value {0.1 -> 1}
-                 - x2 : maximum step {0.1 -> 1}
-            12. loopseg 
-                 - x1 : maximum value {0.1 -> 1}
-                 - x2 : maximum step {0.1 -> 1}
+                 - x1: maximum value {0.1 -> 1}
+                 - x2: maximum step {0.1 -> 1}
+            12. loopseg
+                 - x1: maximum value {0.1 -> 1}
+                 - x2: maximum step {0.1 -> 1}
 
     >>> s = Server().boot()
     >>> s.start()
@@ -1014,6 +1061,7 @@ class XnoiseDur(PyoObject):
 
     """
     def __init__(self, dist=0, min=0., max=1., x1=0.5, x2=0.5, mul=1, add=0):
+        pyoArgsAssert(self, "OOOOOO", min, max, x1, x2, mul, add)
         PyoObject.__init__(self, mul, add)
         self._dist = dist
         self._min = min
@@ -1022,8 +1070,9 @@ class XnoiseDur(PyoObject):
         self._x2 = x2
         dist, min, max, x1, x2, mul, add, lmax = convertArgsToLists(dist, min, max, x1, x2, mul, add)
         for i, t in enumerate(dist):
-            if type(t) == StringType: dist[i] = XNOISE_DICT.get(t, 0)
+            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):
         """
@@ -1031,14 +1080,14 @@ class XnoiseDur(PyoObject):
 
         :Args:
 
-            x : int
+            x: string or int
                 new `dist` attribute.
 
         """
         self._dist = x
         x, lmax = convertArgsToLists(x)
         for i, t in enumerate(x):
-            if type(t) == StringType: x[i] = XNOISE_DICT.get(t, 0)
+            if type(t) in [bytes_t, unicode_t]: x[i] = XNOISE_DICT.get(t, 0)
         [obj.setType(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     def setMin(self, x):
@@ -1047,10 +1096,11 @@ class XnoiseDur(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `min` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._min = x
         x, lmax = convertArgsToLists(x)
         [obj.setMin(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1061,10 +1111,11 @@ class XnoiseDur(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `max` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._max = x
         x, lmax = convertArgsToLists(x)
         [obj.setMax(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1075,10 +1126,11 @@ class XnoiseDur(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `x1` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._x1 = x
         x, lmax = convertArgsToLists(x)
         [obj.setX1(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1089,75 +1141,84 @@ class XnoiseDur(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `x2` attribute.
 
         """
-        self._x2= x
+        pyoArgsAssert(self, "O", x)
+        self._x2 = x
         x, lmax = convertArgsToLists(x)
         [obj.setX2(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, 12, 'lin', 'dist', self._dist, res="int", dataOnly=True),
+                          SLMap(0, 20, 'lin', 'min', self._min),
+                          SLMap(0, 20, 'lin', 'max', self._max),
+                          SLMap(0, 1, 'lin', 'x1', self._x1),
+                          SLMap(0, 1, 'lin', 'x2', self._x2)]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
     @property
-    def dist(self): 
+    def dist(self):
         """string or int. Distribution type."""
         return self._dist
     @dist.setter
-    def dist(self, x): 
+    def dist(self, x):
         self.setDist(x)
     @property
-    def min(self): 
+    def min(self):
         """float or PyoObject. Minimum value."""
         return self._min
     @min.setter
-    def min(self, x): 
+    def min(self, x):
         self.setMin(x)
     @property
-    def max(self): 
+    def max(self):
         """float or PyoObject. Maximum value."""
         return self._max
     @max.setter
-    def max(self, x): 
+    def max(self, x):
         self.setMax(x)
     @property
-    def x1(self): 
+    def x1(self):
         """float or PyoObject. First parameter."""
         return self._x1
     @x1.setter
-    def x1(self, x): 
+    def x1(self, x):
         self.setX1(x)
     @property
-    def x2(self): 
+    def x2(self):
         """float or PyoObject. Second parameter."""
         return self._x2
     @x2.setter
-    def x2(self, x): 
+    def x2(self, x):
         self.setX2(x)
 
 class Urn(PyoObject):
     """
     Periodic pseudo-random integer generator without duplicates.
 
-    Urn generates a pseudo-random integer number between 0 and `max` 
-    values at a frequency specified by `freq` parameter. Urn will 
-    hold generated value until the next generation. Urn works like RandInt, 
+    Urn generates a pseudo-random integer number between 0 and `max`
+    values at a frequency specified by `freq` parameter. Urn will
+    hold generated value until the next generation. Urn works like RandInt,
     except that it keeps track of each number which has been generated. After
     all numbers have been outputed, the pool is reseted and the object send
     a trigger signal.
-    
+
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        max : int, optional
+        max: int, optional
             Maximum value for the random generation. Defaults to 100.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Polling frequency. Defaults to 1.
 
     .. note::
 
-        Urn will sends a trigger signal when the pool is empty. 
-        User can retreive the trigger streams by calling obj['trig']. 
-        Useful to synchronize other processes. 
+        Urn will send a trigger signal when the pool is empty.
+        User can retreive the trigger streams by calling obj['trig'].
+        Useful to synchronize other processes.
 
     >>> s = Server().boot()
     >>> s.start()
@@ -1166,15 +1227,17 @@ class Urn(PyoObject):
     >>> sigL = SineLoop(freq=fr, feedback=.08, mul=0.3).out()
     >>> amp = TrigExpseg(mid["trig"], [(0,0),(.01,.25),(1,0)])
     >>> sigR = SineLoop(midiToHz(84), feedback=0.05, mul=amp).out(1)
-    
+
     """
     def __init__(self, max=100, freq=1., mul=1, add=0):
+        pyoArgsAssert(self, "iOOO", max, freq, mul, add)
         PyoObject.__init__(self, mul, add)
         self._max = max
         self._freq = freq
         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
@@ -1182,13 +1245,14 @@ class Urn(PyoObject):
     def setMax(self, x):
         """
         Replace the `max` attribute.
-        
+
         :Args:
 
-            x : int
+            x: int
                 new `max` attribute.
-        
+
         """
+        pyoArgsAssert(self, "i", x)
         self._max = x
         x, lmax = convertArgsToLists(x)
         [obj.setMax(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1196,34 +1260,138 @@ class Urn(PyoObject):
     def setFreq(self, x):
         """
         Replace the `freq` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `freq` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(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., 2., 'lin', 'max', self._max),
+        self._map_list = [SLMap(1, 1000, 'lin', 'max', self._max, res="int", dataOnly=True),
                           SLMap(0.1, 20., 'lin', 'freq', self._freq),
                           SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
-    def max(self): 
+    def max(self):
         """int. Maximum value."""
         return self._max
     @max.setter
-    def max(self, x): 
+    def max(self, x):
         self.setMax(x)
     @property
-    def freq(self): 
+    def freq(self):
+        """float or PyoObject. Polling frequency."""
+        return self._freq
+    @freq.setter
+    def freq(self, x):
+        self.setFreq(x)
+
+class LogiMap(PyoObject):
+    """
+    Random generator based on the logistic map.
+
+    The logistic equation (sometimes called the Verhulst model or logistic
+    growth curve) is a model of population growth first published by Pierre
+    Verhulst (1845, 1847). The logistic map is a discrete quadratic recurrence
+    equation derived from the logistic equation that can be effectively used
+    as a number generator that exibit chaotic behavior. This object uses the
+    following equation:
+
+        x[n] = (r + 3) * x[n-1] * (1.0 - x[n-1])
+
+    where 'r' is the randomization factor between 0 and 1.
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        chaos: float or PyoObject, optional
+            Randomization factor, 0.0 < chaos < 1.0. Defaults to 0.6.
+        freq: float or PyoObject, optional
+            Polling frequency. Defaults to 1.
+        init: float, optional
+            Initial value, 0.0 < init < 1.0. Defaults to 0.5.
+
+    .. note::
+
+        The method play() resets the internal state to the initial value.
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> val = LogiMap([0.6,0.65], [4,8])
+    >>> mid = Round(Scale(val, 0, 1, [36,48], [72,84]))
+    >>> hz = Snap(mid, [0,2,4,5,7,9,11], 1)
+    >>> env = CosTable([(0,0), (32,1), (4064,1), (4096,0), (8192,0)])
+    >>> amp = TrigEnv(Change(val), table=env, dur=[.25,.125], mul=0.3)
+    >>> osc = RCOsc(hz, mul=amp).out()
+
+    """
+    def __init__(self, chaos=0.6, freq=1.0, init=0.5, mul=1, add=0):
+        pyoArgsAssert(self, "OOnOO", chaos, freq, init, mul, add)
+        PyoObject.__init__(self, mul, add)
+        self._chaos = chaos
+        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
+
+    def setChaos(self, x):
+        """
+        Replace the `chaos` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                new `chaos` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._chaos = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setChaos(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def setFreq(self, x):
+        """
+        Replace the `freq` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                new `freq` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._freq = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setFreq(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.001, 0.999, 'lin', 'chaos', self._chaos),
+                          SLMap(0.1, 20., 'lin', 'freq', self._freq),
+                          SLMapMul(self._mul)]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
+    @property
+    def chaos(self):
+        """float or PyoObject. Randomization factor."""
+        return self._chaos
+    @chaos.setter
+    def chaos(self, x):
+        self.setChaos(x)
+    @property
+    def freq(self):
         """float or PyoObject. Polling frequency."""
         return self._freq
     @freq.setter
-    def freq(self, x): 
+    def freq(self, x):
         self.setFreq(x)
diff --git a/pyolib/server.py b/pyolib/server.py
index b7729a0..37a54e3 100644
--- a/pyolib/server.py
+++ b/pyolib/server.py
@@ -1,107 +1,131 @@
 # -*- coding: utf-8 -*-
+from __future__ import print_function
+from __future__ import absolute_import
 """
-Copyright 2010 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+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 os, time
-from _core import *
-from _widgets import createServerGUI
-        
+import os, sys, time
+from ._core import *
+from ._widgets import createServerGUI
+
 ######################################################################
 ### Proxy of Server object
 ######################################################################
 class Server(object):
     """
     Main processing audio loop callback handler.
-    
-    The Server object handles all communications with Portaudio and 
+
+    The Server object handles all communications with Portaudio and
     Portmidi. It keeps track of all audio streams created as well as
-    connections between them. 
-    
-    An instance of the Server must be booted before defining any 
+    connections between them.
+
+    An instance of the Server must be booted before defining any
     signal processing chain.
 
     :Args:
 
-        sr : int, optional
-            Sampling rate used by Portaudio and the Server to compute samples. 
+        sr: int, optional
+            Sampling rate used by Portaudio and the Server to compute samples.
             Defaults to 44100.
-        nchnls : int, optional
-            Number of input and output channels. Defaults to 2.
-        buffersize : int, optional
-            Number of samples that Portaudio will request from the callback loop. 
+        nchnls: int, optional
+            Number of output channels. The number of input channels will be the
+            same if `ichnls` argument is not defined. Defaults to 2.
+        buffersize: int, optional
+            Number of samples that Portaudio will request from the callback loop.
             Defaults to 256.
 
-            This value has an impact on CPU use (a small buffer size is harder 
-            to compute) and on the latency of the system. 
-            
-            Latency is `buffer size / sampling rate` in seconds. 
-        duplex : int {0, 1}, optional
-            Input - output mode. 0 is output only and 1 is both ways. 
+            This value has an impact on CPU use (a small buffer size is harder
+            to compute) and on the latency of the system.
+
+            Latency is `buffer size / sampling rate` in seconds.
+        duplex: int {0, 1}, optional
+            Input - output mode. 0 is output only and 1 is both ways.
             Defaults to 1.
-        audio : string {'portaudio', 'pa', 'jack', 'coreaudio', 'offline', 'offline_nb}, optional
+        audio: string {'portaudio', 'pa', 'jack', 'coreaudio', 'offline', 'offline_nb', 'embedded'}, optional
             Audio backend to use. 'pa' is equivalent to 'portaudio'. Default is 'portaudio'.
-            
-            'offline' save the audio output in a soundfile as fast as possible in blocking mode, 
+
+            'offline' save the audio output in a soundfile as fast as possible in blocking mode,
 
             ie. the main program doesn't respond until the end of the computation.
-            
-            'offline_nb' save the audio output in a soundfile as fast as possible in non-blocking 
-            mode, 
-            
+
+            'offline_nb' save the audio output in a soundfile as fast as possible in non-blocking
+            mode,
+
             ie. the computation is executed in a separated thread, allowing the program to
-            respond while the computation goes on. 
+            respond while the computation goes on.
 
-            It is the responsibility of the user to make sure that the program doesn't exit before 
+            It is the responsibility of the user to make sure that the program doesn't exit before
             the computation is done.
-        jackname : string, optional
+
+            'embedded' should be used when pyo is embedded inside an host environment via its C api.
+
+            If 'jack' is selected but jackd is not already started when the program is executed, pyo
+            will ask jack to start in the background. Note that pyo never ask jack to close. It is
+            the user's responsability to manage the audio configuration of its system.
+        jackname: string, optional
             Name of jack client. Defaults to 'pyo'
+        ichnls: int, optional
+            Number of input channels if different of output channels. If None (default), ichnls = nchnls.
+        winhost: string, optional
+            Under Windows, pyo's Server will try to use the default devices of the given host.
+            This behaviour can be changed with the SetXXXDevice methods.
 
     .. note::
 
         The following methods must be called **before** booting the server
 
-        - setInOutDevice(x) : Set both input and output devices. See `pa_list_devices()`.
-        - setInputDevice(x) : Set the audio input device number. See `pa_list_devices()`.
-        - setOutputDevice(x) : Set the audio output device number. See `pa_list_devices()`.
-        - setInputOffset(x) : Set the first physical input channel.
-        - setOutputOffset(x) : Set the first physical output channel.
-        - setInOutOffset(x) : Set the first physical input and output channels.
-        - setMidiInputDevice(x) : Set the MIDI input device number. See `pm_list_devices()`.
-        - setMidiOutputDevice(x) : Set the MIDI output device number. See `pm_list_devices()`.
-        - setSamplingRate(x) : Set the sampling rate used by the server.
-        - setBufferSize(x) : Set the buffer size used by the server.
-        - setNchnls(x) : Set the number of channels used by the server.
-        - setDuplex(x) : Set the duplex mode used by the server.
-        - setVerbosity(x) : Set the server's verbosity.
-        - reinit(sr, nchnls, buffersize, duplex, audio, jackname) : Reinit the server's settings.
+        - setInOutDevice(x): Set both input and output devices. See `pa_list_devices()`.
+        - setInputDevice(x): Set the audio input device number. See `pa_list_devices()`.
+        - setOutputDevice(x): Set the audio output device number. See `pa_list_devices()`.
+        - setInputOffset(x): Set the first physical input channel.
+        - setOutputOffset(x): Set the first physical output channel.
+        - setInOutOffset(x): Set the first physical input and output channels.
+        - setMidiInputDevice(x): Set the MIDI input device number. See `pm_list_devices()`.
+        - setMidiOutputDevice(x): Set the MIDI output device number. See `pm_list_devices()`.
+        - setSamplingRate(x): Set the sampling rate used by the server.
+        - setBufferSize(x): Set the buffer size used by the server.
+        - setNchnls(x): Set the number of output (and input if `ichnls` = None) channels used by the server.
+        - setIchnls(x): Set the number of input channels (if different of output channels) used by the server.
+        - setDuplex(x): Set the duplex mode used by the server.
+        - setVerbosity(x): Set the server's verbosity.
+        - reinit(sr, nchnls, buffersize, duplex, audio, jackname): Reinit the server's settings.
+        - deactivateMidi(): Deactivate Midi callback.
+        - setIsJackTransportSlave(x): Set if pyo's server is slave to jack transport or not.
+        - allowMicrosoftMidiDevices(): Allows the Microsoft Midi Mapper or GS Wavetable Synth devices.
 
     >>> # For an 8 channels server in duplex mode with
     >>> # a sampling rate of 48000 Hz and buffer size of 512
     >>> s = Server(sr=48000, nchnls=8, buffersize=512, duplex=1).boot()
     >>> s.start()
-        
+
     """
-    def __init__(self, sr=44100, nchnls=2, buffersize=256, duplex=1, audio='portaudio', jackname='pyo'):
-        if os.environ.has_key("PYO_SERVER_AUDIO") and "offline" not in audio:
+    def __init__(self, sr=44100, nchnls=2, buffersize=256, duplex=1,
+                 audio='portaudio', jackname='pyo', ichnls=None, winhost="wasapi"):
+        if "PYO_SERVER_AUDIO" in os.environ and "offline" not in audio and "embedded" not in audio:
             audio = os.environ["PYO_SERVER_AUDIO"]
         self._time = time
         self._nchnls = nchnls
+        if ichnls is None:
+            self._ichnls = nchnls
+        else:
+            self._ichnls = ichnls
+        self._winhost = winhost
         self._amp = 1.
         self._verbosity = 7
         self._startoffset = 0
@@ -109,10 +133,20 @@ class Server(object):
         self._filename = None
         self._fileformat = 0
         self._sampletype = 0
-        self._server = Server_base(sr, nchnls, buffersize, duplex, audio, jackname)
+        self._globalseed = 0
+        self._resampling = 1
+        self._isJackTransportSlave = False
+        self._server = Server_base(sr, nchnls, buffersize, duplex, audio, jackname, self._ichnls)
         self._server._setDefaultRecPath(os.path.join(os.path.expanduser("~"), "pyo_rec.wav"))
 
+        if sys.platform.startswith("win"):
+            host_default_in, host_default_out = pa_get_default_devices_from_host(winhost)
+            self._server.setInputDevice(host_default_in)
+            self._server.setOutputDevice(host_default_out)
+
     def __del__(self):
+        self.setTime = None
+        self.setRms = None
         if self.getIsBooted():
             if self.getIsStarted():
                 self.stop()
@@ -120,16 +154,23 @@ class Server(object):
             self.shutdown()
             self._time.sleep(.25)
 
-    def reinit(self, sr=44100, nchnls=2, buffersize=256, duplex=1, audio='portaudio', jackname='pyo'):
+    def reinit(self, sr=44100, nchnls=2, buffersize=256, duplex=1,
+               audio='portaudio', jackname='pyo', ichnls=None, winhost="wasapi"):
         """
         Reinit the server'settings. Useful to alternate between real-time and offline server.
-        
+
         :Args:
-        
+
             Same as in the __init__ method.
-        
+
         """
+        self._gui_frame = None
         self._nchnls = nchnls
+        if ichnls is None:
+            self._ichnls = nchnls
+        else:
+            self._ichnls = ichnls
+        self._winhost = winhost
         self._amp = 1.
         self._verbosity = 7
         self._startoffset = 0
@@ -138,60 +179,140 @@ class Server(object):
         self._fileformat = 0
         self._sampletype = 0
         self._globalseed = 0
-        self._server.__init__(sr, nchnls, buffersize, duplex, audio, jackname)
+        self._resampling = 1
+        self._isJackTransportSlave = False
+        self._server.__init__(sr, nchnls, buffersize, duplex, audio, jackname, self._ichnls)
+
+        if sys.platform.startswith("win"):
+            host_default_in, host_default_out = pa_get_default_devices_from_host(winhost)
+            self._server.setInputDevice(host_default_in)
+            self._server.setOutputDevice(host_default_out)
 
-    def gui(self, locals=None, meter=True, timer=True):
+    def setCallback(self, callback):
+        """
+        Register a custom process callback.
+
+        The function given as argument will be called every computation
+        block, just before the computation of the audio object tree.
+        Inside the callback, one can process the data of a table with
+        numpy calls for example.
+
+        """
+        if callable(callback):
+            self._server.setCallback(callback)
+
+    def gui(self, locals=None, meter=True, timer=True, exit=True, title=None):
         """
         Show the server's user interface.
-        
+
         :Args:
-        
-            locals : locals namespace {locals(), None}, optional
+
+            locals: locals namespace {locals(), None}, optional
                 If locals() is given, the interface will show an interpreter extension,
                 giving a way to interact with the running script. Defaults to None.
-            meter : boolean, optinal
-                If True, the interface will show a vumeter of the global output signal. 
+            meter: boolean, optinal
+                If True, the interface will show a vumeter of the global output signal.
                 Defaults to True.
-            timer : boolean, optional
+            timer: boolean, optional
                 If True, the interface will show a clock of the current time.
                 Defaults to True.
-            
+            exit: boolean, optional
+                If True, the python interpreter will exit when the 'Quit' button is pressed,
+                Otherwise, the GUI will be closed leaving the interpreter alive.
+                Defaults to True.
+            title: str, optional
+                Alternate title for the server window. If None (default), generic
+                title, "Pyo Server" is used.
+
         """
-        f, win = createServerGUI(self._nchnls, self.start, self.stop, self.recstart, self.recstop,
-                                 self.setAmp, self.getIsStarted(), locals, self.shutdown, meter, timer, self._amp)
+        self._gui_frame, win = createServerGUI(self._nchnls, self.start, self.stop,
+                                               self.recstart, self.recstop, self.setAmp,
+                                               self.getIsStarted(), locals, self.shutdown,
+                                               meter, timer, self._amp, exit, title)
         if meter:
-            self._server.setAmpCallable(f)
+            self._server.setAmpCallable(self._gui_frame)
         if timer:
-            self._server.setTimeCallable(f)
+            self._server.setTimeCallable(self._gui_frame)
         try:
             win.mainloop()
         except:
-            if win != None:
+            if win is not None:
                 win.MainLoop()
 
+    def closeGui(self):
+        """
+        Programmatically close the server's GUI.
+
+        """
+        if self._gui_frame is not None:
+            self._gui_frame.quit_from_code()
+            self._gui_frame = None
+
     def setTimeCallable(self, func):
+        """
+        Set a function callback that will receive the current time as argument.
+
+        The function will receive four integers in this format:
+                hours, minutes, seconds, milliseconds
+
+        :Args:
+
+            func: python callable
+                Python function or method to call with current time as argument.
+
+        """
         self.setTime = func
         self._server.setTimeCallable(self)
-        
+
+    def setMeterCallable(self, func):
+        """
+        Set a function callback that will receive the current rms values as argument.
+
+        The function will receive a list containing the rms value for each audio channel.
+
+        :Args:
+
+            func: python callable
+                Python function or method to call with current rms values as argument.
+
+        """
+        self.setRms = func
+        self._server.setAmpCallable(self)
+
+    def setMeter(self, meter):
+        """
+        Registers a meter object to the server.
+
+        The object must have a method named `setRms`. This method will be called
+        with the rms values of each audio channel as argument.
+
+        :Args:
+
+            meter: python object
+                Python object with a `setRms` method.
+
+        """
+        self._server.setAmpCallable(meter)
+
     def setInOutDevice(self, x):
         """
         Set both input and output audio devices. See `pa_list_devices()`.
-        
+
         :Args:
 
-            x : int
+            x: int
                 Number of the audio input and output devices.
 
         """
         self._server.setInOutDevice(x)
-        
+
     def setInputDevice(self, x):
         """
         Set the audio input device number. See `pa_list_devices()`.
-        
+
         :Args:
 
-            x : int
+            x: int
                 Number of the audio device listed by Portaudio.
 
         """
@@ -200,10 +321,10 @@ class Server(object):
     def setOutputDevice(self, x):
         """
         Set the audio output device number. See `pa_list_devices()`.
-        
+
         :Args:
 
-            x : int
+            x: int
                 Number of the audio device listed by Portaudio.
 
         """
@@ -212,14 +333,14 @@ class Server(object):
     def setInputOffset(self, x):
         """
         Set the first physical input channel.
-        
+
         Channel number `x` from the soundcard will be assigned to
         server's channel one, channel number `x` + 1 to server's
-        channel two and so on. 
-        
+        channel two and so on.
+
         :Args:
 
-            x : int
+            x: int
                 Channel number.
 
         """
@@ -229,13 +350,13 @@ class Server(object):
         """
         Set the first physical output channel.
 
-        Server's channel one will be assigned to soundcard's channel 
+        Server's channel one will be assigned to soundcard's channel
         number `x`, server's channel two will be assigned to soundcard's
-        channel number `x` + 1 and so on. 
-        
+        channel number `x` + 1 and so on.
+
         :Args:
 
-            x : int
+            x: int
                 Channel number.
 
         """
@@ -250,7 +371,7 @@ class Server(object):
 
         :Args:
 
-            x : int
+            x: int
                 Channel number.
 
         """
@@ -260,10 +381,13 @@ class Server(object):
     def setMidiInputDevice(self, x):
         """
         Set the Midi input device number. See `pm_list_devices()`.
-        
+
+        A number greater than the highest portmidi device index
+        will opened all available input devices.
+
         :Args:
 
-            x : int
+            x: int
                 Number of the Midi device listed by Portmidi.
 
         """
@@ -272,74 +396,96 @@ class Server(object):
     def setMidiOutputDevice(self, x):
         """
         Set the Midi output device number. See `pm_list_devices()`.
-        
+
         :Args:
 
-            x : int
+            x: int
                 Number of the Midi device listed by Portmidi.
 
         """
         self._server.setMidiOutputDevice(x)
- 
+
+    def allowMicrosoftMidiDevices(self):
+        """
+        Allows the Microsoft Midi Mapper or GS Wavetable Synth device.
+
+        These are off by default because they crash on some systems.
+
+        """
+        self._server.allowMicrosoftMidiDevices()
+
     def setSamplingRate(self, x):
         """
         Set the sampling rate used by the server.
-        
+
         :Args:
 
-            x : int
+            x: int
                 New sampling rate, must be supported by the soundcard.
 
-        """  
+        """
         self._server.setSamplingRate(x)
-        
+
     def setBufferSize(self, x):
         """
         Set the buffer size used by the server.
-        
+
         :Args:
 
-            x : int
+            x: int
                 New buffer size.
 
-        """        
+        """
         self._server.setBufferSize(x)
-  
+
     def setNchnls(self, x):
         """
-        Set the number of channels used by the server.
-        
+        Set the number of output (and input if `ichnls` = None) channels used by the server.
+
         :Args:
 
-            x : int
+            x: int
                 New number of channels.
 
         """
         self._nchnls = x
         self._server.setNchnls(x)
 
+    def setIchnls(self, x):
+        """
+        Set the number of input channels (if different of output channels) used by the server.
+
+        :Args:
+
+            x: int
+                New number of input channels.
+
+        """
+        self._ichnls = x
+        self._server.setIchnls(x)
+
     def setDuplex(self, x):
         """
         Set the duplex mode used by the server.
-        
+
         :Args:
 
-            x : int {0 or 1}
+            x: int {0 or 1}
                 New mode. 0 is output only, 1 is both ways.
 
-        """        
+        """
         self._server.setDuplex(x)
 
     def setVerbosity(self, x):
         """
         Set the server's verbosity.
-        
+
         :Args:
 
-            x : int
-                A sum of values to display different levels: 
+            x: int
+                A sum of values to display different levels:
                     - 1 = error
-                    - 2 = message 
+                    - 2 = message
                     - 4 = warning
                     - 8 = debug
 
@@ -347,32 +493,144 @@ 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.
-        
+        Tells the server to auto-connect (or not) Jack ports to System ports.
+
         :Args:
 
-            xin : boolean
+            xin: boolean
                 Input Auto-connection switch. True is enabled (default) and False is disabled.
-            xout : boolean
+            xout: boolean
                 Output Auto-connection switch. True is enabled (default) and False is disabled.
 
-        """        
+        """
         self._server.setJackAuto(xin, xout)
 
+    def setJackAutoConnectInputPorts(self, ports):
+        """
+        Tells the server to auto-connect Jack input ports to pre-defined Jack ports.
+
+        :Args:
+
+            ports: list of list of strings
+                Name of the Jack ports to auto-connect to pyo input channels.
+                There must be exactly one list of port(s) for each pyo input channel.
+
+                [['ports', 'to', 'channel', '1'], ['ports', 'to', 'channel', '2'], ...]
+
+        """
+        ports, lmax = convertArgsToLists(ports)
+        self._server.setJackAutoConnectInputPorts(ports)
+
+    def setJackAutoConnectOutputPorts(self, ports):
+        """
+        Tells the server to auto-connect Jack output ports to pre-defined Jack ports.
+
+        :Args:
+
+            ports: list of list of strings
+                Name of the Jack ports to auto-connect to pyo output channels.
+                There must be exactly one list of port(s) for each pyo output channel.
+
+                [['ports', 'to', 'channel', '1'], ['ports', 'to', 'channel', '2'], ...]
+
+        """
+        ports, lmax = convertArgsToLists(ports)
+        self._server.setJackAutoConnectOutputPorts(ports)
+
+    def setJackInputPortNames(self, name):
+        """
+        Change the short name of pyo's input ports for the jack server.
+
+        This method must be called after the server is booted.
+
+        :Args:
+
+            name: string or list of strings
+                New name of input ports for the jack server. If `name` is a string,
+                '_xxx' (where xxx is the channel number) will be added to it for
+                each input channel. If `name` is a list of strings, They will be
+                used as is and there must be one for each input channel.
+
+        """
+        self._server.setJackInputPortNames(name)
+
+    def setJackOutputPortNames(self, name):
+        """
+        Change the short name of pyo's output ports for the jack server.
+
+        This method must be called after the server is booted.
+
+        :Args:
+
+            name: string or list of strings
+                New name of output ports for the jack server. If `name` is a string,
+                '_xxx' (where xxx is the channel number) will be added to it for
+                each output channel. If `name` is a list of strings, They will be
+                used as is and there must be one for each output channel.
+
+        """
+        self._server.setJackOutputPortNames(name)
+
+    def setIsJackTransportSlave(self, x):
+        """
+        Set if pyo's server is slave to jack transport or not.
+
+        This method must be called before booting the server.
+
+        :Args:
+
+            x: boolean
+                If True, the server's start and stop command will be slave to
+                Jack transport. If False (the default) jack transport is ignored.
+
+        """
+        self._isJackTransportSlave = x
+        self._server.setIsJackTransportSlave(x)
+
     def setGlobalSeed(self, x):
         """
         Set the server's global seed used by random objects.
 
         :Args:
 
-            x : int
+            x: int
                 A positive integer that will be used as the seed by random objects.
 
                 If zero, randoms will be seeded with the system clock current value.
 
-        """        
+        """
         self._globalseed = x
         self._server.setGlobalSeed(x)
 
@@ -383,89 +641,135 @@ class Server(object):
 
         :Args:
 
-            x : float
+            x: float
                 Starting time of the real-time processing.
-            
-        """        
+
+        """
         self._startoffset = x
         self._server.setStartOffset(x)
 
     def setAmp(self, x):
         """
         Set the overall amplitude.
-        
+
         :Args:
 
-            x : float
+            x: float
                 New amplitude.
 
         """
         self._amp = x
         self._server.setAmp(x)
- 
+
+    def beginResamplingBlock(self, x):
+        """
+        Starts a resampling block.
+
+        This factor must be a power-of-two. A positive value means
+        upsampling and a negative value means downsampling. After this
+        call, every PyoObject will be created with an internal sampling
+        rate and buffer size relative to the resampling factor. The method
+        `endResamplingBlock()` should be called at the end of the code
+        block using the resampling factor.
+
+        The `Resample` object can be used inside the resampling block to
+        perform up or down resampling of audio signal created before the
+        block.
+
+        :Args:
+
+            x: int, power-of-two
+                Resampling factor. Must be a power-of-two. A positive
+                value starts an upsampling block while a negative value
+                starts a downsampling block.
+
+        """
+        realx = x
+        x = abs(x)
+        if ((x & (x - 1)) == 0) and x != 0:
+            self._resampling = realx
+            self._server.beginResamplingBlock(realx)
+        else:
+            print("Resampling factor must be a power-of-two (positive or negative).")
+
+    def endResamplingBlock(self):
+        """
+        Ends a resampling block.
+
+        This call ends a code block using a sample rate different from
+        the current sampling rate of the system.
+
+        The `Resample` object can be used after the resampling blick to
+        perform up or down resampling of audio signal created inside the
+        block.
+
+        """
+        self._resampling = 1
+        self._server.endResamplingBlock()
+
     def shutdown(self):
         """
         Shut down and clear the server. This method will erase all objects
-        from the callback loop. This method need to be called before changing 
+        from the callback loop. This method need to be called before changing
         server's parameters like `samplingrate`, `buffersize`, `nchnls`, ...
 
         """
         self._server.shutdown()
-        
+
     def boot(self, newBuffer=True):
         """
-        Boot the server. Must be called before defining any signal processing 
-        chain. Server's parameters like `samplingrate`, `buffersize` or 
-        `nchnls` will be effective after a call to this method. 
-        
-        :Args:
-            
-            newBuffer : bool
-                Specify if the buffers need to be allocated or not. Useful to limit 
-                the allocation of new buffers when the buffer size hasn't change. 
-                
-                Therefore, this is useful to limit calls to the Python interpreter 
-                to get the buffers addresses when using Pyo inside a 
-                C/C++ application with the embedded server. 
-                
+        Boot the server. Must be called before defining any signal processing
+        chain. Server's parameters like `samplingrate`, `buffersize` or
+        `nchnls` will be effective after a call to this method.
+
+        :Args:
+
+            newBuffer: bool
+                Specify if the buffers need to be allocated or not. Useful to limit
+                the allocation of new buffers when the buffer size hasn't change.
+
+                Therefore, this is useful to limit calls to the Python interpreter
+                to get the buffers addresses when using Pyo inside a
+                C/C++ application with the embedded server.
+
                 Defaults to True.
 
         """
         self._server.boot(newBuffer)
         return self
-        
+
     def start(self):
         """
         Start the audio callback loop and begin processing.
-        
+
         """
         self._server.start()
         return self
-    
+
     def stop(self):
         """
         Stop the audio callback loop.
-        
+
         """
         self._server.stop()
 
-    def recordOptions(self, dur=-1, filename=None, fileformat=0, sampletype=0):
+    def recordOptions(self, dur=-1, filename=None, fileformat=0, sampletype=0, quality=0.4):
         """
         Sets options for soundfile created by offline rendering or global recording.
 
         :Args:
 
-            dur : float
+            dur: float
                 Duration, in seconds, of the recorded file. Only used by
                 offline rendering. Must be positive. Defaults to -1.
-            filename : string
+            filename: string
                 Full path of the file to create. If None, a file called
                 `pyo_rec.wav` will be created in the user's home directory.
                 Defaults to None.
-            fileformat : int, optional
+            fileformat: int, optional
                 Format type of the audio file. This function will first try to
-                set the format from the filename extension. 
-                
+                set the format from the filename extension.
+
                 If it's not possible, it uses the fileformat parameter. Supported formats are:
                     0. WAV - Microsoft WAV format (little endian) {.wav, .wave} (default)
                     1. AIFF - Apple/SGI AIFF format (big endian) {.aif, .aiff}
@@ -475,9 +779,9 @@ class Server(object):
                     5. FLAC - FLAC lossless file format {.flac}
                     6. CAF - Core Audio File format {.caf}
                     7. OGG - Xiph OGG container {.ogg}
-            sampletype : int, optional
-                Bit depth encoding of the audio file. 
-                
+            sampletype: int, optional
+                Bit depth encoding of the audio file.
+
                 SD2 and FLAC only support 16 or 24 bit int. Supported types are:
                     0. 16 bits int (default)
                     1. 24 bits int
@@ -486,109 +790,313 @@ class Server(object):
                     4. 64 bits float
                     5. U-Law encoded
                     6. A-Law encoded
+            quality: float, optional
+                The encoding quality value, between 0.0 (lowest quality) and
+                1.0 (highest quality). This argument has an effect only with
+                FLAC and OGG compressed formats. Defaults to 0.4.
 
         """
-        
+
         self._dur = dur
-        if filename == None:
+        if filename is None:
             filename = os.path.join(os.path.expanduser("~"), "pyo_rec.wav")
         self._filename = filename
         ext = filename.rsplit('.')
         if len(ext) >= 2:
             ext = ext[-1].lower()
-            if FILE_FORMATS.has_key(ext):
+            if ext in FILE_FORMATS:
                 fileformat = FILE_FORMATS[ext]
             else:
-                print 'Warning: Unknown file extension. Using fileformat value.'
+                print('Warning: Unknown file extension. Using fileformat value.')
         else:
-            print 'Warning: Filename has no extension. Using fileformat value.'
+            print('Warning: Filename has no extension. Using fileformat value.')
         self._fileformat = fileformat
         self._sampletype = sampletype
-        self._server.recordOptions(dur, filename, fileformat, sampletype)
-        
+        self._server.recordOptions(dur, stringencode(filename), fileformat, sampletype, quality)
+
     def recstart(self, filename=None):
         """
         Begins a default recording of the sound that is sent to the
-        soundcard. This will create a file called `pyo_rec.wav` in 
+        soundcard. This will create a file called `pyo_rec.wav` in
         the user's home directory if no path is supplied or defined
-        with recordOptions method. Uses file format and sample type 
-        defined with recordOptions method. 
-        
+        with recordOptions method. Uses file format and sample type
+        defined with recordOptions method.
+
         :Args:
-        
-            filename : string, optional
+
+            filename: string, optional
                 Name of the file to be created. Defaults to None.
-        
+
         """
-        if filename == None:
-            if self._filename != None:
+        if filename is None:
+            if self._filename is not None:
                 filename = self._filename
             else:
                 filename = os.path.join(os.path.expanduser("~"), "pyo_rec.wav")
         ext = filename.rsplit('.')
         if len(ext) >= 2:
             ext = ext[-1].lower()
-            if FILE_FORMATS.has_key(ext):
+            if ext in FILE_FORMATS:
                 fileformat = FILE_FORMATS[ext]
                 if fileformat != self._fileformat:
                     self._fileformat = fileformat
-                    self._server.recordOptions(self._dur, filename, self._fileformat, self._sampletype)
+                    self._server.recordOptions(self._dur, stringencode(filename), self._fileformat, self._sampletype)
+
+        self._server.recstart(filename)
 
-        self._server.recstart(filename)    
-        
     def recstop(self):
         """
         Stop the previously started recording.
-        
+
         """
         self._server.recstop()
 
-    def sendMidiNote(self, pitch, velocity, channel=0, timestamp=0):
+    def noteout(self, pitch, velocity, channel=0, timestamp=0):
         """
-        Send a MIDI note message to the selected output device. 
-        
+        Send a MIDI note message to the selected midi output device.
+
+        Arguments can be list of values to generate multiple events
+        in one call.
+
         :Args:
-        
-            pitch : int
+
+            pitch: int
                 Midi pitch, between 0 and 127.
-            velocity : int
+            velocity: int
                 Amplitude of the note, between 0 and 127. A note
                 with a velocity of 0 is equivalent to a note off.
-            channel : int, optional
-                The Midi channel, between 1 and 16, on which the 
-                note is sent. A channel of 0 means all channels. 
+            channel: int, optional
+                The Midi channel, between 1 and 16, on which the
+                note is sent. A channel of 0 means all channels.
+                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.
+        """
+        pitch, velocity, channel, timestamp, lmax = convertArgsToLists(pitch, velocity, channel, timestamp)
+        [self._server.noteout(wrap(pitch,i), wrap(velocity,i), wrap(channel,i), wrap(timestamp,i)) for i in range(lmax)]
+
+    def afterout(self, pitch, velocity, channel=0, timestamp=0):
+        """
+        Send an aftertouch message to the selected midi output device.
+
+        Arguments can be list of values to generate multiple events
+        in one call.
+
+        :Args:
+
+            pitch: int
+                Midi key pressed down, between 0 and 127.
+            velocity: int
+                Velocity of the pressure, between 0 and 127.
+            channel: int, optional
+                The Midi channel, between 1 and 16, on which the
+                note is sent. A channel of 0 means all channels.
+                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.
+        """
+        pitch, velocity, channel, timestamp, lmax = convertArgsToLists(pitch, velocity, channel, timestamp)
+        [self._server.afterout(wrap(pitch,i), wrap(velocity,i), wrap(channel,i), wrap(timestamp,i)) for i in range(lmax)]
+
+    def ctlout(self, ctlnum, value, channel=0, timestamp=0):
+        """
+        Send a control change message to the selected midi output device.
+
+        Arguments can be list of values to generate multiple events
+        in one call.
+
+        :Args:
+
+            ctlnum: int
+                Controller number, between 0 and 127.
+            value: int
+                Value of the controller, between 0 and 127.
+            channel: int, optional
+                The Midi channel, between 1 and 16, on which the
+                message is sent. A channel of 0 means all channels.
+                Defaults to 0.
+            timestamp: int, optional
+                The delay time, in milliseconds, before the message
+                is sent on the portmidi stream. A value of 0 means
+                to play the message now. Defaults to 0.
+        """
+        ctlnum, value, channel, timestamp, lmax = convertArgsToLists(ctlnum, value, channel, timestamp)
+        [self._server.ctlout(wrap(ctlnum,i), wrap(value,i), wrap(channel,i), wrap(timestamp,i)) for i in range(lmax)]
+
+    def programout(self, value, channel=0, timestamp=0):
+        """
+        Send a program change message to the selected midi output device.
+
+        Arguments can be list of values to generate multiple events
+        in one call.
+
+        :Args:
+
+            value: int
+                New program number, between 0 and 127.
+            channel: int, optional
+                The Midi channel, between 1 and 16, on which the
+                message is sent. A channel of 0 means all channels.
+                Defaults to 0.
+            timestamp: int, optional
+                The delay time, in milliseconds, before the message
+                is sent on the portmidi stream. A value of 0 means
+                to play the message now. Defaults to 0.
+        """
+        value, channel, timestamp, lmax = convertArgsToLists(value, channel, timestamp)
+        [self._server.programout(wrap(value,i), wrap(channel,i), wrap(timestamp,i)) for i in range(lmax)]
+
+    def pressout(self, value, channel=0, timestamp=0):
+        """
+        Send a channel pressure message to the selected midi output device.
+
+        Arguments can be list of values to generate multiple events
+        in one call.
+
+        :Args:
+
+            value: int
+                Single greatest pressure value, between 0 and 127.
+            channel: int, optional
+                The Midi channel, between 1 and 16, on which the
+                message is sent. A channel of 0 means all channels.
+                Defaults to 0.
+            timestamp: int, optional
+                The delay time, in milliseconds, before the message
+                is sent on the portmidi stream. A value of 0 means
+                to play the message now. Defaults to 0.
+        """
+        value, channel, timestamp, lmax = convertArgsToLists(value, channel, timestamp)
+        [self._server.pressout(wrap(value,i), wrap(channel,i), wrap(timestamp,i)) for i in range(lmax)]
+
+    def bendout(self, value, channel=0, timestamp=0):
+        """
+        Send a pitch bend message to the selected midi output device.
+
+        Arguments can be list of values to generate multiple events
+        in one call.
 
+        :Args:
+
+            value: int
+                14 bits pitch bend value. 8192 is where there is no
+                bending, 0 is full down and 16383 is full up bending.
+            channel: int, optional
+                The Midi channel, between 1 and 16, on which the
+                message is sent. A channel of 0 means all channels.
+                Defaults to 0.
+            timestamp: int, optional
+                The delay time, in milliseconds, before the message
+                is sent on the portmidi stream. A value of 0 means
+                to play the message now. Defaults to 0.
         """
-        self._server.sendMidiNote(pitch, velocity, channel, timestamp)
+        value, channel, timestamp, lmax = convertArgsToLists(value, channel, timestamp)
+        [self._server.bendout(wrap(value,i), wrap(channel,i), wrap(timestamp,i)) for i in range(lmax)]
+
+    def sysexout(self, msg, timestamp=0):
+        """
+        Send a system exclusive message to the selected midi output device.
+
+        Arguments can be list of values/messages to generate multiple events
+        in one call.
+
+        :Args:
+
+            msg: str
+                A valid system exclusive message as a string. The first byte
+                must be 0xf0 and the last one must be 0xf7.
+            timestamp: int, optional
+                The delay time, in milliseconds, before the message
+                is sent on the portmidi stream. A value of 0 means
+                to play the message now. Defaults to 0.
+        """
+        msg, timestamp, lmax = convertArgsToLists(msg, timestamp)
+        [self._server.sysexout(wrap(msg,i), wrap(timestamp,i)) for i in range(lmax)]
+
+    def addMidiEvent(self, status, data1=0, data2=0):
+        """
+        Add a MIDI event in the server processing loop.
+
+        This method can be used to  programmatically simulate incoming
+        MIDI events. In an embedded framework (ie. pyo inside puredata,
+        openframeworks, etc.), this is useful to control a MIDI-driven
+        script from the host program. Arguments can be list of values to
+        generate multiple events in one call.
+
+        The MIDI event buffer is emptied at the end of each processing
+        block. So, for events to be processed, addMidiEvent should be
+        called at the beginning of the block. If you use audio objects
+        to generate MIDI events, they should be created before the rest
+        of the processing chain.
+
+        :Args:
+
+            status: int
+                The status byte, indicating the type of event and the
+                MIDI channel. Typical event type are:
+                    128 -> 143: Noteoff
+                    144 -> 159: Noteon
+                    176 -> 191: Control change
+                    192 -> 207: Program change
+                    209 -> 223: After touch
+                    224 -> 239: Pitch bend
+            data1: int, optional
+                The first data byte (pitch for a midi note, controller
+                number for a control change). Defaults to 0.
+            data2: int, optional
+                The second data byte (velocity for a midi note, value
+                for a control change). Defaults to 0.
+
+        """
+        status, data1, data2, lmax = convertArgsToLists(status, data1, data2)
+        [self._server.addMidiEvent(wrap(status,i), wrap(data1,i), wrap(data2,i)) for i in range(lmax)]
 
     def getStreams(self):
         """
         Return the list of streams loaded in the server.
-        
+
         """
         return self._server.getStreams()
-        
+
     def getSamplingRate(self):
         """
         Return the current sampling rate.
-        
+
         """
         return self._server.getSamplingRate()
-        
+
     def getNchnls(self):
         """
         Return the current number of channels.
-        
+
         """
         return self._server.getNchnls()
-        
+
     def getBufferSize(self):
         """
         Return the current buffer size.
-        
+
         """
         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.
@@ -599,104 +1107,116 @@ class Server(object):
     def getIsStarted(self):
         """
         Returns 1 if the server is started, otherwise returns 0.
-        
+
         """
         return self._server.getIsStarted()
 
     def getIsBooted(self):
         """
         Returns 1 if the server is booted, otherwise returns 0.
-        
+
         """
         return self._server.getIsBooted()
 
+    def deactivateMidi(self):
+        """
+        Deactivate Midi callback. Must be called before the boot() method.
+
+        """
+        self._server.deactivateMidi()
+
     def getMidiActive(self):
         """
         Returns 1 if Midi callback is active, otherwise returns 0.
-        
+
         """
         return self._server.getMidiActive()
 
     def getStreams(self):
         """
         Returns the list of Stream objects currently in the Server memory.
-        
+
         """
         return self._server.getStreams()
 
     def getNumberOfStreams(self):
         """
         Returns the number of streams currently in the Server memory.
-        
+
         """
         return len(self._server.getStreams())
 
     def setServer(self):
         """
         Sets this server as the one to use for new objects when using the embedded device
-        
+
         """
         return self._server.setServer()
-        
-    def flush(self):
-        """
-        Flush the server objects. Need a shutdown before working. This is useful if want to flush a script without freeing the buffers
-        
-        """
-        return self._server.flush()
-    
+
     def getInputAddr(self):
         """
         Return the address of the input buffer
-        
+
         """
         return self._server.getInputAddr()
-        
+
     def getOutputAddr(self):
         """
         Return the address of the output buffer
-        
+
         """
         return self._server.getOutputAddr()
-        
+
     def getServerID(self):
         """
         Return the server ID
-        
+
         """
         return self._server.getServerID()
-        
+
     def getServerAddr(self):
         """
         Return the address of the server
-        
+
         """
         return self._server.getServerAddr()
-        
+
     def getEmbedICallbackAddr(self):
         """
         Return the address of the interleaved embedded callback function
-        
+
         """
         return self._server.getEmbedICallbackAddr()
 
+    def getCurrentTime(self):
+        """
+        Return the current time as a formatted string.
+        """
+        return self._server.getCurrentTime()
+
+    def getCurrentAmp(self):
+        """
+        Return the current amplitudes as a tuple of `nchnls` length.
+        """
+        return self._server.getCurrentAmp()
+
     @property
     def amp(self):
-        """float. Overall amplitude.""" 
+        """float. Overall amplitude."""
         return self._amp
     @amp.setter
-    def amp(self, x): self.setAmp(x) 
+    def amp(self, x): self.setAmp(x)
 
     @property
     def startoffset(self):
-        """float. Starting time of the real-time processing.""" 
+        """float. Starting time of the real-time processing."""
         return self._startoffset
     @startoffset.setter
-    def startoffset(self, x): self.setStartOffset(x) 
+    def startoffset(self, x): self.setStartOffset(x)
 
     @property
     def verbosity(self):
-        """int. Server verbosity.""" 
+        """int. Server verbosity."""
         return self._verbosity
     @verbosity.setter
     def verbosity(self, x):
@@ -707,7 +1227,7 @@ class Server(object):
 
     @property
     def globalseed(self):
-        """int. Server global seed.""" 
+        """int. Server global seed."""
         return self._globalseed
     @globalseed.setter
     def globalseed(self, x):
diff --git a/pyolib/tableprocess.py b/pyolib/tableprocess.py
index 2b4fb7c..e4c1c07 100644
--- a/pyolib/tableprocess.py
+++ b/pyolib/tableprocess.py
@@ -1,67 +1,68 @@
 """
 Set of objects to perform operations on PyoTableObjects.
 
-PyoTableObjects are 1 dimension containers. They can be used to 
+PyoTableObjects are 1 dimension containers. They can be used to
 store audio samples or algorithmic sequences for future uses.
 
 """
 
+from __future__ import absolute_import
 """
-Copyright 2010 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+You should have received a copy of the GNU Lesser General Public
+License along with pyo.  If not, see <http://www.gnu.org/licenses/>.
 """
-from _core import *
-from _maps import *
-from types import SliceType
- 
+from ._core import *
+from ._maps import *
+
 class Osc(PyoObject):
     """
     A simple oscillator reading a waveform table.
-    
+
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
-    
-        table : PyoTableObject
+
+        table: PyoTableObject
             Table containing the waveform samples.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Frequency in cycles per second. Defaults to 1000.
-        phase : float or PyoObject, optional
-            Phase of sampling, expressed as a fraction of a cycle (0 to 1). 
+        phase: float or PyoObject, optional
+            Phase of sampling, expressed as a fraction of a cycle (0 to 1).
             Defaults to 0.
-        interp : int, optional
+        interp: int, optional
             Choice of the interpolation method. Defaults to 2.
                 1. no interpolation
                 2. linear
                 3. cosinus
                 4. cubic
 
-    .. seealso:: 
-        
+    .. seealso::
+
         :py:class:`Phasor`, :py:class:`Sine`
 
     >>> s = Server().boot()
     >>> s.start()
     >>> t = HarmTable([1,0,.33,0,.2,0,.143,0,.111,0,.091])
     >>> a = Osc(table=t, freq=[100,99.2], mul=.2).out()
-     
+
     """
     def __init__(self, table, freq=1000, phase=0, interp=2, mul=1, add=0):
+        pyoArgsAssert(self, "tOOiOO", table, freq, phase, interp, mul, add)
         PyoObject.__init__(self, mul, add)
         self._table = table
         self._freq = freq
@@ -69,17 +70,19 @@ 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):
         """
         Replace the `table` attribute.
-        
+
         :Args:
 
-            x : PyoTableObject
+            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)]
@@ -87,13 +90,14 @@ class Osc(PyoObject):
     def setFreq(self, x):
         """
         Replace the `freq` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `freq` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -101,13 +105,14 @@ class Osc(PyoObject):
     def setPhase(self, x):
         """
         Replace the `phase` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `phase` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._phase = x
         x, lmax = convertArgsToLists(x)
         [obj.setPhase(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -115,13 +120,14 @@ class Osc(PyoObject):
     def setInterp(self, x):
         """
         Replace the `interp` attribute.
-        
+
         :Args:
 
-            x : int {1, 2, 3, 4}
+            x: int {1, 2, 3, 4}
                 new `interp` attribute.
-        
+
         """
+        pyoArgsAssert(self, "i", x)
         self._interp = x
         x, lmax = convertArgsToLists(x)
         [obj.setInterp(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -129,39 +135,40 @@ class Osc(PyoObject):
     def reset(self):
         """
         Resets current phase to 0.
-        
+
         """
         [obj.reset() for i, obj in enumerate(self._base_objs)]
 
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMapFreq(self._freq),
                           SLMapPhase(self._phase),
+                          SLMap(1, 4, 'lin', 'interp', self._interp, res="int", dataOnly=True),
                           SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def table(self):
-        """PyoTableObject. Table containing the waveform samples.""" 
+        """PyoTableObject. Table containing the waveform samples."""
         return self._table
     @table.setter
     def table(self, x): self.setTable(x)
 
     @property
     def freq(self):
-        """float or PyoObject. Frequency in cycles per second.""" 
+        """float or PyoObject. Frequency in cycles per second."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
-    def phase(self): 
-        """float or PyoObject. Phase of sampling.""" 
+    def phase(self):
+        """float or PyoObject. Phase of sampling."""
         return self._phase
     @phase.setter
     def phase(self, x): self.setPhase(x)
 
     @property
-    def interp(self): 
+    def interp(self):
         """int {1, 2, 3, 4}. Interpolation method."""
         return self._interp
     @interp.setter
@@ -174,38 +181,40 @@ class OscLoop(PyoObject):
     OscLoop reads a waveform table with linear interpolation and feedback control.
     The oscillator output, multiplied by `feedback`, is added to the position
     increment and can be used to control the brightness of the oscillator.
-    
-    
+
+
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        table : PyoTableObject
+        table: PyoTableObject
             Table containing the waveform samples.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Frequency in cycles per second. Defaults to 1000.
-        feedback : float or PyoObject, optional
-            Amount of the output signal added to position increment, between 0 and 1. 
+        feedback: float or PyoObject, optional
+            Amount of the output signal added to position increment, between 0 and 1.
             Controls the brightness. Defaults to 0.
 
-    .. seealso:: 
-        
+    .. seealso::
+
         :py:class:`Osc`, :py:class:`SineLoop`
 
     >>> s = Server().boot()
     >>> s.start()
     >>> t = HarmTable([1,0,.33,0,.2,0,.143])
     >>> lfo = Sine(.5, 0, .05, .05)
-    >>> a = OscLoop(table=t, freq=[100,99.3], feedback=lfo, mul=.2).out()   
+    >>> a = OscLoop(table=t, freq=[100,99.3], feedback=lfo, mul=.2).out()
 
     """
     def __init__(self, table, freq=1000, feedback=0, mul=1, add=0):
+        pyoArgsAssert(self, "tOOOO", table, freq, feedback, mul, add)
         PyoObject.__init__(self, mul, add)
         self._table = table
         self._freq = freq
         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):
         """
@@ -213,10 +222,11 @@ class OscLoop(PyoObject):
 
         :Args:
 
-            x : PyoTableObject
+            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)]
@@ -227,10 +237,11 @@ class OscLoop(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `freq` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -241,10 +252,11 @@ class OscLoop(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `feedback` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._feedback = x
         x, lmax = convertArgsToLists(x)
         [obj.setFeedback(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -257,21 +269,21 @@ class OscLoop(PyoObject):
 
     @property
     def table(self):
-        """PyoTableObject. Table containing the waveform samples.""" 
+        """PyoTableObject. Table containing the waveform samples."""
         return self._table
     @table.setter
     def table(self, x): self.setTable(x)
 
     @property
     def freq(self):
-        """float or PyoObject. Frequency in cycles per second.""" 
+        """float or PyoObject. Frequency in cycles per second."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
-    def feedback(self): 
-        """float or PyoObject. Brightness control.""" 
+    def feedback(self):
+        """float or PyoObject. Brightness control."""
         return self._feedback
     @feedback.setter
     def feedback(self, x): self.setFeedback(x)
@@ -284,25 +296,25 @@ class OscTrig(PyoObject):
 
     :Args:
 
-        table : PyoTableObject
+        table: PyoTableObject
             Table containing the waveform samples.
-        trig : PyoObject
+        trig: PyoObject
             Trigger signal. Reset the table pointer position to zero on
             each trig.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Frequency in cycles per second. Defaults to 1000.
-        phase : float or PyoObject, optional
-            Phase of sampling, expressed as a fraction of a cycle (0 to 1). 
+        phase: float or PyoObject, optional
+            Phase of sampling, expressed as a fraction of a cycle (0 to 1).
             Defaults to 0.
-        interp : int, optional
+        interp: int, optional
             Choice of the interpolation method. Defaults to 2.
                 1. no interpolation
                 2. linear
                 3. cosinus
                 4. cubic
 
-    .. seealso:: 
-        
+    .. seealso::
+
         :py:class:`Osc`, :py:class:`Phasor`, :py:class:`Sine`
 
     >>> s = Server().boot()
@@ -314,6 +326,7 @@ class OscTrig(PyoObject):
 
     """
     def __init__(self, table, trig, freq=1000, phase=0, interp=2, mul=1, add=0):
+        pyoArgsAssert(self, "toOOiOO", table, trig, freq, phase, interp, mul, add)
         PyoObject.__init__(self, mul, add)
         self._table = table
         self._trig = trig
@@ -322,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):
         """
@@ -329,10 +343,11 @@ class OscTrig(PyoObject):
 
         :Args:
 
-            x : PyoTableObject
+            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)]
@@ -343,10 +358,11 @@ class OscTrig(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 new `trig` attribute.
 
         """
+        pyoArgsAssert(self, "o", x)
         self._trig = x
         x, lmax = convertArgsToLists(x)
         [obj.setTrig(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -357,10 +373,11 @@ class OscTrig(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `freq` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -371,10 +388,11 @@ class OscTrig(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `phase` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._phase = x
         x, lmax = convertArgsToLists(x)
         [obj.setPhase(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -385,10 +403,11 @@ class OscTrig(PyoObject):
 
         :Args:
 
-            x : int {1, 2, 3, 4}
+            x: int {1, 2, 3, 4}
                 new `interp` attribute.
 
         """
+        pyoArgsAssert(self, "i", x)
         self._interp = x
         x, lmax = convertArgsToLists(x)
         [obj.setInterp(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -403,39 +422,40 @@ class OscTrig(PyoObject):
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMapFreq(self._freq),
                           SLMapPhase(self._phase),
+                          SLMap(1, 4, 'lin', 'interp', self._interp, res="int", dataOnly=True),
                           SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def table(self):
-        """PyoTableObject. Table containing the waveform samples.""" 
+        """PyoTableObject. Table containing the waveform samples."""
         return self._table
     @table.setter
     def table(self, x): self.setTable(x)
 
     @property
     def trig(self):
-        """PyoObject. Trigger signal. Reset pointer position to zero""" 
+        """PyoObject. Trigger signal. Reset pointer position to zero"""
         return self._trig
     @trig.setter
     def trig(self, x): self.setTrig(x)
 
     @property
     def freq(self):
-        """float or PyoObject. Frequency in cycles per second.""" 
+        """float or PyoObject. Frequency in cycles per second."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
-    def phase(self): 
-        """float or PyoObject. Phase of sampling.""" 
+    def phase(self):
+        """float or PyoObject. Phase of sampling."""
         return self._phase
     @phase.setter
     def phase(self, x): self.setPhase(x)
 
     @property
-    def interp(self): 
+    def interp(self):
         """int {1, 2, 3, 4}. Interpolation method."""
         return self._interp
     @interp.setter
@@ -446,65 +466,65 @@ class OscBank(PyoObject):
     Any number of oscillators reading a waveform table.
 
     OscBank mixes the output of any number of oscillators. The frequencies
-    of each oscillator is controlled with two parameters, the base frequency 
-    `freq` and a coefficient of expansion `spread`. Frequencies are computed 
+    of each oscillator is controlled with two parameters, the base frequency
+    `freq` and a coefficient of expansion `spread`. Frequencies are computed
     with the following formula (`n` is the order of the partial):
 
     f_n = freq + freq * spread * n
 
-    The frequencies and amplitudes can be modulated by two random generators 
+    The frequencies and amplitudes can be modulated by two random generators
     with interpolation (each partial have a different set of randoms).
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        table : PyoTableObject
+        table: PyoTableObject
             Table containing the waveform samples.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Base frequency in cycles per second. Defaults to 100.
-        spread : float or PyoObject, optional
-            Coefficient of expansion used to compute partial frequencies. 
-            If `spread` is 0, all partials will be at the base frequency. 
+        spread: float or PyoObject, optional
+            Coefficient of expansion used to compute partial frequencies.
+            If `spread` is 0, all partials will be at the base frequency.
             A value of 1 will generate integer harmonics, a value of 2
             will skip even harmonics and non-integer values will generate
             different series of inharmonic frequencies. Defaults to 1.
-        slope : float or PyoObject, optional
-            specifies the multiplier in the series of amplitude coefficients. 
-            This is a power series: the nth partial will have an amplitude of 
+        slope: float or PyoObject, optional
+            specifies the multiplier in the series of amplitude coefficients.
+            This is a power series: the nth partial will have an amplitude of
             (slope ** n), i.e. strength values trace an exponential curve.
             Defaults to 1.
-        frndf : float or PyoObject, optional
-            Frequency, in cycle per second, of the frequency modulations. 
+        frndf: float or PyoObject, optional
+            Frequency, in cycle per second, of the frequency modulations.
             Defaults to 1.
-        frnda : float or PyoObject, optional
-            Maximum frequency deviation (positive and negative) in portion of 
+        frnda: float or PyoObject, optional
+            Maximum frequency deviation (positive and negative) in portion of
             the partial frequency. A value of 1 means that the frequency can
-            drift from 0 Hz to twice the partial frequency. A value of 0 
+            drift from 0 Hz to twice the partial frequency. A value of 0
             deactivates the frequency deviations. Defaults to 0.
-        arndf : float or PyoObject, optional
-            Frequency, in cycle per second, of the amplitude modulations. 
+        arndf: float or PyoObject, optional
+            Frequency, in cycle per second, of the amplitude modulations.
             Defaults to 1.
-        arnda : float or PyoObject, optional
-            Amount of amplitude deviation. 0 deactivates the amplitude 
+        arnda: float or PyoObject, optional
+            Amount of amplitude deviation. 0 deactivates the amplitude
             modulations and 1 gives full amplitude modulations.
             Defaults to 0.
-        num : int, optional
+        num: int, optional
             Number of oscillators. Available at initialization only.
             Defaults to 24.
-        fjit : boolean, optional
+        fjit: boolean, optional
             If True, a small jitter is added to the frequency of each partial.
             For a large number of oscillators and a very small `spread`, the
             periodicity between partial frequencies can cause very strange
             artefact. Adding a jitter breaks the periodicity. Defaults to False.
 
-    .. seealso:: 
-        
+    .. seealso::
+
         :py:class:`Osc`
 
     .. note::
 
-        Altough parameters can be audio signals, values are sampled only once 
+        Altough parameters can be audio signals, values are sampled only once
         per buffer size. To avoid artefacts, it is recommended to keep variations
         at low rate (< 20 Hz).
 
@@ -518,6 +538,7 @@ class OscBank(PyoObject):
 
     """
     def __init__(self, table, freq=100, spread=1, slope=.9, frndf=1, frnda=0, arndf=1, arnda=0, num=24, fjit=False, mul=1, add=0):
+        pyoArgsAssert(self, "tOOOOOOOibOO", table, freq, spread, slope, frndf, frnda, arndf, arnda, num, fjit, mul, add)
         PyoObject.__init__(self, mul, add)
         self._table = table
         self._freq = freq
@@ -531,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):
         """
@@ -538,10 +560,11 @@ class OscBank(PyoObject):
 
         :Args:
 
-            x : PyoTableObject
+            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)]
@@ -552,10 +575,11 @@ class OscBank(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `freq` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -566,10 +590,11 @@ class OscBank(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `spread` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._spread = x
         x, lmax = convertArgsToLists(x)
         [obj.setSpread(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -580,10 +605,11 @@ class OscBank(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `slope` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._slope = x
         x, lmax = convertArgsToLists(x)
         [obj.setSlope(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -594,10 +620,11 @@ class OscBank(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `frndf` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._frndf = x
         x, lmax = convertArgsToLists(x)
         [obj.setFrndf(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -608,10 +635,11 @@ class OscBank(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `frnda` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._frnda = x
         x, lmax = convertArgsToLists(x)
         [obj.setFrnda(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -622,10 +650,11 @@ class OscBank(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `arndf` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._arndf = x
         x, lmax = convertArgsToLists(x)
         [obj.setArndf(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -636,10 +665,11 @@ class OscBank(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `arnda` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._arnda = x
         x, lmax = convertArgsToLists(x)
         [obj.setArnda(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -650,10 +680,11 @@ class OscBank(PyoObject):
 
         :Args:
 
-            x : boolean
+            x: boolean
                 new `fjit` attribute.
 
         """
+        pyoArgsAssert(self, "b", x)
         self._fjit = x
         x, lmax = convertArgsToLists(x)
         [obj.setFjit(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -671,63 +702,63 @@ class OscBank(PyoObject):
 
     @property
     def table(self):
-        """PyoTableObject. Table containing the waveform samples.""" 
+        """PyoTableObject. Table containing the waveform samples."""
         return self._table
     @table.setter
     def table(self, x): self.setTable(x)
 
     @property
     def freq(self):
-        """float or PyoObject. Frequency in cycles per second.""" 
+        """float or PyoObject. Frequency in cycles per second."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
-    def spread(self): 
-        """float or PyoObject. Frequency expansion factor.""" 
+    def spread(self):
+        """float or PyoObject. Frequency expansion factor."""
         return self._spread
     @spread.setter
     def spread(self, x): self.setSpread(x)
 
     @property
-    def slope(self): 
-        """float or PyoObject. Multiplier in the series of amplitudes.""" 
+    def slope(self):
+        """float or PyoObject. Multiplier in the series of amplitudes."""
         return self._slope
     @slope.setter
     def slope(self, x): self.setSlope(x)
 
     @property
-    def frndf(self): 
-        """float or PyoObject. Frequency of the frequency modulations.""" 
+    def frndf(self):
+        """float or PyoObject. Frequency of the frequency modulations."""
         return self._frndf
     @frndf.setter
     def frndf(self, x): self.setFrndf(x)
 
     @property
-    def frnda(self): 
-        """float or PyoObject. Maximum frequency deviation from 0 to 1.""" 
+    def frnda(self):
+        """float or PyoObject. Maximum frequency deviation from 0 to 1."""
         return self._frnda
     @frnda.setter
     def frnda(self, x): self.setFrnda(x)
 
     @property
-    def arndf(self): 
-        """float or PyoObject. Frequency of the amplitude modulations.""" 
+    def arndf(self):
+        """float or PyoObject. Frequency of the amplitude modulations."""
         return self._arndf
     @arndf.setter
     def arndf(self, x): self.setArndf(x)
 
     @property
-    def arnda(self): 
-        """float or PyoObject. Amount of amplitude deviation from 0 to 1.""" 
+    def arnda(self):
+        """float or PyoObject. Amount of amplitude deviation from 0 to 1."""
         return self._arnda
     @arnda.setter
     def arnda(self, x): self.setArnda(x)
 
     @property
-    def fjit(self): 
-        """boolean. Jitter added to the parial frequencies.""" 
+    def fjit(self):
+        """boolean. Jitter added to the parial frequencies."""
         return self._fjit
     @fjit.setter
     def fjit(self, x): self.setFjit(x)
@@ -738,21 +769,21 @@ class TableRead(PyoObject):
 
     Read sampled sound from a table, with optional looping mode.
 
-    The play() method starts the playback and is not called at the 
+    The play() method starts the playback and is not called at the
     object creation time.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        table : PyoTableObject
+        table: PyoTableObject
             Table containing the waveform samples.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Frequency in cycles per second. Defaults to 1.
-        loop : int {0, 1}, optional
-            Looping mode, 0 means off, 1 means on. 
+        loop: int {0, 1}, optional
+            Looping mode, 0 means off, 1 means on.
             Defaults to 0.
-        interp : int, optional
+        interp: int, optional
             Choice of the interpolation method. Defaults to 2.
                 1. no interpolation
                 2. linear
@@ -761,30 +792,32 @@ class TableRead(PyoObject):
 
     .. note::
 
-        TableRead will sends a trigger signal at the end of the playback if 
-        loop is off or any time it wraps around if loop is on. User can 
+        TableRead will send a trigger signal at the end of the playback if
+        loop is off or any time it wraps around if loop is on. User can
         retreive the trigger streams by calling obj['trig']:
 
         >>> tabr = TableRead(SNDS_PATH + "/transparent.aif").out()
-        >>> trig = TrigRand(tab['trig'])
+        >>> trig = TrigRand(tabr['trig'])
+
+    .. seealso::
 
-    .. seealso:: 
-        
         :py:class:`Osc`
 
     >>> s = Server().boot()
     >>> s.start()
     >>> snd = SndTable(SNDS_PATH + '/transparent.aif')
     >>> freq = snd.getRate()
-    >>> a = TableRead(table=snd, freq=[freq,freq*.99], loop=True, mul=.3).out()   
+    >>> a = TableRead(table=snd, freq=[freq,freq*.99], loop=True, mul=.3).out()
 
     """
     def __init__(self, table, freq=1, loop=0, interp=2, mul=1, add=0):
+        pyoArgsAssert(self, "tObiOO", table, freq, loop, interp, mul, add)
         PyoObject.__init__(self, mul, add)
         self._table = table
         self._freq = freq
         self._loop = loop
         self._interp = interp
+        self._keeplast = 0
         table, freq, loop, interp, mul, add, lmax = convertArgsToLists(table, freq, loop, interp, mul, add)
         self._base_objs = [TableRead_base(wrap(table,i), wrap(freq,i), wrap(loop,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])
@@ -792,13 +825,14 @@ class TableRead(PyoObject):
     def setTable(self, x):
         """
         Replace the `table` attribute.
-        
+
         :Args:
 
-            x : PyoTableObject
+            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)]
@@ -806,13 +840,14 @@ class TableRead(PyoObject):
     def setFreq(self, x):
         """
         Replace the `freq` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `freq` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -820,13 +855,14 @@ class TableRead(PyoObject):
     def setLoop(self, x):
         """
         Replace the `loop` attribute.
-        
+
         :Args:
 
-            x : int {0, 1}
+            x: int {0, 1}
                 new `loop` attribute.
-        
+
         """
+        pyoArgsAssert(self, "b", x)
         self._loop = x
         x, lmax = convertArgsToLists(x)
         [obj.setLoop(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -834,17 +870,34 @@ class TableRead(PyoObject):
     def setInterp(self, x):
         """
         Replace the `interp` attribute.
-        
+
         :Args:
 
-            x : int {1, 2, 3, 4}
+            x: int {1, 2, 3, 4}
                 new `interp` attribute.
-        
+
         """
+        pyoArgsAssert(self, "i", x)
         self._interp = x
         x, lmax = convertArgsToLists(x)
         [obj.setInterp(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
+    def setKeepLast(self, x):
+        """
+        If anything but zero, the object will hold the last value when stopped.
+
+        :Args:
+
+            x: bool
+                If 0, the object will be reset to 0 when stopped, otherwise
+                it will hold its last value.
+
+        """
+        pyoArgsAssert(self, "b", x)
+        self._keeplast = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setKeepLast(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
     def reset(self):
         """
         Resets current phase to 0.
@@ -852,34 +905,36 @@ class TableRead(PyoObject):
         """
         [obj.reset() for i, obj in enumerate(self._base_objs)]
 
-
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
-        self._map_list = [SLMapFreq(self._freq), SLMapMul(self._mul)]
+        self._map_list = [SLMap(0.0001, 1000, 'log', 'freq', self._freq),
+                          SLMap(0, 1, 'lin', 'loop', self._loop, res="int", dataOnly=True),
+                          SLMap(1, 4, 'lin', 'interp', self._interp, res="int", dataOnly=True),
+                          SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def table(self):
-        """PyoTableObject. Table containing the waveform samples.""" 
+        """PyoTableObject. Table containing the waveform samples."""
         return self._table
     @table.setter
     def table(self, x): self.setTable(x)
 
     @property
     def freq(self):
-        """float or PyoObject. Frequency in cycles per second.""" 
+        """float or PyoObject. Frequency in cycles per second."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
-    def loop(self): 
-        """int. Looping mode.""" 
+    def loop(self):
+        """int. Looping mode."""
         return self._loop
     @loop.setter
     def loop(self, x): self.setLoop(x)
 
     @property
-    def interp(self): 
+    def interp(self):
         """int {1, 2, 3, 4}. Interpolation method."""
         return self._interp
     @interp.setter
@@ -889,38 +944,38 @@ class Pulsar(PyoObject):
     """
     Pulsar synthesis oscillator.
 
-    Pulsar synthesis produces a train of sound particles called pulsars 
-    that can make rhythms or tones, depending on the fundamental frequency 
+    Pulsar synthesis produces a train of sound particles called pulsars
+    that can make rhythms or tones, depending on the fundamental frequency
     of the train. Varying the `frac` parameter changes the portion of the
-    period assigned to the waveform and the portion of the period assigned 
-    to its following silence, but maintain the overall pulsar period. This 
+    period assigned to the waveform and the portion of the period assigned
+    to its following silence, but maintain the overall pulsar period. This
     results in an effect much like a sweeping band-pass filter.
 
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
 
-        table : PyoTableObject
+        table: PyoTableObject
             Table containing the waveform samples.
-        env : PyoTableObject
+        env: PyoTableObject
             Table containing the envelope samples.
-        freq : float or PyoObject, optional
+        freq: float or PyoObject, optional
             Frequency in cycles per second. Defaults to 100.
-        frac : float or PyoObject, optional
-            Fraction of the whole period (0 -> 1) given to the waveform. 
+        frac: float or PyoObject, optional
+            Fraction of the whole period (0 -> 1) given to the waveform.
             The rest will be filled with zeros. Defaults to 0.5.
-        phase : float or PyoObject, optional
-            Phase of sampling, expressed as a fraction of a cycle (0 to 1). 
+        phase: float or PyoObject, optional
+            Phase of sampling, expressed as a fraction of a cycle (0 to 1).
             Defaults to 0.
-        interp : int, optional
+        interp: int, optional
             Choice of the interpolation method. Defaults to 2.
                 1. no interpolation
                 2. linear
                 3. cosinus
                 4. cubic
 
-    .. seealso:: 
-        
+    .. seealso::
+
         :py:class:`Osc`
 
     >>> s = Server().boot()
@@ -929,9 +984,10 @@ class Pulsar(PyoObject):
     >>> e = HannTable()
     >>> lfo = Sine([.1,.15], mul=.2, add=.5)
     >>> a = Pulsar(table=w, env=e, freq=80, frac=lfo, mul=.08).out()
-     
+
     """
     def __init__(self, table, env, freq=100, frac=0.5, phase=0, interp=2, mul=1, add=0):
+        pyoArgsAssert(self, "ttOOOiOO", table, env, freq, frac, phase, interp, mul, add)
         PyoObject.__init__(self, mul, add)
         self._table = table
         self._env = env
@@ -941,17 +997,19 @@ 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):
         """
         Replace the `table` attribute.
-        
+
         :Args:
 
-            x : PyoTableObject
+            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)]
@@ -959,13 +1017,14 @@ class Pulsar(PyoObject):
     def setEnv(self, x):
         """
         Replace the `env` attribute.
-        
+
         :Args:
 
-            x : PyoTableObject
+            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_objs)]
@@ -973,13 +1032,14 @@ class Pulsar(PyoObject):
     def setFreq(self, x):
         """
         Replace the `freq` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `freq` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._freq = x
         x, lmax = convertArgsToLists(x)
         [obj.setFreq(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -987,13 +1047,14 @@ class Pulsar(PyoObject):
     def setFrac(self, x):
         """
         Replace the `frac` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `frac` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._frac = x
         x, lmax = convertArgsToLists(x)
         [obj.setFrac(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1001,13 +1062,14 @@ class Pulsar(PyoObject):
     def setPhase(self, x):
         """
         Replace the `phase` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `phase` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._phase = x
         x, lmax = convertArgsToLists(x)
         [obj.setPhase(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1015,13 +1077,18 @@ class Pulsar(PyoObject):
     def setInterp(self, x):
         """
         Replace the `interp` attribute.
-        
+
         :Args:
 
-            x : int {1, 2, 3, 4}
-                new `interp` attribute.
-        
+            x: int {1, 2, 3, 4}
+                Choice of the interpolation method.
+                    1. no interpolation
+                    2. linear
+                    3. cosinus
+                    4. cubic
+
         """
+        pyoArgsAssert(self, "i", x)
         self._interp = x
         x, lmax = convertArgsToLists(x)
         [obj.setInterp(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1030,46 +1097,47 @@ class Pulsar(PyoObject):
         self._map_list = [SLMapFreq(self._freq),
                           SLMap(0., 1., 'lin', 'frac', self._frac),
                           SLMapPhase(self._phase),
+                          SLMap(1, 4, 'lin', 'interp', self._interp, res="int", dataOnly=True),
                           SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def table(self):
-        """PyoTableObject. Table containing the waveform samples.""" 
+        """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 envelope samples.""" 
+        """PyoTableObject. Table containing the envelope samples."""
         return self._env
     @env.setter
     def env(self, x): self.setEnv(x)
 
     @property
     def freq(self):
-        """float or PyoObject. Frequency in cycles per second.""" 
+        """float or PyoObject. Frequency in cycles per second."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
 
     @property
     def frac(self):
-        """float or PyoObject. Fraction of the period assigned to waveform.""" 
+        """float or PyoObject. Fraction of the period assigned to waveform."""
         return self._frac
     @frac.setter
     def frac(self, x): self.setFrac(x)
 
     @property
-    def phase(self): 
-        """float or PyoObject. Phase of sampling.""" 
+    def phase(self):
+        """float or PyoObject. Phase of sampling."""
         return self._phase
     @phase.setter
     def phase(self, x): self.setPhase(x)
 
     @property
-    def interp(self): 
+    def interp(self):
         """int {1, 2, 3, 4}. Interpolation method."""
         return self._interp
     @interp.setter
@@ -1083,9 +1151,9 @@ class Pointer(PyoObject):
 
     :Args:
 
-        table : PyoTableObject
+        table: PyoTableObject
             Table containing the waveform samples.
-        index : PyoObject
+        index: PyoObject
             Normalized position in the table between 0 and 1.
 
     >>> s = Server().boot()
@@ -1097,22 +1165,117 @@ class Pointer(PyoObject):
 
     """
     def __init__(self, table, index, mul=1, add=0):
+        pyoArgsAssert(self, "toOO", table, index, mul, add)
         PyoObject.__init__(self, mul, add)
         self._table = table
         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):
+        """
+        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 setIndex(self, x):
+        """
+        Replace the `index` attribute.
+
+        :Args:
+
+            x: PyoObject
+                new `index` attribute.
+
+        """
+        pyoArgsAssert(self, "o", x)
+        self._index = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setIndex(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def ctrl(self, map_list=None, title=None, wxnoserver=False):
+        self._map_list = [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 index(self):
+        """PyoObject. Index pointer position in the table."""
+        return self._index
+    @index.setter
+    def index(self, x): self.setIndex(x)
+
+class Pointer2(PyoObject):
+    """
+    High quality table reader with control on the pointer position.
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        table: PyoTableObject
+            Table containing the waveform samples.
+        index: PyoObject
+            Normalized position in the table between 0 and 1.
+        interp: int {1, 2, 3, 4}, optional
+            Choice of the interpolation method. Defaults to 4.
+                1. no interpolation
+                2. linear
+                3. cosinus
+                4. cubic
+        autosmooth: boolean, optional
+            If True, a lowpass filter, following the pitch, is applied on
+
+            the output signal to reduce the quantization noise produced
+
+            by very low transpositions. Defaults to True.
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> t = SndTable(SNDS_PATH + '/transparent.aif')
+    >>> freq = t.getRate()
+    >>> p = Phasor(freq=[freq*0.5, freq*0.45])
+    >>> a = Pointer2(table=t, index=p, mul=.3).out()
+
+    """
+    def __init__(self, table, index, interp=4, autosmooth=True, mul=1, add=0):
+        pyoArgsAssert(self, "toibOO", table, index, interp, autosmooth, mul, add)
+        PyoObject.__init__(self, mul, add)
+        self._table = table
+        self._index = index
+        self._interp = interp
+        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):
         """
         Replace the `table` attribute.
-        
+
         :Args:
 
-            x : PyoTableObject
+            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)]
@@ -1120,35 +1283,88 @@ class Pointer(PyoObject):
     def setIndex(self, x):
         """
         Replace the `index` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 new `index` attribute.
-        
+
         """
+        pyoArgsAssert(self, "o", x)
         self._index = x
         x, lmax = convertArgsToLists(x)
         [obj.setIndex(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
+    def setInterp(self, x):
+        """
+        Replace the `interp` attribute.
+
+        :Args:
+
+            x: int {1, 2, 3, 4}
+                new `interp` attribute.
+                    1. no interpolation
+                    2. linear interpolation
+                    3. cosine interpolation
+                    4. cubic interpolation (default)
+
+        """
+        pyoArgsAssert(self, "i", x)
+        self._interp = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setInterp(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def setAutoSmooth(self, x):
+        """
+        Replace the `autosmooth` attribute.
+
+        If True, a lowpass filter, following the playback speed, is applied on
+        the output signal to reduce the quantization noise produced by very
+        low transpositions.
+
+        :Args:
+
+            x: boolean
+                new `autosmooth` attribute.
+
+        """
+        pyoArgsAssert(self, "b", x)
+        self._autosmooth = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setAutoSmooth(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def table(self):
-        """PyoTableObject. Table containing the waveform samples.""" 
+        """PyoTableObject. Table containing the waveform samples."""
         return self._table
     @table.setter
     def table(self, x): self.setTable(x)
 
     @property
     def index(self):
-        """PyoObject. Index pointer position in the table.""" 
+        """PyoObject. Index pointer position in the table."""
         return self._index
     @index.setter
     def index(self, x): self.setIndex(x)
 
+    @property
+    def interp(self):
+        """int {1, 2, 3, 4}. Interpolation method."""
+        return self._interp
+    @interp.setter
+    def interp(self, x): self.setInterp(x)
+
+    @property
+    def autosmooth(self):
+        """boolean. Quantization noise filter."""
+        return self._autosmooth
+    @autosmooth.setter
+    def autosmooth(self, x): self.setAutoSmooth(x)
+
 class TableIndex(PyoObject):
     """
     Table reader by sample position without interpolation.
@@ -1157,10 +1373,10 @@ class TableIndex(PyoObject):
 
     :Args:
 
-        table : PyoTableObject
+        table: PyoTableObject
             Table containing the samples.
-        index : PyoObject
-            Position in the table, as integer audio stream, 
+        index: PyoObject
+            Position in the table, as integer audio stream,
             between 0 and table's size - 1.
 
     >>> s = Server().boot()
@@ -1174,11 +1390,13 @@ class TableIndex(PyoObject):
 
     """
     def __init__(self, table, index, mul=1, add=0):
+        pyoArgsAssert(self, "toOO", table, index, mul, add)
         PyoObject.__init__(self, mul, add)
         self._table = table
         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):
         """
@@ -1186,10 +1404,11 @@ class TableIndex(PyoObject):
 
         :Args:
 
-            x : PyoTableObject
+            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)]
@@ -1200,10 +1419,11 @@ class TableIndex(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 new `index` attribute.
 
         """
+        pyoArgsAssert(self, "o", x)
         self._index = x
         x, lmax = convertArgsToLists(x)
         [obj.setIndex(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1214,14 +1434,14 @@ class TableIndex(PyoObject):
 
     @property
     def table(self):
-        """PyoTableObject. Table containing the samples.""" 
+        """PyoTableObject. Table containing the samples."""
         return self._table
     @table.setter
     def table(self, x): self.setTable(x)
 
     @property
     def index(self):
-        """PyoObject. Position in the table.""" 
+        """PyoObject. Position in the table."""
         return self._index
     @index.setter
     def index(self, x): self.setIndex(x)
@@ -1229,22 +1449,22 @@ class TableIndex(PyoObject):
 class Lookup(PyoObject):
     """
     Uses table to do waveshaping on an audio signal.
-    
+
     Lookup uses a table to apply waveshaping on an input signal
     `index`. The index must be between -1 and 1, it is automatically
     scaled between 0 and len(table)-1 and is used as a position
-    pointer in the table.  
-    
+    pointer in the table.
+
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
-    
-        table : PyoTableObject
+
+        table: PyoTableObject
             Table containing the transfert function.
-        index : PyoObject
+        index: PyoObject
             Audio signal, between -1 and 1, internally converted to be
             used as the index position in the table.
-        
+
     >>> s = Server().boot()
     >>> s.start()
     >>> lfo = Sine(freq=[.15,.2], mul=.2, add=.25)
@@ -1254,22 +1474,25 @@ class Lookup(PyoObject):
 
     """
     def __init__(self, table, index, mul=1, add=0):
+        pyoArgsAssert(self, "toOO", table, index, mul, add)
         PyoObject.__init__(self, mul, add)
         self._table = table
         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):
         """
         Replace the `table` attribute.
-        
+
         :Args:
 
-            x : PyoTableObject
+            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)]
@@ -1277,13 +1500,14 @@ class Lookup(PyoObject):
     def setIndex(self, x):
         """
         Replace the `index` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 new `index` attribute.
-        
+
         """
+        pyoArgsAssert(self, "o", x)
         self._index = x
         x, lmax = convertArgsToLists(x)
         [obj.setIndex(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1294,14 +1518,14 @@ class Lookup(PyoObject):
 
     @property
     def table(self):
-        """PyoTableObject. Table containing the transfert function.""" 
+        """PyoTableObject. Table containing the transfert function."""
         return self._table
     @table.setter
     def table(self, x): self.setTable(x)
 
     @property
     def index(self):
-        """PyoObject. Audio input used as the table index.""" 
+        """PyoObject. Audio input used as the table index."""
         return self._index
     @index.setter
     def index(self, x): self.setIndex(x)
@@ -1313,7 +1537,7 @@ class TableRec(PyoObject):
     See `NewTable` to create an empty table.
 
     The play method is not called at the object creation time. It starts
-    the recording into the table until the table is full. Calling the 
+    the recording into the table until the table is full. Calling the
     play method again restarts the recording and overwrites previously
     recorded samples. The stop method stops the recording. Otherwise, the
     default behaviour is to record through the end of the table.
@@ -1322,12 +1546,12 @@ class TableRec(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Audio signal to write in the table.
-        table : NewTable
+        table: NewTable
             The table where to write samples.
-        fadetime : float, optional
-            Fade time at the beginning and the end of the recording 
+        fadetime: float, optional
+            Fade time at the beginning and the end of the recording
             in seconds. Defaults to 0.
 
     .. note::
@@ -1336,7 +1560,7 @@ class TableRec(PyoObject):
 
         TableRec has no `mul` and `add` attributes.
 
-        TableRec will sends a trigger signal at the end of the recording. 
+        TableRec will send a trigger signal at the end of the recording.
         User can retrieve the trigger streams by calling obj['trig']. In
         this example, the recorded table will be read automatically after
         a recording:
@@ -1345,12 +1569,12 @@ class TableRec(PyoObject):
         >>> t = NewTable(length=1, chnls=1)
         >>> rec = TableRec(a, table=t, fadetime=0.01)
         >>> tr = TrigEnv(rec['trig'], table=t, dur=1).out()
-        
-        obj['time'] outputs an audio stream of the current recording time, 
+
+        obj['time'] outputs an audio stream of the current recording time,
         in samples.
 
-    .. seealso:: 
-        
+    .. seealso::
+
         :py:class:`NewTable`, :py:class:`TrigTableRec`
 
     >>> s = Server(duplex=1).boot()
@@ -1366,6 +1590,7 @@ class TableRec(PyoObject):
 
     """
     def __init__(self, input, table, fadetime=0):
+        pyoArgsAssert(self, "otn", input, table, fadetime)
         PyoObject.__init__(self)
         self._time_dummy = []
         self._input = input
@@ -1387,42 +1612,44 @@ class TableRec(PyoObject):
 
     def setMul(self, x):
         pass
-        
+
     def setAdd(self, x):
-        pass    
+        pass
 
     def setInput(self, x, fadetime=0.05):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 : NewTable
+            x: NewTable
                 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)]
 
     @property
     def input(self):
-        """PyoObject. Audio signal to write in the table.""" 
+        """PyoObject. Audio signal to write in the table."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -1434,108 +1661,134 @@ class TableRec(PyoObject):
     @table.setter
     def table(self, x): self.setTable(x)
 
-class TableMorph(PyoObject):
+class TableWrite(PyoObject):
     """
-    Morphs between multiple PyoTableObjects.
+    TableWrite writes samples into a previously created NewTable.
 
-    Uses an index into a list of PyoTableObjects to morph between adjacent 
-    tables in the list. The resulting morphed function is written into the 
-    `table` object at the beginning of each buffer size. The tables in the 
-    list and the resulting table must be equal in size.
+    See `NewTable` to create an empty table.
+
+    TableWrite takes samples from its `input` stream and writes
+    them at a normalized or raw position given by the `pos` stream.
+    Position must be an audio stream, ie. a PyoObject. This
+    object allows fast recording of values coming from an X-Y
+    pad into a table object.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
-            Morphing index between 0 and 1. 0 is the first table in the list 
-            and 1 is the last.
-        table : NewTable
-            The table where to write morphed waveform.
-        sources : list of PyoTableObject
-            List of tables to interpolate from.
+        input: PyoObject
+            Audio signal to write in the table.
+        pos: PyoObject
+            Audio signal specifying the position where to write the
+            `input` samples. It is a normalized position (in the range
+            0 to 1) in mode=0 or the raw position (in samples) for any
+            other value of mode.
+        table: NewTable
+            The table where to write samples.
+        mode: int, optional
+            Sets the writing pointer mode. If 0, the position must be
+            normalized between 0 (beginning of the table) and 1 (end
+            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::
 
-        The out() method is bypassed. TableMorph returns no signal.
+        The out() method is bypassed. TableWrite returns no signal.
 
-        TableMorph has no `mul` and `add` attributes.
+        TableWrite has no `mul` and `add` attributes.
+
+    .. seealso::
+
+        :py:class:`NewTable`, :py:class:`TableRec`
 
     >>> s = Server(duplex=1).boot()
     >>> s.start()
-    >>> t1 = HarmTable([1,.5,.33,.25,.2,.167,.143,.125,.111,.1,.091])
-    >>> t2 = HarmTable([1,0,.33,0,.2,0,.143,0,.111,0,.091])
-    >>> t3 = NewTable(length=8192./s.getSamplingRate(), chnls=1)
-    >>> lfo = Sine(.25, 0, .5, .5)
-    >>> mor = TableMorph(lfo, t3, [t1,t2])
-    >>> osc = Osc(t3, freq=[199.5,200], mul=.08).out()
+    >>> tab = NewTable(8192/s.getSamplingRate())
+    >>> tab.view()
+    >>> pos = Phasor(.5)
+    >>> val = Sine(.25)
+    >>> rec = TableWrite(val, pos, tab)
+    >>> pat = Pattern(tab.refreshView, 0.05).play()
 
     """
-    def __init__(self, input, table, sources):
+    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._sources = sources
+        self._mode = mode
+        self._maxwindow = maxwindow
         self._in_fader = InputFader(input)
-        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))]
+        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)
 
     def setMul(self, x):
         pass
-        
+
     def setAdd(self, x):
-        pass    
+        pass
 
     def setInput(self, x, fadetime=0.05):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 : NewTable
+            x: NewTable
                 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 setSources(self, x):
+    def setPos(self, x):
         """
-         Replace the `sources` attribute.
-        
+        Replace the `pos` attribute.
+
         :Args:
 
-            x : list of PyoTableObject
-                new `sources` attribute.
-              
+            x: PyoObject
+                new `pos` attribute.
+
         """
-        self._sources = x
-        self._base_sources = [source[0] for source in x]
-        [obj.setSources(self._base_sources) for i, obj in enumerate(self._base_objs)]
-        
+        pyoArgsAssert(self, "o", x)
+        self._pos = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setPos(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
     @property
     def input(self):
-        """PyoObject. Morphing index between 0 and 1.""" 
+        """PyoObject. Audio signal to write in the table."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -1548,44 +1801,169 @@ class TableMorph(PyoObject):
     def table(self, x): self.setTable(x)
 
     @property
-    def sources(self):
-        """list of PyoTableObject. List of tables to interpolate from."""
-        return self._sources
-    @sources.setter
-    def sources(self, x): self.setSources(x)
+    def pos(self):
+        """PyoObject. Normalized position, as audio stream, where to write samples."""
+        return self._pos
+    @pos.setter
+    def pos(self, x): self.setPos(x)
 
-class Granulator(PyoObject):
+class TableMorph(PyoObject):
+    """
+    Morphs between multiple PyoTableObjects.
+
+    Uses an index into a list of PyoTableObjects to morph between adjacent
+    tables in the list. The resulting morphed function is written into the
+    `table` object at the beginning of each buffer size. The tables in the
+    list and the resulting table must be equal in size.
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        input: PyoObject
+            Morphing index between 0 and 1. 0 is the first table in the list
+            and 1 is the last.
+        table: NewTable
+            The table where to write morphed waveform.
+        sources: list of PyoTableObject
+            List of tables to interpolate from.
+
+    .. note::
+
+        The out() method is bypassed. TableMorph returns no signal.
+
+        TableMorph has no `mul` and `add` attributes.
+
+    >>> s = Server(duplex=1).boot()
+    >>> s.start()
+    >>> t1 = HarmTable([1,.5,.33,.25,.2,.167,.143,.125,.111,.1,.091])
+    >>> t2 = HarmTable([1,0,.33,0,.2,0,.143,0,.111,0,.091])
+    >>> t3 = NewTable(length=8192./s.getSamplingRate(), chnls=1)
+    >>> lfo = Sine(.25, 0, .5, .5)
+    >>> mor = TableMorph(lfo, t3, [t1,t2])
+    >>> osc = Osc(t3, freq=[199.5,200], mul=.08).out()
+
+    """
+    def __init__(self, input, table, sources):
+        pyoArgsAssert(self, "otl", input, table, sources)
+        PyoObject.__init__(self)
+        self._input = input
+        self._table = table
+        self._sources = sources
+        self._in_fader = InputFader(input)
+        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)
+
+    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: NewTable
+                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 setSources(self, x):
+        """
+         Replace the `sources` attribute.
+
+        :Args:
+
+            x: list of PyoTableObject
+                new `sources` attribute.
+
+        """
+        pyoArgsAssert(self, "l", x)
+        self._sources = x
+        self._base_sources = [source[0] for source in x]
+        [obj.setSources(self._base_sources) for i, obj in enumerate(self._base_objs)]
+
+    @property
+    def input(self):
+        """PyoObject. Morphing index between 0 and 1."""
+        return self._input
+    @input.setter
+    def input(self, x): self.setInput(x)
+
+    @property
+    def table(self):
+        """NewTable. The table where to write samples."""
+        return self._table
+    @table.setter
+    def table(self, x): self.setTable(x)
+
+    @property
+    def sources(self):
+        """list of PyoTableObject. List of tables to interpolate from."""
+        return self._sources
+    @sources.setter
+    def sources(self, x): self.setSources(x)
+
+class Granulator(PyoObject):
     """
     Granular synthesis generator.
 
     :Parent: :py:class:`PyoObject`
-    
+
     :Args:
 
-        table : PyoTableObject
+        table: PyoTableObject
             Table containing the waveform samples.
-        env : PyoTableObject
+        env: PyoTableObject
             Table containing the grain envelope.
-        pitch : float or PyoObject, optional
-            Overall pitch of the granulator. This value transpose the 
+        pitch: float or PyoObject, optional
+            Overall pitch of the granulator. This value transpose the
             pitch of all grains. 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. 
+        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.
             Defaults to 0.
-        dur : float or PyoObject, optional
-            Duration, in seconds, of the grain. Each grain sampled the 
-            current value of this stream at the beginning of its envelope 
+        dur: float or PyoObject, optional
+            Duration, in seconds, of the grain. 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.1.
-        grains : int, optional
+        grains: int, optional
             Number of grains. Defaults to 8.
-        basedur : float, optional
-            Base duration used to calculate the speed of the pointer to 
-            read the grain at its original pitch. By changing the value of 
+        basedur: float, optional
+            Base duration used to calculate the speed of the pointer to
+            read the grain at its original pitch. By changing the value of
             the `dur` parameter, transposition per grain can be generated.
             Defaults to 0.1.
-    
+
     >>> s = Server().boot()
     >>> s.start()
     >>> snd = SndTable(SNDS_PATH + "/transparent.aif")
@@ -1596,6 +1974,7 @@ class Granulator(PyoObject):
 
     """
     def __init__(self, table, env, pitch=1, pos=0, dur=.1, grains=8, basedur=.1, mul=1, add=0):
+        pyoArgsAssert(self, "ttOOOinOO", table, env, pitch, pos, dur, grains, basedur, mul, add)
         PyoObject.__init__(self, mul, add)
         self._table = table
         self._env = env
@@ -1604,21 +1983,23 @@ class Granulator(PyoObject):
         self._dur = dur
         self._grains = grains
         self._basedur = basedur
-        table, env, pitch, pos, dur, grains, basedur, mul, add, lmax = convertArgsToLists(table, env, pitch, 
+        table, env, pitch, pos, dur, grains, basedur, mul, add, lmax = convertArgsToLists(table, env, pitch,
                                                                         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), 
+        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):
         """
         Replace the `table` attribute.
-        
+
         :Args:
 
-            x : PyoTableObject
+            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)]
@@ -1626,13 +2007,14 @@ class Granulator(PyoObject):
     def setEnv(self, x):
         """
         Replace the `env` attribute.
-        
+
         :Args:
 
-            x : PyoTableObject
+            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_objs)]
@@ -1640,13 +2022,14 @@ class Granulator(PyoObject):
     def setPitch(self, x):
         """
         Replace the `pitch` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            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_objs)]
@@ -1654,13 +2037,14 @@ class Granulator(PyoObject):
     def setPos(self, x):
         """
         Replace the `pos` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            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_objs)]
@@ -1668,13 +2052,14 @@ class Granulator(PyoObject):
     def setDur(self, x):
         """
         Replace the `dur` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            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_objs)]
@@ -1682,13 +2067,14 @@ class Granulator(PyoObject):
     def setGrains(self, x):
         """
         Replace the `grains` attribute.
-        
+
         :Args:
 
-            x : int
+            x: int
                 new `grains` attribute.
-        
+
         """
+        pyoArgsAssert(self, "i", x)
         self._grains = x
         x, lmax = convertArgsToLists(x)
         [obj.setGrains(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1696,13 +2082,14 @@ class Granulator(PyoObject):
     def setBaseDur(self, x):
         """
         Replace the `basedur` attribute.
-        
+
         :Args:
 
-            x : float
+            x: float
                 new `basedur` attribute.
-        
+
         """
+        pyoArgsAssert(self, "n", x)
         self._basedur = x
         x, lmax = convertArgsToLists(x)
         [obj.setBaseDur(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1710,6 +2097,8 @@ class Granulator(PyoObject):
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMap(0.1, 2., 'lin', 'pitch', self._pitch),
                           SLMap(0.01, 1., 'lin', 'dur', self._dur),
+                          SLMap(1, 256, 'lin', 'grains', self._grains, res="int", dataOnly=True),
+                          SLMap(0.001, 1, 'log', 'basedur', self._basedur, dataOnly=True),
                           SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
@@ -1775,14 +2164,14 @@ class TrigTableRec(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Audio signal to write in the table.
-        trig : PyoObject
+        trig: PyoObject
             Audio signal sending triggers.
-        table : NewTable
+        table: NewTable
             The table where to write samples.
-        fadetime : float, optional
-            Fade time at the beginning and the end of the recording 
+        fadetime: float, optional
+            Fade time at the beginning and the end of the recording
             in seconds. Defaults to 0.
 
     .. note::
@@ -1791,14 +2180,14 @@ class TrigTableRec(PyoObject):
 
         TrigTableRec has no `mul` and `add` attributes.
 
-        TrigTableRec will sends a trigger signal at the end of the recording. 
+        TrigTableRec will send a trigger signal at the end of the recording.
         User can retrieve the trigger streams by calling obj['trig'].
 
-        obj['time'] outputs an audio stream of the current recording time, 
+        obj['time'] outputs an audio stream of the current recording time,
         in samples.
 
-    .. seealso:: 
-        
+    .. seealso::
+
         :py:class:`NewTable`, :py:class:`TableRec`
 
     >>> s = Server().boot()
@@ -1812,6 +2201,7 @@ class TrigTableRec(PyoObject):
 
     """
     def __init__(self, input, trig, table, fadetime=0):
+        pyoArgsAssert(self, "ootn", input, trig, table, fadetime)
         PyoObject.__init__(self)
         self._time_dummy = []
         self._input = input
@@ -1823,6 +2213,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':
@@ -1837,7 +2228,7 @@ class TrigTableRec(PyoObject):
         pass
 
     def setAdd(self, x):
-        pass    
+        pass
 
     def setInput(self, x, fadetime=0.05):
         """
@@ -1845,12 +2236,13 @@ class TrigTableRec(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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)
 
@@ -1860,12 +2252,13 @@ class TrigTableRec(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New trigger signal.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Defaults to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._trig = x
         self._in_fader2.setInput(x, fadetime)
 
@@ -1875,24 +2268,25 @@ class TrigTableRec(PyoObject):
 
         :Args:
 
-            x : NewTable
+            x: NewTable
                 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)]
 
     @property
     def input(self):
-        """PyoObject. Audio signal to write in the table.""" 
+        """PyoObject. Audio signal to write in the table."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def trig(self):
-        """PyoObject. Audio signal sending triggers.""" 
+        """PyoObject. Audio signal sending triggers."""
         return self._trig
     @trig.setter
     def trig(self, x): self.setTrig(x)
@@ -1908,7 +2302,7 @@ class Looper(PyoObject):
     """
     Crossfading looper.
 
-    Looper reads audio from a PyoTableObject and plays it back in a loop with 
+    Looper reads audio from a PyoTableObject and plays it back in a loop with
     user-defined pitch, start time, duration and crossfade time. The `mode`
     argument allows the user to choose different looping modes.
 
@@ -1916,47 +2310,58 @@ class Looper(PyoObject):
 
     :Args:
 
-        table : PyoTableObject
+        table: PyoTableObject
             Table containing the waveform samples.
-        pitch : float or PyoObject, optional
-            Transposition factor. 1 is normal pitch, 0.5 is one octave lower, 2 is 
+        pitch: float or PyoObject, optional
+            Transposition factor. 1 is normal pitch, 0.5 is one octave lower, 2 is
             one octave higher. Negative values are not allowed. Defaults to 1.
-        start : float or PyoObject, optional
-            Starting point, in seconds, of the loop, updated only once per loop cycle. 
+        start: float or PyoObject, optional
+            Starting point, in seconds, of the loop, updated only once per loop cycle.
             Defaults to 0.
-        dur : float or PyoObject, optional
-            Duration, in seconds, of the loop, updated only once per loop cycle. 
+        dur: float or PyoObject, optional
+            Duration, in seconds, of the loop, updated only once per loop cycle.
             Defaults to 1.
-        xfade : float or PyoObject {0 -> 50}, optional
-            Percent of the loop time used to crossfade readers, updated only once per 
+        xfade: float or PyoObject {0 -> 50}, optional
+            Percent of the loop time used to crossfade readers, updated only once per
             loop cycle and clipped between 0 and 50. Defaults to 20.
-        mode : int {0, 1, 2, 3}, optional
-            Loop modes. Defaults to 1. 
+        mode: int {0, 1, 2, 3}, optional
+            Loop modes. Defaults to 1.
                 0. no loop
-                1. forward 
+                1. forward
                 2. backward
                 3. back-and-forth
-        xfadeshape : int {0, 1, 2}, optional
-            Crossfade envelope shape. Defaults to 0. 
+        xfadeshape: int {0, 1, 2}, optional
+            Crossfade envelope shape. Defaults to 0.
                 0. linear
                 1. equal power
                 2. sigmoid
-        startfromloop : boolean, optional
+        startfromloop: boolean, optional
             If True, reading will begin directly at the loop start point. Otherwise, it
             begins at the beginning of the table. Defaults to False.
-        interp : int {1, 2, 3, 4}, optional
+        interp: int {1, 2, 3, 4}, optional
             Choice of the interpolation method. Defaults to 2.
                 1. no interpolation
                 2. linear
                 3. cosinus
                 4. cubic
-        autosmooth : boolean, optional
+        autosmooth: boolean, optional
             If True, a lowpass filter, following the pitch, is applied on the output signal
             to reduce the quantization noise produced by very low transpositions.
             Defaults to False.
 
-    .. seealso:: 
-        
+    .. note::
+
+        Looper will send a trigger signal every new playback starting point
+        (i.e. when the object is activated and at the beginning of the crossfade
+        of a loop. User can retrieve the trigger streams by calling obj['trig'].
+
+        Looper also outputs a time stream, given the current position of the
+        reading pointer, normalized between 0.0 and 1.0 (1.0 means the beginning
+        of the crossfade), inside the loop. User can retrieve the trigger streams
+        by calling obj['time']. New in version 0.8.1.
+
+    .. seealso::
+
         :py:class:`Granulator`, :py:class:`Pointer`
 
     >>> s = Server().boot()
@@ -1969,7 +2374,11 @@ class Looper(PyoObject):
 
     """
     def __init__(self, table, pitch=1, start=0, dur=1., xfade=20, mode=1, xfadeshape=0, startfromloop=False, interp=2, autosmooth=False, mul=1, add=0):
+        pyoArgsAssert(self, "tOOOOiibibOO", table, pitch, start, dur, xfade, mode, xfadeshape, startfromloop, interp, autosmooth, mul, add)
         PyoObject.__init__(self, mul, add)
+        self._time_dummy = []
+        self._appendfade = 0
+        self._fadeinseconds = 0
         self._table = table
         self._pitch = pitch
         self._start = start
@@ -1982,8 +2391,22 @@ class Looper(PyoObject):
         self._autosmooth = autosmooth
         table, pitch, start, dur, xfade, mode, xfadeshape, startfromloop, interp, autosmooth, mul, add, lmax = convertArgsToLists(
                                         table, pitch, start, dur, xfade, mode, xfadeshape, startfromloop, interp, autosmooth, mul, add)
-        self._base_objs = [Looper_base(wrap(table,i), wrap(pitch,i), wrap(start,i), wrap(dur,i), wrap(xfade,i), wrap(mode,i), 
+        self._base_objs = [Looper_base(wrap(table,i), wrap(pitch,i), wrap(start,i), wrap(dur,i), wrap(xfade,i), wrap(mode,i),
             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':
+            self._time_dummy.append(Dummy([obj for obj in self._time_objs]))
+            return self._time_dummy[-1]
+        return PyoObject.__getitem__(self, i)
+
+    def stop(self):
+        if self._time_objs is not None:
+            [obj.stop() for obj in self._time_objs]
+        return PyoObject.stop(self)
 
     def setTable(self, x):
         """
@@ -1991,10 +2414,11 @@ class Looper(PyoObject):
 
         :Args:
 
-            x : PyoTableObject
+            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)]
@@ -2005,10 +2429,11 @@ class Looper(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            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_objs)]
@@ -2019,10 +2444,11 @@ class Looper(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `start` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._start = x
         x, lmax = convertArgsToLists(x)
         [obj.setStart(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2033,10 +2459,11 @@ class Looper(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            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_objs)]
@@ -2047,10 +2474,11 @@ class Looper(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `xfade` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._xfade = x
         x, lmax = convertArgsToLists(x)
         [obj.setXfade(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2061,10 +2489,11 @@ class Looper(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 new `xfadeshape` attribute.
 
         """
+        pyoArgsAssert(self, "i", x)
         self._xfadeshape = x
         x, lmax = convertArgsToLists(x)
         [obj.setXfadeShape(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2075,10 +2504,11 @@ class Looper(PyoObject):
 
         :Args:
 
-            x : boolean
+            x: boolean
                 new `startfromloop` attribute.
 
         """
+        pyoArgsAssert(self, "b", x)
         self._startfromloop = x
         x, lmax = convertArgsToLists(x)
         [obj.setStartFromLoop(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2089,10 +2519,11 @@ class Looper(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 new `mode` attribute.
 
         """
+        pyoArgsAssert(self, "i", x)
         self._mode = x
         x, lmax = convertArgsToLists(x)
         [obj.setMode(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2103,10 +2534,11 @@ class Looper(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 new `interp` attribute.
 
         """
+        pyoArgsAssert(self, "i", x)
         self._interp = x
         x, lmax = convertArgsToLists(x)
         [obj.setInterp(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2117,18 +2549,77 @@ class Looper(PyoObject):
 
         :Args:
 
-            x : boolean
+            x: boolean
                 new `autosmooth` attribute.
 
         """
+        pyoArgsAssert(self, "b", x)
         self._autosmooth = x
         x, lmax = convertArgsToLists(x)
         [obj.setAutoSmooth(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
+    def reset(self):
+        """
+        Resets internal reading pointers to 0.
+
+        """
+        [obj.reset() for obj in self._base_objs]
+
+    def loopnow(self):
+        """
+        Sarts a new loop immediately.
+
+        """
+        [obj.loopnow() for obj in self._base_objs]
+
+    def appendFadeTime(self, x):
+        """
+        Change the position of the crossfade regarding loop duration.
+
+        :Args:
+
+            x: boolean
+                If 0 (the default), the crossfade duration lies inside the
+                loop duration, producing a loop that is shorter than the
+                `dur` value.
+
+                If 1, the crossfade starts after the loop duration, expecting
+                samples after the loop to perform the fadeout. This mode gives
+                a loop of a length of the `dur` value.
+
+        """
+        pyoArgsAssert(self, "b", x)
+        self._appendfade = x
+        x, lmax = convertArgsToLists(x)
+        [obj.appendFadeTime(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
+    def fadeInSeconds(self, x):
+        """
+        Change the crossfade time unit (`xfade` unit type).
+
+        :Args:
+
+            x: boolean
+                If 0 (the default), the crossfade duration (`xfade` value) is
+                a percent of the loop time, between 0 and 50.
+
+                If 1, the crossfade duration (`xfade` value) is set in seconds,
+                between 0 and half the loop length.
+
+        """
+        pyoArgsAssert(self, "b", x)
+        self._fadeinseconds = x
+        x, lmax = convertArgsToLists(x)
+        [obj.fadeInSeconds(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, 2., 'lin', 'pitch', self._pitch),
                           SLMap(0., self._table.getDur(), 'lin', 'start', self._start),
-                          SLMap(0.01, 1., 'lin', 'dur', self._dur),
+                          SLMap(0.01, self._table.getDur(), 'lin', 'dur', self._dur),
+                          SLMap(1, 50, 'lin', 'xfade', self._xfade),
+                          SLMap(0, 3, 'lin', 'mode', self._mode, res="int", dataOnly=True),
+                          SLMap(0, 2, 'lin', 'xfadeshape', self._xfadeshape, res="int", dataOnly=True),
+                          SLMap(1, 4, 'lin', 'interp', self._interp, res="int", dataOnly=True),
                           SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
@@ -2201,7 +2692,7 @@ class Looper(PyoObject):
         return self._autosmooth
     @autosmooth.setter
     def autosmooth(self, x): self.setAutoSmooth(x)
-    
+
 class TablePut(PyoObject):
     """
     Writes values, without repetitions, from an audio stream into a DataTable.
@@ -2213,7 +2704,7 @@ class TablePut(PyoObject):
     repetitions.
 
     The play method is not called at the object creation time. It starts
-    the recording into the table until the table is full. Calling the 
+    the recording into the table until the table is full. Calling the
     play method again restarts the recording and overwrites previously
     recorded values. The stop method stops the recording. Otherwise, the
     default behaviour is to record through the end of the table.
@@ -2222,9 +2713,9 @@ class TablePut(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Audio signal to write in the table.
-        table : DataTable
+        table: DataTable
             The table where to write values.
 
     .. note::
@@ -2233,11 +2724,11 @@ class TablePut(PyoObject):
 
         TablePut has no `mul` and `add` attributes.
 
-        TablePut will sends a trigger signal at the end of the recording. 
+        TablePut will send a trigger signal at the end of the recording.
         User can retrieve the trigger streams by calling obj['trig'].
 
-    .. seealso:: 
-        
+    .. seealso::
+
         :py:class:`DataTable`, :py:class:`NewTable`, :py:class:`TableRec`
 
     >>> s = Server().boot()
@@ -2252,6 +2743,7 @@ class TablePut(PyoObject):
 
     """
     def __init__(self, input, table):
+        pyoArgsAssert(self, "ot", input, table)
         PyoObject.__init__(self)
         self._input = input
         self._table = table
@@ -2265,42 +2757,44 @@ class TablePut(PyoObject):
 
     def setMul(self, x):
         pass
-        
+
     def setAdd(self, x):
-        pass    
+        pass
 
     def setInput(self, x, fadetime=0.05):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 : DataTable
+            x: DataTable
                 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)]
 
     @property
     def input(self):
-        """PyoObject. Audio signal to write in the table.""" 
+        """PyoObject. Audio signal to write in the table."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -2311,95 +2805,227 @@ class TablePut(PyoObject):
         return self._table
     @table.setter
     def table(self, x): self.setTable(x)
-    
-class Granule(PyoObject):
+
+class TableFill(PyoObject):
     """
-    Another granular synthesis generator.
+    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:
 
-        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. A new grain gets the current value
-            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. 
-            Defaults to 0.
-        dur : float or PyoObject, optional
-            Duration, in seconds, of the grain. 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.1.
-    
+        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()
-    >>> snd = SndTable(SNDS_PATH+"/transparent.aif")
-    >>> end = snd.getSize() - s.getSamplingRate() * 0.2
-    >>> env = HannTable()
-    >>> pos = Randi(min=0, max=1, freq=[0.25, 0.3], mul=end)
-    >>> dns = Randi(min=10, max=30, freq=.1)
-    >>> pit = Randi(min=0.99, max=1.01, freq=100)
-    >>> grn = Granule(snd, env, dens=dns, pitch=pit, pos=pos, dur=.2, mul=.1).out()
+    >>> 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, table, env, dens=50, pitch=1, pos=0, dur=.1, mul=1, add=0):
-        PyoObject.__init__(self, mul, add)
+    def __init__(self, input, table):
+        pyoArgsAssert(self, "ot", input, table)
+        PyoObject.__init__(self)
+        self._input = input
         self._table = table
-        self._env = env
-        self._dens = dens
-        self._pitch = pitch
-        self._pos = pos
-        self._dur = dur
-        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._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
+            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 setEnv(self, x):
+    def getCurrentPos(self, all=False):
         """
-        Replace the `env` attribute.
-        
+        Returns the current pointer position, in samples, in the table.
+
         :Args:
 
-            x : PyoTableObject
-                new `env` attribute.
-        
-        """
-        self._env = x
-        x, lmax = convertArgsToLists(x)
-        [obj.setEnv(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+            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.
 
-    def setDens(self, x):
         """
-        Replace the `dens` attribute.
-        
-        :Args:
+        pyoArgsAssert(self, "B", all)
+        if not all:
+            return self._base_objs[0].getCurrentPos()
+        else:
+            return [obj.getCurrentPos() for obj in self._base_objs]
 
-            x : float or PyoObject
+    @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.
+
+    As of pyo 0.7.4, users can call the `setSync` method to change the
+    granulation mode (either synchronous or asynchronous) of the 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. A new grain gets the current value
+            of `pitch` as its reading speed. 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 hold it until the end of the grain. Defaults to 0.1.
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> snd = SndTable(SNDS_PATH+"/transparent.aif")
+    >>> end = snd.getSize() - s.getSamplingRate() * 0.2
+    >>> env = HannTable()
+    >>> pos = Randi(min=0, max=1, freq=[0.25, 0.3], mul=end)
+    >>> dns = Randi(min=10, max=30, freq=.1)
+    >>> pit = Randi(min=0.99, max=1.01, freq=100)
+    >>> grn = Granule(snd, env, dens=dns, pitch=pit, pos=pos, dur=.2, mul=.1).out()
+
+    """
+    def __init__(self, table, env, dens=50, pitch=1, pos=0, dur=.1, mul=1, add=0):
+        pyoArgsAssert(self, "ttOOOOOO", table, env, dens, pitch, pos, dur, 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._sync = 1
+        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):
+        """
+        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 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_objs)]
+
+    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_objs)]
@@ -2407,13 +3033,14 @@ class Granule(PyoObject):
     def setPitch(self, x):
         """
         Replace the `pitch` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            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_objs)]
@@ -2421,13 +3048,14 @@ class Granule(PyoObject):
     def setPos(self, x):
         """
         Replace the `pos` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            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_objs)]
@@ -2435,17 +3063,34 @@ class Granule(PyoObject):
     def setDur(self, x):
         """
         Replace the `dur` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            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_objs)]
 
+    def setSync(self, x):
+        """
+        Sets the granulation mode, synchronous or asynchronous.
+
+        :Args:
+
+            x: boolean
+                True means synchronous granulation (the default)
+                while False means asynchronous.
+
+        """
+        pyoArgsAssert(self, "b", x)
+        self._sync = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setSync(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, 250, 'lin', 'dens', self._dens),
                           SLMap(0.25, 2., 'lin', 'pitch', self._pitch),
@@ -2507,9 +3152,9 @@ class TableScale(PyoObject):
 
     :Args:
 
-        table : PyoTableObject
+        table: PyoTableObject
             Table containing the original values.
-        outtable : PyoTableObject
+        outtable: PyoTableObject
             Table where to write the scaled values.
 
     >>> s = Server().boot()
@@ -2526,22 +3171,25 @@ class TableScale(PyoObject):
 
     """
     def __init__(self, table, outtable, mul=1, add=0):
+        pyoArgsAssert(self, "ttOO", table, outtable, mul, add)
         PyoObject.__init__(self, mul, add)
         self._table = table
         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):
         """
         Replace the `table` attribute.
-        
+
         :Args:
 
-            x : PyoTableObject
+            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)]
@@ -2549,13 +3197,14 @@ class TableScale(PyoObject):
     def setOuttable(self, x):
         """
         Replace the `outtable` attribute.
-        
+
         :Args:
 
-            x : PyoTableObject
+            x: PyoTableObject
                 new `outtable` attribute.
-        
+
         """
+        pyoArgsAssert(self, "t", x)
         self._outtable = x
         x, lmax = convertArgsToLists(x)
         [obj.setOuttable(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2566,14 +3215,710 @@ class TableScale(PyoObject):
 
     @property
     def table(self):
-        """PyoTableObject. Table containing the original values.""" 
+        """PyoTableObject. Table containing the original values."""
         return self._table
     @table.setter
     def table(self, x): self.setTable(x)
 
     @property
     def outtable(self):
-        """PyoTableObject. Scaled output table.""" 
+        """PyoTableObject. Scaled output table."""
         return self._outtable
     @outtable.setter
     def outtable(self, x): self.setOuttable(x)
+
+class Particle(PyoObject):
+    """
+    A full control granular synthesis generator.
+
+    :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 sampled 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.
+        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=5, max=100, freq=.1)
+    >>> pit = Randh(min=0.99, max=1.01, freq=100)
+    >>> pos = Randi(min=0, max=1, freq=0.25, mul=end)
+    >>> dur = Randi(min=0.01, max=0.25, freq=0.15)
+    >>> dev = Randi(min=0, max=1, freq=0.2)
+    >>> pan = Noise(0.5, 0.5)
+    >>> grn = Particle(snd, env, dns, pit, pos, dur, dev, pan, chnls=2, mul=.2).out()
+
+    """
+    def __init__(self, table, env, dens=50, pitch=1, pos=0, dur=.1, dev=0.01, pan=0.5, chnls=1, mul=1, add=0):
+        pyoArgsAssert(self, "ttOOOOOOIOO", table, env, dens, pitch, pos, dur, dev, pan, 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._chnls = chnls
+        table, env, dens, pitch, pos, dur, dev, pan, mul, add, lmax = convertArgsToLists(table, env, dens, pitch, pos, dur, dev, pan, mul, add)
+        self._base_players = [MainParticle_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), chnls) for i in range(lmax)]
+        self._base_objs = []
+        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):
+        """
+        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 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),
+                          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)
+
+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 f3a4a3f..ff15d01 100644
--- a/pyolib/tables.py
+++ b/pyolib/tables.py
@@ -1,27 +1,30 @@
+from __future__ import division
+from __future__ import print_function
+from __future__ import absolute_import
 """
-Copyright 2010 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+You should have received a copy of the GNU Lesser General Public
+License along with pyo.  If not, see <http://www.gnu.org/licenses/>.
 """
-from _core import *
-from _maps import *
-from _widgets import createGraphWindow, createDataGraphWindow, createSndViewTableWindow
-from types import ListType
+from ._core import *
+from ._maps import *
+from ._widgets import createGraphWindow, createDataGraphWindow, createSndViewTableWindow
 from math import pi
+import copy
 
 ######################################################################
 ### Tables
@@ -30,17 +33,17 @@ class HarmTable(PyoTableObject):
     """
     Harmonic waveform generator.
 
-    Generates composite waveforms made up of weighted sums 
+    Generates composite waveforms made up of weighted sums
     of simple sinusoids.
 
     :Parent: :py:class:`PyoTableObject`
 
     :Args:
 
-        list : list, optional
-            Relative strengths of the fixed harmonic partial numbers 1,2,3, etc. 
+        list: list, optional
+            Relative strengths of the fixed harmonic partial numbers 1,2,3, etc.
             Defaults to [1].
-        size : int, optional
+        size: int, optional
             Table size in samples. Defaults to 8192.
 
     >>> s = Server().boot()
@@ -51,28 +54,83 @@ class HarmTable(PyoTableObject):
 
     """
     def __init__(self, list=[1., 0.], size=8192):
+        pyoArgsAssert(self, "lI", list, size)
         PyoTableObject.__init__(self, size)
-        self._list = list
-        self._base_objs = [HarmTable_base(list, size)]
-    
+        self._auto_normalize = False
+        self._list = copy.deepcopy(list)
+        self._base_objs = [HarmTable_base(self._list, size)]
+
+    def autoNormalize(self, x):
+        """
+        Activate/deactivate automatic normalization when harmonics changed.
+
+        :Args:
+
+            x: boolean
+                True for activating automatic normalization, False for
+                deactivating it.
+
+        """
+        self._auto_normalize = x
+        if self._auto_normalize:
+            self.normalize()
+
     def replace(self, list):
         """
-        Redraw the waveform according to a new set of harmonics 
+        Redraw the waveform according to a new set of harmonics
         relative strengths.
-        
+
         :Args:
-        
-            list : list
-                Relative strengths of the fixed harmonic partial 
+
+            list: list
+                Relative strengths of the fixed harmonic partial
                 numbers 1,2,3, etc.
 
-        """      
+        """
+        pyoArgsAssert(self, "l", list)
         self._list = list
         [obj.replace(list) for obj in self._base_objs]
+        if self._auto_normalize:
+            self.normalize()
         self.refreshView()
 
+    def _get_current_data(self):
+        # internal that returns the data to draw in a DataTableGrapher.
+        return self._list
+
+    def graph(self, yrange=(-1.0, 1.0), title=None, wxnoserver=False):
+        """
+        Opens a multislider window to control the data values.
+
+        When editing the grapher with the mouse, the new values are
+        sent to the object to replace the table content.
+
+        :Args:
+
+            yrange: tuple, optional
+                Set the min and max values of the Y axis of the multislider.
+                Defaults to (0.0, 1.0).
+            title: string, optional
+                Title of the window. If none is provided, the name of the
+                class is used.
+            wxnoserver: boolean, optional
+                With wxPython graphical toolkit, if True, tells the
+                interpreter that there will be no server window.
+
+        If `wxnoserver` is set to True, the interpreter will not wait for
+        the server GUI before showing the controller window.
+
+        .. note::
+            
+            The number of bars in the graph is initialized to the length
+            of the list of relative strentghs at the time the graph is 
+            created.
+
+        """
+        createDataGraphWindow(self, yrange, title, wxnoserver)
+
     @property
-    def list(self): 
+    def list(self):
         """list. Relative strengths of the fixed harmonic partial numbers."""
         return self._list
     @list.setter
@@ -88,10 +146,10 @@ class SawTable(PyoTableObject):
 
     :Args:
 
-        order : int, optional
-            Number of harmonics sawtooth is made of. 
+        order: int, optional
+            Number of harmonics sawtooth is made of.
             Defaults to 10.
-        size : int, optional
+        size: int, optional
             Table size in samples. Defaults to 8192.
 
     >>> s = Server().boot()
@@ -101,28 +159,30 @@ class SawTable(PyoTableObject):
 
     """
     def __init__(self, order=10, size=8192):
+        pyoArgsAssert(self, "II", order, size)
         PyoTableObject.__init__(self, size)
         self._order = order
-        list = [1./i for i in range(1,(order+1))]
+        list = [1. / i for i in range(1,(order+1))]
         self._base_objs = [HarmTable_base(list, size)]
-    
+
     def setOrder(self, x):
         """
         Change the `order` attribute and redraw the waveform.
-        
+
         :Args:
-        
-            x : int
+
+            x: int
                 New number of harmonics
 
-        """      
+        """
+        pyoArgsAssert(self, "I", x)
         self._order = x
-        list = [1./i for i in range(1,(self._order+1))]
+        list = [1. / i for i in range(1,(self._order+1))]
         [obj.replace(list) for obj in self._base_objs]
         self.refreshView()
 
     @property
-    def order(self): 
+    def order(self):
         """int. Number of harmonics sawtooth is made of."""
         return self._order
     @order.setter
@@ -138,10 +198,10 @@ class SquareTable(PyoTableObject):
 
     :Args:
 
-        order : int, optional
-            Number of harmonics square waveform is made of. The waveform will 
+        order: int, optional
+            Number of harmonics square waveform is made of. The waveform will
             contains `order` odd harmonics. Defaults to 10.
-        size : int, optional
+        size: int, optional
             Table size in samples. Defaults to 8192.
 
     >>> s = Server().boot()
@@ -151,38 +211,40 @@ class SquareTable(PyoTableObject):
 
     """
     def __init__(self, order=10, size=8192):
+        pyoArgsAssert(self, "II", order, size)
         PyoTableObject.__init__(self, size)
         self._order = order
         list = []
         for i in range(1,(order*2)):
             if i%2 == 1:
-                list.append(1./i)
+                list.append(1. / i)
             else:
-                list.append(0.)    
+                list.append(0.)
         self._base_objs = [HarmTable_base(list, size)]
-    
+
     def setOrder(self, x):
         """
         Change the `order` attribute and redraw the waveform.
-        
+
         :Args:
-        
-            x : int
+
+            x: int
                 New number of harmonics
 
-        """      
+        """
+        pyoArgsAssert(self, "I", x)
         self._order = x
         list = []
         for i in range(1,(self._order*2)):
             if i%2 == 1:
-                list.append(1./i)
+                list.append(1. / i)
             else:
-                list.append(0.)    
+                list.append(0.)
         [obj.replace(list) for obj in self._base_objs]
         self.refreshView()
 
     @property
-    def order(self): 
+    def order(self):
         """int. Number of harmonics square waveform is made of."""
         return self._order
     @order.setter
@@ -192,19 +254,19 @@ class ChebyTable(PyoTableObject):
     """
     Chebyshev polynomials of the first kind.
 
-    Uses Chebyshev coefficients to generate stored polynomial functions 
-    which, under waveshaping, can be used to split a sinusoid into 
-    harmonic partials having a pre-definable spectrum. 
+    Uses Chebyshev coefficients to generate stored polynomial functions
+    which, under waveshaping, can be used to split a sinusoid into
+    harmonic partials having a pre-definable spectrum.
 
     :Parent: :py:class:`PyoTableObject`
 
     :Args:
 
-        list : list, optional
-            Relative strengths of partials numbers 1,2,3, ..., 12 that will 
-            result when a sinusoid of amplitude 1 is waveshaped using this 
+        list: list, optional
+            Relative strengths of partials numbers 1,2,3, ..., 12 that will
+            result when a sinusoid of amplitude 1 is waveshaped using this
             function table. Up to 12 partials can be specified. Defaults to [1].
-        size : int, optional
+        size: int, optional
             Table size in samples. Defaults to 8192.
 
     >>> s = Server().boot()
@@ -216,32 +278,52 @@ class ChebyTable(PyoTableObject):
 
     """
     def __init__(self, list=[1., 0.], size=8192):
+        pyoArgsAssert(self, "lI", list, size)
         PyoTableObject.__init__(self, size)
-        self._list = list
-        self._base_objs = [ChebyTable_base(list, size)]
-    
+        self._auto_normalize = False
+        self._list = copy.deepcopy(list)
+        self._base_objs = [ChebyTable_base(self._list, size)]
+
+    def autoNormalize(self, x):
+        """
+        Activate/deactivate automatic normalization when harmonics changed.
+
+        :Args:
+
+            x: boolean
+                True for activating automatic normalization, False for
+                deactivating it.
+
+        """
+        self._auto_normalize = x
+        if self._auto_normalize:
+            self.normalize()
+
     def replace(self, list):
         """
-        Redraw the waveform according to a new set of harmonics 
-        relative strengths that will result when a sinusoid of 
+        Redraw the waveform according to a new set of harmonics
+        relative strengths that will result when a sinusoid of
         amplitude 1 is waveshaped using this function table.
-        
+
         :Args:
-        
-            list : list
-                Relative strengths of the fixed harmonic partial 
+
+            list: list
+                Relative strengths of the fixed harmonic partial
                 numbers 1,2,3, ..., 12. Up to 12 partials can be specified.
 
-        """ 
+        """
+        pyoArgsAssert(self, "l", list)
         self._list = list
         [obj.replace(list) for obj in self._base_objs]
+        if self._auto_normalize:
+            self.normalize()
         self.refreshView()
 
     def getNormTable(self):
         """
-        Return a DataTable filled with the normalization function 
+        Return a DataTable filled with the normalization function
         corresponding to the current polynomial.
-        
+
         """
         if sum(self._list[1::2]) == 0:
             data = self._base_objs[0].getNormTable(0)
@@ -249,22 +331,57 @@ class ChebyTable(PyoTableObject):
             data = self._base_objs[0].getNormTable(1)
         return DataTable(size=len(data), init=data).normalize()
 
+    def _get_current_data(self):
+        # internal that returns the data to draw in a DataTableGrapher.
+        return self._list
+
+    def graph(self, yrange=(-1.0, 1.0), title=None, wxnoserver=False):
+        """
+        Opens a multislider window to control the data values.
+
+        When editing the grapher with the mouse, the new values are
+        sent to the object to replace the table content.
+
+        :Args:
+
+            yrange: tuple, optional
+                Set the min and max values of the Y axis of the multislider.
+                Defaults to (0.0, 1.0).
+            title: string, optional
+                Title of the window. If none is provided, the name of the
+                class is used.
+            wxnoserver: boolean, optional
+                With wxPython graphical toolkit, if True, tells the
+                interpreter that there will be no server window.
+
+        If `wxnoserver` is set to True, the interpreter will not wait for
+        the server GUI before showing the controller window.
+
+        .. note::
+            
+            The number of bars in the graph is initialized to the length
+            of the list of relative strentghs at the time the graph is 
+            created.
+
+        """
+        createDataGraphWindow(self, yrange, title, wxnoserver)
+
     @property
-    def list(self): 
+    def list(self):
         """list. Relative strengths of the fixed harmonic partial numbers."""
         return self._list
     @list.setter
     def list(self, x): self.replace(x)
-        
+
 class HannTable(PyoTableObject):
     """
-    Generates Hanning window function. 
+    Generates Hanning window function.
 
     :Parent: :py:class:`PyoTableObject`
 
     :Args:
 
-        size : int, optional
+        size: int, optional
             Table size in samples. Defaults to 8192.
 
     >>> s = Server().boot()
@@ -276,22 +393,23 @@ class HannTable(PyoTableObject):
 
     """
     def __init__(self, size=8192):
+        pyoArgsAssert(self, "I", size)
         PyoTableObject.__init__(self, size)
         self._base_objs = [HannTable_base(size)]
 
 class SincTable(PyoTableObject):
     """
-    Generates sinc window function. 
+    Generates sinc window function.
 
     :Parent: :py:class:`PyoTableObject`
 
     :Args:
 
-        freq : float, optional
+        freq: float, optional
             Frequency, in radians, of the sinc function. Defaults to pi*2.
-        windowed : boolean, optional
+        windowed: boolean, optional
             If True, an hanning window is applied on the sinc function. Defaults to False.
-        size : int, optional
+        size: int, optional
             Table size in samples. Defaults to 8192.
 
     >>> import math
@@ -302,6 +420,7 @@ class SincTable(PyoTableObject):
 
     """
     def __init__(self, freq=pi*2, windowed=False, size=8192):
+        pyoArgsAssert(self, "NBI", freq, windowed, size)
         PyoTableObject.__init__(self, size)
         self._freq = freq
         self._windowed = windowed
@@ -313,10 +432,11 @@ class SincTable(PyoTableObject):
 
         :Args:
 
-            x : float
+            x: float
                 New frequency in radians.
 
         """
+        pyoArgsAssert(self, "N", x)
         self._freq = x
         [obj.setFreq(x) for obj in self._base_objs]
         self.refreshView()
@@ -327,22 +447,23 @@ class SincTable(PyoTableObject):
 
         :Args:
 
-            x : boolean
+            x: boolean
                 New windowed flag.
 
         """
+        pyoArgsAssert(self, "B", x)
         self._windowed = x
         [obj.setWindowed(x) for obj in self._base_objs]
         self.refreshView()
 
     @property
-    def freq(self): 
+    def freq(self):
         """float. Frequency of the sinc function."""
         return self._freq
     @freq.setter
     def freq(self, x): self.setFreq(x)
     @property
-    def windowed(self): 
+    def windowed(self):
         """boolean. Windowed flag."""
         return self._windowed
     @windowed.setter
@@ -350,13 +471,13 @@ class SincTable(PyoTableObject):
 
 class WinTable(PyoTableObject):
     """
-    Generates different kind of windowing functions. 
+    Generates different kind of windowing functions.
 
     :Parent: :py:class:`PyoTableObject`
 
     :Args:
 
-        type : int, optional
+        type: int, optional
             Windowing function. Possible choices are:
                 0. Rectangular (no window)
                 1. Hamming
@@ -367,7 +488,7 @@ class WinTable(PyoTableObject):
                 6. Blackman-Harris 7-term
                 7. Tuckey (alpha = 0.66)
                 8. Sine (half-sine window)
-        size : int, optional
+        size: int, optional
             Table size in samples. Defaults to 8192.
 
     >>> s = Server().boot()
@@ -379,6 +500,7 @@ class WinTable(PyoTableObject):
 
     """
     def __init__(self, type=2, size=8192):
+        pyoArgsAssert(self, "II", type, size)
         PyoTableObject.__init__(self, size)
         self._type = type
         self._base_objs = [WinTable_base(type, size)]
@@ -389,16 +511,17 @@ class WinTable(PyoTableObject):
 
         :Args:
 
-            type : int {0 -> 8}
+            type: int {0 -> 8}
                 Windowing function.
 
         """
+        pyoArgsAssert(self, "I", type)
         self._type = type
         [obj.setType(type) for obj in self._base_objs]
         self.refreshView()
 
     @property
-    def type(self): 
+    def type(self):
         """int. Windowing function."""
         return self._type
     @type.setter
@@ -406,16 +529,16 @@ class WinTable(PyoTableObject):
 
 class ParaTable(PyoTableObject):
     """
-    Generates parabola window function. 
+    Generates parabola window function.
 
-    The parabola is a conic section, the intersection of a right circular conical 
+    The parabola is a conic section, the intersection of a right circular conical
     surface and a plane parallel to a generating straight line of that surface.
 
     :Parent: :py:class:`PyoTableObject`
 
     :Args:
 
-        size : int, optional
+        size: int, optional
             Table size in samples. Defaults to 8192.
 
     >>> s = Server().boot()
@@ -427,6 +550,7 @@ class ParaTable(PyoTableObject):
 
     """
     def __init__(self, size=8192):
+        pyoArgsAssert(self, "I", size)
         PyoTableObject.__init__(self, size)
         self._base_objs = [ParaTable_base(size)]
 
@@ -438,18 +562,18 @@ class LinTable(PyoTableObject):
 
     :Args:
 
-        list : list, optional
-            List of tuples indicating location and value of each points 
-            in the table. The default, [(0,0.), (8191, 1.)], creates a 
-            straight line from 0.0 at location 0 to 1.0 at the end of the 
+        list: list, optional
+            List of tuples indicating location and value of each points
+            in the table. The default, [(0,0.), (8191, 1.)], creates a
+            straight line from 0.0 at location 0 to 1.0 at the end of the
             table (size - 1). Location must be an integer.
-        size : int, optional
+        size: int, optional
             Table size in samples. Defaults to 8192.
 
     .. note::
 
-        Locations in the list must be in increasing order. If the last value 
-        is less than size, the rest of the table will be filled with zeros. 
+        Locations in the list must be in increasing order. If the last value
+        is less than size, the rest of the table will be filled with zeros.
 
     >>> s = Server().boot()
     >>> s.start()
@@ -460,25 +584,27 @@ class LinTable(PyoTableObject):
 
     """
     def __init__(self, list=[(0, 0.), (8191, 1.)], size=8192):
+        pyoArgsAssert(self, "lI", list, size)
         PyoTableObject.__init__(self, size)
         if size < list[-1][0]:
-            print "LinTable warning : size smaller than last point position."
-            print "                   Increased size to last point position + 1"
+            print("LinTable warning: size smaller than last point position.")
+            print("                   Increased size to last point position + 1")
             size = list[-1][0] + 1
             self._size = size
-        self._base_objs = [LinTable_base(list, size)]
-    
+        self._base_objs = [LinTable_base(copy.deepcopy(list), size)]
+
     def replace(self, list):
         """
         Draw a new envelope according to the new `list` parameter.
-        
+
         :Args:
-        
-            list : list
-                List of tuples indicating location and value of each points 
+
+            list: list
+                List of tuples indicating location and value of each points
                 in the table. Location must be integer.
 
-        """ 
+        """
+        pyoArgsAssert(self, "l", list)
         self._list = list
         [obj.replace(list) for obj in self._base_objs]
         self.refreshView()
@@ -486,21 +612,22 @@ class LinTable(PyoTableObject):
     def loadRecFile(self, filename, tolerance=0.02):
         """
         Import an automation recording file in the table.
-        
+
         loadRecFile takes a recording file, usually from a ControlRec object,
         as `filename` parameter, applies a filtering pre-processing to eliminate
-        redundancies and loads the result in the table as a list of points. 
-        Filtering process can be controled with the `tolerance` parameter. 
-        
+        redundancies and loads the result in the table as a list of points.
+        Filtering process can be controled with the `tolerance` parameter.
+
         :Args:
-        
-            filename : string
+
+            filename: string
                 Full path of an automation recording file.
-            tolerance : float, optional
+            tolerance: float, optional
                 Tolerance of the filter. A higher value will eliminate more points.
                 Defaults to 0.02.
 
         """
+        pyoArgsAssert(self, "SN", filename, tolerance)
         _path, _name = os.path.split(filename)
         # files = sorted([f for f in os.listdir(_path) if _name+"_" in f])
         # if _name not in files: files.append(_name)
@@ -529,32 +656,32 @@ class LinTable(PyoTableObject):
         Opens a grapher window to control the shape of the envelope.
 
         When editing the grapher with the mouse, the new set of points
-        will be send to the object on mouse up. 
-        
-        Ctrl+C with focus on the grapher will copy the list of points to the 
+        will be send to the object on mouse up.
+
+        Ctrl+C with focus on the grapher will copy the list of points to the
         clipboard, giving an easy way to insert the new shape in a script.
 
         :Args:
 
-            yrange : tuple, optional
+            yrange: tuple, optional
                 Set the min and max values of the Y axis of the graph.
                 Defaults to (0.0, 1.0).
-            title : string, optional
-                Title of the window. If none is provided, the name of the 
+            title: string, optional
+                Title of the window. If none is provided, the name of the
                 class is used.
-            wxnoserver : boolean, optional
-                With wxPython graphical toolkit, if True, tells the 
+            wxnoserver: boolean, optional
+                With wxPython graphical toolkit, if True, tells the
                 interpreter that there will be no server window.
-                
-        If `wxnoserver` is set to True, the interpreter will not wait for 
-        the server GUI before showing the controller window. 
+
+        If `wxnoserver` is set to True, the interpreter will not wait for
+        the server GUI before showing the controller window.
 
         """
         createGraphWindow(self, 0, self._size, yrange, title, wxnoserver)
 
     @property
     def list(self):
-        """list. List of tuples indicating location and value of each points in the table.""" 
+        """list. List of tuples indicating location and value of each points in the table."""
         return self.getPoints()
     @list.setter
     def list(self, x): self.replace(x)
@@ -567,19 +694,19 @@ class LogTable(PyoTableObject):
 
     :Args:
 
-        list : list, optional
-            List of tuples indicating location and value of each points 
-            in the table. The default, [(0,0.), (8191, 1.)], creates a 
-            logarithmic line from 0.0 at location 0 to 1.0 at the end of 
+        list: list, optional
+            List of tuples indicating location and value of each points
+            in the table. The default, [(0,0.), (8191, 1.)], creates a
+            logarithmic line from 0.0 at location 0 to 1.0 at the end of
             the table (size - 1). Location must be an integer.
-        size : int, optional
+        size: int, optional
             Table size in samples. Defaults to 8192.
 
     .. note::
 
-        Locations in the list must be in increasing order. If the last value 
-        is less than size, the rest of the table will be filled with zeros. 
-        
+        Locations in the list must be in increasing order. If the last value
+        is less than size, the rest of the table will be filled with zeros.
+
         Values must be greater than 0.0.
 
     >>> s = Server().boot()
@@ -590,13 +717,14 @@ class LogTable(PyoTableObject):
 
     """
     def __init__(self, list=[(0, 0.), (8191, 1.)], size=8192):
+        pyoArgsAssert(self, "lI", list, size)
         PyoTableObject.__init__(self, size)
         if size < list[-1][0]:
-            print "LogTable warning : size smaller than last point position."
-            print "                   Increased size to last point position + 1"
+            print("LogTable warning: size smaller than last point position.")
+            print("                   Increased size to last point position + 1")
             size = list[-1][0] + 1
             self._size = size
-        self._base_objs = [LogTable_base(list, size)]
+        self._base_objs = [LogTable_base(copy.deepcopy(list), size)]
 
     def replace(self, list):
         """
@@ -604,11 +732,12 @@ class LogTable(PyoTableObject):
 
         :Args:
 
-            list : list
-                List of tuples indicating location and value of each points 
+            list: list
+                List of tuples indicating location and value of each points
                 in the table. Location must be integer.
 
-        """ 
+        """
+        pyoArgsAssert(self, "l", list)
         self._list = list
         [obj.replace(list) for obj in self._base_objs]
         self.refreshView()
@@ -619,18 +748,19 @@ class LogTable(PyoTableObject):
 
         loadRecFile takes a recording file, usually from a ControlRec object,
         as `filename` parameter, applies a filtering pre-processing to eliminate
-        redundancies and loads the result in the table as a list of points. 
-        Filtering process can be controled with the `tolerance` parameter. 
+        redundancies and loads the result in the table as a list of points.
+        Filtering process can be controled with the `tolerance` parameter.
 
         :Args:
 
-            filename : string
+            filename: string
                 Full path of an automation recording file.
-            tolerance : float, optional
+            tolerance: float, optional
                 Tolerance of the filter. A higher value will eliminate more points.
                 Defaults to 0.02.
 
         """
+        pyoArgsAssert(self, "SN", filename, tolerance)
         _path, _name = os.path.split(filename)
         # files = sorted([f for f in os.listdir(_path) if _name+"_" in f])
         # if _name not in files: files.append(_name)
@@ -659,32 +789,32 @@ class LogTable(PyoTableObject):
         Opens a grapher window to control the shape of the envelope.
 
         When editing the grapher with the mouse, the new set of points
-        will be send to the object on mouse up. 
+        will be send to the object on mouse up.
 
-        Ctrl+C with focus on the grapher will copy the list of points to the 
+        Ctrl+C with focus on the grapher will copy the list of points to the
         clipboard, giving an easy way to insert the new shape in a script.
 
         :Args:
 
-            yrange : tuple, optional
+            yrange: tuple, optional
                 Set the min and max values of the Y axis of the graph.
                 Defaults to (0.0, 1.0).
-            title : string, optional
-                Title of the window. If none is provided, the name of the 
+            title: string, optional
+                Title of the window. If none is provided, the name of the
                 class is used.
-            wxnoserver : boolean, optional
-                With wxPython graphical toolkit, if True, tells the 
+            wxnoserver: boolean, optional
+                With wxPython graphical toolkit, if True, tells the
                 interpreter that there will be no server window.
-                
-        If `wxnoserver` is set to True, the interpreter will not wait for 
-        the server GUI before showing the controller window. 
+
+        If `wxnoserver` is set to True, the interpreter will not wait for
+        the server GUI before showing the controller window.
 
         """
         createGraphWindow(self, 4, self._size, yrange, title, wxnoserver)
 
     @property
     def list(self):
-        """list. List of tuples indicating location and value of each points in the table.""" 
+        """list. List of tuples indicating location and value of each points in the table."""
         return self.getPoints()
     @list.setter
     def list(self, x): self.replace(x)
@@ -697,18 +827,18 @@ class CosLogTable(PyoTableObject):
 
     :Args:
 
-        list : list, optional
-            List of tuples indicating location and value of each points 
-            in the table. The default, [(0,0.), (8191, 1.)], creates a 
-            logarithmic line from 0.0 at location 0 to 1.0 at the end of 
+        list: list, optional
+            List of tuples indicating location and value of each points
+            in the table. The default, [(0,0.), (8191, 1.)], creates a
+            logarithmic line from 0.0 at location 0 to 1.0 at the end of
             the table (size - 1). Location must be an integer.
-        size : int, optional
+        size: int, optional
             Table size in samples. Defaults to 8192.
 
     .. note::
 
-        Locations in the list must be in increasing order. If the last value 
-        is less than size, the rest of the table will be filled with zeros. 
+        Locations in the list must be in increasing order. If the last value
+        is less than size, the rest of the table will be filled with zeros.
 
         Values must be greater than 0.0.
 
@@ -720,13 +850,14 @@ class CosLogTable(PyoTableObject):
 
     """
     def __init__(self, list=[(0, 0.), (8191, 1.)], size=8192):
+        pyoArgsAssert(self, "lI", list, size)
         PyoTableObject.__init__(self, size)
         if size < list[-1][0]:
-            print "CosLogTable warning : size smaller than last point position."
-            print "                   Increased size to last point position + 1"
+            print("CosLogTable warning: size smaller than last point position.")
+            print("                   Increased size to last point position + 1")
             size = list[-1][0] + 1
             self._size = size
-        self._base_objs = [CosLogTable_base(list, size)]
+        self._base_objs = [CosLogTable_base(copy.deepcopy(list), size)]
 
     def replace(self, list):
         """
@@ -734,11 +865,12 @@ class CosLogTable(PyoTableObject):
 
         :Args:
 
-            list : list
-                List of tuples indicating location and value of each points 
+            list: list
+                List of tuples indicating location and value of each points
                 in the table. Location must be integer.
 
-        """ 
+        """
+        pyoArgsAssert(self, "l", list)
         self._list = list
         [obj.replace(list) for obj in self._base_objs]
         self.refreshView()
@@ -749,18 +881,19 @@ class CosLogTable(PyoTableObject):
 
         loadRecFile takes a recording file, usually from a ControlRec object,
         as `filename` parameter, applies a filtering pre-processing to eliminate
-        redundancies and loads the result in the table as a list of points. 
-        Filtering process can be controled with the `tolerance` parameter. 
+        redundancies and loads the result in the table as a list of points.
+        Filtering process can be controled with the `tolerance` parameter.
 
         :Args:
 
-            filename : string
+            filename: string
                 Full path of an automation recording file.
-            tolerance : float, optional
+            tolerance: float, optional
                 Tolerance of the filter. A higher value will eliminate more points.
                 Defaults to 0.02.
 
         """
+        pyoArgsAssert(self, "SN", filename, tolerance)
         _path, _name = os.path.split(filename)
         # files = sorted([f for f in os.listdir(_path) if _name+"_" in f])
         # if _name not in files: files.append(_name)
@@ -789,32 +922,32 @@ class CosLogTable(PyoTableObject):
         Opens a grapher window to control the shape of the envelope.
 
         When editing the grapher with the mouse, the new set of points
-        will be send to the object on mouse up. 
+        will be send to the object on mouse up.
 
-        Ctrl+C with focus on the grapher will copy the list of points to the 
+        Ctrl+C with focus on the grapher will copy the list of points to the
         clipboard, giving an easy way to insert the new shape in a script.
 
         :Args:
 
-            yrange : tuple, optional
+            yrange: tuple, optional
                 Set the min and max values of the Y axis of the graph.
                 Defaults to (0.0, 1.0).
-            title : string, optional
-                Title of the window. If none is provided, the name of the 
+            title: string, optional
+                Title of the window. If none is provided, the name of the
                 class is used.
-            wxnoserver : boolean, optional
-                With wxPython graphical toolkit, if True, tells the 
+            wxnoserver: boolean, optional
+                With wxPython graphical toolkit, if True, tells the
                 interpreter that there will be no server window.
-                
-        If `wxnoserver` is set to True, the interpreter will not wait for 
-        the server GUI before showing the controller window. 
+
+        If `wxnoserver` is set to True, the interpreter will not wait for
+        the server GUI before showing the controller window.
 
         """
         createGraphWindow(self, 5, self._size, yrange, title, wxnoserver)
 
     @property
     def list(self):
-        """list. List of tuples indicating location and value of each points in the table.""" 
+        """list. List of tuples indicating location and value of each points in the table."""
         return self.getPoints()
     @list.setter
     def list(self, x): self.replace(x)
@@ -827,18 +960,18 @@ class CosTable(PyoTableObject):
 
     :Args:
 
-        list : list, optional
-            List of tuples indicating location and value of each points 
-            in the table. The default, [(0,0.), (8191, 1.)], creates a 
-            cosine line from 0.0 at location 0 to 1.0 at the end of the 
+        list: list, optional
+            List of tuples indicating location and value of each points
+            in the table. The default, [(0,0.), (8191, 1.)], creates a
+            cosine line from 0.0 at location 0 to 1.0 at the end of the
             table (size - 1). Location must be an integer.
-        size : int, optional
+        size: int, optional
             Table size in samples. Defaults to 8192.
 
     .. note::
 
-        Locations in the list must be in increasing order. If the last value 
-        is less than size, the rest of the table will be filled with zeros. 
+        Locations in the list must be in increasing order. If the last value
+        is less than size, the rest of the table will be filled with zeros.
 
     >>> s = Server().boot()
     >>> s.start()
@@ -849,25 +982,27 @@ class CosTable(PyoTableObject):
 
     """
     def __init__(self, list=[(0, 0.), (8191, 1.)], size=8192):
+        pyoArgsAssert(self, "lI", list, size)
         PyoTableObject.__init__(self, size)
         if size < list[-1][0]:
-            print "CosTable warning : size smaller than last point position."
-            print "                   Increased size to last point position + 1"
+            print("CosTable warning: size smaller than last point position.")
+            print("                   Increased size to last point position + 1")
             size = list[-1][0] + 1
             self._size = size
-        self._base_objs = [CosTable_base(list, size)]
-    
+        self._base_objs = [CosTable_base(copy.deepcopy(list), size)]
+
     def replace(self, list):
         """
         Draw a new envelope according to the new `list` parameter.
-        
+
         :Args:
-        
-            list : list
-                List of tuples indicating location and value of each points 
+
+            list: list
+                List of tuples indicating location and value of each points
                 in the table. Location must be integer.
 
-        """      
+        """
+        pyoArgsAssert(self, "l", list)
         self._list = list
         [obj.replace(list) for obj in self._base_objs]
         self.refreshView()
@@ -878,18 +1013,19 @@ class CosTable(PyoTableObject):
 
         loadRecFile takes a recording file, usually from a ControlRec object,
         as `filename` parameter, applies a filtering pre-processing to eliminate
-        redundancies and loads the result in the table as a list of points. 
-        Filtering process can be controled with the `tolerance` parameter. 
+        redundancies and loads the result in the table as a list of points.
+        Filtering process can be controled with the `tolerance` parameter.
 
         :Args:
 
-            filename : string
+            filename: string
                 Full path of an automation recording file.
-            tolerance : float, optional
+            tolerance: float, optional
                 Tolerance of the filter. A higher value will eliminate more points.
                 Defaults to 0.02.
 
         """
+        pyoArgsAssert(self, "SN", filename, tolerance)
         _path, _name = os.path.split(filename)
         # files = sorted([f for f in os.listdir(_path) if _name+"_" in f])
         # if _name not in files: files.append(_name)
@@ -918,32 +1054,32 @@ class CosTable(PyoTableObject):
         Opens a grapher window to control the shape of the envelope.
 
         When editing the grapher with the mouse, the new set of points
-        will be send to the object on mouse up. 
+        will be send to the object on mouse up.
 
-        Ctrl+C with focus on the grapher will copy the list of points to the 
+        Ctrl+C with focus on the grapher will copy the list of points to the
         clipboard, giving an easy way to insert the new shape in a script.
 
         :Args:
 
-            yrange : tuple, optional
+            yrange: tuple, optional
                 Set the min and max values of the Y axis of the graph.
                 Defaults to (0.0, 1.0).
-            title : string, optional
-                Title of the window. If none is provided, the name of the 
+            title: string, optional
+                Title of the window. If none is provided, the name of the
                 class is used.
-            wxnoserver : boolean, optional
-                With wxPython graphical toolkit, if True, tells the 
+            wxnoserver: boolean, optional
+                With wxPython graphical toolkit, if True, tells the
                 interpreter that there will be no server window.
-                
-        If `wxnoserver` is set to True, the interpreter will not wait for 
-        the server GUI before showing the controller window. 
+
+        If `wxnoserver` is set to True, the interpreter will not wait for
+        the server GUI before showing the controller window.
 
         """
         createGraphWindow(self, 1, self._size, yrange, title, wxnoserver)
 
     @property
     def list(self):
-        """list. List of tuples indicating location and value of each points in the table.""" 
+        """list. List of tuples indicating location and value of each points in the table."""
         return self.getPoints()
     @list.setter
     def list(self, x): self.replace(x)
@@ -954,32 +1090,32 @@ class CurveTable(PyoTableObject):
 
     CurveTable uses Hermite interpolation (sort of cubic interpolation)
     to calculate each points of the curve. This algorithm allows tension
-    and biasing controls. Tension can be used to tighten up the curvature 
-    at the known points. The bias is used to twist the curve about the 
+    and biasing controls. Tension can be used to tighten up the curvature
+    at the known points. The bias is used to twist the curve about the
     known points.
 
     :Parent: :py:class:`PyoTableObject`
 
     :Args:
 
-        list : list, optional
-            List of tuples indicating location and value of each points 
-            in the table. The default, [(0,0.), (8191, 1.)], creates a 
-            curved line from 0.0 at location 0 to 1.0 at the end of the 
+        list: list, optional
+            List of tuples indicating location and value of each points
+            in the table. The default, [(0,0.), (8191, 1.)], creates a
+            curved line from 0.0 at location 0 to 1.0 at the end of the
             table (size - 1). Location must be an integer.
-        tension : float, optional
+        tension: float, optional
             Curvature at the known points. 1 is high, 0 normal, -1 is low.
             Defaults to 0.
-        bias : float, optional
+        bias: float, optional
             Curve attraction (for each segments) toward bundary points.
-            0 is even, positive is towards first point, negative is towards 
+            0 is even, positive is towards first point, negative is towards
             the second point. Defaults to 0.
-        size : int, optional
+        size: int, optional
             Table size in samples. Defaults to 8192.
 
     .. note::
 
-        Locations in the list must be in increasing order. If the last value 
+        Locations in the list must be in increasing order. If the last value
         is less than size, the rest of the table will be filled with zeros.
 
         High tension or bias values can create unstable or very loud table,
@@ -994,28 +1130,30 @@ class CurveTable(PyoTableObject):
 
     """
     def __init__(self, list=[(0, 0.), (8191, 1.)], tension=0, bias=0, size=8192):
+        pyoArgsAssert(self, "lNNI", list, tension, bias, size)
         PyoTableObject.__init__(self, size)
         if size < list[-1][0]:
-            print "CurveTable warning : size smaller than last point position."
-            print "                     Increased size to last point position + 1"
+            print("CurveTable warning: size smaller than last point position.")
+            print("                     Increased size to last point position + 1")
             size = list[-1][0] + 1
             self._size = size
         self._tension = tension
         self._bias = bias
-        self._base_objs = [CurveTable_base(list, tension, bias, size)]
+        self._base_objs = [CurveTable_base(copy.deepcopy(list), tension, bias, size)]
 
     def setTension(self, x):
         """
         Replace the `tension` attribute.
-        
+
         1 is high, 0 normal, -1 is low.
-        
+
         :Args:
-        
-            x : float
+
+            x: float
                 New `tension` attribute.
-        
+
         """
+        pyoArgsAssert(self, "N", x)
         self._tension = x
         [obj.setTension(x) for obj in self._base_objs]
         self.refreshView()
@@ -1023,31 +1161,33 @@ class CurveTable(PyoTableObject):
     def setBias(self, x):
         """
         Replace the `bias` attribute.
-        
-        0 is even, positive is towards first point, negative is towards 
+
+        0 is even, positive is towards first point, negative is towards
         the second point.
-        
+
         :Args:
-        
-            x : float
+
+            x: float
                 New `bias` attribute.
-        
+
         """
+        pyoArgsAssert(self, "N", x)
         self._bias = x
         [obj.setBias(x) for obj in self._base_objs]
         self.refreshView()
-     
+
     def replace(self, list):
         """
         Draw a new envelope according to the new `list` parameter.
-        
+
         :Args:
-        
-            list : list
-                List of tuples indicating location and value of each points 
+
+            list: list
+                List of tuples indicating location and value of each points
                 in the table. Location must be integer.
 
-        """      
+        """
+        pyoArgsAssert(self, "l", list)
         self._list = list
         [obj.replace(list) for obj in self._base_objs]
         self.refreshView()
@@ -1058,18 +1198,19 @@ class CurveTable(PyoTableObject):
 
         loadRecFile takes a recording file, usually from a ControlRec object,
         as `filename` parameter, applies a filtering pre-processing to eliminate
-        redundancies and loads the result in the table as a list of points. 
-        Filtering process can be controled with the `tolerance` parameter. 
+        redundancies and loads the result in the table as a list of points.
+        Filtering process can be controled with the `tolerance` parameter.
 
         :Args:
 
-            filename : string
+            filename: string
                 Full path of an automation recording file.
-            tolerance : float, optional
+            tolerance: float, optional
                 Tolerance of the filter. A higher value will eliminate more points.
                 Defaults to 0.02.
 
         """
+        pyoArgsAssert(self, "SN", filename, tolerance)
         _path, _name = os.path.split(filename)
         # files = sorted([f for f in os.listdir(_path) if _name+"_" in f])
         # if _name not in files: files.append(_name)
@@ -1085,7 +1226,7 @@ class CurveTable(PyoTableObject):
             self._list = values
             obj.replace(values)
         self.refreshView()
-        
+
     def getPoints(self):
         """
         Returns list of points of the current table.
@@ -1098,46 +1239,46 @@ class CurveTable(PyoTableObject):
         Opens a grapher window to control the shape of the envelope.
 
         When editing the grapher with the mouse, the new set of points
-        will be send to the object on mouse up. 
+        will be send to the object on mouse up.
 
-        Ctrl+C with focus on the grapher will copy the list of points to the 
+        Ctrl+C with focus on the grapher will copy the list of points to the
         clipboard, giving an easy way to insert the new shape in a script.
 
         :Args:
 
-            yrange : tuple, optional
+            yrange: tuple, optional
                 Set the min and max values of the Y axis of the graph.
                 Defaults to (0.0, 1.0).
-            title : string, optional
-                Title of the window. If none is provided, the name of the 
+            title: string, optional
+                Title of the window. If none is provided, the name of the
                 class is used.
-            wxnoserver : boolean, optional
-                With wxPython graphical toolkit, if True, tells the 
+            wxnoserver: boolean, optional
+                With wxPython graphical toolkit, if True, tells the
                 interpreter that there will be no server window.
-                
-        If `wxnoserver` is set to True, the interpreter will not wait for 
-        the server GUI before showing the controller window. 
+
+        If `wxnoserver` is set to True, the interpreter will not wait for
+        the server GUI before showing the controller window.
 
         """
         createGraphWindow(self, 3, self._size, yrange, title, wxnoserver)
 
     @property
     def tension(self):
-        """float. Curvature tension.""" 
+        """float. Curvature tension."""
         return self._tension
     @tension.setter
     def tension(self, x): self.setTension(x)
 
     @property
     def bias(self):
-        """float. Curve Attraction.""" 
+        """float. Curve Attraction."""
         return self._bias
     @bias.setter
     def bias(self, x): self.setBias(x)
 
     @property
     def list(self):
-        """list. List of tuples indicating location and value of each points in the table.""" 
+        """list. List of tuples indicating location and value of each points in the table."""
         return self.getPoints()
     @list.setter
     def list(self, x): self.replace(x)
@@ -1150,23 +1291,23 @@ class ExpTable(PyoTableObject):
 
     :Args:
 
-        list : list, optional
-            List of tuples indicating location and value of each points 
-            in the table. The default, [(0,0.), (8192, 1.)], creates a 
-            exponential line from 0.0 at location 0 to 1.0 at the end of 
+        list: list, optional
+            List of tuples indicating location and value of each points
+            in the table. The default, [(0,0.), (8192, 1.)], creates a
+            exponential line from 0.0 at location 0 to 1.0 at the end of
             the table. Location must be an integer.
-        exp : float, optional
+        exp: float, optional
             Exponent factor. Used to control the slope of the curve.
             Defaults to 10.
-        inverse : boolean, optional
-            If True, downward slope will be inversed. Useful to create 
+        inverse: boolean, optional
+            If True, downward slope will be inversed. Useful to create
             biexponential curves. Defaults to True.
-        size : int, optional
+        size: int, optional
             Table size in samples. Defaults to 8192.
 
     .. note::
 
-        Locations in the list must be in increasing order. If the last value 
+        Locations in the list must be in increasing order. If the last value
         is less than size, the rest of the table will be filled with zeros.
 
     >>> s = Server().boot()
@@ -1177,26 +1318,28 @@ class ExpTable(PyoTableObject):
 
     """
     def __init__(self, list=[(0, 0.), (8192, 1.)], exp=10, inverse=True, size=8192):
+        pyoArgsAssert(self, "lNBI", list, exp, inverse, size)
         PyoTableObject.__init__(self, size)
         if size < list[-1][0]:
-            print "ExpTable warning : size smaller than last point position."
-            print "                   Increased size to last point position + 1"
+            print("ExpTable warning: size smaller than last point position.")
+            print("                   Increased size to last point position + 1")
             size = list[-1][0] + 1
             self._size = size
         self._exp = exp
         self._inverse = inverse
-        self._base_objs = [ExpTable_base(list, exp, inverse, size)]
+        self._base_objs = [ExpTable_base(copy.deepcopy(list), exp, inverse, size)]
 
     def setExp(self, x):
         """
         Replace the `exp` attribute.
-        
+
         :Args:
-        
-            x : float
+
+            x: float
                 New `exp` attribute.
-        
+
         """
+        pyoArgsAssert(self, "N", x)
         self._exp = x
         [obj.setExp(x) for obj in self._base_objs]
         self.refreshView()
@@ -1204,28 +1347,30 @@ class ExpTable(PyoTableObject):
     def setInverse(self, x):
         """
         Replace the `inverse` attribute.
-        
+
         :Args:
-        
-            x : boolean
+
+            x: boolean
                 New `inverse` attribute.
-        
+
         """
+        pyoArgsAssert(self, "B", x)
         self._inverse = x
         [obj.setInverse(x) for obj in self._base_objs]
         self.refreshView()
-  
+
     def replace(self, list):
         """
         Draw a new envelope according to the new `list` parameter.
-        
+
         :Args:
-        
-            list : list
-                List of tuples indicating location and value of each points 
+
+            list: list
+                List of tuples indicating location and value of each points
                 in the table. Location must be integer.
 
         """
+        pyoArgsAssert(self, "l", list)
         self._list = list
         [obj.replace(list) for obj in self._base_objs]
         self.refreshView()
@@ -1236,18 +1381,19 @@ class ExpTable(PyoTableObject):
 
         loadRecFile takes a recording file, usually from a ControlRec object,
         as `filename` parameter, applies a filtering pre-processing to eliminate
-        redundancies and loads the result in the table as a list of points. 
-        Filtering process can be controled with the `tolerance` parameter. 
+        redundancies and loads the result in the table as a list of points.
+        Filtering process can be controled with the `tolerance` parameter.
 
         :Args:
 
-            filename : string
+            filename: string
                 Full path of an automation recording file.
-            tolerance : float, optional
+            tolerance: float, optional
                 Tolerance of the filter. A higher value will eliminate more points.
                 Defaults to 0.02.
 
         """
+        pyoArgsAssert(self, "SN", filename, tolerance)
         _path, _name = os.path.split(filename)
         # files = sorted([f for f in os.listdir(_path) if _name+"_" in f])
         # if _name not in files: files.append(_name)
@@ -1263,7 +1409,7 @@ class ExpTable(PyoTableObject):
             self._list = values
             obj.replace(values)
         self.refreshView()
-        
+
     def getPoints(self):
         """
         Returns list of points of the current table.
@@ -1276,44 +1422,44 @@ class ExpTable(PyoTableObject):
         Opens a grapher window to control the shape of the envelope.
 
         When editing the grapher with the mouse, the new set of points
-        will be send to the object on mouse up. 
+        will be send to the object on mouse up.
 
-        Ctrl+C with focus on the grapher will copy the list of points to the 
+        Ctrl+C with focus on the grapher will copy the list of points to the
         clipboard, giving an easy way to insert the new shape in a script.
 
         :Args:
 
-            yrange : tuple, optional
+            yrange: tuple, optional
                 Set the min and max values of the Y axis of the graph.
                 Defaults to (0.0, 1.0).
-            title : string, optional
-                Title of the window. If none is provided, the name of the 
+            title: string, optional
+                Title of the window. If none is provided, the name of the
                 class is used.
-            wxnoserver : boolean, optional
-                With wxPython graphical toolkit, if True, tells the 
+            wxnoserver: boolean, optional
+                With wxPython graphical toolkit, if True, tells the
                 interpreter that there will be no server window.
-                
-        If `wxnoserver` is set to True, the interpreter will not wait for 
-        the server GUI before showing the controller window. 
+
+        If `wxnoserver` is set to True, the interpreter will not wait for
+        the server GUI before showing the controller window.
 
         """
         createGraphWindow(self, 2, self._size, yrange, title, wxnoserver)
 
     @property
     def exp(self):
-        """float. Exponent factor.""" 
+        """float. Exponent factor."""
         return self._exp
     @exp.setter
     def exp(self, x): self.setExp(x)
     @property
     def inverse(self):
-        """boolean. Inverse factor.""" 
+        """boolean. Inverse factor."""
         return self._inverse
     @inverse.setter
     def inverse(self, x): self.setInverse(x)
     @property
     def list(self):
-        """list. List of tuples indicating location and value of each points in the table.""" 
+        """list. List of tuples indicating location and value of each points in the table."""
         return self.getPoints()
     @list.setter
     def list(self, x): self.replace(x)
@@ -1322,25 +1468,26 @@ class SndTable(PyoTableObject):
     """
     Transfers data from a soundfile into a function table.
 
-    If `chnl` is None, the table will contain as many table streams as 
+    If `chnl` is None, the table will contain as many table streams as
     necessary to read all channels of the loaded sound.
 
     :Parent: :py:class:`PyoTableObject`
 
     :Args:
 
-        path : string, optional
+        path: string, optional
             Full path name of the sound. The defaults, None, creates an empty
             table.
-        chnl : int, optional
-            Channel number to read in. Available at initialization time only.
+        chnl: int, optional
+            Channel number to read in. The count starts at 0 (first channel is
+            is 0, second is 1 and so on). Available at initialization time only.
             The default (None) reads all channels.
-        start : float, optional
-            Begins reading at `start` seconds into the file. Available at 
+        start: float, optional
+            Begins reading at `start` seconds into the file. Available at
             initialization time only. Defaults to 0.
-        stop : float, optional
-            Stops reading at `stop` seconds into the file. Available at 
-            initialization time only. The default (None) means the end of 
+        stop: float, optional
+            Stops reading at `stop` seconds into the file. Available at
+            initialization time only. The default (None) means the end of
             the file.
 
     >>> s = Server().boot()
@@ -1361,21 +1508,21 @@ class SndTable(PyoTableObject):
         self._dur = []
         self._base_objs = []
         path, lmax = convertArgsToLists(path)
-        if self._path == None:
+        if self._path is None:
             self._base_objs = [SndTable_base("", 0, 0) for i in range(initchnls)]
         else:
             for p in path:
                 _size, _dur, _snd_sr, _snd_chnls, _format, _type = sndinfo(p)
-                if chnl == None:
-                    if stop == None:
-                        self._base_objs.extend([SndTable_base(p, i, start) for i in range(_snd_chnls)])
+                if chnl is None:
+                    if stop is None:
+                        self._base_objs.extend([SndTable_base(stringencode(p), i, start) for i in range(_snd_chnls)])
                     else:
-                        self._base_objs.extend([SndTable_base(p, i, start, stop) for i in range(_snd_chnls)])
+                        self._base_objs.extend([SndTable_base(stringencode(p), i, start, stop) for i in range(_snd_chnls)])
                 else:
-                    if stop == None:
-                        self._base_objs.append(SndTable_base(p, chnl, start))
+                    if stop is None:
+                        self._base_objs.append(SndTable_base(stringencode(p), chnl, start))
                     else:
-                        self._base_objs.append(SndTable_base(p, chnl, start, stop))
+                        self._base_objs.append(SndTable_base(stringencode(p), chnl, start, stop))
                 self._size.append(self._base_objs[-1].getSize())
                 self._dur.append(self._size[-1] / float(_snd_sr))
             if lmax == 1:
@@ -1385,25 +1532,25 @@ class SndTable(PyoTableObject):
     def setSound(self, path, start=0, stop=None):
         """
         Load a new sound in the table.
-        
+
         Keeps the number of channels of the sound loaded at initialization.
-        If the new sound has less channels, it will wrap around and load 
-        the same channels many times. If the new sound has more channels, 
+        If the new sound has less channels, it will wrap around and load
+        the same channels many times. If the new sound has more channels,
         the extra channels will be skipped.
-        
+
         :Args:
-        
-            path : string
+
+            path: string
                 Full path of the new sound.
-            start : float, optional
+            start: float, optional
                 Begins reading at `start` seconds into the file. Defaults to 0.
-            stop : float, optional
-                Stops reading at `stop` seconds into the file. The default (None) 
+            stop: float, optional
+                Stops reading at `stop` seconds into the file. The default (None)
                 means the end of the file.
 
         """
         self._path = path
-        if type(path) == ListType:
+        if type(path) == list:
             self._size = []
             self._dur = []
             path, lmax = convertArgsToLists(path)
@@ -1412,44 +1559,45 @@ class SndTable(PyoTableObject):
                 _size, _dur, _snd_sr, _snd_chnls, _format, _type = sndinfo(p)
                 self._size.append(_size)
                 self._dur.append(_dur)
-                if stop == None:
-                    obj.setSound(p, 0, start)
+                if stop is None:
+                    obj.setSound(stringencode(p), 0, start)
                 else:
-                    obj.setSound(p, 0, start, stop)
+                    obj.setSound(stringencode(p), 0, start, stop)
         else:
             _size, _dur, _snd_sr, _snd_chnls, _format, _type = sndinfo(path)
             self._size = _size
             self._dur = _dur
-            if stop == None:
-                [obj.setSound(path, (i%_snd_chnls), start) for i, obj in enumerate(self._base_objs)]
+            if stop is None:
+                [obj.setSound(stringencode(path), (i%_snd_chnls), start) for i, obj in enumerate(self._base_objs)]
             else:
-                [obj.setSound(path, (i%_snd_chnls), start, stop) for i, obj in enumerate(self._base_objs)]
+                [obj.setSound(stringencode(path), (i%_snd_chnls), start, stop) for i, obj in enumerate(self._base_objs)]
         self.refreshView()
+        self._resetView()
 
     def append(self, path, crossfade=0, start=0, stop=None):
         """
         Append a sound to the one already in the table with crossfade.
 
         Keeps the number of channels of the sound loaded at initialization.
-        If the new sound has less channels, it will wrap around and load 
-        the same channels many times. If the new sound has more channels, 
+        If the new sound has less channels, it will wrap around and load
+        the same channels many times. If the new sound has more channels,
         the extra channels will be skipped.
 
         :Args:
 
-            path : string
+            path: string
                 Full path of the new sound.
-            crossfade : float, optional
-                Crossfade time, in seconds, between the sound already in the table 
+            crossfade: float, optional
+                Crossfade time, in seconds, between the sound already in the table
                 and the new one. Defaults to 0.
-            start : float, optional
+            start: float, optional
                 Begins reading at `start` seconds into the file. Defaults to 0.
-            stop : float, optional
-                Stops reading at `stop` seconds into the file. The default, None, 
+            stop: float, optional
+                Stops reading at `stop` seconds into the file. The default, None,
                 means the end of the file.
 
         """
-        if type(path) == ListType:
+        if type(path) == list:
             self._size = []
             self._dur = []
             path, lmax = convertArgsToLists(path)
@@ -1458,50 +1606,50 @@ class SndTable(PyoTableObject):
                 _size, _dur, _snd_sr, _snd_chnls, _format, _type = sndinfo(p)
                 self._size.append(_size)
                 self._dur.append(_dur)
-                if stop == None:
-                    obj.append(p, crossfade, 0, start)
+                if stop is None:
+                    obj.append(stringencode(p), crossfade, 0, start)
                 else:
-                    obj.append(p, crossfade, 0, start, stop)
+                    obj.append(stringencode(p), crossfade, 0, start, stop)
         else:
             _size, _dur, _snd_sr, _snd_chnls, _format, _type = sndinfo(path)
             self._size = _size
             self._dur = _dur
-            if stop == None:
-                [obj.append(path, crossfade, (i%_snd_chnls), start) for i, obj in enumerate(self._base_objs)]
+            if stop is None:
+                [obj.append(stringencode(path), crossfade, (i%_snd_chnls), start) for i, obj in enumerate(self._base_objs)]
             else:
-                [obj.append(path, crossfade, (i%_snd_chnls), start, stop) for i, obj in enumerate(self._base_objs)]
+                [obj.append(stringencode(path), crossfade, (i%_snd_chnls), start, stop) for i, obj in enumerate(self._base_objs)]
         self.refreshView()
 
     def insert(self, path, pos=0, crossfade=0, start=0, stop=None):
         """
         Insert a sound into the one already in the table with crossfade.
 
-        Insert a sound at position `pos`, specified in seconds, 
+        Insert a sound at position `pos`, specified in seconds,
         with crossfading at the beginning and the end of the insertion.
-        
+
         Keeps the number of channels of the sound loaded at initialization.
-        If the new sound has less channels, it will wrap around and load 
-        the same channels many times. If the new sound has more channels, 
+        If the new sound has less channels, it will wrap around and load
+        the same channels many times. If the new sound has more channels,
         the extra channels will be skipped.
 
         :Args:
 
-            path : string
+            path: string
                 Full path of the new sound.
-            pos : float, optional
+            pos: float, optional
                 Position in the table, in seconds, where to insert the new sound.
                 Defaults to 0.
-            crossfade : float, optional
-                Crossfade time, in seconds, between the sound already in the table 
+            crossfade: float, optional
+                Crossfade time, in seconds, between the sound already in the table
                 and the new one. Defaults to 0.
-            start : float, optional
+            start: float, optional
                 Begins reading at `start` seconds into the file. Defaults to 0.
-            stop : float, optional
-                Stops reading at `stop` seconds into the file. The default, None, 
+            stop: float, optional
+                Stops reading at `stop` seconds into the file. The default, None,
                 means the end of the file.
 
         """
-        if type(path) == ListType:
+        if type(path) == list:
             self._size = []
             self._dur = []
             path, lmax = convertArgsToLists(path)
@@ -1510,66 +1658,81 @@ class SndTable(PyoTableObject):
                 _size, _dur, _snd_sr, _snd_chnls, _format, _type = sndinfo(p)
                 self._size.append(_size)
                 self._dur.append(_dur)
-                if stop == None:
-                    obj.insert(p, pos, crossfade, 0, start)
+                if stop is None:
+                    obj.insert(stringencode(p), pos, crossfade, 0, start)
                 else:
-                    obj.insert(p, pos, crossfade, 0, start, stop)
+                    obj.insert(stringencode(p), pos, crossfade, 0, start, stop)
         else:
             _size, _dur, _snd_sr, _snd_chnls, _format, _type = sndinfo(path)
             self._size = _size
             self._dur = _dur
-            if stop == None:
-                [obj.insert(path, pos, crossfade, (i%_snd_chnls), start) for i, obj in enumerate(self._base_objs)]
+            if stop is None:
+                [obj.insert(stringencode(path), pos, crossfade, (i%_snd_chnls), start) for i, obj in enumerate(self._base_objs)]
             else:
-                [obj.insert(path, pos, crossfade, (i%_snd_chnls), start, stop) for i, obj in enumerate(self._base_objs)]
+                [obj.insert(stringencode(path), pos, crossfade, (i%_snd_chnls), start, stop) for i, obj in enumerate(self._base_objs)]
         self.refreshView()
 
-    def getRate(self):
+    def getRate(self, all=True):
         """
-        Return the frequency in cps at which the sound will be read at its 
+        Return the frequency in cps at which the sound will be read at its
         original pitch.
-        
+
+        :Args:
+
+            all: boolean
+                If the table contains more than one sound and `all` is True,
+                returns a list of all durations. Otherwise, returns only the
+                first duration as a float.
+
         """
-        if type(self._path) == ListType:
-            return [obj.getRate() for obj in self._base_objs]
+        if type(self._path) == list:
+            _rate = [obj.getRate() for obj in self._base_objs]
         else:
-            return self._base_objs[0].getRate()
+            _rate = self._base_objs[0].getRate()
+
+        if all:
+            return _rate
+        else:
+            if type(_rate) == list:
+                return _rate[0]
+            else:
+                return _rate
 
     def getDur(self, all=True):
         """
         Return the duration of the sound in seconds.
-        
+
         :Args:
-        
-            all : boolean
+
+            all: boolean
                 If the table contains more than one sound and `all` is True,
                 returns a list of all durations. Otherwise, returns only the
                 first duration as a float.
-        
+
         """
-        if type(self._path) == ListType:
+        if type(self._path) == list:
             _dur = [1./obj.getRate() for obj in self._base_objs]
-        else:    
+        else:
             _dur = 1./self._base_objs[0].getRate()
 
         if all:
             return _dur
         else:
-            if type(_dur) == ListType:
+            if type(_dur) == list:
                 return _dur[0]
             else:
                 return _dur
 
     def setSize(self, x):
-        print "SndTable has no setSize method!"
+        print("SndTable has no setSize method!")
 
     def getSize(self, all=True):
         """
         Return the size of the table in samples.
 
         :Args:
-        
-            all : boolean
+
+            all: boolean
                 If the table contains more than one sound and `all` is True,
                 returns a list of all sizes. Otherwise, returns only the
                 first size as an int.
@@ -1583,21 +1746,48 @@ class SndTable(PyoTableObject):
         if all:
             return _size
         else:
-            if type(_size) == ListType:
+            if type(_size) == list:
                 return _size[0]
             else:
                 return _size
 
+    def getViewTable(self, size, begin=0, end=0):
+        """
+        Return a list of points (in X, Y pixel values) for each channel in the table.
+        These lists can be draw on a DC (WxPython) with a DrawLines method.
+
+        :Args:
+
+            size: tuple
+                Size, (X, Y) pixel values, of the waveform container window.
+            begin: float, optional
+                First position in the the table, in seconds, where to get samples.
+                Defaults to 0.
+            end: float, optional
+                Last position in the table, in seconds, where to get samples.
+
+                if this value is set to 0, that means the end of the table. Defaults to 0.
+
+        """
+        w, h = size
+        chnls = len(self._base_objs)
+        img = []
+        imgHeight = h // chnls
+        for i in range(chnls):
+            off = h // chnls * i
+            img.append(self._base_objs[i].getViewTable((w, imgHeight), begin, end, off))
+        return img
+
     def getEnvelope(self, points):
         """
         Return the amplitude envelope of the table.
-        
-        Return a list, of length `chnl`, of lists of length `points` filled 
+
+        Return a list, of length `chnl`, of lists of length `points` filled
         with the amplitude envelope of the table.
-        
+
         :Args:
-        
-            points : int
+
+            points: int
                 Number of points of the amplitude analysis.
 
         """
@@ -1609,69 +1799,74 @@ class SndTable(PyoTableObject):
 
         :Args:
 
-            title : string, optional
-                Window title. Defaults to "Table waveform". 
-            wxnoserver : boolean, optional
-                With wxPython graphical toolkit, if True, tells the 
+            title: string, optional
+                Window title. Defaults to "Table waveform".
+            wxnoserver: boolean, optional
+                With wxPython graphical toolkit, if True, tells the
                 interpreter that there will be no server window.
-            mouse_callback : callable
-                If provided, this function will be called with the mouse 
+            mouse_callback: callable
+                If provided, this function will be called with the mouse
                 position, inside the frame, as argument. Defaults to None.
-                
-        If `wxnoserver` is set to True, the interpreter will not wait for 
-        the server GUI before showing the controller window. 
+
+        If `wxnoserver` is set to True, the interpreter will not wait for
+        the server GUI before showing the controller window.
 
         """
         createSndViewTableWindow(self, title, wxnoserver, self.__class__.__name__, mouse_callback)
 
     def refreshView(self):
-        if self.viewFrame != None:
+        if self.viewFrame is not None:
             self.viewFrame.update()
 
+    def _resetView(self):
+        if self.viewFrame is not None:
+            if hasattr(self.viewFrame, "_setZoom"):
+                self.viewFrame._setZoom()
+
     @property
     def sound(self):
-        """string. Full path of the sound.""" 
+        """string. Full path of the sound."""
         return self._path
     @sound.setter
     def sound(self, x): self.setSound(x)
 
     @property
     def path(self):
-        """string. Full path of the sound.""" 
+        """string. Full path of the sound."""
         return self._path
     @path.setter
     def path(self, x): self.setSound(x)
 
     @property
     def chnl(self):
-        """int. Channel to read in.""" 
+        """int. Channel to read in."""
         return self._chnl
     @chnl.setter
-    def chnl(self, x): print "'chnl' attribute is read-only."
+    def chnl(self, x): print("'chnl' attribute is read-only.")
 
     @property
     def start(self):
-        """float. Start point, in seconds, to read into the file.""" 
+        """float. Start point, in seconds, to read into the file."""
         return self._start
     @start.setter
-    def start(self, x): print "'start' attribute is read-only."
+    def start(self, x): print("'start' attribute is read-only.")
 
     @property
     def stop(self):
-        """float. Stop point, in seconds, to read into the file.""" 
+        """float. Stop point, in seconds, to read into the file."""
         return self._stop
     @stop.setter
-    def stop(self, x): print "SndTable 'stop' attribute is read-only."
+    def stop(self, x): print("SndTable 'stop' attribute is read-only.")
 
     @property
     def size(self):
         return self._size
     @size.setter
-    def size(self, x): print "SndTable 'size' attribute is read-only."
+    def size(self, x): print("SndTable 'size' attribute is read-only.")
 
 class NewTable(PyoTableObject):
     """
-    Create an empty table ready for recording. 
+    Create an empty table ready for recording.
 
     See :py:class:`TableRec` to write samples in the table.
 
@@ -1679,20 +1874,20 @@ class NewTable(PyoTableObject):
 
     :Args:
 
-        length : float
+        length: float
             Length of the table in seconds.
-        chnls : int, optional
-            Number of channels that will be handled by the table. 
+        chnls: int, optional
+            Number of channels that will be handled by the table.
             Defaults to 1.
-        init : list of floats, optional
+        init: list of floats, optional
             Initial table. List of list can match the number of channels,
-            otherwise, the list will be loaded in all tablestreams. 
+            otherwise, the list will be loaded in all tablestreams.
             Defaults to None.
-        feedback : float, optional
+        feedback: float, optional
             Amount of old data to mix with a new recording. Defaults to 0.0.
 
-    .. seealso:: 
-        
+    .. seealso::
+
         :py:class:`DataTable`, :py:class:`TableRec`
 
     >>> s = Server(duplex=1).boot()
@@ -1708,15 +1903,16 @@ class NewTable(PyoTableObject):
 
     """
     def __init__(self, length, chnls=1, init=None, feedback=0.0):
+        pyoArgsAssert(self, "NILN", length, chnls, init, feedback)
         PyoTableObject.__init__(self)
         self._length = length
         self._chnls = chnls
         self._init = init
         self._feedback = feedback
-        if init == None:
+        if init is None:
             self._base_objs = [NewTable_base(length, None, feedback) for i in range(chnls)]
         else:
-            if type(init[0]) != ListType: 
+            if type(init[0]) != list:
                 init = [init]
             self._base_objs = [NewTable_base(length, wrap(init,i), feedback) for i in range(chnls)]
         self._size = self._base_objs[0].getSize()
@@ -1724,17 +1920,18 @@ class NewTable(PyoTableObject):
     def replace(self, x):
         """
         Replaces the actual table.
-        
+
         :Args:
-        
-            x : list of floats
+
+            x: list of floats
                 New table. Must be of the same size as the actual table.
 
-                List of list can match the number of channels, otherwise, 
+                List of list can match the number of channels, otherwise,
                 the list will be loaded in all tablestreams.
 
         """
-        if type(x[0]) != ListType: 
+        pyoArgsAssert(self, "l", x)
+        if type(x[0]) != list:
             x = [x]
         [obj.setTable(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
         self.refreshView()
@@ -1745,84 +1942,115 @@ class NewTable(PyoTableObject):
 
         :Args:
 
-            x : float
+            x: float
                 New `feedback` value.
 
         """
+        pyoArgsAssert(self, "N", x)
         self._feedback = x
         [obj.setFeedback(x) for i, obj in enumerate(self._base_objs)]
 
     def getLength(self):
         """
         Returns the length of the table in seconds.
-        
+
         """
         return self._base_objs[0].getLength()
 
-    def getDur(self):
+    def getDur(self, all=True):
         """
         Returns the length of the table in seconds.
-        
+
+        The `all` argument is there for compatibility with SndTable but
+        is not used for now.
+
         """
         return self._base_objs[0].getLength()
-        
+
     def getRate(self):
         """
-        Returns the frequency (cycle per second) to give to an 
+        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()
 
+    def getViewTable(self, size, begin=0, end=0):
+        """
+        Return a list of points (in X, Y pixel values) for each channel in the table.
+        These lists can be draw on a DC (WxPython) with a DrawLines method.
+
+        :Args:
+
+            size: tuple
+                Size, (X, Y) pixel values, of the waveform container window.
+            begin: float, optional
+                First position in the the table, in seconds, where to get samples.
+                Defaults to 0.
+            end: float, optional
+                Last position in the table, in seconds, where to get samples.
+
+                if this value is set to 0, that means the end of the table. Defaults to 0.
+
+        """
+        w, h = size
+        chnls = len(self._base_objs)
+        img = []
+        imgHeight = h // chnls
+        for i in range(chnls):
+            off = h // chnls * i
+            img.append(self._base_objs[i].getViewTable((w, imgHeight), begin, end, off))
+        return img
+
     def view(self, title="Sound waveform", wxnoserver=False, mouse_callback=None):
         """
         Opens a window showing the contents of the table.
 
         :Args:
 
-            title : string, optional
-                Window title. Defaults to "Table waveform". 
-            wxnoserver : boolean, optional
-                With wxPython graphical toolkit, if True, tells the 
+            title: string, optional
+                Window title. Defaults to "Table waveform".
+            wxnoserver: boolean, optional
+                With wxPython graphical toolkit, if True, tells the
                 interpreter that there will be no server window.
-            mouse_callback : callable
-                If provided, this function will be called with the mouse 
+            mouse_callback: callable
+                If provided, this function will be called with the mouse
                 position, inside the frame, as argument. Defaults to None.
-                
-        If `wxnoserver` is set to True, the interpreter will not wait for 
-        the server GUI before showing the controller window. 
+
+        If `wxnoserver` is set to True, the interpreter will not wait for
+        the server GUI before showing the controller window.
 
         """
         createSndViewTableWindow(self, title, wxnoserver, self.__class__.__name__, mouse_callback)
 
     def refreshView(self):
-        if self.viewFrame != None:
+        if self.viewFrame is not None:
             self.viewFrame.update()
 
     @property
     def length(self):
-        """float. Length of the table in seconds.""" 
+        """float. Length of the table in seconds."""
         return self._length
     @length.setter
-    def length(self, x): print "'length' attribute is read-only."
+    def length(self, x): print("'length' attribute is read-only.")
 
     @property
     def chnls(self):
-        """int. Number of channels that will be handled by the table.""" 
+        """int. Number of channels that will be handled by the table."""
         return self._chnls
     @chnls.setter
-    def chnls(self, x): print "'chnls' attribute is read-only."
+    def chnls(self, x): print("'chnls' attribute is read-only.")
 
     @property
     def init(self):
-        """list of floats. Initial table.""" 
+        """list of floats. Initial table."""
         return self._init
     @init.setter
-    def init(self, x): print "'init' attribute is read-only."
+    def init(self, x): print("'init' attribute is read-only.")
 
     @property
     def feedback(self):
-        """float. Amount of old data to mix with a new recording.""" 
+        """float. Amount of old data to mix with a new recording."""
         return self._feedback
     @feedback.setter
     def feedback(self, x): self.setFeedback(x)
@@ -1831,7 +2059,7 @@ class NewTable(PyoTableObject):
     def size(self):
         return self._size
     @size.setter
-    def size(self, x): print "NewTable 'size' attribute is read-only."
+    def size(self, x): print("NewTable 'size' attribute is read-only.")
 
 class DataTable(PyoTableObject):
     """
@@ -1843,17 +2071,17 @@ class DataTable(PyoTableObject):
 
     :Args:
 
-        size : int
+        size: int
             Size of the table in samples.
-        chnls : int, optional
-            Number of channels that will be handled by the table. 
+        chnls: int, optional
+            Number of channels that will be handled by the table.
             Defaults to 1.
-        init : list of floats, optional
+        init: list of floats, optional
             Initial table. List of list can match the number of channels,
-            otherwise, the list will be loaded in all tablestreams. 
+            otherwise, the list will be loaded in all tablestreams.
+
+    .. seealso::
 
-    .. seealso:: 
-        
         :py:class:`NewTable`, :py:class:`TableRec`
 
     >>> s = Server().boot()
@@ -1867,13 +2095,14 @@ class DataTable(PyoTableObject):
 
     """
     def __init__(self, size, chnls=1, init=None):
+        pyoArgsAssert(self, "IIL", size, chnls, init)
         PyoTableObject.__init__(self, size)
         self._chnls = chnls
         self._init = init
-        if init == None:
+        if init is None:
             self._base_objs = [DataTable_base(size) for i in range(chnls)]
         else:
-            if type(init[0]) != ListType:
+            if type(init[0]) != list:
                 init = [init]
             self._base_objs = [DataTable_base(size, wrap(init,i)) for i in range(chnls)]
 
@@ -1883,68 +2112,533 @@ class DataTable(PyoTableObject):
 
         :Args:
 
-            x : list of floats
+            x: list of floats
                 New table. Must be of the same size as the actual table.
-                
-                List of list can match the number of channels, otherwise, 
+
+                List of list can match the number of channels, otherwise,
                 the list will be loaded in all tablestreams.
 
         """
-        if type(x[0]) != ListType: 
+        pyoArgsAssert(self, "l", x)
+        if type(x[0]) != list:
             x = [x]
         [obj.setTable(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
         self.refreshView()
 
     def getRate(self):
         """
-        Returns the frequency (cycle per second) to give to an 
+        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()
 
+    def _get_current_data(self):
+        # internal that returns the data to draw in a DataTableGrapher.
+        return self.getTable()
+
     def graph(self, yrange=(0.0, 1.0), title=None, wxnoserver=False):
         """
         Opens a multislider window to control the data values.
 
         When editing the grapher with the mouse, the new values are
-        sent to the object to replace the table content. 
+        sent to the object to replace the table content.
 
         :Args:
 
-            yrange : tuple, optional
+            yrange: tuple, optional
                 Set the min and max values of the Y axis of the multislider.
                 Defaults to (0.0, 1.0).
-            title : string, optional
-                Title of the window. If none is provided, the name of the 
+            title: string, optional
+                Title of the window. If none is provided, the name of the
                 class is used.
-            wxnoserver : boolean, optional
-                With wxPython graphical toolkit, if True, tells the 
+            wxnoserver: boolean, optional
+                With wxPython graphical toolkit, if True, tells the
                 interpreter that there will be no server window.
-                
-        If `wxnoserver` is set to True, the interpreter will not wait for 
-        the server GUI before showing the controller window. 
+
+        If `wxnoserver` is set to True, the interpreter will not wait for
+        the server GUI before showing the controller window.
 
         """
         createDataGraphWindow(self, yrange, title, wxnoserver)
 
     @property
     def size(self):
-        """int. Length of the table in samples.""" 
+        """int. Length of the table in samples."""
         return self._size
     @size.setter
-    def size(self, x): print "DataTable 'size' attribute is read-only."
+    def size(self, x): print("DataTable 'size' attribute is read-only.")
 
     @property
     def chnls(self):
-        """int. Number of channels that will be handled by the table.""" 
+        """int. Number of channels that will be handled by the table."""
         return self._chnls
     @chnls.setter
-    def chnls(self, x): print "'chnls' attribute is read-only."
+    def chnls(self, x): print("'chnls' attribute is read-only.")
 
     @property
     def init(self):
-        """list of floats. Initial table.""" 
+        """list of floats. Initial table."""
         return self._init
     @init.setter
-    def init(self, x): print "'init' attribute is read-only."
+    def init(self, x): print("'init' attribute is read-only.")
+
+class AtanTable(PyoTableObject):
+    """
+    Generates an arctangent transfert function.
+
+    This table allow the creation the classic arctangent transfert functions,
+    useful in distortion design. See Lookup object for a simple table lookup
+    process.
+
+    :Parent: :py:class:`PyoTableObject`
+
+    :Args:
+
+        slope: float, optional
+            Slope of the arctangent function, between 0 and 1. Defaults to 0.5.
+        size: int, optional
+            Table size in samples. Defaults to 8192.
+
+    >>> import math
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> t = AtanTable(slope=0.8)
+    >>> a = Sine(freq=[149,150])
+    >>> l = Lookup(table=t, index=a, mul=0.3).out()
+
+    """
+    def __init__(self, slope=0.5, size=8192):
+        pyoArgsAssert(self, "NI", slope, size)
+        PyoTableObject.__init__(self, size)
+        self._slope = slope
+        self._base_objs = [AtanTable_base(slope, size)]
+
+    def setSlope(self, x):
+        """
+        Change the slope of the arctangent function. This will redraw the table.
+
+        :Args:
+
+            x: float
+                New slope between 0 and 1.
+
+        """
+        pyoArgsAssert(self, "N", x)
+        self._slope = x
+        [obj.setSlope(x) for obj in self._base_objs]
+        self.refreshView()
+
+    @property
+    def slope(self):
+        """float. slope of the arctangent function."""
+        return self._slope
+    @slope.setter
+    def slope(self, x): self.setSlope(x)
+
+class PartialTable(PyoTableObject):
+    """
+    Inharmonic waveform generator.
+
+    Generates waveforms made of inharmonic components. Partials are
+    given as a list of 2-values tuple, where the first one is the
+    partial number (can be float) and the second one is the strength
+    of the partial.
+
+    The object uses the first two decimal values of each partial to
+    compute a higher harmonic at a multiple of 100 (so each component
+    is in reality truly harmonic). If the oscillator has a frequency
+    divided by 100, the real desired partials will be restituted.
+
+    The list:
+
+    [(1, 1), (1.1, 0.7), (1.15, 0.5)] will draw a table with:
+
+    harmonic 100: amplitude = 1
+    harmonic 110: amplitude = 0.7
+    harmonic 115: amplitude = 0.5
+
+    To listen to a signal composed of 200, 220 and 230 Hz, one should
+    declared an oscillator like this (frequency of 200Hz divided by 100):
+
+    a = Osc(t, freq=2, mul=0.5).out()
+
+    :Parent: :py:class:`PyoTableObject`
+
+    :Args:
+
+        list: list of tuple, optional
+            List of 2-values tuples. First value is the partial number (float up
+            to two decimal values) and second value is its amplitude (relative to
+            the other harmonics). Defaults to [(1,1), (1.33,0.5),(1.67,0.3)].
+        size: int, optional
+            Table size in samples. Because computed harmonics are very high in
+            frequency, the table size must be bigger than a classic HarmTable.
+            Defaults to 65536.
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> t = PartialTable([(1,1), (2.37, 0.5), (4.55, 0.3)]).normalize()
+    >>> # Play with fundamentals 199 and 200 Hz
+    >>> a = Osc(table=t, freq=[1.99,2], mul=.2).out()
+
+    """
+    def __init__(self, list=[(1,1), (1.33,0.5),(1.67,0.3)], size=65536):
+        pyoArgsAssert(self, "lI", list, size)
+        PyoTableObject.__init__(self, size)
+        self._list = list
+        self._par_table = HarmTable(self._create_list(), size)
+        self._base_objs = self._par_table.getBaseObjects()
+        self.normalize()
+
+    def _create_list(self):
+        # internal method used to compute the harmonics's weight
+        hrms = [(int(x*100.), y) for x, y in self._list]
+        l = []
+        ind = 0
+        for i in range(10000):
+            if i == hrms[ind][0]:
+                l.append(hrms[ind][1])
+                ind += 1
+                if ind == len(hrms):
+                    break
+            else:
+                l.append(0)
+        return l
+
+    def replace(self, list):
+        """
+        Redraw the waveform according to a new set of harmonics
+        relative strengths.
+
+        :Args:
+
+            list: list of tuples
+                Each tuple contains the partial number, as a float,
+                and its strength.
+
+        """
+        pyoArgsAssert(self, "l", list)
+        self._list = list
+        [obj.replace(self._create_list()) for obj in self._base_objs]
+        self.normalize()
+        self.refreshView()
+
+    @property
+    def list(self):
+        """list. List of partial numbers and strength."""
+        return self._list
+    @list.setter
+    def list(self, x): self.replace(x)
+
+class PadSynthTable(PyoTableObject):
+    """
+    Generates wavetable with the PadSynth algorithm from Nasca Octavian Paul.
+
+    This object generates a wavetable with the PadSynth algorithm describe here:
+
+    http://zynaddsubfx.sourceforge.net/doc/PADsynth/PADsynth.htm
+
+    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.
+
+    To get the desired pitch from the table, the playback speed must be
+    `sr / table size`. This speed can be transposed to obtain different
+    pitches from a single wavetable.
+
+    :Parent: :py:class:`PyoTableObject`
+
+    :Args:
+
+        basefreq: float, optional
+            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
+            The spreading factor for the harmonics. Each harmonic real frequency
+            is computed as `basefreq * pow(n, spread)` where `n` is the harmonic
+            order. Defaults to 1.
+        bw: float, optional
+            The bandwidth of the first harmonic in cents. The bandwidth allows
+            to control the harmonic profile using a gaussian distribution (bell
+            shape). Defaults to 50.
+        bwscl: float, optional
+            The bandswidth scale specifies how much the bandwidth of the
+            harmonic increase according to its frequency. Defaults to 1.
+        nharms: int, optional
+            The number of harmonics in the generated wavetable. Higher
+            numbers of harmonics take more time to generate the wavetable.
+            Defaults to 64.
+        damp: float, optional
+            The amplitude damping factor specifies how much the amplitude
+            of the harmonic decrease according to its order. It uses a
+            simple power serie, `amp = pow(damp, n)` where `n` is the
+            harmonic order. Defaults to 0.7.
+        size: int, optional
+            Table size in samples. Must be a power-of-two, usually a big one!
+            Defaults to 262144.
+
+    .. note::
+
+        Many thanks to Nasca Octavian Paul for making this beautiful algorithm
+        and releasing it under Public Domain.
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> f = s.getSamplingRate() / 262144
+    >>> t = PadSynthTable(basefreq=midiToHz(48), spread=1.205, bw=10, bwscl=1.5)
+    >>> a = Osc(table=t, freq=f, phase=[0, 0.5], mul=0.5).out()
+
+    """
+    def __init__(self, basefreq=440, spread=1, bw=50, bwscl=1, nharms=64, damp=0.7, size=262144):
+        pyoArgsAssert(self, "NNNNINI", basefreq, spread, bw, bwscl, nharms, damp, size)
+        PyoTableObject.__init__(self, size)
+        self._basefreq = basefreq
+        self._spread = spread
+        self._bw = bw
+        self._bwscl = bwscl
+        self._nharms = nharms
+        self._damp = damp
+        self._base_objs = [PadSynthTable_base(basefreq, spread, bw, bwscl, nharms, damp, size)]
+
+    def setBaseFreq(self, x, generate=True):
+        """
+        Change the base frequency of the algorithm.
+
+        :Args:
+
+            x: float
+                New base frequency in Hz.
+            generate: boolean, optional
+                If True, a new table will be computed with changed value.
+
+        """
+        pyoArgsAssert(self, "NB", x, generate)
+        self._basefreq = x
+        [obj.setBaseFreq(x, generate) for obj in self._base_objs]
+        if generate:
+            self.refreshView()
+
+    def setSpread(self, x, generate=True):
+        """
+        Change the frequency spreading factor of the algorithm.
+
+        :Args:
+
+            x: float
+                New spread factor.
+            generate: boolean, optional
+                If True, a new table will be computed with changed value.
+
+        """
+        pyoArgsAssert(self, "NB", x, generate)
+        self._spread = x
+        [obj.setSpread(x, generate) for obj in self._base_objs]
+        if generate:
+            self.refreshView()
+
+    def setBw(self, x, generate=True):
+        """
+        Change the bandwidth of the first harmonic.
+
+        :Args:
+
+            x: float
+                New bandwidth in cents.
+            generate: boolean, optional
+                If True, a new table will be computed with changed value.
+
+        """
+        pyoArgsAssert(self, "NB", x, generate)
+        self._bw = x
+        [obj.setBw(x, generate) for obj in self._base_objs]
+        if generate:
+            self.refreshView()
+
+    def setBwScl(self, x, generate=True):
+        """
+        Change the bandwidth scaling factor.
+
+        :Args:
+
+            x: float
+                New bandwidth scaling factor.
+            generate: boolean, optional
+                If True, a new table will be computed with changed value.
+
+        """
+        pyoArgsAssert(self, "NB", x, generate)
+        self._bwscl = x
+        [obj.setBwScl(x, generate) for obj in self._base_objs]
+        if generate:
+            self.refreshView()
+
+    def setNharms(self, x, generate=True):
+        """
+        Change the number of harmonics.
+
+        :Args:
+
+            x: int
+                New number of harmonics.
+            generate: boolean, optional
+                If True, a new table will be computed with changed value.
+
+        """
+        pyoArgsAssert(self, "IB", x, generate)
+        self._nharms = x
+        [obj.setNharms(x, generate) for obj in self._base_objs]
+        if generate:
+            self.refreshView()
+
+    def setDamp(self, x, generate=True):
+        """
+        Change the amplitude damping factor.
+
+        :Args:
+
+            x: float
+                New amplitude damping factor.
+            generate: boolean, optional
+                If True, a new table will be computed with changed value.
+
+        """
+        pyoArgsAssert(self, "NB", x, generate)
+        self._damp = x
+        [obj.setDamp(x, generate) for obj in self._base_objs]
+        if generate:
+            self.refreshView()
+
+    def setSize(self, size, generate=True):
+        """
+        Change the size of the table.
+
+        This will erase the previously drawn waveform.
+
+        :Args:
+
+            size: int
+                New table size in samples. Must be a power-of-two.
+            generate: boolean, optional
+                If True, a new table will be computed with changed value.
+
+        """
+        pyoArgsAssert(self, "IB", size, generate)
+        self._size = size
+        [obj.setSize(size, generate) for obj in self._base_objs]
+        if generate:
+            self.refreshView()
+
+    @property
+    def basefreq(self):
+        """float. Base frequency in Hz."""
+        return self._basefreq
+    @basefreq.setter
+    def basefreq(self, x): self.setBaseFreq(x)
+
+    @property
+    def spread(self):
+        """float. Frequency spreading factor."""
+        return self._spread
+    @spread.setter
+    def spread(self, x): self.setSpread(x)
+
+    @property
+    def bw(self):
+        """float. Bandwitdh of the first harmonic in cents."""
+        return self._bw
+    @bw.setter
+    def bw(self, x): self.setBw(x)
+
+    @property
+    def bwscl(self):
+        """float. Bandwitdh scaling factor."""
+        return self._bwscl
+    @bwscl.setter
+    def bwscl(self, x): self.setBwScl(x)
+
+    @property
+    def nharms(self):
+        """int. Number of harmonics."""
+        return self._nharms
+    @nharms.setter
+    def nharms(self, x): self.setNharms(x)
+
+    @property
+    def damp(self):
+        """float. Amplitude damping factor."""
+        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 dac00f0..f9508ca 100644
--- a/pyolib/triggers.py
+++ b/pyolib/triggers.py
@@ -1,37 +1,38 @@
+from __future__ import division
+from __future__ import print_function
+from __future__ import absolute_import
 """
 Set of objects to manage triggers streams.
 
 A trigger is an audio signal with a value of 1 surrounded by 0s.
 
-TrigXXX objects use this kind of signal to generate different 
+TrigXXX objects use this kind of signal to generate different
 processes with sampling rate time accuracy.
 
 """
-
 """
-Copyright 2010 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+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 sys
-from _core import *
-from _maps import *
-from _widgets import createGraphWindow
-from types import SliceType, ListType, TupleType
+from ._core import *
+from ._maps import *
+from ._widgets import createGraphWindow
+import weakref
 
 class Trig(PyoObject):
     """
@@ -60,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)
@@ -82,19 +84,19 @@ class Metro(PyoObject):
 
     A trigger is an audio signal with a value of 1 surrounded by 0s.
 
-    The play() method starts the metro and is not called at the object 
+    The play() method starts the metro and is not called at the object
     creation time.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        time : float or PyoObject, optional
+        time: float or PyoObject, optional
             Time between each trigger in seconds. Defaults to 1.
-        poly : int, optional
-            Metronome polyphony. Denotes how many independent streams are 
+        poly: int, optional
+            Metronome polyphony. Denotes how many independent streams are
             generated by the metronome, allowing overlapping processes.
-            
+
             Available only at initialization. Defaults to 1.
 
     .. note::
@@ -113,29 +115,31 @@ class Metro(PyoObject):
 
     """
     def __init__(self, time=1, poly=1):
+        pyoArgsAssert(self, "OI", time, poly)
         PyoObject.__init__(self)
         self._time = time
         self._poly = poly
         time, lmax = convertArgsToLists(time)
-        self._base_objs = [Metro_base(wrap(time,i)*poly, (float(j)/poly)) for i in range(lmax) for j in range(poly)]
+        self._base_objs = [Metro_base(wrap(time,i)*poly, (float(j) / poly)) for i in range(lmax) for j in range(poly)]
 
     def setTime(self, x):
         """
         Replace the `time` attribute.
-        
+
         :Args:
-        
-            x : float or PyoObject
+
+            x: float or PyoObject
                 New `time` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._time = x
         x, lmax = convertArgsToLists(x)
         [obj.setTime(wrap(x,i)*self._poly) for i, obj in enumerate(self._base_objs)]
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
-        
+
     def setMul(self, x):
         pass
 
@@ -151,10 +155,10 @@ class Metro(PyoObject):
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMap(0.001, 1., 'log', 'time', self._time)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
-         
+
     @property
     def time(self):
-        """float or PyoObject. Time between each trigger in seconds.""" 
+        """float or PyoObject. Time between each trigger in seconds."""
         return self._time
     @time.setter
     def time(self, x): self.setTime(x)
@@ -165,22 +169,29 @@ class Seq(PyoObject):
 
     A trigger is an audio signal with a value of 1 surrounded by 0s.
 
-    The play() method starts the sequence and is not called at the object 
+    The play() method starts the sequence and is not called at the object
     creation time.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        time : float or PyoObject, optional
+        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
+        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.
+        speed: float or PyoObject, optional
+            Continuous speed factor. This factor multiplies the speed of the
+            internal timer continuously. It can be useful to create time
+            deceleration or acceleration. Defaults to 1.
 
     .. note::
 
@@ -197,21 +208,21 @@ class Seq(PyoObject):
     >>> a = SineLoop(tr, feedback=0.07, mul=amp).out()
 
     """
-    def __init__(self, time=1, seq=[1], poly=1):
+    def __init__(self, time=1, seq=[1], poly=1, onlyonce=False, speed=1):
+        pyoArgsAssert(self, "OlIBO", time, seq, poly, onlyonce, speed)
         PyoObject.__init__(self)
-        if type(seq) != ListType:
-            print >> sys.stderr, 'TypeError: "seq" argument of %s must be a list.\n' % self.__class__.__name__
-            exit()
         self._time = time
         self._seq = seq
         self._poly = poly
-        time, lmax = convertArgsToLists(time)
-        if type(seq[0]) != ListType:
-            self._base_players = [Seqer_base(wrap(time,i), seq, poly) for i in range(lmax)]
+        self._onlyonce = onlyonce
+        self._speed = speed
+        time, speed, lmax = convertArgsToLists(time, speed)
+        if type(seq[0]) != list:
+            self._base_players = [Seqer_base(wrap(time,i), seq, poly, onlyonce, wrap(speed,i)) 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, wrap(speed,i)) 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):
@@ -220,30 +231,61 @@ class Seq(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `time` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._time = x
         x, lmax = convertArgsToLists(x)
         [obj.setTime(wrap(x,i)) for i, obj in enumerate(self._base_players)]
 
+    def setSpeed(self, x):
+        """
+        Replace the `speed` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                New `speed` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._speed = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setSpeed(wrap(x,i)) for i, obj in enumerate(self._base_players)]
+
     def setSeq(self, x):
         """
         Replace the `seq` attribute.
 
         :Args:
 
-            x : list of ints
+            x: list of floats
                 New `seq` attribute.
 
         """
+        pyoArgsAssert(self, "l", x)
         self._seq = x
-        if type(x[0]) != ListType:
+        if type(x[0]) != list:
             [obj.setSeq(x) for i, obj in enumerate(self._base_players)]
         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)
 
@@ -265,18 +307,32 @@ class Seq(PyoObject):
 
     @property
     def time(self):
-        """float or PyoObject. Base time between each trigger in seconds.""" 
+        """float or PyoObject. Base time between each trigger in seconds."""
         return self._time
     @time.setter
     def time(self, x): self.setTime(x)
 
     @property
+    def speed(self):
+        """float or PyoObject. Continuous speed factor."""
+        return self._speed
+    @speed.setter
+    def speed(self, x): self.setSpeed(x)
+
+    @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.
@@ -285,19 +341,19 @@ class Cloud(PyoObject):
 
     A trigger is an audio signal with a value of 1 surrounded by 0s.
 
-    The play() method starts the Cloud and is not called at the object 
+    The play() method starts the Cloud and is not called at the object
     creation time.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        density : float or PyoObject, optional
+        density: float or PyoObject, optional
             Average number of triggers per second. Defaults to 10.
-        poly : int, optional
-            Cloud polyphony. Denotes how many independent streams are 
+        poly: int, optional
+            Cloud polyphony. Denotes how many independent streams are
             generated by the object, allowing overlapping processes.
-            
+
             Available only at initialization. Defaults to 1.
 
     .. note::
@@ -316,6 +372,7 @@ class Cloud(PyoObject):
 
     """
     def __init__(self, density=10, poly=1):
+        pyoArgsAssert(self, "OI", density, poly)
         PyoObject.__init__(self)
         self._density = density
         self._poly = poly
@@ -326,20 +383,21 @@ class Cloud(PyoObject):
     def setDensity(self, x):
         """
         Replace the `density` attribute.
-        
+
         :Args:
-        
-            x : float or PyoObject
+
+            x: float or PyoObject
                 New `density` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._density = x
         x, lmax = convertArgsToLists(x)
         [obj.setDensity(wrap(x,i)) for i, obj in enumerate(self._base_players)]
-       
+
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
-        
+
     def setMul(self, x):
         pass
 
@@ -355,10 +413,10 @@ class Cloud(PyoObject):
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMap(0, 100., 'lin', 'density', self._density)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
-         
+
     @property
     def density(self):
-        """float or PyoObject. Average density of triggers generation.""" 
+        """float or PyoObject. Average density of triggers generation."""
         return self._density
     @density.setter
     def density(self, x): self.setDensity(x)
@@ -366,7 +424,7 @@ class Cloud(PyoObject):
 class Beat(PyoObject):
     """
     Generates algorithmic trigger patterns.
-    
+
     A trigger is an audio signal with a value of 1 surrounded by 0s.
 
     Beat generates measures of length `taps` and uses weight parameters
@@ -375,46 +433,49 @@ class Beat(PyoObject):
 
     User can store the current pattern in one of the 32 preset slots with
     the store() method and recall it later with recall(x).
-    
+
     A preset is a list where the first value is the number of beats in the
     measure, followed by 1s and 0s. For a 4/4 measure with only down beats:
-    
-    [16, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0] 
-    
-    The play() method starts the Beat and is not called at the object 
+
+    [16, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0]
+
+    The play() method starts the Beat and is not called at the object
     creation time.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        time : float or PyoObject, optional
+        time: float or PyoObject, optional
             Time, in seconds, between each beat of the pattern. Defaults to 0.125.
-        taps : int, optional
+        taps: int, optional
             Number of beats in the generated pattern, max = 64. Defaults to 16.
-        w1 : int {0 -> 100}, optional
+        w1: int {0 -> 100}, optional
             Probability for down beats. Defaults to 80.
-        w2 : int {0 -> 100}, optional
+        w2: int {0 -> 100}, optional
             Probability for up beats. Defaults to 50.
-        w3 : int {0 -> 100}, optional
+        w3: int {0 -> 100}, optional
             Probability for the weakest beats. Defaults to 30.
-        poly : int, optional
-            Beat polyphony. Denotes how many independent streams are 
+        poly: int, optional
+            Beat polyphony. Denotes how many independent streams are
             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::
 
         Beat outputs many signals identified with a string between brackets:
-        
-        obj['tap'] returns audio stream of the current tap of the measure.
-        obj['amp'] returns audio stream of the current beat amplitude.
-        obj['dur'] returns audio stream of the current beat duration in seconds.
-        obj['end'] returns audio stream with a trigger just before the end of the measure.
-        
+
+        |  obj['tap'] returns audio stream of the current tap of the measure.
+        |  obj['amp'] returns audio stream of the current beat amplitude.
+        |  obj['dur'] returns audio stream of the current beat duration in seconds.
+        |  obj['end'] returns audio stream with a trigger just before the end of the measure.
+
         obj without brackets returns the generated trigger stream of the measure.
-         
+
         The out() method is bypassed. Beat's signal can not be sent to audio outs.
 
         Beat has no `mul` and `add` attributes.
@@ -429,7 +490,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):
+    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 = []
@@ -441,8 +503,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)]
@@ -462,12 +525,12 @@ class Beat(PyoObject):
         if i == 'end':
             self._end_dummy.append(Dummy([obj for obj in self._end_objs]))
             return self._end_dummy[-1]
-        if type(i) == SliceType:
+        if type(i) == slice:
             return self._base_objs[i]
         if i < len(self._base_objs):
             return self._base_objs[i]
         else:
-            print "'i' too large!"         
+            print("'i' too large!")
 
     def get(self, identifier="amp", all=False):
         """
@@ -480,14 +543,14 @@ class Beat(PyoObject):
 
         :Args:
 
-            identifier : string {"tap", "amp", "dur"}
+            identifier: string {"tap", "amp", "dur"}
                 Address string parameter identifying audio stream.
                 Defaults to "amp".
-            all : boolean, optional
+            all: boolean, optional
                 If True, the first value of each object's stream
-                will be returned as a list. 
-                
-                If False, only the value of the first object's 
+                will be returned as a list.
+
+                If False, only the value of the first object's
                 stream will be returned as a float.
 
         """
@@ -496,12 +559,26 @@ class Beat(PyoObject):
         else:
             return [obj._getStream().getValue() for obj in self.__getitem__(identifier).getBaseObjects()]
 
-    def new(self):
+    def reset(self):
+        """
+        Reset internal counters to initialization values.
+
+        """
+        [obj.reset() for obj in self._base_players]
+
+    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):
         """
@@ -513,13 +590,14 @@ class Beat(PyoObject):
     def store(self, x):
         """
         Store the current pattern in memory `x`.
-        
+
         :Args:
-        
-            x : int
+
+            x: int
                 Memory number. 0 <= x < 32.
 
         """
+        pyoArgsAssert(self, "I", x)
         [obj.store(x) for i, obj in enumerate(self._base_players)]
 
     def recall(self, x):
@@ -528,12 +606,13 @@ class Beat(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 Memory number. 0 <= x < 32.
 
         """
+        pyoArgsAssert(self, "I", x)
         [obj.recall(x) for i, obj in enumerate(self._base_players)]
-        
+
     def getPresets(self):
         """
         Returns the list of stored presets.
@@ -541,22 +620,23 @@ class Beat(PyoObject):
         """
         if len(self._base_players) == 1:
             return self._base_players[0].getPresets()
-        else:    
+        else:
             return [obj.getPresets() for obj in self._base_players]
 
     def setPresets(self, x):
         """
         Store a list presets.
-        
+
         :Args:
-        
-            x : list
+
+            x: list
                 List of presets.
 
         """
+        pyoArgsAssert(self, "l", x)
         if len(self._base_players) == 1:
             return self._base_players[0].setPresets(x)
-        else:    
+        else:
             return [obj.setPresets(x[i]) for i, obj in enumerate(self._base_players)]
 
     def setTime(self, x):
@@ -565,10 +645,11 @@ class Beat(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `time` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._time = x
         x, lmax = convertArgsToLists(x)
         [obj.setTime(wrap(x,i)) for i, obj in enumerate(self._base_players)]
@@ -579,10 +660,11 @@ class Beat(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 New `taps` attribute.
 
         """
+        pyoArgsAssert(self, "I", x)
         self._taps = x
         x, lmax = convertArgsToLists(x)
         [obj.setTaps(wrap(x,i)) for i, obj in enumerate(self._base_players)]
@@ -593,10 +675,11 @@ class Beat(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 New `w1` attribute.
 
         """
+        pyoArgsAssert(self, "n", x)
         self.setWeights(w1=x)
 
     def setW2(self, x):
@@ -605,10 +688,11 @@ class Beat(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 New `w2` attribute.
 
         """
+        pyoArgsAssert(self, "n", x)
         self.setWeights(w2=x)
 
     def setW3(self, x):
@@ -617,34 +701,49 @@ class Beat(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 New `w3` attribute.
 
         """
+        pyoArgsAssert(self, "n", x)
         self.setWeights(w3=x)
-        
+
     def setWeights(self, w1=None, w2=None, w3=None):
         """
         Replace the weight attributes.
-        
+
         Arguments set to `None` remain unchanged.
 
         :Args:
 
-            w1 : int, optional
+            w1: int, optional
                 New `w1` attribute. Defaults to None.
-            w2 : int, optional
+            w2: int, optional
                 New `w2` attribute. Defaults to None.
-            w3 : int, optional
+            w3: int, optional
                 New `w3` attribute. Defaults to None.
 
         """
-        if w1 != None: self._w1 = w1
-        if w2 != None: self._w2 = w2
-        if w3 != None: self._w3 = w3
+        if w1 is not None: self._w1 = w1
+        if w2 is not None: self._w2 = w2
+        if w3 is not None: self._w3 = w3
         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)]
@@ -676,64 +775,75 @@ class Beat(PyoObject):
         pass
 
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
-        self._map_list = [SLMap(0.001, 1., 'lin', 'time', self._time)]
+        self._map_list = [SLMap(0.001, 1., 'lin', 'time', self._time),
+                          SLMap(2, 64, 'lin', 'taps', self._taps, res="int", dataOnly=True),
+                          SLMap(0, 100, 'lin', 'w1', self._w1, res="int", dataOnly=True),
+                          SLMap(0, 100, 'lin', 'w2', self._w2, res="int", dataOnly=True),
+                          SLMap(0, 100, 'lin', 'w3', self._w3, res="int", dataOnly=True)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def time(self):
-        """float or PyoObject. Time, in seconds, between each beat.""" 
+        """float or PyoObject. Time, in seconds, between each beat."""
         return self._time
     @time.setter
     def time(self, x): self.setTime(x)
 
     @property
     def taps(self):
-        """int. Number of beats in the generated pattern.""" 
+        """int. Number of beats in the generated pattern."""
         return self._taps
     @taps.setter
     def taps(self, x): self.setTaps(x)
 
     @property
     def w1(self):
-        """int. Probability for down beats.""" 
+        """int. Probability for down beats."""
         return self._w1
     @w1.setter
     def w1(self, x): self.setW1(x)
 
     @property
     def w2(self):
-        """int. Probability for up beats.""" 
+        """int. Probability for up beats."""
         return self._w2
     @w2.setter
     def w2(self, x): self.setW2(x)
 
     @property
     def w3(self):
-        """int. Probability for other beats.""" 
+        """int. Probability for other beats."""
         return self._w3
     @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.
 
-    TrigRandInt generates a pseudo-random number integer number between 
-    0 and `max` values each time it receives a trigger in its `input` 
+    TrigRandInt generates a pseudo-random number integer number between
+    0 and `max` values each time it receives a trigger in its `input`
     parameter. The value is kept until the next trigger.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Audio signal sending triggers.
-        max : float or PyoObject, optional
+        max: float or PyoObject, optional
             Maximum value for the random generation. Defaults to 100.
 
     .. note::
 
-        The out() method is bypassed. TrigRandInt's signal can not be sent 
+        The out() method is bypassed. TrigRandInt's signal can not be sent
         to audio outs.
 
     >>> s = Server().boot()
@@ -746,12 +856,14 @@ class TrigRandInt(PyoObject):
 
     """
     def __init__(self, input, max=100., mul=1, add=0):
+        pyoArgsAssert(self, "oOOO", input, max, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._max = max
         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):
         """
@@ -759,12 +871,13 @@ class TrigRandInt(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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)
 
@@ -774,10 +887,11 @@ class TrigRandInt(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `max` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._max = x
         x, lmax = convertArgsToLists(x)
         [obj.setMax(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -791,42 +905,42 @@ class TrigRandInt(PyoObject):
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
-    def input(self): 
+    def input(self):
         """PyoObject. Audio trigger signal."""
         return self._input
     @input.setter
-    def input(self, x): 
+    def input(self, x):
         self.setInput(x)
     @property
-    def max(self): 
+    def max(self):
         """float or PyoObject. Maximum value."""
         return self._max
     @max.setter
-    def max(self, x): 
+    def max(self, x):
         self.setMax(x)
 
 class TrigRand(PyoObject):
     """
     Pseudo-random number generator.
 
-    TrigRand generates a pseudo-random number between `min` and `max` 
-    values each time it receives a trigger in its `input` parameter. 
+    TrigRand generates a pseudo-random number between `min` and `max`
+    values each time it receives a trigger in its `input` parameter.
     The value is kept until the next trigger.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Audio signal sending triggers.
-        min : float or PyoObject, optional
+        min: float or PyoObject, optional
             Minimum value for the random generation. Defaults to 0.
-        max : float or PyoObject, optional
+        max: float or PyoObject, optional
             Maximum value for the random generation. Defaults to 1.
-        port : float, optional
+        port: float, optional
             Portamento. Time to reach a new value. Defaults to 0.
-        init : float, optional
-            Initial value. Available at initialization time only. 
+        init: float, optional
+            Initial value. Available at initialization time only.
             Defaults to 0.
 
     >>> s = Server().boot()
@@ -839,6 +953,7 @@ class TrigRand(PyoObject):
 
     """
     def __init__(self, input, min=0., max=1., port=0., init=0., mul=1, add=0):
+        pyoArgsAssert(self, "oOOnnOO", input, min, max, port, init, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._min = min
@@ -847,32 +962,35 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setMin(self, x):
         """
         Replace the `min` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `min` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._min = x
         x, lmax = convertArgsToLists(x)
         [obj.setMin(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -880,13 +998,14 @@ class TrigRand(PyoObject):
     def setMax(self, x):
         """
         Replace the `max` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `max` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._max = x
         x, lmax = convertArgsToLists(x)
         [obj.setMax(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -894,13 +1013,14 @@ class TrigRand(PyoObject):
     def setPort(self, x):
         """
         Replace the `port` attribute.
-        
+
         :Args:
 
-            x : float
+            x: float
                 new `port` attribute.
-        
+
         """
+        pyoArgsAssert(self, "n", x)
         self._port = x
         x, lmax = convertArgsToLists(x)
         [obj.setPort(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -912,54 +1032,54 @@ class TrigRand(PyoObject):
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
-    def input(self): 
+    def input(self):
         """PyoObject. Audio trigger signal."""
         return self._input
     @input.setter
-    def input(self, x): 
+    def input(self, x):
         self.setInput(x)
     @property
-    def min(self): 
+    def min(self):
         """float or PyoObject. Minimum value."""
         return self._min
     @min.setter
-    def min(self, x): 
+    def min(self, x):
         self.setMin(x)
     @property
-    def max(self): 
+    def max(self):
         """float or PyoObject. Maximum value."""
         return self._max
     @max.setter
-    def max(self, x): 
+    def max(self, x):
         self.setMax(x)
     @property
-    def port(self): 
+    def port(self):
         """float. Ramp time."""
         return self._port
     @port.setter
-    def port(self, x): 
+    def port(self, x):
         self.setPort(x)
 
 class TrigChoice(PyoObject):
     """
     Random generator from user's defined values.
 
-    TrigChoice chooses randomly a new value in list `choice` each 
-    time it receives a trigger in its `input` parameter. The value 
+    TrigChoice chooses randomly a new value in list `choice` each
+    time it receives a trigger in its `input` parameter. The value
     is kept until the next trigger.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Audio signal sending triggers.
-        choice : list of floats
+        choice: list of floats
             Possible values for the random generation.
-        port : float, optional
+        port: float, optional
             Portamento. Time to reach a new value. Defaults to 0.
-        init : float, optional
-            Initial value. Available at initialization time only. 
+        init: float, optional
+            Initial value. Available at initialization time only.
             Defaults to 0.
 
     >>> s = Server().boot()
@@ -972,49 +1092,50 @@ class TrigChoice(PyoObject):
 
     """
     def __init__(self, input, choice, port=0., init=0., mul=1, add=0):
+        pyoArgsAssert(self, "olnnOO", input, choice, port, init, mul, add)
         PyoObject.__init__(self, mul, add)
-        if type(choice) != ListType:
-            print >> sys.stderr, 'TypeError: "choice" argument of %s must be a list.\n' % self.__class__.__name__
-            exit()
         self._input = input
         self._choice = choice
         self._port = port
         self._in_fader = InputFader(input)
         in_fader, port, init, mul, add, lmax = convertArgsToLists(self._in_fader, port, init, mul, add)
-        if type(choice[0]) != ListType:
+        if type(choice[0]) != list:
             self._base_objs = [TrigChoice_base(wrap(in_fader,i), choice, wrap(port,i), wrap(init,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
         else:
             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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setChoice(self, x):
         """
         Replace the `choice` attribute.
-        
+
         :Args:
 
-            x : list of floats
+            x: list of floats
                 new `choice` attribute.
-        
+
         """
+        pyoArgsAssert(self, "l", x)
         self._choice = x
-        if type(x[0]) != ListType:
+        if type(x[0]) != list:
             [obj.setChoice(self._choice) for i, obj in enumerate(self._base_objs)]
         else:
             [obj.setChoice(wrap(self._choice,i)) for i, obj in enumerate(self._base_objs)]
@@ -1022,61 +1143,62 @@ class TrigChoice(PyoObject):
     def setPort(self, x):
         """
         Replace the `port` attribute.
-        
+
         :Args:
 
-            x : float
+            x: float
                 new `port` attribute.
-        
+
         """
+        pyoArgsAssert(self, "n", x)
         self._port = x
         x, lmax = convertArgsToLists(x)
         [obj.setPort(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     @property
-    def input(self): 
+    def input(self):
         """PyoObject. Audio trigger signal."""
         return self._input
     @input.setter
-    def input(self, x): 
+    def input(self, x):
         self.setInput(x)
     @property
-    def choice(self): 
+    def choice(self):
         """list of floats. Possible values."""
         return self._choice
     @choice.setter
-    def choice(self, x): 
+    def choice(self, x):
         self.setChoice(x)
     @property
-    def port(self): 
+    def port(self):
         """float. Ramp time."""
         return self._port
     @port.setter
-    def port(self, x): 
+    def port(self, x):
         self.setPort(x)
 
 class TrigFunc(PyoObject):
     """
     Python function callback.
 
-    TrigFunc calls the function given at parameter `function` each 
+    TrigFunc calls the function given at parameter `function` each
     time it receives a trigger in its `input` parameter.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Audio signal sending triggers.
-        function : Python function
+        function: Python function
             Function to be called.
-        arg : anything, optional
+        arg: anything, optional
             Argument sent to the function's call. If None, the function
             will be called without argument. Defaults to None.
 
     .. note::
 
-        The out() method is bypassed. TrigFunc's signal can not be sent 
+        The out() method is bypassed. TrigFunc's signal can not be sent
         to audio outs.
 
         TrigFunc has no `mul` and `add` attributes.
@@ -1098,59 +1220,55 @@ class TrigFunc(PyoObject):
 
     """
     def __init__(self, input, function, arg=None):
+        pyoArgsAssert(self, "oc", input, function)
         PyoObject.__init__(self)
-        if type(function) == ListType or type(function) == TupleType:
-            if not callable(function[0]):
-                print >> sys.stderr, 'TypeError: "function" argument of %s must be callable.\n' % self.__class__.__name__
-                exit()
-        else:
-            if not callable(function):
-                print >> sys.stderr, 'TypeError: "function" argument of %s must be callable.\n' % self.__class__.__name__
-                exit()
         self._input = input
-        self._function = function
+        self._function = getWeakMethodRef(function)
         self._arg = arg
         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), wrap(function,i), wrap(arg,i)) for i in range(lmax)]
+        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)
 
     def setMul(self, x):
         pass
-        
+
     def setAdd(self, x):
-        pass    
+        pass
 
     def setInput(self, x, fadetime=0.05):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setFunction(self, x):
         """
         Replace the `function` attribute.
-        
+
         :Args:
 
-            x : Python function
+            x: Python function
                 new `function` attribute.
-        
+
         """
-        self._function = x
+        pyoArgsAssert(self, "c", x)
+        self._function = getWeakMethodRef(x)
         x, lmax = convertArgsToLists(x)
-        [obj.setFunction(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+        [obj.setFunction(WeakMethod(wrap(x,i))) for i, obj in enumerate(self._base_objs)]
 
     def setArg(self, x):
         """
@@ -1158,7 +1276,7 @@ class TrigFunc(PyoObject):
 
         :Args:
 
-            x : Anything
+            x: Anything
                 new `arg` attribute.
 
         """
@@ -1167,45 +1285,45 @@ class TrigFunc(PyoObject):
         [obj.setArg(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     @property
-    def input(self): 
+    def input(self):
         """PyoObject. Audio trigger signal."""
         return self._input
     @input.setter
-    def input(self, x): 
+    def input(self, x):
         self.setInput(x)
     @property
-    def function(self): 
+    def function(self):
         """Python callable. Function to be called."""
         return self._function
     @function.setter
-    def function(self, x): 
+    def function(self, x):
         self.setFunction(x)
     @property
-    def arg(self): 
+    def arg(self):
         """Anything. Callable's argument."""
         return self._arg
     @arg.setter
-    def arg(self, x): 
+    def arg(self, x):
         self.setArg(x)
-     
+
 class TrigEnv(PyoObject):
     """
     Envelope reader generator.
 
-    TrigEnv starts reading an envelope in `dur` seconds each time it 
+    TrigEnv starts reading an envelope in `dur` seconds each time it
     receives a trigger in its `input` parameter.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Audio signal sending triggers.
-        table : PyoTableObject
+        table: PyoTableObject
             Table containing the envelope.
-        dur : float or PyoObject, optional
+        dur: float or PyoObject, optional
             Duration in seconds of the envelope. Defaults to 1.
-        interp : int, optional
+        interp: int, optional
             Choice of the interpolation method. Defaults to 2.
                 1. no interpolation
                 2. linear
@@ -1214,9 +1332,9 @@ class TrigEnv(PyoObject):
 
     .. note::
 
-        TrigEnv will sends a trigger signal at the end of the playback. 
-        User can retreive the trigger streams by calling obj['trig']. 
-        Useful to synchronize other processes. 
+        TrigEnv will send a trigger signal at the end of the playback.
+        User can retreive the trigger streams by calling obj['trig'].
+        Useful to synchronize other processes.
 
     >>> s = Server().boot()
     >>> s.start()
@@ -1228,6 +1346,7 @@ class TrigEnv(PyoObject):
 
     """
     def __init__(self, input, table, dur=1, interp=2, mul=1, add=0):
+        pyoArgsAssert(self, "otOiOO", input, table, dur, interp, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._table = table
@@ -1237,46 +1356,50 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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
+            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 setDur(self, x):
         """
         Replace the `dur` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            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_objs)]
@@ -1284,13 +1407,14 @@ class TrigEnv(PyoObject):
     def setInterp(self, x):
         """
         Replace the `interp` attribute.
-        
+
         :Args:
 
-            x : int {1, 2, 3, 4}
+            x: int {1, 2, 3, 4}
                 new `interp` attribute.
-        
+
         """
+        pyoArgsAssert(self, "i", x)
         self._interp = x
         x, lmax = convertArgsToLists(x)
         [obj.setInterp(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1300,60 +1424,60 @@ class TrigEnv(PyoObject):
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
-    def input(self): 
+    def input(self):
         """PyoObject. Audio trigger signal."""
         return self._input
     @input.setter
-    def input(self, x): 
+    def input(self, x):
         self.setInput(x)
     @property
-    def table(self): 
+    def table(self):
         """PyoTableObject. Envelope table."""
         return self._table
     @table.setter
-    def table(self, x): 
+    def table(self, x):
         self.setTable(x)
     @property
-    def dur(self): 
+    def dur(self):
         """float or PyoObject. Duration in seconds."""
         return self._dur
     @dur.setter
-    def dur(self, x): 
+    def dur(self, x):
         self.setDur(x)
     @property
-    def interp(self): 
+    def interp(self):
         """int {1, 2, 3, 4}, Interpolation method."""
         return self._interp
     @interp.setter
-    def interp(self, x): 
+    def interp(self, x):
         self.setInterp(x)
 
 class TrigLinseg(PyoObject):
     """
     Line segments trigger.
 
-    TrigLinseg starts reading a break-points line segments each time it 
+    TrigLinseg starts reading a break-points line segments each time it
     receives a trigger in its `input` parameter.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Audio signal sending triggers.
-        list : list of tuples
+        list: list of tuples
             Points used to construct the line segments. Each tuple is a
-            new point in the form (time, value). 
-            
+            new point in the form (time, value).
+
             Times are given in seconds and must be in increasing order.
 
     .. note::
 
-        TrigLinseg will sends a trigger signal at the end of the playback. 
-        User can retreive the trigger streams by calling obj['trig']. 
-        Useful to synchronize other processes. 
+        TrigLinseg will send a trigger signal at the end of the playback.
+        User can retreive the trigger streams by calling obj['trig'].
+        Useful to synchronize other processes.
 
-        The out() method is bypassed. TrigLinseg's signal can not be sent 
+        The out() method is bypassed. TrigLinseg's signal can not be sent
         to audio outs.
 
     >>> s = Server().boot()
@@ -1364,19 +1488,15 @@ class TrigLinseg(PyoObject):
 
     """
     def __init__(self, input, list, mul=1, add=0):
+        pyoArgsAssert(self, "olOO", input, list, mul, add)
         PyoObject.__init__(self, mul, add)
-        if type(list) != ListType:
-            print >> sys.stderr, 'TypeError: "list" argument of %s must be a list of tuples.\n' % self.__class__.__name__
-            exit()
-        if type(list[0]) != TupleType:
-            print >> sys.stderr, 'TypeError: "list" argument of %s must be a list of tuples.\n' % self.__class__.__name__
-            exit()
         self._input = input
         self._list = list
         self._in_fader = InputFader(input)
         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)
@@ -1384,28 +1504,30 @@ class TrigLinseg(PyoObject):
     def setInput(self, x, fadetime=0.05):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setList(self, x):
         """
         Replace the `list` attribute.
-        
+
         :Args:
 
-            x : list of tuples
+            x: list of tuples
                 new `list` attribute.
-        
+
         """
+        pyoArgsAssert(self, "l", x)
         self._list = x
         [obj.setList(x) for i, obj in enumerate(self._base_objs)]
 
@@ -1415,7 +1537,7 @@ class TrigLinseg(PyoObject):
 
         :Args:
 
-            x : list of tuples
+            x: list of tuples
                 new `list` attribute.
 
         """
@@ -1433,37 +1555,37 @@ class TrigLinseg(PyoObject):
         Opens a grapher window to control the shape of the envelope.
 
         When editing the grapher with the mouse, the new set of points
-        will be send to the object on mouse up. 
+        will be send to the object on mouse up.
 
-        Ctrl+C with focus on the grapher will copy the list of points to the 
+        Ctrl+C with focus on the grapher will copy the list of points to the
         clipboard, giving an easy way to insert the new shape in a script.
 
         :Args:
 
-            xlen : float, optional
+            xlen: float, optional
                 Set the maximum value of the X axis of the graph. If None, the
                 maximum value is retrieve from the current list of points.
                 Defaults to None.
-            yrange : tuple, optional
+            yrange: tuple, optional
                 Set the min and max values of the Y axis of the graph. If
                 None, min and max are retrieve from the current list of points.
                 Defaults to None.
-            title : string, optional
-                Title of the window. If none is provided, the name of the 
+            title: string, optional
+                Title of the window. If none is provided, the name of the
                 class is used.
-            wxnoserver : boolean, optional
-                With wxPython graphical toolkit, if True, tells the 
+            wxnoserver: boolean, optional
+                With wxPython graphical toolkit, if True, tells the
                 interpreter that there will be no server window.
-                
-        If `wxnoserver` is set to True, the interpreter will not wait for 
-        the server GUI before showing the controller window. 
+
+        If `wxnoserver` is set to True, the interpreter will not wait for
+        the server GUI before showing the controller window.
 
         """
-        if xlen == None:
+        if xlen is None:
             xlen = float(self._list[-1][0])
         else:
             xlen = float(xlen)
-        if yrange == None:
+        if yrange is None:
             ymin = float(min([x[1] for x in self._list]))
             ymax = float(max([x[1] for x in self._list]))
             if ymin == ymax:
@@ -1473,50 +1595,50 @@ class TrigLinseg(PyoObject):
         createGraphWindow(self, 0, xlen, yrange, title, wxnoserver)
 
     @property
-    def input(self): 
+    def input(self):
         """PyoObject. Audio trigger signal."""
         return self._input
     @input.setter
-    def input(self, x): 
+    def input(self, x):
         self.setInput(x)
     @property
-    def list(self): 
+    def list(self):
         """list of tuples. Points used to construct the line segments."""
         return self._list
     @list.setter
-    def list(self, x): 
+    def list(self, x):
         self.setList(x)
 
 class TrigExpseg(PyoObject):
     """
     Exponential segments trigger.
 
-    TrigExpseg starts reading break-points exponential segments each time 
+    TrigExpseg starts reading break-points exponential segments each time
     it receives a trigger in its `input` parameter.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Audio signal sending triggers.
-        list : list of tuples
+        list: list of tuples
             Points used to construct the line segments. Each tuple is a
-            new point in the form (time, value). 
-            
+            new point in the form (time, value).
+
             Times are given in seconds and must be in increasing order.
-        exp : float, optional
+        exp: float, optional
             Exponent factor. Used to control the slope of the curves.
             Defaults to 10.
-        inverse : boolean, optional
-            If True, downward slope will be inversed. Useful to create 
+        inverse: boolean, optional
+            If True, downward slope will be inversed. Useful to create
             biexponential curves. Defaults to True.
 
     .. note::
 
-        TrigExpseg will sends a trigger signal at the end of the playback.
+        TrigExpseg will send a trigger signal at the end of the playback.
         User can retreive the trigger streams by calling obj['trig'].
-        Useful to synchronize other processes. 
+        Useful to synchronize other processes.
 
         The out() method is bypassed. TrigExpseg's signal can not be sent
         to audio outs.
@@ -1529,13 +1651,8 @@ class TrigExpseg(PyoObject):
 
     """
     def __init__(self, input, list, exp=10, inverse=True, mul=1, add=0):
+        pyoArgsAssert(self, "olnbOO", input, list, exp, inverse, mul, add)
         PyoObject.__init__(self, mul, add)
-        if type(list) != ListType:
-            print >> sys.stderr, 'TypeError: "list" argument of %s must be a list of tuples.\n' % self.__class__.__name__
-            exit()
-        if type(list[0]) != TupleType:
-            print >> sys.stderr, 'TypeError: "list" argument of %s must be a list of tuples.\n' % self.__class__.__name__
-            exit()
         self._input = input
         self._list = list
         self._exp = exp
@@ -1544,6 +1661,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)
@@ -1551,28 +1669,30 @@ class TrigExpseg(PyoObject):
     def setInput(self, x, fadetime=0.05):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setList(self, x):
         """
         Replace the `list` attribute.
-        
+
         :Args:
 
-            x : list of tuples
+            x: list of tuples
                 new `list` attribute.
-        
+
         """
+        pyoArgsAssert(self, "l", x)
         self._list = x
         [obj.setList(x) for i, obj in enumerate(self._base_objs)]
 
@@ -1582,10 +1702,11 @@ class TrigExpseg(PyoObject):
 
         :Args:
 
-            x : float
+            x: float
                 new `exp` attribute.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._exp = x
         x, lmax = convertArgsToLists(x)
         [obj.setExp(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1596,10 +1717,11 @@ class TrigExpseg(PyoObject):
 
         :Args:
 
-            x : boolean
+            x: boolean
                 new `inverse` attribute.
 
         """
+        pyoArgsAssert(self, "b", x)
         self._inverse = x
         x, lmax = convertArgsToLists(x)
         [obj.setInverse(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1610,7 +1732,7 @@ class TrigExpseg(PyoObject):
 
         :Args:
 
-            x : list of tuples
+            x: list of tuples
                 new `list` attribute.
 
         """
@@ -1628,37 +1750,37 @@ class TrigExpseg(PyoObject):
         Opens a grapher window to control the shape of the envelope.
 
         When editing the grapher with the mouse, the new set of points
-        will be send to the object on mouse up. 
+        will be send to the object on mouse up.
 
-        Ctrl+C with focus on the grapher will copy the list of points to the 
+        Ctrl+C with focus on the grapher will copy the list of points to the
         clipboard, giving an easy way to insert the new shape in a script.
 
         :Args:
 
-            xlen : float, optional
+            xlen: float, optional
                 Set the maximum value of the X axis of the graph. If None, the
                 maximum value is retrieve from the current list of points.
                 Defaults to None.
-            yrange : tuple, optional
+            yrange: tuple, optional
                 Set the min and max values of the Y axis of the graph. If
                 None, min and max are retrieve from the current list of points.
                 Defaults to None.
-            title : string, optional
-                Title of the window. If none is provided, the name of the 
+            title: string, optional
+                Title of the window. If none is provided, the name of the
                 class is used.
-            wxnoserver : boolean, optional
-                With wxPython graphical toolkit, if True, tells the 
+            wxnoserver: boolean, optional
+                With wxPython graphical toolkit, if True, tells the
                 interpreter that there will be no server window.
-                
-        If `wxnoserver` is set to True, the interpreter will not wait for 
-        the server GUI before showing the controller window. 
+
+        If `wxnoserver` is set to True, the interpreter will not wait for
+        the server GUI before showing the controller window.
 
         """
-        if xlen == None:
+        if xlen is None:
             xlen = float(self._list[-1][0])
         else:
             xlen = float(xlen)
-        if yrange == None:
+        if yrange is None:
             ymin = float(min([x[1] for x in self._list]))
             ymax = float(max([x[1] for x in self._list]))
             if ymin == ymax:
@@ -1668,53 +1790,53 @@ class TrigExpseg(PyoObject):
         createGraphWindow(self, 2, xlen, yrange, title, wxnoserver)
 
     @property
-    def input(self): 
+    def input(self):
         """PyoObject. Audio trigger signal."""
         return self._input
     @input.setter
-    def input(self, x): 
+    def input(self, x):
         self.setInput(x)
     @property
-    def list(self): 
+    def list(self):
         """list of tuples. Points used to construct the line segments."""
         return self._list
     @list.setter
-    def list(self, x): 
+    def list(self, x):
         self.setList(x)
     @property
-    def exp(self): 
+    def exp(self):
         """float. Exponent factor."""
         return self._exp
     @exp.setter
-    def exp(self, x): 
+    def exp(self, x):
         self.setExp(x)
     @property
-    def inverse(self): 
+    def inverse(self):
         """boolean. Inversion of downward slope."""
         return self._inverse
     @inverse.setter
-    def inverse(self, x): 
+    def inverse(self, x):
         self.setInverse(x)
 
 class TrigXnoise(PyoObject):
     """
     Triggered X-class pseudo-random generator.
 
-    Xnoise implements a few of the most common noise distributions. 
-    A new value is generated each time the object receive a trigger 
+    Xnoise implements a few of the most common noise distributions.
+    A new value is generated each time the object receive a trigger
     in input. Each distribution generates values in the range 0 and 1.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Audio signal sending triggers.
-        dist : string or int, optional
+        dist: string or int, optional
             Distribution type. Defaults to 0.
-        x1 : float or PyoObject, optional
+        x1: float or PyoObject, optional
             First parameter. Defaults to 0.5.
-        x2 : float or PyoObject, optional
+        x2: float or PyoObject, optional
             Second parameter. Defaults to 0.5.
 
     .. note::
@@ -1733,50 +1855,50 @@ class TrigXnoise(PyoObject):
             10. poisson
             11. walker (drunk)
             12. loopseg (drunk with looped segments)
-            
+
         Depending on the distribution, `x1` and `x2` parameters are applied
         as follow (names as string, or associated number can be used as `dist`
         parameter):
 
             0. uniform
-                - x1 : not used
-                - x2 : not used
+                - x1: not used
+                - x2: not used
             1. linear_min
-                - x1 : not used
-                - x2 : not used
+                - x1: not used
+                - x2: not used
             2. linear_max
-                - x1 : not used
-                - x2 : not used
+                - x1: not used
+                - x2: not used
             3. triangle
-                - x1 : not used
-                - x2 : not used
+                - x1: not used
+                - x2: not used
             4. expon_min
-                - x1 : slope {0 = no slope -> 10 = sharp slope}
-                - x2 : not used
+                - x1: slope {0 = no slope -> 10 = sharp slope}
+                - x2: not used
             5. expon_max
-                - x1 : slope {0 = no slope -> 10 = sharp slope}
-                - x2 : not used
+                - x1: slope {0 = no slope -> 10 = sharp slope}
+                - x2: not used
             6. biexpon
-                - x1 : bandwidth {0 = huge bandwidth -> 10 = narrow bandwidth}
-                - x2 : not used
+                - x1: bandwidth {0 = huge bandwidth -> 10 = narrow bandwidth}
+                - x2: not used
             7. cauchy
-                - x1 : bandwidth {0 = narrow bandwidth -> 10 = huge bandwidth}
-                - x2 : not used
+                - x1: bandwidth {0 = narrow bandwidth -> 10 = huge bandwidth}
+                - x2: not used
             8. weibull
-                - x1 : mean location {0 -> 1}
-                - x2 : shape {0.5 = linear min, 1.5 = expon min, 3.5 = gaussian}
+                - x1: mean location {0 -> 1}
+                - x2: shape {0.5 = linear min, 1.5 = expon min, 3.5 = gaussian}
             9. gaussian
-                - x1 : mean location {0 -> 1}
-                - x2 : bandwidth {0 =  narrow bandwidth -> 10 = huge bandwidth}
+                - x1: mean location {0 -> 1}
+                - x2: bandwidth {0 =  narrow bandwidth -> 10 = huge bandwidth}
             10. poisson
-                 - x1 : gravity center {0 = low values -> 10 = high values}
-                 - x2 : compress/expand range {0.1 = full compress -> 4 full expand}
+                 - x1: gravity center {0 = low values -> 10 = high values}
+                 - x2: compress/expand range {0.1 = full compress -> 4 full expand}
             11. walker
-                 - x1 : maximum value {0.1 -> 1}
-                 - x2 : maximum step {0.1 -> 1}
-            12. loopseg 
-                 - x1 : maximum value {0.1 -> 1}
-                 - x2 : maximum step {0.1 -> 1}
+                 - x1: maximum value {0.1 -> 1}
+                 - x2: maximum step {0.1 -> 1}
+            12. loopseg
+                 - x1: maximum value {0.1 -> 1}
+                 - x2: maximum step {0.1 -> 1}
 
     >>> s = Server().boot()
     >>> s.start()
@@ -1789,6 +1911,7 @@ class TrigXnoise(PyoObject):
 
     """
     def __init__(self, input, dist=0, x1=0.5, x2=0.5, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOO", input, x1, x2, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._dist = dist
@@ -1797,8 +1920,9 @@ class TrigXnoise(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, dist, x1, x2, mul, add, lmax = convertArgsToLists(self._in_fader, dist, x1, x2, mul, add)
         for i, t in enumerate(dist):
-            if type(t) == StringType: dist[i] = XNOISE_DICT.get(t, 0)
+            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):
         """
@@ -1806,12 +1930,13 @@ class TrigXnoise(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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)
 
@@ -1821,14 +1946,14 @@ class TrigXnoise(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 new `dist` attribute.
 
         """
         self._dist = x
         x, lmax = convertArgsToLists(x)
         for i, t in enumerate(x):
-            if type(t) == StringType: x[i] = XNOISE_DICT.get(t, 0)
+            if type(t) in [bytes_t, unicode_t]: x[i] = XNOISE_DICT.get(t, 0)
         [obj.setType(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     def setX1(self, x):
@@ -1837,10 +1962,11 @@ class TrigXnoise(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `x1` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._x1 = x
         x, lmax = convertArgsToLists(x)
         [obj.setX1(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1851,72 +1977,80 @@ class TrigXnoise(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `x2` attribute.
 
         """
-        self._x2= x
+        pyoArgsAssert(self, "O", x)
+        self._x2 = x
         x, lmax = convertArgsToLists(x)
         [obj.setX2(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, 12, "lin", "dist", self._dist, res="int", dataOnly=True),
+                          SLMap(0.01, 10.0, "log", "x1", self._x1, dataOnly=True),
+                          SLMap(0.01, 10.0, "log", "x2", self._x2, dataOnly=True),
+                          SLMapMul(self._mul)]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
     @property
-    def input(self): 
+    def input(self):
         """PyoObject. Audio trigger signal."""
         return self._input
     @input.setter
-    def input(self, x): 
+    def input(self, x):
         self.setInput(x)
     @property
-    def dist(self): 
+    def dist(self):
         """string or int. Distribution type."""
         return self._dist
     @dist.setter
-    def dist(self, x): 
+    def dist(self, x):
         self.setDist(x)
     @property
-    def x1(self): 
+    def x1(self):
         """float or PyoObject. First parameter."""
         return self._x1
     @x1.setter
-    def x1(self, x): 
+    def x1(self, x):
         self.setX1(x)
     @property
-    def x2(self): 
+    def x2(self):
         """float or PyoObject. Second parameter."""
         return self._x2
     @x2.setter
-    def x2(self, x): 
+    def x2(self, x):
         self.setX2(x)
 
 class TrigXnoiseMidi(PyoObject):
     """
     Triggered X-class midi notes pseudo-random generator.
 
-    Xnoise implements a few of the most common noise distributions. 
-    A new value is generated each time the object receive a trigger 
-    in input. Each distribution generates integer values in the range 
-    defined with `mrange` parameter and output can be scaled on midi 
+    Xnoise implements a few of the most common noise distributions.
+    A new value is generated each time the object receive a trigger
+    in input. Each distribution generates integer values in the range
+    defined with `mrange` parameter and output can be scaled on midi
     notes, hertz or transposition factor.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-    input : PyoObject
+    input: PyoObject
         Audio signal sending triggers.
-    dist : string of int, optional
+    dist: string of int, optional
         Distribution type. Defaults to 0.
-    x1 : float or PyoObject, optional
+    x1: float or PyoObject, optional
         First parameter. Defaults to 0.5.
-    x2 : float or PyoObject, optional
+    x2: float or PyoObject, optional
         Second parameter. Defaults to 0.5.
-    scale : int {0, 1, 2}, optional
+    scale: int {0, 1, 2}, optional
         Output format. 0 = MIDI, 1 = Hertz, 2 = transposition factor.
          Defaults to 0.
 
-        In the transposition mode, the central key (the key where there 
+        In the transposition mode, the central key (the key where there
         is no transposition) is (`minrange` + `maxrange`) / 2.
-    mrange : tuple of int, optional
+    mrange: tuple of int, optional
         Minimum and maximum possible values, in Midi notes. Available
         only at initialization time. Defaults to (0, 127).
 
@@ -1936,50 +2070,50 @@ class TrigXnoiseMidi(PyoObject):
             10. poisson
             11. walker (drunk)
             12. loopseg (drunk with looped segments)
-            
+
         Depending on the distribution, `x1` and `x2` parameters are applied
         as follow (names as string, or associated number can be used as `dist`
         parameter):
 
             0. uniform
-                - x1 : not used
-                - x2 : not used
+                - x1: not used
+                - x2: not used
             1. linear_min
-                - x1 : not used
-                - x2 : not used
+                - x1: not used
+                - x2: not used
             2. linear_max
-                - x1 : not used
-                - x2 : not used
+                - x1: not used
+                - x2: not used
             3. triangle
-                - x1 : not used
-                - x2 : not used
+                - x1: not used
+                - x2: not used
             4. expon_min
-                - x1 : slope {0 = no slope -> 10 = sharp slope}
-                - x2 : not used
+                - x1: slope {0 = no slope -> 10 = sharp slope}
+                - x2: not used
             5. expon_max
-                - x1 : slope {0 = no slope -> 10 = sharp slope}
-                - x2 : not used
+                - x1: slope {0 = no slope -> 10 = sharp slope}
+                - x2: not used
             6. biexpon
-                - x1 : bandwidth {0 = huge bandwidth -> 10 = narrow bandwidth}
-                - x2 : not used
+                - x1: bandwidth {0 = huge bandwidth -> 10 = narrow bandwidth}
+                - x2: not used
             7. cauchy
-                - x1 : bandwidth {0 = narrow bandwidth -> 10 = huge bandwidth}
-                - x2 : not used
+                - x1: bandwidth {0 = narrow bandwidth -> 10 = huge bandwidth}
+                - x2: not used
             8. weibull
-                - x1 : mean location {0 -> 1}
-                - x2 : shape {0.5 = linear min, 1.5 = expon min, 3.5 = gaussian}
+                - x1: mean location {0 -> 1}
+                - x2: shape {0.5 = linear min, 1.5 = expon min, 3.5 = gaussian}
             9. gaussian
-                - x1 : mean location {0 -> 1}
-                - x2 : bandwidth {0 =  narrow bandwidth -> 10 = huge bandwidth}
+                - x1: mean location {0 -> 1}
+                - x2: bandwidth {0 =  narrow bandwidth -> 10 = huge bandwidth}
             10. poisson
-                 - x1 : gravity center {0 = low values -> 10 = high values}
-                 - x2 : compress/expand range {0.1 = full compress -> 4 full expand}
+                 - x1: gravity center {0 = low values -> 10 = high values}
+                 - x2: compress/expand range {0.1 = full compress -> 4 full expand}
             11. walker
-                 - x1 : maximum value {0.1 -> 1}
-                 - x2 : maximum step {0.1 -> 1}
-            12. loopseg 
-                 - x1 : maximum value {0.1 -> 1}
-                 - x2 : maximum step {0.1 -> 1}
+                 - x1: maximum value {0.1 -> 1}
+                 - x2: maximum step {0.1 -> 1}
+            12. loopseg
+                 - x1: maximum value {0.1 -> 1}
+                 - x2: maximum step {0.1 -> 1}
 
     >>> s = Server().boot()
     >>> s.start()
@@ -1992,6 +2126,7 @@ class TrigXnoiseMidi(PyoObject):
 
     """
     def __init__(self, input, dist=0, x1=0.5, x2=0.5, scale=0, mrange=(0,127), mul=1, add=0):
+        pyoArgsAssert(self, "oOOixOO", input, x1, x2, scale, mrange, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._dist = dist
@@ -2002,8 +2137,9 @@ class TrigXnoiseMidi(PyoObject):
         self._in_fader = InputFader(input)
         in_fader, dist, x1, x2, scale, mrange, mul, add, lmax = convertArgsToLists(self._in_fader, dist, x1, x2, scale, mrange, mul, add)
         for i, t in enumerate(dist):
-            if type(t) == StringType: dist[i] = XNOISE_DICT.get(t, 0)
+            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):
         """
@@ -2011,12 +2147,13 @@ class TrigXnoiseMidi(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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)
 
@@ -2026,31 +2163,32 @@ class TrigXnoiseMidi(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 new `dist` attribute.
 
         """
         self._dist = x
         x, lmax = convertArgsToLists(x)
         for i, t in enumerate(x):
-            if type(t) == StringType: x[i] = XNOISE_DICT.get(t, 0)
+            if type(t) in [bytes_t, unicode_t]: x[i] = XNOISE_DICT.get(t, 0)
         [obj.setType(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     def setScale(self, x):
         """
         Replace the `scale` attribute.
 
-        Possible values are: 
+        Possible values are:
             0. Midi notes
             1. Hertz
             2. transposition factor (centralkey is (`minrange` + `maxrange`) / 2
 
         :Args:
 
-            x : int {0, 1, 2}
+            x: int {0, 1, 2}
                 new `scale` attribute.
 
         """
+        pyoArgsAssert(self, "i", x)
         self._scale = x
         x, lmax = convertArgsToLists(x)
         [obj.setScale(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2061,12 +2199,13 @@ class TrigXnoiseMidi(PyoObject):
 
         :Args:
 
-            mini : int
+            mini: int
                 minimum output midi range.
-            maxi : int
+            maxi: int
                 maximum output midi range.
 
         """
+        pyoArgsAssert(self, "ii", mini, maxi)
         self._mrange = (mini, maxi)
         mini, maxi, lmax = convertArgsToLists(mini, maxi)
         [obj.setRange(wrap(mini,i), wrap(maxi,i)) for i, obj in enumerate(self._base_objs)]
@@ -2077,10 +2216,11 @@ class TrigXnoiseMidi(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `x1` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._x1 = x
         x, lmax = convertArgsToLists(x)
         [obj.setX1(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2091,56 +2231,64 @@ class TrigXnoiseMidi(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `x2` attribute.
 
         """
-        self._x2= x
+        pyoArgsAssert(self, "O", x)
+        self._x2 = x
         x, lmax = convertArgsToLists(x)
         [obj.setX2(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, 12, "lin", "dist", self._dist, res="int", dataOnly=True),
+                          SLMap(0.01, 10.0, "log", "x1", self._x1, dataOnly=True),
+                          SLMap(0.01, 10.0, "log", "x2", self._x2, dataOnly=True),
+                          SLMapMul(self._mul)]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
     @property
-    def input(self): 
+    def input(self):
         """PyoObject. Audio trigger signal."""
         return self._input
     @input.setter
-    def input(self, x): 
+    def input(self, x):
         self.setInput(x)
     @property
-    def dist(self): 
+    def dist(self):
         """string or int. Distribution type."""
         return self._dist
     @dist.setter
-    def dist(self, x): 
+    def dist(self, x):
         self.setDist(x)
     @property
-    def x1(self): 
+    def x1(self):
         """float or PyoObject. First parameter."""
         return self._x1
     @x1.setter
-    def x1(self, x): 
+    def x1(self, x):
         self.setX1(x)
     @property
-    def x2(self): 
+    def x2(self):
         """float or PyoObject. Second parameter."""
         return self._x2
     @x2.setter
-    def x2(self, x): 
+    def x2(self, x):
         self.setX2(x)
     @property
-    def scale(self): 
+    def scale(self):
         """int. Output format."""
         return self._scale
     @scale.setter
-    def scale(self, x): 
+    def scale(self, x):
         self.setScale(x)
 
 class Counter(PyoObject):
     """
     Integer count generator.
 
-    Counter keeps track of all triggers received, outputs the current 
-    count constrained within `min` and `max` range, and can be set to 
+    Counter keeps track of all triggers received, outputs the current
+    count constrained within `min` and `max` range, and can be set to
     count up, down, or up-and-down.
 
 
@@ -2148,14 +2296,14 @@ class Counter(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Audio signal sending triggers.
-        min : int, optional
+        min: int, optional
             Minimum value of the count, included in the count. Defaults to 0.
-        max : int, optional
-            Maximum value of the count. excluded of the count. 
+        max: int, optional
+            Maximum value of the count. excluded of the count.
             The counter will count up to max - 1. Defaults to 100.
-        dir : int {0, 1, 2}, optional
+        dir: int {0, 1, 2}, optional
             Direction of the count. Defaults to 0. Three possible values:
                 0. up
                 1. down
@@ -2163,11 +2311,11 @@ class Counter(PyoObject):
 
     .. note::
 
-        The out() method is bypassed. Counter's signal can not be sent 
+        The out() method is bypassed. Counter's signal can not be sent
         to audio outs.
 
-    .. seealso:: 
-        
+    .. seealso::
+
         :py:class:`Select`
 
     >>> s = Server().boot()
@@ -2178,6 +2326,7 @@ class Counter(PyoObject):
 
     """
     def __init__(self, input, min=0, max=100, dir=0, mul=1, add=0):
+        pyoArgsAssert(self, "oiiiOO", input, min, max, dir, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._min = min
@@ -2186,6 +2335,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)
@@ -2193,28 +2343,30 @@ class Counter(PyoObject):
     def setInput(self, x, fadetime=0.05):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setMin(self, x):
         """
         Replace the `min` attribute.
-        
+
         :Args:
 
-            x : int
+            x: int
                 new `min` attribute.
-        
+
         """
+        pyoArgsAssert(self, "i", x)
         self._min = x
         x, lmax = convertArgsToLists(x)
         [obj.setMin(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2222,13 +2374,14 @@ class Counter(PyoObject):
     def setMax(self, x):
         """
         Replace the `max` attribute.
-        
+
         :Args:
 
-            x : int
+            x: int
                 new `max` attribute.
-        
+
         """
+        pyoArgsAssert(self, "i", x)
         self._max = x
         x, lmax = convertArgsToLists(x)
         [obj.setMax(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2236,13 +2389,14 @@ class Counter(PyoObject):
     def setDir(self, x):
         """
         Replace the `dir` attribute.
-        
+
         :Args:
 
-            x : int {0, 1, 2}
+            x: int {0, 1, 2}
                 new `dir` attribute.
-        
+
         """
+        pyoArgsAssert(self, "i", x)
         self._dir = x
         x, lmax = convertArgsToLists(x)
         [obj.setDir(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2254,40 +2408,50 @@ class Counter(PyoObject):
 
         :Args:
 
-            value : int, optional
+            value: int, optional
                 Value where to reset the count. Defaults to None.
 
         """
+        if value is not None:
+            pyoArgsAssert(self, "i", value)
         value, lmax = convertArgsToLists(value)
         [obj.reset(wrap(value,i)) for i, obj in enumerate(self._base_objs)]
 
+    def ctrl(self, map_list=None, title=None, wxnoserver=False):
+        self._map_list = [SLMap(0, 100, 'lin', 'min', self._min, res="int", dataOnly=True),
+                          SLMap(0, 1000, 'lin', 'max', self._max, res="int", dataOnly=True),
+                          SLMap(0, 2, 'lin', 'dir', self._dir, res="int", dataOnly=True),
+                          SLMap(0, 1000, 'lin', 'mul', self._mul),
+                          SLMap(0, 1000, 'lin', 'add', self._add)]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
     @property
-    def input(self): 
+    def input(self):
         """PyoObject. Audio trigger signal."""
         return self._input
     @input.setter
-    def input(self, x): 
+    def input(self, x):
         self.setInput(x)
     @property
-    def min(self): 
+    def min(self):
         """int. Minimum value."""
         return self._min
     @min.setter
-    def min(self, x): 
+    def min(self, x):
         self.setMin(x)
     @property
-    def max(self): 
+    def max(self):
         """int. Maximum value."""
         return self._max
     @max.setter
-    def max(self, x): 
+    def max(self, x):
         self.setMax(x)
     @property
-    def dir(self): 
+    def dir(self):
         """int. Direction of the count."""
         return self._dir
     @dir.setter
-    def dir(self, x): 
+    def dir(self, x):
         self.setDir(x)
 
 class Select(PyoObject):
@@ -2302,18 +2466,18 @@ class Select(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Audio signal. Must contains integer numbers.
-        value : int, optional
+        value: int, optional
             Value to be matched to send a trigger. Defaults to 0.
 
     .. note::
 
-        The out() method is bypassed. Select's signal can not be sent 
+        The out() method is bypassed. Select's signal can not be sent
         to audio outs.
 
-    .. seealso:: 
-        
+    .. seealso::
+
         :py:class:`Counter`
 
     >>> s = Server().boot()
@@ -2328,12 +2492,14 @@ class Select(PyoObject):
 
     """
     def __init__(self, input, value=0, mul=1, add=0):
+        pyoArgsAssert(self, "oiOO", input, value, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._value = value
         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)
@@ -2341,45 +2507,51 @@ class Select(PyoObject):
     def setInput(self, x, fadetime=0.05):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setValue(self, x):
         """
         Replace the `value` attribute.
-        
+
         :Args:
 
-            x : int
+            x: int
                 new `value` attribute.
-        
+
         """
+        pyoArgsAssert(self, "i", x)
         self._value = x
         x, lmax = 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, 100, 'lin', 'value', self._value, res="int", dataOnly=True)]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
     @property
-    def input(self): 
+    def input(self):
         """PyoObject. Audio signal."""
         return self._input
     @input.setter
-    def input(self, x): 
+    def input(self, x):
         self.setInput(x)
     @property
-    def value(self): 
+    def value(self):
         """int. Matching value."""
         return self._value
     @value.setter
-    def value(self, x): 
+    def value(self, x):
         self.setValue(x)
 
 class Change(PyoObject):
@@ -2390,12 +2562,12 @@ class Change(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Audio signal. Must contains integer numbers.
 
     .. note::
 
-        The out() method is bypassed. Change's signal can not be sent 
+        The out() method is bypassed. Change's signal can not be sent
         to audio outs.
 
     >>> s = Server().boot()
@@ -2408,11 +2580,13 @@ class Change(PyoObject):
 
     """
     def __init__(self, input, mul=1, add=0):
+        pyoArgsAssert(self, "oOO", input, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         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)
@@ -2420,58 +2594,59 @@ class Change(PyoObject):
     def setInput(self, x, fadetime=0.05):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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)
 
     @property
-    def input(self): 
+    def input(self):
         """PyoObject. Audio signal."""
         return self._input
     @input.setter
-    def input(self, x): 
+    def input(self, x):
         self.setInput(x)
 
 class Thresh(PyoObject):
     """
     Informs when a signal crosses a threshold.
-    
-    Thresh sends a trigger when a signal crosses a threshold. The `dir` 
-    parameter can be used to set the crossing mode, down-up, up-down, or 
+
+    Thresh sends a trigger when a signal crosses a threshold. The `dir`
+    parameter can be used to set the crossing mode, down-up, up-down, or
     both.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Audio signal sending triggers.
-        threshold : float or PyoObject, optional
+        threshold: float or PyoObject, optional
             Threshold value. Defaults to 0.
-        dir : int {0, 1, 2}, optional
+        dir: int {0, 1, 2}, optional
             There are three modes of using Thresh:
                 0. down-up (default)
                     sends a trigger when current value is higher than the
-                    threshold, while old value was equal to or lower than 
+                    threshold, while old value was equal to or lower than
                     the threshold.
                 1. up-down
                     sends a trigger when current value is lower than the
-                    threshold, while old value was equal to or higher than 
+                    threshold, while old value was equal to or higher than
                     the threshold.
                 2. both direction
                     sends a trigger in both the two previous cases.
-    
+
     .. note::
 
-        The out() method is bypassed. Thresh's signal can not be sent 
+        The out() method is bypassed. Thresh's signal can not be sent
         to audio outs.
 
     >>> s = Server().boot()
@@ -2481,9 +2656,10 @@ class Thresh(PyoObject):
     >>> t = LinTable([(0,0), (50,1), (250,.3), (8191,0)])
     >>> env = TrigEnv(b, table=t, dur=.5, mul=.3)
     >>> sine = Sine(freq=[500,600,700], mul=env).out()
-    
+
     """
     def __init__(self, input, threshold=0., dir=0, mul=1, add=0):
+        pyoArgsAssert(self, "oOiOO", input, threshold, dir, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._threshold = threshold
@@ -2491,6 +2667,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)
@@ -2498,28 +2675,30 @@ class Thresh(PyoObject):
     def setInput(self, x, fadetime=0.05):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setThreshold(self, x):
         """
         Replace the `threshold` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `threshold` attribute.
-        
+
         """
+        pyoArgsAssert(self, "O", x)
         self._threshold = x
         x, lmax = convertArgsToLists(x)
         [obj.setThreshold(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2527,37 +2706,38 @@ class Thresh(PyoObject):
     def setDir(self, x):
         """
         Replace the `dir` attribute.
-        
+
         :Args:
 
-            x : int {0, 1, 2}
+            x: int {0, 1, 2}
                 new `dir` attribute.
-        
+
         """
+        pyoArgsAssert(self, "i", x)
         self._dir = x
         x, lmax = convertArgsToLists(x)
         [obj.setDir(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     @property
-    def input(self): 
+    def input(self):
         """PyoObject. Audio signal."""
         return self._input
     @input.setter
-    def input(self, x): 
+    def input(self, x):
         self.setInput(x)
     @property
-    def threshold(self): 
+    def threshold(self):
         """float or PyoObject. Threshold value."""
         return self._threshold
     @threshold.setter
-    def threshold(self, x): 
+    def threshold(self, x):
         self.setThreshold(x)
     @property
-    def dir(self): 
+    def dir(self):
         """int. User mode."""
         return self._dir
     @dir.setter
-    def dir(self, x): 
+    def dir(self, x):
         self.setDir(x)
 
 class Percent(PyoObject):
@@ -2571,15 +2751,15 @@ class Percent(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Audio signal sending triggers.
-        percent : float or PyoObject, optional
-            How much percentage of triggers to let pass, 
+        percent: float or PyoObject, optional
+            How much percentage of triggers to let pass,
             between 0 and 100. Defaults to 50.
 
     .. note::
 
-        The out() method is bypassed. Percent's signal can not 
+        The out() method is bypassed. Percent's signal can not
         be sent to audio outs.
 
     >>> s = Server().boot()
@@ -2594,12 +2774,14 @@ class Percent(PyoObject):
 
     """
     def __init__(self, input, percent=50., mul=1, add=0):
+        pyoArgsAssert(self, "oOOO", input, percent, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._percent = percent
         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)
@@ -2610,12 +2792,13 @@ class Percent(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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)
 
@@ -2625,10 +2808,11 @@ class Percent(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `percent` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._percent = x
         x, lmax = convertArgsToLists(x)
         [obj.setPercent(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2638,35 +2822,35 @@ class Percent(PyoObject):
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
-    def input(self): 
+    def input(self):
         """PyoObject. Audio signal."""
         return self._input
     @input.setter
-    def input(self, x): 
+    def input(self, x):
         self.setInput(x)
     @property
-    def percent(self): 
+    def percent(self):
         """float or PyoObject. Percentage value."""
         return self._percent
     @percent.setter
-    def percent(self, x): 
+    def percent(self, x):
         self.setPercent(x)
 
 class Timer(PyoObject):
     """
     Reports elapsed time between two trigs.
 
-    A trigger in `input2` signal starts an internal timer. The next trigger 
-    in `input` signal stops it and reports the elapsed time between the two 
-    triggers. Useful for filtering triggers that are too close to each other. 
+    A trigger in `input2` signal starts an internal timer. The next trigger
+    in `input` signal stops it and reports the elapsed time between the two
+    triggers. Useful for filtering triggers that are too close to each other.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Trigger signal. Stops the timer and reports elapsed time.
-        input2 : PyoObject
+        input2: PyoObject
             Trigger signal. Starts the timer if not already started.
 
     .. note::
@@ -2687,6 +2871,7 @@ class Timer(PyoObject):
 
     """
     def __init__(self, input, input2, mul=1, add=0):
+        pyoArgsAssert(self, "ooOO", input, input2, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._input2 = input2
@@ -2694,6 +2879,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):
         """
@@ -2701,12 +2887,13 @@ class Timer(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
@@ -2716,25 +2903,26 @@ class Timer(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input2 = x
         self._in_fader2.setInput(x, fadetime)
 
     @property
     def input(self):
-        """PyoObject. Timer stop signal.""" 
+        """PyoObject. Timer stop signal."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def input2(self):
-        """PyoObject. Timer start signal.""" 
+        """PyoObject. Timer start signal."""
         return self._input2
     @input2.setter
     def input2(self, x): self.setInput2(x)
@@ -2744,20 +2932,30 @@ class Iter(PyoObject):
     Triggers iterate over a list of values.
 
     Iter loops over a list of user-defined values. When a trigger is received
-    in `input`, Iter moves up to the next value in the list, with wrap-around. 
+    in `input`, Iter moves up to the next value in the list, with wrap-around.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Audio signal sending triggers.
-        choice : list of floats
-            Sequence of values over which to iterate.
-        init : float, optional
-            Initial value. Available at initialization time only. 
+        choice: list of floats or PyoObjects
+            Sequence of values over which to iterate. If a PyoObject with
+            more than one audio streams is given, the streams will be 
+            flattened and inserted in the main list. See setChoice method
+            for more details.
+        init: float, optional
+            Initial value. Available at initialization time only.
             Defaults to 0.
 
+    .. note::
+
+        Iter will send a trigger signal when the iterator hits the
+        last value of the list `choice`. User can retreive the trigger 
+        streams by calling obj['trig']. Useful to synchronize other 
+        processes.
+
     >>> s = Server().boot()
     >>> s.start()
     >>> l1 = [300, 350, 400, 450, 500, 550]
@@ -2770,20 +2968,21 @@ class Iter(PyoObject):
 
     """
     def __init__(self, input, choice, init=0., mul=1, add=0):
+        pyoArgsAssert(self, "olnOO", input, choice, init, mul, add)
         PyoObject.__init__(self, mul, add)
-        if type(choice) != ListType:
-            print >> sys.stderr, 'TypeError: "choice" argument of %s must be a list.\n' % self.__class__.__name__
-            exit()
         self._input = input
         self._choice = choice
         self._in_fader = InputFader(input)
         in_fader, init, mul, add, lmax = convertArgsToLists(self._in_fader, init, mul, add)
-        if type(choice[0]) != ListType:
-            self._base_objs = [Iter_base(wrap(in_fader,i), choice, wrap(init,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
+        x = self._flatten(choice)
+        if type(x[0]) != list:
+            self._base_objs = [Iter_base(wrap(in_fader,i), x, wrap(init,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
         else:
-            choicelen = len(choice)
+            choicelen = len(x)
             lmax = max(choicelen, lmax)
-            self._base_objs = [Iter_base(wrap(in_fader,i), wrap(choice,i), wrap(init,i), wrap(mul,i), wrap(add,i)) for i in range(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):
         """
@@ -2791,77 +2990,111 @@ class Iter(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 _flatten(self, x):
+        if type(x[0]) != list:
+            lst = []
+            for ob in x:
+                if isinstance(ob, PyoObject):
+                    lst.extend(ob.getBaseObjects())
+                else:
+                    lst.append(ob)
+        else:
+            lst = []
+            for sub in x:
+                sublst = []
+                for ob in sub:
+                    if isinstance(ob, PyoObject):
+                        sublst.extend(ob.getBaseObjects())
+                    else:
+                        sublst.append(ob)
+                lst.append(sublst)
+        return lst
+
     def setChoice(self, x):
         """
         Replace the `choice` attribute.
 
+        `x` is a sequence of values over which to iterate. If a PyoObject 
+        with more than one audio streams is given, the streams will be 
+        flattened and inserted in the main list. For example, the choices:
+
+            [100, Randi(100,200,4), 200, Sig(250, mul=[1, 2])]
+
+        will expand to:
+            
+            [100, rand_val, 200, 250, 500] # the last two are audio streams.
+
         :Args:
 
-            x : list of floats
+            x: list of floats or PyoObjects
                 new `choice` attribute.
 
         """
+        pyoArgsAssert(self, "l", x)
         self._choice = x
-        if type(x[0]) != ListType:
-            [obj.setChoice(self._choice) for i, obj in enumerate(self._base_objs)]
+        x = self._flatten(x)
+        if type(x[0]) != list:
+            [obj.setChoice(x) for i, obj in enumerate(self._base_objs)]
         else:
-            [obj.setChoice(wrap(self._choice,i)) for i, obj in enumerate(self._base_objs)]
+            [obj.setChoice(wrap(x, i)) for i, obj in enumerate(self._base_objs)]
 
     def reset(self, x=0):
         """
         Resets the current count.
-        
+
         :Args:
-        
-            x : int, optional
+
+            x: int, optional
                 Value where to reset the count. Defaults to 0.
-        
+
         """
+        pyoArgsAssert(self, "I", x)
         [obj.reset(x) for obj in self._base_objs]
-        
+
     @property
-    def input(self): 
+    def input(self):
         """PyoObject. Audio trigger signal."""
         return self._input
     @input.setter
-    def input(self, x): 
+    def input(self, x):
         self.setInput(x)
     @property
-    def choice(self): 
-        """list of floats. Possible values."""
+    def choice(self):
+        """list of floats or PyoObjects. Possible values."""
         return self._choice
     @choice.setter
-    def choice(self, x): 
+    def choice(self, x):
         self.setChoice(x)
 
 class Count(PyoObject):
     """
     Counts integers at audio rate.
 
-    Count generates a signal increasing by 1 each sample when it receives a 
-    trigger. It can be used to do sample playback using TableIndex. 
+    Count generates a signal increasing by 1 each sample when it receives a
+    trigger. It can be used to do sample playback using TableIndex.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Trigger signal. Start or Restart the count.
-        min : int, optional
+        min: int, optional
             Minimum value of the count, included in the count. Defaults to 0.
-        max : int, optional
+        max: int, optional
             Maximum value of the count. excluded of the count. Defaults to 0.
-            
-            A value of 0 eliminates the maximum, and the count continues 
+
+            A value of 0 eliminates the maximum, and the count continues
             increasing without resetting.
 
     >>> s = Server().boot()
@@ -2872,6 +3105,7 @@ class Count(PyoObject):
 
     """
     def __init__(self, input, min=0, max=0, mul=1, add=0):
+        pyoArgsAssert(self, "oiiOO", input, min, max, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._min = min
@@ -2879,6 +3113,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):
         """
@@ -2886,12 +3121,13 @@ class Count(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New input signal.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
@@ -2901,10 +3137,11 @@ class Count(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 new `min` attribute.
 
         """
+        pyoArgsAssert(self, "i", x)
         self._min = x
         x, lmax = convertArgsToLists(x)
         [obj.setMin(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -2915,50 +3152,57 @@ class Count(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 new `max` attribute.
 
         """
+        pyoArgsAssert(self, "i", x)
         self._max = x
         x, lmax = 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, 10000, 'lin', 'min', self._min, res="int", dataOnly=True),
+                          SLMap(10000, 1000000, 'lin', 'max', self._max, res="int", dataOnly=True),
+                          SLMapMul(self._mul)]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
     @property
-    def input(self): 
+    def input(self):
         """PyoObject. Trigger signal. Start/Restart the count."""
         return self._input
     @input.setter
-    def input(self, x): 
+    def input(self, x):
         self.setInput(x)
     @property
-    def min(self): 
+    def min(self):
         """int. Minimum value."""
         return self._min
     @min.setter
-    def min(self, x): 
+    def min(self, x):
         self.setMin(x)
     @property
-    def max(self): 
+    def max(self):
         """int. Maximum value."""
         return self._max
     @max.setter
-    def max(self, x): 
+    def max(self, x):
         self.setMax(x)
 
 class NextTrig(PyoObject):
     """
     A trigger in the second stream opens a gate only for the next one in the first stream.
 
-    When the gate is opened by a trigger in `input2` signal, the next trigger 
+    When the gate is opened by a trigger in `input2` signal, the next trigger
     in `input` signal is allowed to pass and automatically closes the gate.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Trigger signal. Trigger stream waiting for the gate to be opened.
-        input2 : PyoObject
+        input2: PyoObject
             Trigger signal. Trigger stream opening the gate.
 
     .. note::
@@ -2977,6 +3221,7 @@ class NextTrig(PyoObject):
 
     """
     def __init__(self, input, input2, mul=1, add=0):
+        pyoArgsAssert(self, "ooOO", input, input2, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._input2 = input2
@@ -2984,6 +3229,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):
         """
@@ -2991,12 +3237,13 @@ class NextTrig(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
@@ -3006,28 +3253,29 @@ class NextTrig(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input2 = x
         self._in_fader2.setInput(x, fadetime)
 
     @property
-    def input(self): 
+    def input(self):
         """PyoObject. Incoming trigger stream signal."""
         return self._input
     @input.setter
-    def input(self, x): 
+    def input(self, x):
         self.setInput(x)
     @property
-    def input2(self): 
+    def input2(self):
         """PyoObject. Trigger stream opening the gate."""
         return self._input2
     @input2.setter
-    def input2(self, x): 
+    def input2(self, x):
         self.setInput2(x)
 
 class TrigVal(PyoObject):
@@ -3041,16 +3289,16 @@ class TrigVal(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Audio signal sending triggers.
-        value : float or PyoObject, optional
+        value: float or PyoObject, optional
             Next value. Defaults to 0.
-        init : float, optional
+        init: float, optional
             Initial value. Defaults to 0.
 
     .. note::
 
-        The out() method is bypassed. TrigVal's signal can not be sent 
+        The out() method is bypassed. TrigVal's signal can not be sent
         to audio outs.
 
     >>> s = Server().boot()
@@ -3064,12 +3312,14 @@ class TrigVal(PyoObject):
 
     """
     def __init__(self, input, value=0., init=0., mul=1, add=0):
+        pyoArgsAssert(self, "oOnOO", input, value, init, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._value = value
         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):
         """
@@ -3077,12 +3327,13 @@ class TrigVal(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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)
 
@@ -3092,10 +3343,11 @@ class TrigVal(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 new `value` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._value = x
         x, lmax = convertArgsToLists(x)
         [obj.setValue(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -3109,16 +3361,552 @@ class TrigVal(PyoObject):
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
-    def input(self): 
+    def input(self):
         """PyoObject. Audio trigger signal."""
         return self._input
     @input.setter
-    def input(self, x): 
+    def input(self, x):
         self.setInput(x)
     @property
-    def value(self): 
+    def value(self):
         """float or PyoObject. Next value."""
         return self._value
     @value.setter
-    def value(self, x): 
+    def value(self, x):
         self.setValue(x)
+
+class Euclide(PyoObject):
+    """
+    Euclidean rhythm generator.
+
+    This object generates euclidean trigger patterns, resulting in onsets
+    in the rhythm to be as equidistant as possible.
+
+    A trigger is an audio signal with a value of 1 surrounded by 0s.
+
+    The play() method starts the Euclide and is not called at the object
+    creation time.
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        time: float or PyoObject, optional
+            Time, in seconds, between each beat of the pattern. Defaults to 0.125.
+        taps: int, optional
+            Number of beats in the generated pattern (measure length), max = 64.
+            Defaults to 16.
+        onsets: int, optional
+            Number of onsets (a positive tap) in the generated pattern.
+            Defaults to 10.
+        poly: int, optional
+            Beat polyphony. Denotes how many independent streams are
+            generated by the object, allowing overlapping processes.
+
+            Available only at initialization. Defaults to 1.
+
+    .. note::
+
+        Euclide outputs many signals identified with a string between brackets:
+
+        |  obj['tap'] returns audio stream of the current tap of the measure.
+        |  obj['amp'] returns audio stream of the current beat amplitude.
+        |  obj['dur'] returns audio stream of the current beat duration in seconds.
+        |  obj['end'] returns audio stream with a trigger just before the end of the measure.
+
+        obj without brackets returns the generated trigger stream of the measure.
+
+        The out() method is bypassed. Euclide's signal can not be sent to audio outs.
+
+        Euclide has no `mul` and `add` attributes.
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> t = CosTable([(0,0), (100,1), (500,.3), (8191,0)])
+    >>> beat = Euclide(time=.125, taps=16, onsets=[8,7], poly=1).play()
+    >>> trmid = TrigXnoiseMidi(beat, dist=12, mrange=(60, 96))
+    >>> trhz = Snap(trmid, choice=[0,2,3,5,7,8,10], scale=1)
+    >>> tr2 = TrigEnv(beat, table=t, dur=beat['dur'], mul=beat['amp'])
+    >>> a = Sine(freq=trhz, mul=tr2*0.3).out()
+
+    """
+    def __init__(self, time=.125, taps=16, onsets=10, poly=1):
+        pyoArgsAssert(self, "OiiI", time, taps, onsets, poly)
+        PyoObject.__init__(self)
+        self._tap_dummy = []
+        self._amp_dummy = []
+        self._dur_dummy = []
+        self._end_dummy = []
+        self._time = time
+        self._taps = taps
+        self._onsets = onsets
+        self._poly = poly
+        time, taps, onsets, lmax = convertArgsToLists(time, taps, onsets)
+        self._base_players = [Beater_base(wrap(time,i), wrap(taps,i), wrap([100]*lmax,i), poly) 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)]
+        self._dur_objs = [BeatDurStream_base(wrap(self._base_players,j), i) for i in range(poly) for j in range(lmax)]
+        self._end_objs = [BeatEndStream_base(wrap(self._base_players,j), i) for i in range(poly) for j in range(lmax)]
+        for i in range(lmax):
+            preset = [wrap(taps,i)] + self.__generate__(wrap(onsets,i), wrap(taps,i))
+            self._base_players[i].setPresets([preset])
+            self._base_players[i].recall(0)
+
+    def __generate__(self, m, k):
+        """
+        Generates the euclidean rhythm for `m` onsets
+        in a measure of length `k` (number of taps).
+        Looping implementation, faster than recursive.
+        """
+        if m < 1: m = 1
+        if k < 1: k = 1
+        if m > k: m = k
+        k -= m
+        mv, kv = [1], [0]
+        while k > 1:
+            if m > k:
+                m, k = k, m-k
+                mv, kv = mv+kv, mv
+            else:
+                m, k = m, k-m
+                mv, kv = mv+kv, kv
+        return mv * m + kv * k
+
+    def __getitem__(self, i):
+        if i == 'tap':
+            self._tap_dummy.append(Dummy([obj for obj in self._tap_objs]))
+            return self._tap_dummy[-1]
+        if i == 'amp':
+            self._amp_dummy.append(Dummy([obj for obj in self._amp_objs]))
+            return self._amp_dummy[-1]
+        if i == 'dur':
+            self._dur_dummy.append(Dummy([obj for obj in self._dur_objs]))
+            return self._dur_dummy[-1]
+        if i == 'end':
+            self._end_dummy.append(Dummy([obj for obj in self._end_objs]))
+            return self._end_dummy[-1]
+        if type(i) == slice:
+            return self._base_objs[i]
+        if i < len(self._base_objs):
+            return self._base_objs[i]
+        else:
+            print("'i' too large!")
+
+    def get(self, identifier="amp", all=False):
+        """
+        Return the first sample of the current buffer as a float.
+
+        Can be used to convert audio stream to usable Python data.
+
+        "tap", "amp" or "dur" must be given to `identifier` to specify
+        which stream to get value from.
+
+        :Args:
+
+            identifier: string {"tap", "amp", "dur"}
+                Address string parameter identifying audio stream.
+                Defaults to "amp".
+            all: boolean, optional
+                If True, the first value of each object's stream
+                will be returned as a list.
+
+                If False, only the value of the first object's
+                stream will be returned as a float.
+
+        """
+        if not all:
+            return self.__getitem__(identifier)[0]._getStream().getValue()
+        else:
+            return [obj._getStream().getValue() for obj in self.__getitem__(identifier).getBaseObjects()]
+
+    def setTime(self, x):
+        """
+        Replace the `time` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                New `time` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._time = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setTime(wrap(x,i)) for i, obj in enumerate(self._base_players)]
+
+    def setTaps(self, x):
+        """
+        Replace the `taps` attribute.
+
+        :Args:
+
+            x: int
+                New `taps` attribute.
+
+        """
+        pyoArgsAssert(self, "i", x)
+        self._taps = x
+        x, onsets, lmax = convertArgsToLists(x, self._onsets)
+        for i in range(len(self._base_players)):
+            preset = [wrap(x,i)] + self.__generate__(wrap(onsets,i), wrap(x,i))
+            self._base_players[i].setPresets([preset])
+            self._base_players[i].recall(0)
+
+    def setOnsets(self, x):
+        """
+        Replace the `onsets` attribute.
+
+        :Args:
+
+            x: int
+                New `onsets` attribute.
+
+        """
+        pyoArgsAssert(self, "i", x)
+        self._onsets = x
+        x, taps, lmax = convertArgsToLists(x, self._taps)
+        for i in range(len(self._base_players)):
+            preset = [wrap(taps,i)] + self.__generate__(wrap(x,i), wrap(taps,i))
+            self._base_players[i].setPresets([preset])
+            self._base_players[i].recall(0)
+
+    def reset(self):
+        """
+        Reset internal counters to initialization values.
+
+        """
+        [obj.reset() 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)]
+        self._amp_objs = [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._amp_objs)]
+        self._dur_objs = [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._dur_objs)]
+        self._end_objs = [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._end_objs)]
+        return PyoObject.play(self, dur, delay)
+
+    def stop(self):
+        [obj.stop() for obj in self._tap_objs]
+        [obj.stop() for obj in self._amp_objs]
+        [obj.stop() for obj in self._dur_objs]
+        [obj.stop() for obj in self._end_objs]
+        return PyoObject.stop(self)
+
+    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 setSub(self, x):
+        pass
+
+    def setDiv(self, x):
+        pass
+
+    def ctrl(self, map_list=None, title=None, wxnoserver=False):
+        self._map_list = [SLMap(0.01, 1., 'lin', 'time', self._time),
+                          SLMap(2, 64, 'lin', 'taps', self._taps, res="int", dataOnly=True),
+                          SLMap(0, 64, 'lin', 'onsets', self._onsets, res="int", dataOnly=True)]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
+    @property
+    def time(self):
+        """float or PyoObject. Time, in seconds, between each beat."""
+        return self._time
+    @time.setter
+    def time(self, x): self.setTime(x)
+
+    @property
+    def taps(self):
+        """int. Number of beats in the generated pattern."""
+        return self._taps
+    @taps.setter
+    def taps(self, x): self.setTaps(x)
+
+    @property
+    def onsets(self):
+        """int. Number of onsets in the generated pattern."""
+        return self._onsets
+    @onsets.setter
+    def onsets(self, x): self.setOnsets(x)
+
+class TrigBurst(PyoObject):
+    """
+    Generates a time/amplitude expandable trigger pattern.
+
+    A trigger is an audio signal with a value of 1 surrounded by 0s.
+
+    When TrigBurst receives a trigger in its `input` argument, it starts
+    to output `count` triggers with a variable delay between each trigger
+    of the pattern. If `expand` is less than 1.0, the delay becomes shorter,
+    if it is greater than 1.0, the delay becomes longer.
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        input: PyoObject
+            Input signal sending triggers.
+        time: float or PyoObject, optional
+            Base time, in seconds, between each trig of the serie. Defaults to 0.25.
+        count: int, optional
+            Number of trigs generated (length of the serie). Defaults to 10.
+        expand: float, optional
+            Timing power serie factor. Each delay before the next trig is the
+            current delay (starting with `time`) times `expand` factor. Defaults to 1.0.
+        ampfade: float, optional
+            Amplitude power serie factor. Each amplitude in the serie is the
+            current amplitude (starting at 1) times `ampfade` factor. Defaults to 1.0.
+        poly: int, optional
+            Voice polyphony. Denotes how many independent streams are
+            generated by the object, allowing overlapping processes.
+
+            Available only at initialization. Defaults to 1.
+
+    .. note::
+
+        TrigBurst outputs many signals identified with a string between brackets:
+
+        |  obj['tap'] returns audio stream of the current tap of the serie.
+        |  obj['amp'] returns audio stream of the current beat amplitude.
+        |  obj['dur'] returns audio stream of the current beat duration in seconds.
+        |  obj['end'] returns audio stream with a trigger just before the end of the serie.
+
+        obj without brackets returns the generated trigger stream of the serie.
+
+        The out() method is bypassed. TrigBurst's signal can not be sent to audio outs.
+
+        TrigBurst has no `mul` and `add` attributes.
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> env = CosTable([(0,0), (100,0.5), (500, 0.3), (4096,0.3), (8192,0)])
+    >>> m = Metro(2).play()
+    >>> tb = TrigBurst(m, time=0.15, count=[15,20], expand=[0.92,0.9], ampfade=0.85)
+    >>> amp = TrigEnv(tb, env, dur=tb["dur"], mul=tb["amp"]*0.3)
+    >>> a = Sine([800,600], mul=amp)
+    >>> rev = STRev(a, inpos=[0,1], revtime=1.5, cutoff=5000, bal=0.1).out()
+
+    """
+    def __init__(self, input, time=.25, count=10, expand=1.0, ampfade=1.0, poly=1):
+        pyoArgsAssert(self, "oOinnI", input, time, count, expand, ampfade, poly)
+        PyoObject.__init__(self)
+        self._tap_dummy = []
+        self._amp_dummy = []
+        self._dur_dummy = []
+        self._end_dummy = []
+        self._input = input
+        self._time = time
+        self._count = count
+        self._expand = expand
+        self._ampfade = ampfade
+        self._poly = poly
+        self._in_fader = InputFader(input)
+        in_fader, time, count, expand, ampfade, lmax = convertArgsToLists(self._in_fader, time, count, expand, ampfade)
+        self._base_players = [TrigBurster_base(wrap(in_fader,i), wrap(time,i), wrap(count,i), wrap(expand,i), wrap(ampfade,i), poly) for i in range(lmax)]
+        self._base_objs = [TrigBurst_base(wrap(self._base_players,j), i) for i in range(poly) for j in range(lmax)]
+        self._tap_objs = [TrigBurstTapStream_base(wrap(self._base_players,j), i) for i in range(poly) for j in range(lmax)]
+        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':
+            self._tap_dummy.append(Dummy([obj for obj in self._tap_objs]))
+            return self._tap_dummy[-1]
+        if i == 'amp':
+            self._amp_dummy.append(Dummy([obj for obj in self._amp_objs]))
+            return self._amp_dummy[-1]
+        if i == 'dur':
+            self._dur_dummy.append(Dummy([obj for obj in self._dur_objs]))
+            return self._dur_dummy[-1]
+        if i == 'end':
+            self._end_dummy.append(Dummy([obj for obj in self._end_objs]))
+            return self._end_dummy[-1]
+        if type(i) == slice:
+            return self._base_objs[i]
+        if i < len(self._base_objs):
+            return self._base_objs[i]
+        else:
+            print("'i' too large!")
+
+    def get(self, identifier="amp", all=False):
+        """
+        Return the first sample of the current buffer as a float.
+
+        Can be used to convert audio stream to usable Python data.
+
+        "tap", "amp" or "dur" must be given to `identifier` to specify
+        which stream to get value from.
+
+        :Args:
+
+            identifier: string {"tap", "amp", "dur"}
+                Address string parameter identifying audio stream.
+                Defaults to "amp".
+            all: boolean, optional
+                If True, the first value of each object's stream
+                will be returned as a list.
+
+                If False, only the value of the first object's
+                stream will be returned as a float.
+
+        """
+        if not all:
+            return self.__getitem__(identifier)[0]._getStream().getValue()
+        else:
+            return [obj._getStream().getValue() for obj in self.__getitem__(identifier).getBaseObjects()]
+
+    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 setTime(self, x):
+        """
+        Replace the `time` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                New `time` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._time = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setTime(wrap(x,i)) for i, obj in enumerate(self._base_players)]
+
+    def setCount(self, x):
+        """
+        Replace the `count` attribute.
+
+        :Args:
+
+            x: int
+                New `count` attribute.
+
+        """
+        pyoArgsAssert(self, "i", x)
+        self._count = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setCount(wrap(x,i)) for i, obj in enumerate(self._base_players)]
+
+    def setExpand(self, x):
+        """
+        Replace the `expand` attribute.
+
+        :Args:
+
+            x: float
+                New `expand` attribute.
+
+        """
+        pyoArgsAssert(self, "n", x)
+        self._expand = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setExpand(wrap(x,i)) for i, obj in enumerate(self._base_players)]
+
+    def setAmpfade(self, x):
+        """
+        Replace the `ampfade` attribute.
+
+        :Args:
+
+            x: float
+                New `ampfade` attribute.
+
+        """
+        pyoArgsAssert(self, "n", x)
+        self._ampfade = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setAmpfade(wrap(x,i)) for i, obj in enumerate(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)]
+        self._amp_objs = [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._amp_objs)]
+        self._dur_objs = [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._dur_objs)]
+        self._end_objs = [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._end_objs)]
+        return PyoObject.play(self, dur, delay)
+
+    def stop(self):
+        [obj.stop() for obj in self._tap_objs]
+        [obj.stop() for obj in self._amp_objs]
+        [obj.stop() for obj in self._dur_objs]
+        [obj.stop() for obj in self._end_objs]
+        return PyoObject.stop(self)
+
+    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 setSub(self, x):
+        pass
+
+    def setDiv(self, x):
+        pass
+
+    def ctrl(self, map_list=None, title=None, wxnoserver=False):
+        self._map_list = [SLMap(0.1, 1., 'lin', 'time', self._time, dataOnly=True),
+                          SLMap(2, 128, 'lin', 'count', self._count, res="int", dataOnly=True),
+                          SLMap(0.5, 2.0, 'lin', 'expand', self._expand, dataOnly=True),
+                          SLMap(0.5, 1.0, 'lin', 'ampfade', self._ampfade, dataOnly=True)]
+        PyoObject.ctrl(self, map_list, title, wxnoserver)
+
+    @property
+    def input(self):
+        """PyoObject. Audio trigger signal."""
+        return self._input
+    @input.setter
+    def input(self, x): self.setInput(x)
+
+    @property
+    def time(self):
+        """float or PyoObject. Base time, in seconds, between each trig."""
+        return self._time
+    @time.setter
+    def time(self, x): self.setTime(x)
+
+    @property
+    def count(self):
+        """int. Number of triggers in the generated serie."""
+        return self._count
+    @count.setter
+    def count(self, x): self.setCount(x)
+
+    @property
+    def expand(self):
+        """float. Time's power expansion factor."""
+        return self._expand
+    @expand.setter
+    def expand(self, x): self.setExpand(x)
+
+    @property
+    def ampfade(self):
+        """float. Amplitude's power expansion factor."""
+        return self._ampfade
+    @ampfade.setter
+    def ampfade(self, x): self.setAmpfade(x)
diff --git a/pyolib/utils.py b/pyolib/utils.py
index f1de462..81f2a7b 100644
--- a/pyolib/utils.py
+++ b/pyolib/utils.py
@@ -1,30 +1,31 @@
+from __future__ import print_function
+from __future__ import absolute_import
 """
 Miscellaneous objects.
 
 """
 
 """
-Copyright 2010 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+You should have received a copy of the GNU Lesser General Public
+License along with pyo.  If not, see <http://www.gnu.org/licenses/>.
 """
-from _core import *
-from _maps import *
-from types import SliceType
+from ._core import *
+from ._maps import *
 import threading, time
 
 class Clean_objects(threading.Thread):
@@ -32,13 +33,13 @@ class Clean_objects(threading.Thread):
     Stops and deletes PyoObjects after a given time.
 
     The start() method starts the thread timer (must be called).
-    
+
     :Args:
 
-        time : float
-            Time, in seconds, to wait before calling stop on the given 
+        time: float
+            Time, in seconds, to wait before calling stop on the given
             objects and deleting them.
-        *args : PyoObject(s)
+        *args: PyoObject(s)
             Objects to delete.
 
     >>> s = Server().boot()
@@ -48,20 +49,20 @@ class Clean_objects(threading.Thread):
     >>> c = Biquad(a, freq=500, q=2, mul=b).out()
     >>> dump = Clean_objects(6, a, b, c)
     >>> dump.start()
-    
+
     """
     def __init__(self, time, *args):
         threading.Thread.__init__(self)
         self.t = time
         self.args = args
-        
+
     def run(self):
         time.sleep(self.t)
         for arg in self.args:
             try: arg.stop()
             except: pass
         for arg in self.args:
-            del arg 
+            del arg
 
 class Print(PyoObject):
     """
@@ -71,21 +72,21 @@ class Print(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to filter.
-        method : int {0, 1}, optional
+        method: int {0, 1}, optional
             There is two methods to set when a value is printed (Defaults to 0):
             0. at a periodic interval.
             1. everytime the value changed.
-        interval : float, optional
+        interval: float, optional
             Interval, in seconds, between each print. Used by method 0.
             Defaults to 0.25.
-        message : str, optional
+        message: str, optional
             Message to print before the current value. Defaults to "".
 
     .. note::
 
-        The out() method is bypassed. Print's signal can not be sent to 
+        The out() method is bypassed. Print's signal can not be sent to
         audio outs.
 
         Print has no `mul` and `add` attributes.
@@ -98,6 +99,7 @@ class Print(PyoObject):
 
     """
     def __init__(self, input, method=0, interval=0.25, message=""):
+        pyoArgsAssert(self, "oins", input, method, interval, message)
         PyoObject.__init__(self)
         self._input = input
         self._method = method
@@ -106,32 +108,35 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     def setMethod(self, x):
         """
         Replace the `method` attribute.
-        
+
         :Args:
 
-            x : int {0, 1}
+            x: int {0, 1}
                 New `method` attribute.
 
         """
+        pyoArgsAssert(self, "i", x)
         self._method = x
         x, lmax = convertArgsToLists(x)
         [obj.setMethod(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -142,10 +147,11 @@ class Print(PyoObject):
 
         :Args:
 
-            x : float
+            x: float
                 New `interval` attribute.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._interval = x
         x, lmax = convertArgsToLists(x)
         [obj.setInterval(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -156,10 +162,11 @@ class Print(PyoObject):
 
         :Args:
 
-            x : str
+            x: str
                 New `message` attribute.
 
         """
+        pyoArgsAssert(self, "s", x)
         self._message = x
         x, lmax = convertArgsToLists(x)
         [obj.setMessage(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -169,28 +176,28 @@ class Print(PyoObject):
 
     @property
     def input(self):
-        """PyoObject. Input signal.""" 
+        """PyoObject. Input signal."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def method(self):
-        """int. Controls when a value is printed.""" 
+        """int. Controls when a value is printed."""
         return self._method
     @method.setter
     def method(self, x): self.setMethod(x)
 
     @property
     def interval(self):
-        """float. For method 0, interval, in seconds, between each print.""" 
+        """float. For method 0, interval, in seconds, between each print."""
         return self._interval
     @interval.setter
     def interval(self, x): self.setInterval(x)
 
     @property
     def message(self):
-        """str. Message to print before the current value.""" 
+        """str. Message to print before the current value."""
         return self._message
     @message.setter
     def message(self, x): self.setMessage(x)
@@ -200,28 +207,28 @@ class Snap(PyoObject):
     Snap input values on a user's defined midi scale.
 
     Snap takes an audio input of floating-point values from 0
-    to 127 and output the nearest value in the `choice` parameter. 
-    `choice` can be defined on any number of octaves and the real 
-    snapping values will be automatically expended. The object 
-    will take care of the input octave range. According to `scale` 
-    parameter, output can be in midi notes, hertz or transposition 
+    to 127 and output the nearest value in the `choice` parameter.
+    `choice` can be defined on any number of octaves and the real
+    snapping values will be automatically expended. The object
+    will take care of the input octave range. According to `scale`
+    parameter, output can be in midi notes, hertz or transposition
     factor (centralkey = 60).
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Incoming Midi notes as an audio stream.
-        choice : list of floats
+        choice: list of floats
             Possible values, as midi notes, for output.
-        scale : int {0, 1, 2}, optional
+        scale: int {0, 1, 2}, optional
             Pitch output format.
                 0. MIDI (default)
                 1. Hertz
                 2. transposition factor
 
-            In the transpo mode, the central key (the key where there 
+            In the transpo mode, the central key (the key where there
             is no transposition) is 60.
 
     >>> s = Server().boot()
@@ -236,89 +243,91 @@ class Snap(PyoObject):
 
     """
     def __init__(self, input, choice, scale=0, mul=1, add=0):
+        pyoArgsAssert(self, "oliOO", input, choice, scale, mul, add)
         PyoObject.__init__(self, mul, add)
-        if type(choice) != ListType:
-            print >> sys.stderr, 'TypeError: "choice" argument of %s must be a list.\n' % self.__class__.__name__
-            exit()
         self._input = input
         self._choice = choice
         self._scale = scale
         self._in_fader = InputFader(input)
         in_fader, scale, mul, add, lmax = convertArgsToLists(self._in_fader, scale, mul, add)
-        if type(choice[0]) != ListType:
+        if type(choice[0]) != list:
             self._base_objs = [Snap_base(wrap(in_fader,i), choice, wrap(scale,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
         else:
             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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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 setChoice(self, x):
         """
         Replace the `choice` attribute.
-        
+
         :Args:
 
-            x : list of floats
+            x: list of floats
                 new `choice` attribute.
-        
+
         """
+        pyoArgsAssert(self, "l", x)
         self._choice = x
         [obj.setChoice(x) for i, obj in enumerate(self._base_objs)]
 
     def setScale(self, x):
         """
         Replace the `scale` attribute.
-        
-        Possible values are: 
+
+        Possible values are:
             0. Midi notes
             1. Hertz
             2. transposition factor (centralkey = 60)
 
         :Args:
 
-            x : int {0, 1, 2}
+            x: int {0, 1, 2}
                 new `scale` attribute.
 
         """
+        pyoArgsAssert(self, "i", x)
         self._scale = x
         x, lmax = convertArgsToLists(x)
         [obj.setScale(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     @property
-    def input(self): 
+    def input(self):
         """PyoObject. Audio signal to transform."""
         return self._input
     @input.setter
-    def input(self, x): 
+    def input(self, x):
         self.setInput(x)
     @property
-    def choice(self): 
+    def choice(self):
         """list of floats. Possible values."""
         return self._choice
     @choice.setter
-    def choice(self, x): 
+    def choice(self, x):
         self.setChoice(x)
     @property
-    def scale(self): 
+    def scale(self):
         """int. Output format."""
         return self._scale
     @scale.setter
-    def scale(self, x): 
+    def scale(self, x):
         self.setScale(x)
 
 class Interp(PyoObject):
@@ -329,11 +338,11 @@ class Interp(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             First input signal.
-        input2 : PyoObject
+        input2: PyoObject
             Second input signal.
-        interp : float or PyoObject, optional
+        interp: float or PyoObject, optional
             Averaging value. 0 means only first signal, 1 means only second
             signal. Default to 0.5.
 
@@ -346,6 +355,7 @@ class Interp(PyoObject):
 
     """
     def __init__(self, input, input2, interp=0.5, mul=1, add=0):
+        pyoArgsAssert(self, "ooOOO", input, input2, interp, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._input2 = input2
@@ -354,47 +364,51 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     def setInput2(self, x, fadetime=0.05):
         """
         Replace the `input2` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input2 = x
         self._in_fader2.setInput(x, fadetime)
-        
+
     def setInterp(self, x):
         """
         Replace the `interp` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `interp` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._interp = x
         x, lmax = convertArgsToLists(x)
         [obj.setInterp(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -402,46 +416,46 @@ class Interp(PyoObject):
     def ctrl(self, map_list=None, title=None, wxnoserver=False):
         self._map_list = [SLMap(0., 1., "lin", "interp", self._interp), SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
-      
+
     @property
     def input(self):
-        """PyoObject. First input signal.""" 
+        """PyoObject. First input signal."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def input2(self):
-        """PyoObject. Second input signal.""" 
+        """PyoObject. Second input signal."""
         return self._input2
     @input2.setter
     def input2(self, x): self.setInput2(x)
 
     @property
     def interp(self):
-        """float or PyoObject. Averaging value.""" 
+        """float or PyoObject. Averaging value."""
         return self._interp
     @interp.setter
     def interp(self, x): self.setInterp(x)
 
 class SampHold(PyoObject):
     """
-    Performs a sample-and-hold operation on its input. 
+    Performs a sample-and-hold operation on its input.
 
-    SampHold performs a sample-and-hold operation on its input according 
-    to the value of `controlsig`. If `controlsig` equals `value`, the input 
-    is sampled and holded until next sampling.
+    SampHold performs a sample-and-hold operation on its input according
+    to the value of `controlsig`. If `controlsig` equals `value`, the input
+    is sampled and held until next sampling.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal.
-        controlsig : PyoObject
+        controlsig: PyoObject
             Controls when to sample the signal.
-        value : float or PyoObject, optional
-            Sampling targeted value. Default to 0.0.
+        value: float or PyoObject, optional
+            Sampling target value. Default to 0.0.
 
     >>> s = Server().boot()
     >>> s.start()
@@ -452,6 +466,7 @@ class SampHold(PyoObject):
 
     """
     def __init__(self, input, controlsig, value=0.0, mul=1, add=0):
+        pyoArgsAssert(self, "ooOOO", input, controlsig, value, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._controlsig = controlsig
@@ -460,68 +475,72 @@ 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):
         """
         Replace the `input` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     def setControlsig(self, x, fadetime=0.05):
         """
         Replace the `controlsig` attribute.
-        
+
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New control signal.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._controlsig = x
         self._in_fader2.setInput(x, fadetime)
-        
+
     def setValue(self, x):
         """
         Replace the `value` attribute.
-        
+
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `value` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._value = x
         x, lmax = convertArgsToLists(x)
         [obj.setValue(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     @property
     def input(self):
-        """PyoObject. Input signal.""" 
+        """PyoObject. Input signal."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def controlsig(self):
-        """PyoObject. Control signal.""" 
+        """PyoObject. Control signal."""
         return self._controlsig
     @controlsig.setter
     def controlsig(self, x): self.setControlsig(x)
 
     @property
     def value(self):
-        """float or PyoObject. Targeted value.""" 
+        """float or PyoObject. Target value."""
         return self._value
     @value.setter
     def value(self, x): self.setValue(x)
@@ -530,24 +549,24 @@ class Record(PyoObject):
     """
     Writes input sound in an audio file on the disk.
 
-    `input` parameter must be a valid PyoObject or an addition of 
+    `input` parameter must be a valid PyoObject or an addition of
     PyoObjects, parameters can't be in list format.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to record.
-        filename : string
+        filename: string
             Full path of the file to create.
-        chnls : int, optional
+        chnls: int, optional
             Number of channels in the audio file. Defaults to 2.
-        fileformat : int, optional
+        fileformat: int, optional
             Format type of the audio file. Defaults to 0.
 
-            Record will first try to set the format from the filename extension. 
-            
+            Record will first try to set the format from the filename extension.
+
             If it's not possible, it uses the fileformat parameter. Supported formats are:
                 0. WAV - Microsoft WAV format (little endian) {.wav, .wave}
                 1. AIFF - Apple/SGI AIFF format (big endian) {.aif, .aiff}
@@ -557,9 +576,9 @@ class Record(PyoObject):
                 5. FLAC - FLAC lossless file format {.flac}
                 6. CAF - Core Audio File format {.caf}
                 7. OGG - Xiph OGG container {.ogg}
-        sampletype : int, optional
-            Bit depth encoding of the audio file. 
-            
+        sampletype: int, optional
+            Bit depth encoding of the audio file.
+
             SD2 and FLAC only support 16 or 24 bit int. Supported types are:
                 0. 16 bits int (default)
                 1. 24 bits int
@@ -568,20 +587,24 @@ class Record(PyoObject):
                 4. 64 bits float
                 5. U-Law encoded
                 6. A-Law encoded
-        buffering : int, optional
+        buffering: int, optional
             Number of bufferSize to wait before writing samples to disk.
-            
+
             High buffering uses more memory but improves performance.
             Defaults to 4.
+        quality: float, optional
+            The encoding quality value, between 0.0 (lowest quality) and
+            1.0 (highest quality). This argument has an effect only with
+            FLAC and OGG compressed formats. Defaults to 0.4.
 
     .. note::
 
-        All parameters can only be set at intialization time.    
+        All parameters can only be set at intialization time.
 
-        The stop() method must be called on the object to close the file 
+        The stop() method must be called on the object to close the file
         properly.
 
-        The out() method is bypassed. Record's signal can not be sent to 
+        The out() method is bypassed. Record's signal can not be sent to
         audio outs.
 
         Record has no `mul` and `add` attributes.
@@ -600,36 +623,62 @@ class Record(PyoObject):
     >>> clean.start()
 
     """
-    def __init__(self, input, filename, chnls=2, fileformat=0, sampletype=0, buffering=4):
+    def __init__(self, input, filename, chnls=2, fileformat=0, sampletype=0, buffering=4, quality=0.4):
+        pyoArgsAssert(self, "oSIIIIN", input, filename, chnls, fileformat, sampletype, buffering, quality)
         PyoObject.__init__(self)
         self._input = input
+        self._in_fader = InputFader(input)
         ext = filename.rsplit('.')
         if len(ext) >= 2:
             ext = ext[-1].lower()
-            if FILE_FORMATS.has_key(ext):
+            if ext in FILE_FORMATS:
                 fileformat = FILE_FORMATS[ext]
             else:
-                print 'Warning: Unknown file extension. Using fileformat value.'
+                print('Warning: Unknown file extension. Using fileformat value.')
         else:
-            print 'Warning: Filename has no extension. Using fileformat value.'
-        self._base_objs = [Record_base(self._input.getBaseObjects(), filename, chnls, fileformat, sampletype, buffering)]
+            print('Warning: Filename has no extension. Using fileformat value.')
+        self._base_objs = [Record_base(self._in_fader.getBaseObjects(), stringencode(filename), chnls, fileformat, sampletype, buffering, quality)]
+        self.play()
 
     def out(self, chnl=0, inc=1, dur=0, delay=0):
         return self.play(dur, delay)
 
+    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. Default to 0.05.
+
+        """
+        pyoArgsAssert(self, "oN", x, fadetime)
+        self._input = x
+        self._in_fader.setInput(x, fadetime)
+
+    @property
+    def input(self):
+        """PyoObject. Input signal to filter."""
+        return self._input
+    @input.setter
+    def input(self, x): self.setInput(x)
+
 class Denorm(PyoObject):
     """
     Mixes low level noise to an input signal.
 
-    Mixes low level (~1e-24 for floats, and ~1e-60 for doubles) noise to a an input signal. 
-    Can be used before IIR filters and reverbs to avoid denormalized numbers which may 
-    otherwise result in significantly increased CPU usage. 
+    Mixes low level (~1e-24 for floats, and ~1e-60 for doubles) noise to a an input signal.
+    Can be used before IIR filters and reverbs to avoid denormalized numbers which may
+    otherwise result in significantly increased CPU usage.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
 
     >>> s = Server().boot()
@@ -641,11 +690,13 @@ class Denorm(PyoObject):
 
     """
     def __init__(self, input, mul=1, add=0):
+        pyoArgsAssert(self, "oOO", input, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         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):
         """
@@ -653,18 +704,19 @@ class Denorm(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     @property
     def input(self):
-        """PyoObject. Input signal to filter.""" 
+        """PyoObject. Input signal to filter."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -680,46 +732,46 @@ class ControlRec(PyoObject):
     Each line in the text files contains two values, the absolute time
     in seconds and the sampled value.
 
-    The play() method starts the recording and is not called at the 
+    The play() method starts the recording and is not called at the
     object creation time.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to sample.
-        filename : string
+        filename: string
             Full path (without extension) used to create the files.
-             
+
             "_000" will be added to file's names with increasing digits
-            according to the number of streams in input. 
-            
-            The same filename can be passed to a ControlRead object to 
+            according to the number of streams in input.
+
+            The same filename can be passed to a ControlRead object to
             read all related files.
-        rate : int, optional
+        rate: int, optional
             Rate at which the input values are sampled. Defaults to 1000.
-        dur : float, optional
+        dur: float, optional
             Duration of the recording, in seconds. If 0.0, the recording
-            won't stop until the end of the performance. 
-            
-            If greater than 0.0, the `stop` method is automatically called 
+            won't stop until the end of the performance.
+
+            If greater than 0.0, the `stop` method is automatically called
             at the end of the recording.
 
     .. note::
 
-        All parameters can only be set at intialization time.    
+        All parameters can only be set at intialization time.
 
-        The write() method must be called on the object to write the files 
+        The write() method must be called on the object to write the files
         on the disk.
 
-        The out() method is bypassed. ControlRec's signal can not be sent to 
+        The out() method is bypassed. ControlRec's signal can not be sent to
         audio outs.
 
         ControlRec has no `mul` and `add` attributes.
 
-    .. seealso:: 
-        
+    .. seealso::
+
         :py:class:`ControlRead`
 
     >>> s = Server().boot()
@@ -736,6 +788,7 @@ class ControlRec(PyoObject):
 
     """
     def __init__(self, input, filename, rate=1000, dur=0.0):
+        pyoArgsAssert(self, "oSIN", input, filename, rate, dur)
         PyoObject.__init__(self)
         self._input = input
         self._filename = filename
@@ -752,7 +805,7 @@ class ControlRec(PyoObject):
     def write(self):
         """
         Writes recorded values in text files on the disk.
-        
+
         """
         for i, obj in enumerate(self._base_objs):
             f = open(os.path.join(self._path, "%s_%03d" % (self._name, i)), "w")
@@ -769,20 +822,20 @@ class ControlRead(PyoObject):
 
     :Args:
 
-        filename : string
-            Full path (without extension) used to create the files. 
-            
-            Usually the same filename as the one given to a ControlRec 
-            object to record automation. 
-            
+        filename: string
+            Full path (without extension) used to create the files.
+
+            Usually the same filename as the one given to a ControlRec
+            object to record automation.
+
             The directory will be scaned and all files
             named "filename_xxx" will add a new stream in the object.
-        rate : int, optional
+        rate: int, optional
             Rate at which the values are sampled. Defaults to 1000.
-        loop : boolean, optional
-            Looping mode, False means off, True means on. 
+        loop: boolean, optional
+            Looping mode, False means off, True means on.
             Defaults to False.
-        interp : int, optional
+        interp: int, optional
             Choice of the interpolation method.
                 1. no interpolation
                 2. linear (default)
@@ -791,19 +844,19 @@ class ControlRead(PyoObject):
 
     .. note::
 
-        ControlRead will sends a trigger signal at the end of the playback if 
-        loop is off or any time it wraps around if loop is on. User can 
+        ControlRead will send a trigger signal at the end of the playback if
+        loop is off or any time it wraps around if loop is on. User can
         retreive the trigger streams by calling obj['trig']:
 
         >>> rnds = ControlRead(home+"/freq_auto", loop=True)
         >>> t = SndTable(SNDS_PATH+"/transparent.aif")
         >>> loop = TrigEnv(rnds["trig"], t, dur=[.2,.3,.4,.5], mul=.5).out()
 
-        The out() method is bypassed. ControlRead's signal can not be sent to 
+        The out() method is bypassed. ControlRead's signal can not be sent to
         audio outs.
 
-    .. seealso:: 
-        
+    .. seealso::
+
         :py:class:`ControlRec`
 
     >>> s = Server().boot()
@@ -816,6 +869,7 @@ class ControlRead(PyoObject):
 
     """
     def __init__(self, filename, rate=1000, loop=False, interp=2, mul=1, add=0):
+        pyoArgsAssert(self, "SIBIOO", filename, rate, loop, interp, mul, add)
         PyoObject.__init__(self, mul, add)
         self._filename = filename
         self._path, self._name = os.path.split(filename)
@@ -832,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)
@@ -842,10 +897,11 @@ class ControlRead(PyoObject):
 
         :Args:
 
-            x : int
+            x: int
                 new `rate` attribute.
 
         """
+        pyoArgsAssert(self, "i", x)
         self._rate = x
         x, lmax = convertArgsToLists(x)
         [obj.setRate(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -856,10 +912,11 @@ class ControlRead(PyoObject):
 
         :Args:
 
-            x : boolean
+            x: boolean
                 new `loop` attribute.
 
         """
+        pyoArgsAssert(self, "b", x)
         self._loop = x
         x, lmax = convertArgsToLists(x)
         [obj.setLoop(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -870,30 +927,31 @@ class ControlRead(PyoObject):
 
         :Args:
 
-            x : int {1, 2, 3, 4}
+            x: int {1, 2, 3, 4}
                 new `interp` attribute.
 
         """
+        pyoArgsAssert(self, "i", x)
         self._interp = x
         x, lmax = convertArgsToLists(x)
         [obj.setInterp(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     @property
     def rate(self):
-        """int. Sampling frequency in cycles per second.""" 
+        """int. Sampling frequency in cycles per second."""
         return self._rate
     @rate.setter
     def rate(self, x): self.setRate(x)
 
     @property
-    def loop(self): 
-        """boolean. Looping mode.""" 
+    def loop(self):
+        """boolean. Looping mode."""
         return self._loop
     @loop.setter
     def loop(self, x): self.setLoop(x)
 
     @property
-    def interp(self): 
+    def interp(self):
         """int {1, 2, 3, 4}. Interpolation method."""
         return self._interp
     @interp.setter
@@ -910,38 +968,38 @@ class NoteinRec(PyoObject):
     Each line in the text files contains three values, the absolute time
     in seconds, the Midi pitch and the normalized velocity.
 
-    The play() method starts the recording and is not called at the 
+    The play() method starts the recording and is not called at the
     object creation time.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : Notein
+        input: Notein
             Notein signal to sample.
-        filename : string
+        filename: string
             Full path (without extension) used to create the files.
-             
+
             "_000" will be added to file's names with increasing digits
-            according to the number of streams in input. 
-            
-            The same filename can be passed to a NoteinRead object to read 
+            according to the number of streams in input.
+
+            The same filename can be passed to a NoteinRead object to read
             all related files.
 
     .. note::
 
-        All parameters can only be set at intialization time.    
+        All parameters can only be set at intialization time.
 
-        The `write` method must be called on the object to write the files 
+        The `write` method must be called on the object to write the files
         on the disk.
 
-        The out() method is bypassed. NoteinRec's signal can not be sent to 
+        The out() method is bypassed. NoteinRec's signal can not be sent to
         audio outs.
 
         NoteinRec has no `mul` and `add` attributes.
 
-    .. seealso:: 
-        
+    .. seealso::
+
         :py:class:`NoteinRead`
 
     >>> s = Server().boot()
@@ -953,6 +1011,7 @@ class NoteinRec(PyoObject):
 
     """
     def __init__(self, input, filename):
+        pyoArgsAssert(self, "oS", input, filename)
         PyoObject.__init__(self)
         self._input = input
         self._filename = filename
@@ -983,33 +1042,33 @@ class NoteinRead(PyoObject):
 
     :Args:
 
-        filename : string
-            Full path (without extension) used to create the files. 
-            
-            Usually the same filename as the one given to a NoteinRec 
-            object to record automation. 
-            
+        filename: string
+            Full path (without extension) used to create the files.
+
+            Usually the same filename as the one given to a NoteinRec
+            object to record automation.
+
             The directory will be scaned and all files
             named "filename_xxx" will add a new stream in the object.
-        loop : boolean, optional
-            Looping mode, False means off, True means on. 
+        loop: boolean, optional
+            Looping mode, False means off, True means on.
             Defaults to False.
 
     .. note::
 
-        NoteinRead will sends a trigger signal at the end of the playback if 
-        loop is off or any time it wraps around if loop is on. User can 
+        NoteinRead will send a trigger signal at the end of the playback if
+        loop is off or any time it wraps around if loop is on. User can
         retreive the trigger streams by calling obj['trig']:
 
         >>> notes = NoteinRead(home+"/notes_rec", loop=True)
         >>> t = SndTable(SNDS_PATH+"/transparent.aif")
         >>> loop = TrigEnv(notes["trig"], t, dur=[.2,.3,.4,.5], mul=.25).out()
 
-        The out() method is bypassed. NoteinRead's signal can not be sent to 
+        The out() method is bypassed. NoteinRead's signal can not be sent to
         audio outs.
 
-    .. seealso:: 
-        
+    .. seealso::
+
         :py:class:`NoteinRec`
 
     >>> s = Server().boot()
@@ -1022,6 +1081,7 @@ class NoteinRead(PyoObject):
 
     """
     def __init__(self, filename, loop=False, mul=1, add=0):
+        pyoArgsAssert(self, "SBOO", filename, loop, mul, add)
         PyoObject.__init__(self, mul, add)
         self._pitch_dummy = []
         self._velocity_dummy = []
@@ -1045,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':
@@ -1059,24 +1120,24 @@ class NoteinRead(PyoObject):
     def get(self, identifier="pitch", all=False):
         """
         Return the first sample of the current buffer as a float.
-        
+
         Can be used to convert audio stream to usable Python data.
-        
+
         "pitch" or "velocity" must be given to `identifier` to specify
         which stream to get value from.
-        
+
         :Args:
 
-            identifier : string {"pitch", "velocity"}
+            identifier: string {"pitch", "velocity"}
                 Address string parameter identifying audio stream.
                 Defaults to "pitch".
-            all : boolean, optional
+            all: boolean, optional
                 If True, the first value of each object's stream
-                will be returned as a list. 
-                
-                If False, only the value of the first object's stream 
+                will be returned as a list.
+
+                If False, only the value of the first object's stream
                 will be returned as a float.
-                 
+
         """
         if not all:
             return self.__getitem__(identifier)[0]._getStream().getValue()
@@ -1092,17 +1153,18 @@ class NoteinRead(PyoObject):
 
         :Args:
 
-            x : boolean
+            x: boolean
                 new `loop` attribute.
 
         """
+        pyoArgsAssert(self, "b", x)
         self._loop = x
         x, lmax = convertArgsToLists(x)
         [obj.setLoop(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     @property
-    def loop(self): 
-        """boolean. Looping mode.""" 
+    def loop(self):
+        """boolean. Looping mode."""
         return self._loop
     @loop.setter
     def loop(self, x): self.setLoop(x)
@@ -1119,7 +1181,7 @@ class DBToA(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal, decibel value.
 
     >>> s = Server().boot()
@@ -1132,11 +1194,13 @@ class DBToA(PyoObject):
     """
 
     def __init__(self, input, mul=1, add=0):
+        pyoArgsAssert(self, "oOO", input, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         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):
         """
@@ -1144,18 +1208,19 @@ class DBToA(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -1172,7 +1237,7 @@ class AToDB(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal, amplitude value.
 
     >>> s = Server().boot()
@@ -1186,11 +1251,13 @@ class AToDB(PyoObject):
     """
 
     def __init__(self, input, mul=1, add=0):
+        pyoArgsAssert(self, "oOO", input, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         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):
         """
@@ -1198,18 +1265,19 @@ class AToDB(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -1218,26 +1286,26 @@ class Scale(PyoObject):
     """
     Maps an input range of audio values to an output range.
 
-    Scale maps an input range of audio values to an output range. 
-    The ranges can be specified with `min` and `max` reversed for 
-    invert-mapping. If specified, the mapping can also be exponential. 
+    Scale maps an input range of audio values to an output range.
+    The ranges can be specified with `min` and `max` reversed for
+    invert-mapping. If specified, the mapping can also be exponential.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        inmin : float or PyoObject, optional
+        inmin: float or PyoObject, optional
             Minimum input value. Defaults to 0.
-        inmax : float or PyoObject, optional
+        inmax: float or PyoObject, optional
             Maximum input value. Defaults to 1.
-        outmin : float or PyoObject, optional
+        outmin: float or PyoObject, optional
             Minimum output value. Defaults to 0.
-        outmax : float or PyoObject, optional
+        outmax: float or PyoObject, optional
             Maximum output value. Defaults to 1.
-        exp : float, optional
-            Exponent value, specifies the nature of the scaling curve. 
+        exp: float, optional
+            Exponent value, specifies the nature of the scaling curve.
             Values between 0 and 1 give a reversed curve.  Defaults to 1.0.
 
     >>> s = Server().boot()
@@ -1251,6 +1319,7 @@ class Scale(PyoObject):
 
     """
     def __init__(self, input, inmin=0, inmax=1, outmin=0, outmax=1, exp=1, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOOnOO", input, inmin, inmax, outmin, outmax, exp, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._inmin = inmin
@@ -1261,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):
         """
@@ -1268,12 +1338,13 @@ class Scale(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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)
 
@@ -1283,10 +1354,11 @@ class Scale(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `inmin` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._inmin = x
         x, lmax = convertArgsToLists(x)
         [obj.setInMin(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1297,10 +1369,11 @@ class Scale(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `inmax` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._inmax = x
         x, lmax = convertArgsToLists(x)
         [obj.setInMax(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1311,10 +1384,11 @@ class Scale(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `outmin` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._outmin = x
         x, lmax = convertArgsToLists(x)
         [obj.setOutMin(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1325,10 +1399,11 @@ class Scale(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `outmax` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._outmax = x
         x, lmax = convertArgsToLists(x)
         [obj.setOutMax(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1339,47 +1414,48 @@ class Scale(PyoObject):
 
         :Args:
 
-            x : float
+            x: float
                 New `exp` attribute.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._exp = x
         x, lmax = convertArgsToLists(x)
         [obj.setExp(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., 127., 'lin', 'inmin',  self._inmin),
-                          SLMap(0., 127., 'lin', 'inmax',  self._inmax),
-                          SLMap(0., 127., 'lin', 'outmin',  self._outmin),
-                          SLMap(0., 127., 'lin', 'outmax',  self._outmax),
-                          SLMap(1., 10., 'lin', 'exp',  self._exp),
+        self._map_list = [SLMap(0., 127., 'lin', 'inmin', self._inmin),
+                          SLMap(0., 127., 'lin', 'inmax', self._inmax),
+                          SLMap(0., 127., 'lin', 'outmin', self._outmin),
+                          SLMap(0., 127., 'lin', 'outmax', self._outmax),
+                          SLMap(1., 10., 'lin', 'exp', self._exp),
                           SLMapMul(self._mul)]
         PyoObject.ctrl(self, map_list, title, wxnoserver)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def inmin(self):
-        """float or PyoObject. Minimum input value.""" 
+        """float or PyoObject. Minimum input value."""
         return self._inmin
     @inmin.setter
     def inmin(self, x): self.setInMin(x)
 
     @property
     def inmax(self):
-        """float or PyoObject. Maximum input value.""" 
+        """float or PyoObject. Maximum input value."""
         return self._inmax
     @inmax.setter
     def inmax(self, x): self.setInMax(x)
 
     @property
     def outmin(self):
-        """float or PyoObject. Minimum output value.""" 
+        """float or PyoObject. Minimum output value."""
         return self._outmin
     @outmin.setter
     def outmin(self, x): self.setOutMin(x)
@@ -1408,7 +1484,7 @@ class CentsToTranspo(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal, cents value.
 
     >>> s = Server().boot()
@@ -1421,11 +1497,13 @@ class CentsToTranspo(PyoObject):
     """
 
     def __init__(self, input, mul=1, add=0):
+        pyoArgsAssert(self, "oOO", input, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         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):
         """
@@ -1433,18 +1511,19 @@ class CentsToTranspo(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -1459,7 +1538,7 @@ class TranspoToCents(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal, transposition factor.
 
     >>> s = Server().boot()
@@ -1473,11 +1552,13 @@ class TranspoToCents(PyoObject):
     """
 
     def __init__(self, input, mul=1, add=0):
+        pyoArgsAssert(self, "oOO", input, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         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):
         """
@@ -1485,18 +1566,19 @@ class TranspoToCents(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -1505,14 +1587,14 @@ class MToF(PyoObject):
     """
     Returns the frequency (Hz) equivalent to a midi note.
 
-    Returns the frequency (Hz) equivalent to a midi note, 
+    Returns the frequency (Hz) equivalent to a midi note,
     60 = 261.62556530066814 Hz.
 
     :Parent: :py:class:`PyoObject`
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal as midi note.
 
     >>> s = Server().boot()
@@ -1525,11 +1607,71 @@ class MToF(PyoObject):
     """
 
     def __init__(self, input, mul=1, add=0):
+        pyoArgsAssert(self, "oOO", input, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         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):
+        """
+        Replace the `input` attribute.
+
+        :Args:
+
+            x: PyoObject
+                New signal to process.
+            fadetime: float, optional
+                Crossfade time between old and new input. Default to 0.05.
+
+        """
+        pyoArgsAssert(self, "oN", x, fadetime)
+        self._input = x
+        self._in_fader.setInput(x, fadetime)
+
+    @property
+    def input(self):
+        """PyoObject. Input signal to process."""
+        return self._input
+    @input.setter
+    def input(self, x): self.setInput(x)
+
+class FToM(PyoObject):
+    """
+    Returns the midi note equivalent to a frequency in Hz.
+
+    Returns the midi note equivalent to a frequency in Hz,
+    440.0 (hz) = 69.
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        input: PyoObject
+            Input signal as frequency in Hz.
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> lfo = Sine([0.2,0.25], mul=300, add=600)
+    >>> src = SineLoop(freq=lfo, feedback=0.05)
+    >>> hz = Yin(src, minfreq=100, maxfreq=1000, cutoff=500)
+    >>> mid = FToM(hz)
+    >>> fr = Snap(mid, choice=[0,2,5,7,9], scale=1)
+    >>> freq = Port(fr, risetime=0.01, falltime=0.01)
+    >>> syn = SineLoop(freq, feedback=0.05, mul=0.3).out()
+
+    """
+
+    def __init__(self, input, mul=1, add=0):
+        pyoArgsAssert(self, "oOO", input, mul, add)
+        PyoObject.__init__(self, mul, add)
+        self._input = input
+        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):
         """
@@ -1537,18 +1679,19 @@ class MToF(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
@@ -1564,10 +1707,10 @@ class MToT(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal as midi note.
-        centralkey : float, optional
-            The midi note that returns a transposition factor of 1, 
+        centralkey: float, optional
+            The midi note that returns a transposition factor of 1,
             that is to say no transposition. Defaults to 60.
 
     >>> s = Server().boot()
@@ -1583,12 +1726,14 @@ class MToT(PyoObject):
     """
 
     def __init__(self, input, centralkey=60.0, mul=1, add=0):
+        pyoArgsAssert(self, "onOO", input, centralkey, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._centralkey = centralkey
         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):
         """
@@ -1596,12 +1741,13 @@ class MToT(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            fadetime: float, optional
                 Crossfade time between old and new input. Default to 0.05.
 
         """
+        pyoArgsAssert(self, "oN", x, fadetime)
         self._input = x
         self._in_fader.setInput(x, fadetime)
 
@@ -1611,23 +1757,24 @@ class MToT(PyoObject):
 
         :Args:
 
-            x : float
+            x: float
                 New `centralkey` attribute.
 
         """
+        pyoArgsAssert(self, "n", x)
         self._centralkey = x
         x, lmax = convertArgsToLists(x)
         [obj.setCentralKey(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
     @property
     def centralkey(self):
-        """float. The midi note that returns no transposition.""" 
+        """float. The midi note that returns no transposition."""
         return self._centralkey
     @centralkey.setter
     def centralkey(self, x): self.setCentralKey(x)
@@ -1643,11 +1790,11 @@ class Between(PyoObject):
 
     :Args:
 
-        input : PyoObject
+        input: PyoObject
             Input signal to process.
-        min : float or PyoObject, optional
+        min: float or PyoObject, optional
             Minimum range value. Defaults to 0.
-        max : float or PyoObject, optional
+        max: float or PyoObject, optional
             Maximum range value. Defaults to 1.
 
     >>> s = Server().boot()
@@ -1659,6 +1806,7 @@ class Between(PyoObject):
 
     """
     def __init__(self, input, min=-1.0, max=1.0, mul=1, add=0):
+        pyoArgsAssert(self, "oOOOO", input, min, max, mul, add)
         PyoObject.__init__(self, mul, add)
         self._input = input
         self._min = min
@@ -1666,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):
         """
@@ -1673,12 +1822,13 @@ class Between(PyoObject):
 
         :Args:
 
-            x : PyoObject
+            x: PyoObject
                 New signal to process.
-            fadetime : float, optional
+            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)
 
@@ -1688,10 +1838,11 @@ class Between(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `min` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._min = x
         x, lmax = convertArgsToLists(x)
         [obj.setMin(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1702,10 +1853,11 @@ class Between(PyoObject):
 
         :Args:
 
-            x : float or PyoObject
+            x: float or PyoObject
                 New `max` attribute.
 
         """
+        pyoArgsAssert(self, "O", x)
         self._max = x
         x, lmax = convertArgsToLists(x)
         [obj.setMax(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -1718,21 +1870,189 @@ class Between(PyoObject):
 
     @property
     def input(self):
-        """PyoObject. Input signal to process.""" 
+        """PyoObject. Input signal to process."""
         return self._input
     @input.setter
     def input(self, x): self.setInput(x)
 
     @property
     def min(self):
-        """float or PyoObject. Minimum range value.""" 
+        """float or PyoObject. Minimum range value."""
         return self._min
     @min.setter
     def min(self, x): self.setMin(x)
 
     @property
     def max(self):
-        """float or PyoObject. Maximum range value.""" 
+        """float or PyoObject. Maximum range value."""
         return self._max
     @max.setter
     def max(self, x): self.setMax(x)
+
+class TrackHold(PyoObject):
+    """
+    Performs a track-and-hold operation on its input.
+
+    TrackHold lets pass the signal in `input` without modification but hold
+    a sample according to the value of `controlsig`. If `controlsig` equals
+    `value`, the input is sampled and held, otherwise, it passes thru.
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        input: PyoObject
+            Input signal.
+        controlsig: PyoObject
+            Controls when to sample the signal.
+        value: float or PyoObject, optional
+            Sampling target value. Default to 0.0.
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> ph = Phasor([3,4])
+    >>> lf = Sine(.2, mul=.5, add=.5)
+    >>> th = TrackHold(lf, ph > 0.5, 1, mul=500, add=300)
+    >>> a = Sine(th, mul=.3).out()
+
+    """
+    def __init__(self, input, controlsig, value=0.0, mul=1, add=0):
+        pyoArgsAssert(self, "ooOOO", input, controlsig, value, mul, add)
+        PyoObject.__init__(self, mul, add)
+        self._input = input
+        self._controlsig = controlsig
+        self._value = value
+        self._in_fader = InputFader(input)
+        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):
+        """
+        Replace the `input` attribute.
+
+        :Args:
+
+            x: PyoObject
+                New signal to process.
+            fadetime: float, optional
+                Crossfade time between old and new input. Default to 0.05.
+
+        """
+        pyoArgsAssert(self, "oN", x, fadetime)
+        self._input = x
+        self._in_fader.setInput(x, fadetime)
+
+    def setControlsig(self, x, fadetime=0.05):
+        """
+        Replace the `controlsig` attribute.
+
+        :Args:
+
+            x: PyoObject
+                New control signal.
+            fadetime: float, optional
+                Crossfade time between old and new input. Default to 0.05.
+
+        """
+        pyoArgsAssert(self, "oN", x, fadetime)
+        self._controlsig = x
+        self._in_fader2.setInput(x, fadetime)
+
+    def setValue(self, x):
+        """
+        Replace the `value` attribute.
+
+        :Args:
+
+            x: float or PyoObject
+                New `value` attribute.
+
+        """
+        pyoArgsAssert(self, "O", x)
+        self._value = x
+        x, lmax = convertArgsToLists(x)
+        [obj.setValue(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)
+
+    @property
+    def controlsig(self):
+        """PyoObject. Control signal."""
+        return self._controlsig
+    @controlsig.setter
+    def controlsig(self, x): self.setControlsig(x)
+
+    @property
+    def value(self):
+        """float or PyoObject. Target value."""
+        return self._value
+    @value.setter
+    def value(self, x): self.setValue(x)
+
+class Resample(PyoObject):
+    """
+    Realtime upsampling or downsampling of an audio signal.
+
+    This object should be used in the context of a resampling block
+    created with the Server's methods `beginResamplingBlock` and
+    `EndResamplingBlock`.
+
+    If used inside the block, it will resample its input signal according
+    to the resampling factor given to `beginResamplingFactor`. If the factor
+    is a negative value, the new virtual sampling rate will be
+    `current sr / abs(factor)`. If the factor is a postive value, the new
+    virtual sampling rate will be `current sr * factor`.
+
+    If used after `endResamplingBlock`, it will resample its input signal
+    to the current sampling rate of the server.
+
+    The `mode` argument specifies the interpolation/decimation mode used
+    internally.
+
+    :Parent: :py:class:`PyoObject`
+
+    :Args:
+
+        input: PyoObject
+            Input signal to resample.
+        mode: int, optional
+            The interpolation/decimation mode. Defaults to 1.
+            For the upsampling process, possible values are:
+                0: zero-padding
+                1: sample-and-hold
+                2 or higher: the formula `mode * resampling factor` gives
+                the FIR lowpass kernel length used to interpolate.
+            For the downsampling process, possible values are:
+                0 or 1: discard extra samples
+                2 or higher: the formula `mode * abs(resampling factor)`
+                gives the FIR lowpass kernel length used for the decimation.
+            Available at initialization time only.
+
+    >>> s = Server().boot()
+    >>> s.start()
+    >>> drv = Sine(.5, phase=[0, 0.5], mul=0.49, add=0.5)
+    >>> sig = SfPlayer(SNDS_PATH+"/transparent.aif", loop=True)
+    >>> s.beginResamplingBlock(8)
+    >>> sigup = Resample(sig, mode=32)
+    >>> drvup = Resample(drv, mode=1)
+    >>> disto = Disto(sigup, drive=drvup, mul=0.5)
+    >>> s.endResamplingBlock()
+    >>> sigdown = Resample(disto, mode=32, mul=0.4).out()
+
+    """
+
+    def __init__(self, input, mode=1, mul=1, add=0):
+        pyoArgsAssert(self, "oiOO", input, mode, mul, add)
+        PyoObject.__init__(self, mul, add)
+        self._input = input
+        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/pyolib/wxgui.py b/pyolib/wxgui.py
new file mode 100644
index 0000000..2f4ff70
--- /dev/null
+++ b/pyolib/wxgui.py
@@ -0,0 +1,988 @@
+"""
+The classes in this module are based on internal classes that where
+originally designed to help the creation of graphical tools for the
+control and the visualization of audio signals. WxPython must be installed
+under the current Python distribution to access these classes.
+
+"""
+from __future__ import absolute_import
+from ._widgets import PYO_USE_WX
+
+if not PYO_USE_WX:
+    NO_WX_MESSAGE = "WxPython must be installed on the system to use pyo's wx widgets."
+    class PyoGuiControlSlider:
+
+        def __init__(self, *args, **kwargs):
+            raise Exception(NO_WX_MESSAGE)
+    class PyoGuiVuMeter:
+
+        def __init__(self, *args, **kwargs):
+            raise Exception(NO_WX_MESSAGE)
+    class PyoGuiGrapher:
+
+        def __init__(self, *args, **kwargs):
+            raise Exception(NO_WX_MESSAGE)
+    class PyoGuiMultiSlider:
+
+        def __init__(self, *args, **kwargs):
+            raise Exception(NO_WX_MESSAGE)
+    class PyoGuiSpectrum:
+
+        def __init__(self, *args, **kwargs):
+            raise Exception(NO_WX_MESSAGE)
+    class PyoGuiScope:
+
+        def __init__(self, *args, **kwargs):
+            raise Exception(NO_WX_MESSAGE)
+    class PyoGuiSndView:
+
+        def __init__(self, *args, **kwargs):
+            raise Exception(NO_WX_MESSAGE)
+else:
+    import wx
+    import wx.lib.newevent
+    from ._wxwidgets import ControlSlider, VuMeter, Grapher, DataMultiSlider
+    from ._wxwidgets import SpectrumPanel, ScopePanel, SndViewTablePanel, HRangeSlider
+
+    if "phoenix" not in wx.version():
+        wx.QueueEvent = wx.PostEvent
+
+    # Custom events
+    PyoGuiControlSliderEvent, EVT_PYO_GUI_CONTROL_SLIDER = wx.lib.newevent.NewEvent()
+    PyoGuiGrapherEvent, EVT_PYO_GUI_GRAPHER = wx.lib.newevent.NewEvent()
+    PyoGuiMultiSliderEvent, EVT_PYO_GUI_MULTI_SLIDER = wx.lib.newevent.NewEvent()
+    PyoGuiSndViewMousePositionEvent, EVT_PYO_GUI_SNDVIEW_MOUSE_POSITION = wx.lib.newevent.NewEvent()
+    PyoGuiSndViewSelectionEvent, EVT_PYO_GUI_SNDVIEW_SELECTION = wx.lib.newevent.NewEvent()
+
+    class PyoGuiControlSlider(ControlSlider):
+        """
+        Floating-point control slider.
+
+        :Parent: wx.Panel
+
+        :Events:
+
+            EVT_PYO_GUI_CONTROL_SLIDER
+                Sent after any change of the slider position. The current
+                value of the slider can be retrieve with the `value`
+                attribute of the generated event. The object itself can be
+                retrieve with the `object` attribute of the event and the
+                object's id with the `id` attrbute.
+
+        :Args:
+
+            parent: wx.Window
+                The parent window.
+            minvalue: float
+                The minimum value of the slider.
+            maxvalue: float
+                The maximum value of the slider.
+            init: float, optional
+                The initial value of the slider. If None, the slider
+                inits to the minimum value. Defaults to None.
+            pos: tuple, optional
+                The slider's position in pixel (x, y). Defaults to (0, 0).
+            size: tuple, optional
+                The slider's size in pixel (x, y). Defaults to (200, 16).
+            log: boolean, optional
+                If True, creates a logarithmic slider (minvalue must be
+                greater than 0). Defaults to False.
+            integer: boolean, optional
+                If True, creates an integer slider. Defaults to False.
+            powoftwo: boolean, optional
+                If True, creates a power-of-two slider (log is automatically
+                False and integer is True). If True, minvalue and maxvalue
+                must be exponents to base 2 but init is a real power-of-two
+                value. Defaults to False.
+            orient: {wx.HORIZONTAL or wx.VERTICAL}, optional
+                The slider's orientation. Defaults to wx.HORIZONTAL.
+
+        """
+        def __init__(self, parent, minvalue, maxvalue, init=None, pos=(0, 0),
+                     size=(200, 16), log=False, integer=False, powoftwo=False,
+                     orient=wx.HORIZONTAL):
+            super(PyoGuiControlSlider, self).__init__(parent, minvalue, maxvalue,
+                                                      init, pos, size, log,
+                                                      self._outFunction, integer,
+                                                      powoftwo,
+                                                      parent.GetBackgroundColour(),
+                                                      orient)
+
+        def _outFunction(self, value):
+            evt = PyoGuiControlSliderEvent(value=value, id=self.GetId(), object=self)
+            wx.QueueEvent(self, evt)
+
+        def enable(self):
+            """
+            Enable the slider for user input.
+
+            """
+            super(PyoGuiControlSlider, self).Enable()
+
+        def disable(self):
+            """
+            Disable the slider for user input.
+
+            """
+            super(PyoGuiControlSlider, self).Disable()
+
+        def setValue(self, x, propagate=True):
+            """
+            Sets a new value to the slider.
+
+            :Args:
+
+                x: int or float
+                    The controller number.
+                propagate: boolean, optional
+                    If True, an event will be sent after the call.
+
+            """
+            super(PyoGuiControlSlider, self).SetValue(x, propagate)
+
+        def setMidiCtl(self, x, propagate=True):
+            """
+            Sets the midi controller number to show on the slider.
+
+            :Args:
+
+                x: int
+                    The controller number.
+                propagate: boolean, optional
+                    If True, an event will be sent after the call.
+
+            """
+            super(PyoGuiControlSlider, self).setMidiCtl(x, propagate)
+
+        def setRange(self, minvalue, maxvalue):
+            """
+            Sets new minimum and maximum values.
+
+            :Args:
+
+                minvalue: int or float
+                    The new minimum value.
+                maxvalue: int or float
+                    The new maximum value.
+
+            """
+            super(PyoGuiControlSlider, self).setRange(minvalue, maxvalue)
+
+        def getValue(self):
+            """
+            Returns the current value of the slider.
+
+            """
+            return super(PyoGuiControlSlider, self).GetValue()
+
+        def getMidiCtl(self):
+            """
+            Returns the midi controller number, if any, assigned to the slider.
+
+            """
+            return super(PyoGuiControlSlider, self).getMidiCtl()
+
+        def getMinValue(self):
+            """
+            Returns the current minimum value.
+
+            """
+            return super(PyoGuiControlSlider, self).getMinValue()
+
+        def getMaxValue(self):
+            """
+            Returns the current maximum value.
+
+            """
+            return super(PyoGuiControlSlider, self).getMaxValue()
+
+        def getInit(self):
+            """
+            Returns the initial value.
+
+            """
+            return super(PyoGuiControlSlider, self).getInit()
+
+        def getRange(self):
+            """
+            Returns minimum and maximum values as a list.
+
+            """
+            return super(PyoGuiControlSlider, self).getRange()
+
+        def isInteger(self):
+            """
+            Returns True if the slider manage only integer, False otherwise.
+
+            """
+            return self.integer
+
+        def isLog(self):
+            """
+            Returns True if the slider is logarithmic, False otherwise.
+
+            """
+            return self.log
+
+        def isPowOfTwo(self):
+            """
+            Returns True if the slider manage only power-of-two values, False otherwise.
+
+            """
+            return self.powoftwo
+
+    class PyoGuiVuMeter(VuMeter):
+        """
+        Multi-channels Vu Meter.
+
+        When registered as the Server's meter, its internal method `setRms`
+        will be called each buffer size with a list of normalized amplitudes
+        as argument. The `setRms` method can also be registered as the
+        function callback of a PeakAmp object.
+
+        :Parent: wx.Panel
+
+        :Args:
+
+            parent: wx.Window
+                The parent window.
+            nchnls: int, optional
+                The initial number of channels of the meter. Defaults to 2.
+            pos: wx.Point, optional
+                Window position in pixels. Defaults to (0, 0).
+            size: tuple, optional
+                The meter's size in pixels (x, y). Defaults to (200, 11).
+            orient: {wx.HORIZONTAL or wx.VERTICAL}, optional
+                The meter's orientation. Defaults to wx.HORIZONTAL.
+            style: int, optional
+                Window style (see wx.Window documentation). Defaults to 0.
+
+        """
+        def __init__(self, parent, nchnls=2, pos=(0, 0), size=(200, 11),
+                     orient=wx.HORIZONTAL, style=0):
+            super(PyoGuiVuMeter, self).__init__(parent, size, nchnls, orient,
+                                                pos, style)
+
+        def setNchnls(self, nchnls):
+            """
+            Sets the number of channels of the meter.
+
+            :Args:
+
+                nchnls: int
+                    The number of channels.
+
+            """
+            super(PyoGuiVuMeter, self).setNumSliders(nchnls)
+
+    class PyoGuiGrapher(Grapher):
+        """
+        Multi-modes break-points function editor.
+
+        :Parent: wx.Panel
+
+        :Events:
+
+            EVT_PYO_GUI_GRAPHER
+                Sent after any change of the grapher function. The current
+                list of points of the grapher can be retrieve with the `value`
+                attribute of the generated event. The object itself can be
+                retrieve with the `object` attribute of the event and the
+                object's id with the `id` attrbute.
+
+        :Args:
+
+            parent: wx.Window
+                The parent window.
+            xlen: int, optional
+                The length, in samples, of the grapher. Defaults to 8192.
+            yrange: two-values tuple, optional
+                A tuple indicating the minimum and maximum values of the Y-axis.
+                Defaults to (0, 1).
+            init: list of two-values tuples, optional
+                The initial break-points function set as normalized values.
+                A point is defined with its X and Y positions as a tuple.
+                Defaults to [(0.0, 0.0), (1.0, 1.0)].
+            mode: int, optional
+                The grapher mode definning how line segments will be draw.
+                Possible modes are:
+                    0. linear (default)
+                    1. cosine
+                    2. exponential (uses `exp` and `inverse` arguments)
+                    3. curve       (uses `tension` and `bias` arguments)
+                    4. logarithmic
+                    5. logarithmic cosine
+            exp: int or float, optional
+                The exponent factor for an exponential graph. Defaults to 10.0.
+            inverse: boolean, optional
+                If True, downward slope will be inversed. Useful to create
+                biexponential curves. Defaults to True.
+            tension: int or float, optional
+                Curvature at the known points. 1 is high, 0 normal, -1 is low.
+                Defaults to 0.
+            bias: int or float, optional
+                Curve attraction (for each segments) toward bundary points.
+                0 is even, positive is towards first point, negative is towards
+                the second point. Defaults to 0.
+            pos: wx.Point, optional
+                Window position in pixels. Defaults to (0, 0).
+            size: wx.Size, optional
+                Window size in pixels. Defaults to (300, 200).
+            style: int, optional
+                Window style (see wx.Window documentation). Defaults to 0.
+
+        """
+        def __init__(self, parent, xlen=8192, yrange=(0, 1), init=[(0.0, 0.0), (1.0, 1.0)],
+                     mode=0, exp=10, inverse=True, tension=0, bias=0, pos=(0, 0),
+                     size=(300, 200), style=0):
+            super(PyoGuiGrapher, self).__init__(parent, xlen, yrange, init, mode,
+                                                exp, inverse, tension, bias,
+                                                self._outFunction, pos, size, style)
+
+        def _outFunction(self, value):
+            evt = PyoGuiGrapherEvent(value=value, id=self.GetId(), object=self)
+            wx.QueueEvent(self, evt)
+
+        def _refresh(self):
+            self.Refresh()
+            self.sendValues()
+
+        def reset(self):
+            """
+            Resets the points to the initial state.
+
+            """
+            super(PyoGuiGrapher, self).reset()
+
+        def getPoints(self):
+            """
+            Returns the current normalized points of the grapher.
+
+            """
+            return super(PyoGuiGrapher, self).getPoints()
+
+        def getValues(self):
+            """
+            Returns the current points, according to Y-axis range, of the grapher.
+
+            """
+            return super(PyoGuiGrapher, self).getValues()
+
+        def setPoints(self, pts):
+            """
+            Sets a new group of normalized points in the grapher.
+
+            :Args:
+
+                pts: list of two-values tuples
+                    New normalized (between 0 and 1) points.
+
+            """
+            self.points = [pt for pt in pts]
+            self._refresh()
+
+        def setValues(self, vals):
+            """
+            Sets a new group of points, according to Y-axis range, in the grapher.
+
+            :Args:
+
+                vals: list of two-values tuples
+                    New real points.
+
+            """
+            self.points = [self.valuesToPoint(val) for val in vals]
+            self._refresh()
+
+        def setYrange(self, yrange):
+            """
+            Sets a new Y-axis range to the grapher.
+
+            :Args:
+
+                yrange: two-values tuple
+                    New Y-axis range.
+
+            """
+            vals = self.getValues()
+            self.yrange = yrange
+            self.setValues(vals)
+
+        def setInitPoints(self, pts):
+            """
+            Sets a new initial normalized points list to the grapher.
+
+            :Args:
+
+                pts: list of two-values tuples
+                    New normalized (between 0 and 1) initial points.
+
+            """
+            super(PyoGuiGrapher, self).setInitPoints(pts)
+
+        def setMode(self, x):
+            """
+            Changes the grapher's mode.
+
+            :Args:
+
+                x: int
+                    New mode. Possible modes are:
+                        0. linear (default)
+                        1. cosine
+                        2. exponential (uses `exp` and `inverse` arguments)
+                        3. curve       (uses `tension` and `bias` arguments)
+                        4. logarithmic
+                        5. logarithmic cosine
+
+            """
+            self.mode = x
+            self._refresh()
+
+        def setExp(self, x):
+            """
+            Changes the grapher's exponent factor for exponential graph.
+
+            :Args:
+
+                x: float
+                    New exponent factor.
+
+            """
+            self.exp = x
+            self._refresh()
+
+        def setInverse(self, x):
+            """
+            Changes the grapher's inverse boolean for exponential graph.
+
+            :Args:
+
+                x: boolean
+                    New inverse factor.
+
+            """
+            self.inverse = x
+            self._refresh()
+
+        def setTension(self, x):
+            """
+            Changes the grapher's tension factor for curved graph.
+
+            :Args:
+
+                x: float
+                    New tension factor.
+
+            """
+            self.tension = x
+            self._refresh()
+
+        def setBias(self, x):
+            """
+            Changes the grapher's bias factor for curved graph.
+
+            :Args:
+
+                x: float
+                    New bias factor.
+
+            """
+            self.bias = x
+            self._refresh()
+
+    class PyoGuiMultiSlider(DataMultiSlider):
+        """
+        Data multi-sliders editor.
+
+        :Parent: wx.Panel
+
+        :Events:
+
+            EVT_PYO_GUI_MULTI_SLIDER
+                Sent after any change of the multi-sliders values. The current
+                list of values of the multi-sliders can be retrieve with the
+                `value` attribute of the generated event. The object itself can
+                be retrieve with the `object` attribute of the event and the
+                object's id with the `id` attrbute.
+
+        :Args:
+
+            parent: wx.Window
+                The parent window.
+            xlen: int, optional
+                The number of sliders in the multi-sliders. Defaults to 16.
+            yrange: two-values tuple
+                A tuple indicating the minimum and maximum values of the Y-axis.
+                Defaults to (0, 1).
+            init: list values, optional
+                The initial list of values of the multi-sliders.
+                Defaults to None, meaning all sliders initialized to the
+                minimum value.
+            pos: wx.Point, optional
+                Window position in pixels. Defaults to (0, 0).
+            size: wx.Size, optional
+                Window size in pixels. Defaults to (300, 200).
+            style: int, optional
+                Window style (see wx.Window documentation). Defaults to 0.
+
+        """
+        def __init__(self, parent, xlen=16, yrange=(0, 1), init=None,
+                    pos=(0, 0), size=(300, 200), style=0):
+            if init is None:
+                init = [yrange[0]] * xlen
+            else:
+                if len(init) < xlen:
+                    init += [yrange[0]] * (xlen - len(init))
+                elif len(init) > xlen:
+                    init = init[:xlen]
+            super(PyoGuiMultiSlider, self).__init__(parent, init, yrange,
+                                                    self._outFunction, pos,
+                                                    size, style)
+
+        def _outFunction(self, value):
+            evt = PyoGuiMultiSliderEvent(value=value, id=self.GetId(), object=self)
+            wx.QueueEvent(self, evt)
+
+        def reset(self):
+            """
+            Resets the sliders to their initial state.
+
+            """
+            super(PyoGuiMultiSlider, self).reset()
+
+        def getValues(self):
+            """
+            Returns the current values of the sliders.
+
+            """
+            return [v for v in self.values]
+
+        def setValues(self, vals):
+            """
+            Sets new values to the sliders.
+
+            :Args:
+
+                vals: list of values
+                    New values.
+
+            """
+            wx.CallAfter(super(PyoGuiMultiSlider, self).update, vals)
+
+        def setYrange(self, yrange):
+            """
+            Sets a new Y-axis range to the multi-sliders.
+
+            :Args:
+
+                yrange: two-values tuple
+                    New Y-axis range.
+
+            """
+            self.yrange = (float(yrange[0]), float(yrange[1]))
+            self.Refresh()
+
+    class PyoGuiSpectrum(SpectrumPanel):
+        """
+        Frequency spectrum display.
+
+        This widget should be used with the Spectrum object, which measures
+        the magnitude of an input signal versus frequency within a user
+        defined range. It can show both magnitude and frequency on linear
+        or logarithmic scale.
+
+        To create the bridge between the analyzer and the display, the
+        Spectrum object must be registered in the PyoGuiSpectrum object
+        with the setAnalyzer(obj) method. The Spectrum object will
+        automatically call the update(points) method to refresh the display.
+
+        :Parent: wx.Panel
+
+        :Args:
+
+            parent: wx.Window
+                The parent window.
+            lowfreq: int or float, optional
+                The lowest frequency, in Hz, to display on the X-axis.
+                Defaults to 0.
+            highfreq: int or float, optional
+                The highest frequency, in Hz, to display on the X-axis.
+                Defaults to 22050.
+            fscaling: int, optional
+                The frequency scaling on the X-axis. 0 means linear, 1 means
+                logarithmic. Defaults to 0.
+            mscaling: int, optional
+                The magnitude scaling on the Y-axis. 0 means linear, 1 means
+                logarithmic. Defaults to 0.
+            pos: wx.Point, optional
+                Window position in pixels. Defaults to (0, 0).
+            size: wx.Size, optional
+                Window size in pixels. Defaults to (300, 200).
+            style: int, optional
+                Window style (see wx.Window documentation). Defaults to 0.
+
+        """
+        def __init__(self, parent, lowfreq=0, highfreq=22050, fscaling=0,
+                     mscaling=0, pos=(0, 0), size=(300, 200), style=0):
+            super(PyoGuiSpectrum, self).__init__(parent, 1, lowfreq, highfreq,
+                                                 fscaling, mscaling, pos, size, style)
+
+        def update(self, points):
+            """
+            Display updating method.
+
+            This method is automatically called by the audio analyzer
+            object (Spectrum) with points to draw as arguments. The points
+            are already formatted for the current drawing surface to save
+            CPU cycles.
+
+            The method setAnalyzer(obj) must be used to register the audio
+            analyzer object.
+
+            :Args:
+
+                points: list of list of tuples
+                    A list containing n-channels list of tuples. A tuple
+                    is a point (X-Y coordinates) to draw.
+
+            """
+            wx.CallAfter(self.setImage, points)
+
+        def setAnalyzer(self, object):
+            """
+            Register an audio analyzer object (Spectrum).
+
+            :Args:
+
+                object: Spectrum object
+                    The audio object performing the frequency analysis.
+
+            """
+            self.obj = object
+            self.obj.setFunction(self.update)
+            self.obj.setLowFreq(self.lowfreq)
+            self.obj.setHighFreq(self.highfreq)
+            self.obj.setFscaling(self.fscaling)
+            self.obj.setMscaling(self.mscaling)
+
+        def setLowFreq(self, x):
+            """
+            Changes the lowest frequency of the display.
+
+            This method propagates the value to the audio analyzer.
+
+            :Args:
+
+                x: int or float
+                    New lowest frequency.
+
+            """
+            if self.obj is not None:
+                self.obj.setLowFreq(x)
+            super(PyoGuiSpectrum, self).setLowFreq(x)
+
+        def setHighFreq(self, x):
+            """
+            Changes the highest frequency of the display.
+
+            This method propagates the value to the audio analyzer.
+
+            :Args:
+
+                x: int or float
+                    New highest frequency.
+
+            """
+            if self.obj is not None:
+                self.obj.setHighFreq(x)
+            super(PyoGuiSpectrum, self).setHighFreq(x)
+
+        def setFscaling(self, x):
+            """
+            Changes the frequency scaling (X-axis) of the display.
+
+            This method propagates the value to the audio analyzer.
+
+            :Args:
+
+                x: int
+                    0 means linear scaling, 1 means logarithmic scaling.
+
+            """
+            if self.obj is not None:
+                self.obj.setFscaling(x)
+            super(PyoGuiSpectrum, self).setFscaling(x)
+
+        def setMscaling(self, x):
+            """
+            Changes the magnitude scaling (Y-axis) of the display.
+
+            This method propagates the value to the audio analyzer.
+
+            :Args:
+
+                x: int
+                    0 means linear scaling, 1 means logarithmic scaling.
+
+            """
+            if self.obj is not None:
+                self.obj.setMscaling(x)
+            super(PyoGuiSpectrum, self).setMscaling(x)
+
+    class PyoGuiScope(ScopePanel):
+        """
+        Oscilloscope display.
+
+        This widget should be used with the Scope object, which computes
+        the waveform of an input signal to display on a GUI.
+
+        To create the bridge between the analyzer and the display, the
+        Scope object must be registered in the PyoGuiScope object with
+        the setAnalyzer(obj) method. The Scope object will automatically
+        call the update(points) method to refresh the display.
+
+        :Parent: wx.Panel
+
+        :Args:
+
+            parent: wx.Window
+                The parent window.
+            length: float, optional
+                Length, in seconds, of the waveform segment displayed on
+                the window. Defaults to 0.05.
+            gain: float, optional
+                Linear gain applied to the signal to be displayed.
+                Defaults to 0.67.
+            pos: wx.Point, optional
+                Window position in pixels. Defaults to (0, 0).
+            size: wx.Size, optional
+                Window size in pixels. Defaults to (300, 200).
+            style: int, optional
+                Window style (see wx.Window documentation). Defaults to 0.
+
+        """
+        def __init__(self, parent, length=0.05, gain=0.67, pos=(0, 0),
+                     size=(300, 200), style=0):
+            super(PyoGuiScope, self).__init__(parent, None, pos, size, style)
+            super(PyoGuiScope, self).setLength(length)
+            super(PyoGuiScope, self).setGain(gain)
+
+        def update(self, points):
+            """
+            Display updating method.
+
+            This method is automatically called by the audio analyzer
+            object (Scope) with points to draw as arguments. The points
+            are already formatted for the current drawing surface to save
+            CPU cycles.
+
+            The method setAnalyzer(obj) must be used to register the audio
+            analyzer object.
+
+            :Args:
+
+                points: list of list of tuples
+                    A list containing n-channels list of tuples. A tuple
+                    is a point (X-Y coordinates) to draw.
+
+            """
+            wx.CallAfter(self.setImage, points)
+
+        def setAnalyzer(self, object):
+            """
+            Register an audio analyzer object (Scope).
+
+            :Args:
+
+                object: Scope object
+                    The audio object performing the waveform analysis.
+
+            """
+            self.obj = object
+            self.obj.setFunction(self.update)
+            self.obj.setLength(self.length)
+            self.obj.setGain(self.gain)
+
+        def setLength(self, x):
+            """
+            Changes the length, in seconds, of the displayed audio segment.
+
+            This method propagates the value to the audio analyzer.
+
+            :Args:
+
+                x: float
+                    New segment length in seconds.
+
+            """
+            if self.obj is not None:
+                self.obj.setLength(x)
+            super(PyoGuiScope, self).setLength(x)
+
+        def setGain(self, x):
+            """
+            Changes the gain applied to the input signal.
+
+            This method propagates the value to the audio analyzer.
+
+            :Args:
+
+                x: float
+                    New linear gain.
+
+            """
+            if self.obj is not None:
+                self.obj.setGain(x)
+            super(PyoGuiScope, self).setGain(x)
+
+    # left-click + drag ===> event position
+    # right-click + drag ===> highlight a selection + event selection (start, end)
+    # Shift + right-click + drag ===> move the selection + event selection (start, end)
+    # Ctrl + right-click ===> delete the selection + event selection (0.0, 1.0)
+    class PyoGuiSndView(wx.Panel):
+        """
+        Soundfile display.
+
+        This widget should be used with the SndTable object, which keeps
+        soundfile in memory and computes the waveform to display on the GUI.
+
+        To create the bridge between the audio memory and the display, the
+        SndTable object must be registered in the PyoGuiSndView object with
+        the setTable(object) method.
+
+        The SndTable object will automatically call the update() method to
+        refresh the display when the table is modified.
+
+        :Parent: wx.Panel
+
+        :Events:
+
+            EVT_PYO_GUI_SNDVIEW_MOUSE_POSITION
+                Sent when the mouse is moving on the panel with the left
+                button pressed. The `value` attribute of the event will
+                hold the normalized position of the mouse into the sound.
+                For X-axis value, 0.0 is the beginning of the sound and 1.0
+                is the end of the sound. For the Y-axis, 0.0 is the bottom
+                of the panel and 1.0 is the top. The object itself can be
+                retrieve with the `object` attribute of the event and the
+                object's id with the `id` attrbute.
+            EVT_PYO_GUI_SNDVIEW_SELECTION
+                Sent when a new region is selected on the panel. A new
+                selection is created with a Right-click and drag on the panel.
+                The current selection can be moved with Shift+Right-click and
+                drag. Ctrl+Right-click (Cmd on OSX) remove the selected region.
+                The `value` attribute of the event will hold the normalized
+                selection as a tuple (min, max). 0.0 means the beginning of
+                the sound and 1.0 means the end of the sound. The object itself
+                can be retrieve with the `object` attribute of the event and the
+                object's id with the `id` attrbute.
+
+        :Args:
+
+            parent: wx.Window
+                The parent window.
+            pos: wx.Point, optional
+                Window position in pixels. Defaults to (0, 0).
+            size: wx.Size, optional
+                Window size in pixels. Defaults to (300, 200).
+            style: int, optional
+                Window style (see wx.Window documentation). Defaults to 0.
+
+        """
+        def __init__(self, parent, pos=(0, 0), size=(300, 200), style=0):
+            wx.Panel.__init__(self, parent, pos=pos, size=size, style=style)
+            box = wx.BoxSizer(wx.VERTICAL)
+            self._curzoom = (0.0, 1.0)
+            self.sndview = SndViewTablePanel(self, None,
+                                             self._position_callback,
+                                             self._select_callback)
+            box.Add(self.sndview, 1, wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, 5)
+            self.zoom = HRangeSlider(self, minvalue=0, maxvalue=1,
+                                     valtype='float', function=self._setZoom,
+                                     backColour=parent.GetBackgroundColour())
+            box.Add(self.zoom, 0, wx.EXPAND|wx.LEFT|wx.RIGHT, 5)
+            self.SetSizer(box)
+
+        def _setZoom(self, values=None):
+            if values is None:
+                values = self._curzoom
+            dur = self.sndview.getDur()
+            self.sndview.setBegin(dur * values[0])
+            self.sndview.setEnd(dur * values[1])
+            self._curzoom = values
+            self.update()
+
+        def _position_callback(self, pos):
+            evt = PyoGuiSndViewMousePositionEvent(value=pos, id=self.GetId(), object=self)
+            wx.QueueEvent(self, evt)
+
+        def _select_callback(self, selection):
+            selection = (max(0.0, min(selection)), min(max(selection), 1.0))
+            evt = PyoGuiSndViewSelectionEvent(value=selection, id=self.GetId(), object=self)
+            wx.QueueEvent(self, evt)
+
+        def __del__(self):
+            if self.sndview.obj is not None:
+                self.sndview.obj._setViewFrame(None)
+
+        def update(self):
+            """
+            Display updating method.
+
+            This method is automatically called by the audio memory
+            object (SndTable) when the table is modified.
+
+            The method setTable(obj) must be used to register the audio
+            memory object.
+
+            """
+            wx.CallAfter(self.sndview.setImage)
+
+        def setTable(self, object):
+            """
+            Register an audio memory object (SndTable).
+
+            :Args:
+
+                object: SndTable object
+                    The audio table keeping the sound in memory.
+
+            """
+            object._setViewFrame(self)
+            self.sndview.obj = object
+            self.sndview.setBegin(0.0)
+            self.sndview.setEnd(object.getDur(False))
+            self.sndview.chnls = len(object)
+            self.update()
+
+        def setSelection(self, start, stop):
+            """
+            Changes the selected region.
+
+            This method will trigger a EVT_PYO_GUI_SNDVIEW_SELECTION event
+            with a tuple (start, stop) as value.
+
+            :Args:
+
+                start: float
+                    The starting point of the selected region. This value
+                    must be normalized between 0 and 1 (0 is the beginning
+                    of the sound, 1 is the end).
+                stop: float
+                    The ending point of the selected region. This value
+                    must be normalized between 0 and 1 (0 is the beginning
+                    of the sound, 1 is the end).
+
+            """
+            self.sndview.setSelection(start, stop)
+
+        def resetSelection(self):
+            """
+            Removes the selected region.
+
+            This method will trigger a EVT_PYO_GUI_SNDVIEW_SELECTION event
+            with a tuple (0.0, 1.0) as value.
+
+            """
+            self.sndview.resetSelection()
diff --git a/scripts/compile_win.bat b/scripts/compile_win.bat
index 39bde38..3f97f1f 100644
--- a/scripts/compile_win.bat
+++ b/scripts/compile_win.bat
@@ -1,19 +1,29 @@
 echo off
-
-echo *** Compile for python2.6 ***
-C:\Python26\python.exe setup.py install --use-double
-
-RMDIR /S /Q build
+
+RMDIR /S /Q build
 
 echo *** Compile for python2.7 ***
 C:\Python27\python.exe setup.py install --use-double
 
 RMDIR /S /Q build
+
+echo *** Compile for python3.5-32 ***
+C:\Users\olivier\AppData\Local\Programs\Python\Python35-32\python.exe setup.py install --use-double
+
+RMDIR /S /Q build
+
+echo *** Compile for python3.6-32 ***
+C:\Users\olivier\AppData\Local\Programs\Python\Python36-32\python.exe setup.py install --use-double
+
+RMDIR /S /Q build
 
 cd utils
 
-echo *** Build E-Pyo for python2.6 ***
-C:\Python26\python.exe epyo_builder_win32.py
-
 echo *** Build E-Pyo for python2.7 ***
 C:\Python27\python.exe epyo_builder_win32.py
+
+echo *** Build E-Pyo for python3.5-32 ***
+C:\Users\olivier\AppData\Local\Programs\Python\Python35-32\python.exe epyo_builder_win32.py
+
+echo *** Build E-Pyo for python3.6-32 ***
+C:\Users\olivier\AppData\Local\Programs\Python\Python36-32\python.exe epyo_builder_win32.py
diff --git a/scripts/get_dependencies.sh b/scripts/get_dependencies.sh
deleted file mode 100644
index beea096..0000000
--- a/scripts/get_dependencies.sh
+++ /dev/null
@@ -1,46 +0,0 @@
-if cd /usr/local/include; 
-then 
-    pwd;
-else 
-    sudo mkdir /usr/local/include
-    cd /usr/local/include;
-fi
-sudo curl http://www.iact.umontreal.ca/pyo_dep_headers/portaudio.h -o "portaudio.h"
-sudo curl http://www.iact.umontreal.ca/pyo_dep_headers/portmidi.h -o "portmidi.h"
-sudo curl http://www.iact.umontreal.ca/pyo_dep_headers/porttime.h -o "porttime.h"
-sudo curl http://www.iact.umontreal.ca/pyo_dep_headers/sndfile.h -o "sndfile.h"
-
-
-if cd lo;
-then
-    pwd;
-else
-    sudo mkdir lo
-    cd lo;
-fi    
-sudo curl http://www.iact.umontreal.ca/pyo_dep_headers/lo/lo_endian.h -o "lo_endian.h"
-sudo curl http://www.iact.umontreal.ca/pyo_dep_headers/lo/lo_errors.h -o "lo_errors.h"
-sudo curl http://www.iact.umontreal.ca/pyo_dep_headers/lo/lo_lowlevel.h -o "lo_lowlevel.h"
-sudo curl http://www.iact.umontreal.ca/pyo_dep_headers/lo/lo_macros.h -o "lo_macros.h"
-sudo curl http://www.iact.umontreal.ca/pyo_dep_headers/lo/lo_osc_types.h -o "lo_osc_types.h"
-sudo curl http://www.iact.umontreal.ca/pyo_dep_headers/lo/lo_throw.h -o "lo_throw.h"
-sudo curl http://www.iact.umontreal.ca/pyo_dep_headers/lo/lo_types.h -o "lo_types.h"
-sudo curl http://www.iact.umontreal.ca/pyo_dep_headers/lo/lo.h -o "lo.h"
-
-if cd /usr/local/lib; 
-then 
-    pwd;
-else 
-    sudo mkdir /usr/local/lib
-    cd /usr/local/lib;
-fi
-sudo curl http://www.iact.umontreal.ca/pyo_deps/liblo.0.dylib -o "liblo.0.dylib"
-sudo curl http://www.iact.umontreal.ca/pyo_deps/libportaudio.2.dylib -o "libportaudio.2.dylib"
-sudo curl http://www.iact.umontreal.ca/pyo_deps/libportmidi.dylib -o "libportmidi.dylib"
-sudo curl http://www.iact.umontreal.ca/pyo_deps/libsndfile.1.dylib -o "libsndfile.1.dylib"
-sudo rm libsndfile.dylib
-sudo ln -s libsndfile.1.dylib libsndfile.dylib
-sudo rm liblo.dylib
-sudo ln -s liblo.0.dylib liblo.dylib
-sudo rm libportaudio.dylib
-sudo ln -s libportaudio.2.dylib libportaudio.dylib
diff --git a/scripts/get_dependencies_x86_64.sh b/scripts/get_dependencies_x86_64.sh
deleted file mode 100644
index 81626d0..0000000
--- a/scripts/get_dependencies_x86_64.sh
+++ /dev/null
@@ -1,46 +0,0 @@
-if cd /usr/local/include; 
-then 
-    pwd;
-else 
-    sudo mkdir /usr/local/include
-    cd /usr/local/include;
-fi
-sudo curl http://www.iact.umontreal.ca/pyo_dep_headers_x86_64/portaudio.h -o "portaudio.h"
-sudo curl http://www.iact.umontreal.ca/pyo_dep_headers_x86_64/portmidi.h -o "portmidi.h"
-sudo curl http://www.iact.umontreal.ca/pyo_dep_headers_x86_64/porttime.h -o "porttime.h"
-sudo curl http://www.iact.umontreal.ca/pyo_dep_headers_x86_64/sndfile.h -o "sndfile.h"
-
-
-if cd lo;
-then
-    pwd;
-else
-    sudo mkdir lo
-    cd lo;
-fi    
-sudo curl http://www.iact.umontreal.ca/pyo_dep_headers_x86_64/lo/lo_endian.h -o "lo_endian.h"
-sudo curl http://www.iact.umontreal.ca/pyo_dep_headers_x86_64/lo/lo_errors.h -o "lo_errors.h"
-sudo curl http://www.iact.umontreal.ca/pyo_dep_headers_x86_64/lo/lo_lowlevel.h -o "lo_lowlevel.h"
-sudo curl http://www.iact.umontreal.ca/pyo_dep_headers_x86_64/lo/lo_macros.h -o "lo_macros.h"
-sudo curl http://www.iact.umontreal.ca/pyo_dep_headers_x86_64/lo/lo_osc_types.h -o "lo_osc_types.h"
-sudo curl http://www.iact.umontreal.ca/pyo_dep_headers_x86_64/lo/lo_throw.h -o "lo_throw.h"
-sudo curl http://www.iact.umontreal.ca/pyo_dep_headers_x86_64/lo/lo_types.h -o "lo_types.h"
-sudo curl http://www.iact.umontreal.ca/pyo_dep_headers_x86_64/lo/lo.h -o "lo.h"
-
-if cd /usr/local/lib; 
-then 
-    pwd;
-else 
-    sudo mkdir /usr/local/lib
-    cd /usr/local/lib;
-fi
-sudo curl http://www.iact.umontreal.ca/pyo_deps_x86_64/liblo.7.dylib -o "liblo.7.dylib"
-sudo curl http://www.iact.umontreal.ca/pyo_deps_x86_64/libportaudio.2.dylib -o "libportaudio.2.dylib"
-sudo curl http://www.iact.umontreal.ca/pyo_deps_x86_64/libportmidi.dylib -o "libportmidi.dylib"
-sudo curl http://www.iact.umontreal.ca/pyo_deps_x86_64/libsndfile.1.dylib -o "libsndfile.1.dylib"
-sudo rm libsndfile.dylib
-sudo ln -s libsndfile.1.dylib libsndfile.dylib
-sudo rm liblo.dylib
-sudo ln -s liblo.7.dylib liblo.dylib
-sudo rm libportaudio.dylib
-sudo ln -s libportaudio.2.dylib libportaudio.dylib
diff --git a/scripts/html_man.py b/scripts/html_man.py
index a127f07..1d239f4 100644
--- a/scripts/html_man.py
+++ b/scripts/html_man.py
@@ -1,25 +1,23 @@
 """
-Copyright 2010 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+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 os, inspect, shutil
-from types import ListType
 from pyo import *
 
 #######################################################
@@ -32,7 +30,7 @@ if man_file == 'manual-dev':
     man_version = 'latest sources'
 else:
     man_version = 'version %s' % PYO_VERSION
-print PYO_VERSION
+print(PYO_VERSION)
 
 try:
     os.mkdir(os.getcwd() + '/doc')
@@ -213,7 +211,7 @@ creation of sophisticated signal processing chains with all the benefits of a ma
 for key in ['Server', 'Stream', 'TableStream', 'PyoObjectBase', 'Map', 'functions']:
     f.write('\chapter[%s</A> : %s]{%s}\n\n' % (key, getDocFirstLine(key), key))
     f.write(getDoc(key))
-    if type(OBJECTS_TREE[key]) == ListType:
+    if type(OBJECTS_TREE[key]) == list:
         for obj in OBJECTS_TREE[key]:
             f.write('\section[%s</A> : %s]{%s}\n\n' % (obj, getDocFirstLine(obj), obj))
             f.write(getDoc(obj))
@@ -223,7 +221,7 @@ for key in ['Server', 'Stream', 'TableStream', 'PyoObjectBase', 'Map', 'function
         for key2 in key2list:
             f.write('\section[%s</A> : %s]{%s}\n\n' % (key2, getDocFirstLine(key2), key2))
             f.write(getDoc(key2))
-            if type(OBJECTS_TREE[key][key2]) == ListType:
+            if type(OBJECTS_TREE[key][key2]) == list:
                 for obj in OBJECTS_TREE[key][key2]:
                     f.write('\subsection[%s</A> : %s]{%s}\n\n' % (obj, getDocFirstLine(obj), obj))
                     f.write(getDoc(obj))
@@ -281,7 +279,7 @@ shutil.copy('scripts/prettify.css', 'doc/%s' % man_file)
 shutil.copy('scripts/prettify.js', 'doc/%s' % man_file)
 
 # Upload on iACT server
-print "Upload documentation (y/n)?"
+print("Upload documentation (y/n)?")
 ans = raw_input()
 if (ans == 'y'):
     os.system('scp -r doc/%s sysop at 132.204.178.49:/Library/WebServer/Documents/pyo/' % man_file)
diff --git a/scripts/radiopyo-template.py b/scripts/radiopyo-template.py
new file mode 100644
index 0000000..bb07eec
--- /dev/null
+++ b/scripts/radiopyo-template.py
@@ -0,0 +1,57 @@
+#!/usr/bin/env python
+# encoding: utf-8
+"""
+Template for a RadioPyo song (version 1.0).
+
+A RadioPyo song is a musical python script using the python-pyo 
+module to create the audio processing chain. You can connect to
+the radio here : http://radiopyo.acaia.ca/ 
+
+There is only a few rules:
+    1 - It must be a one-page script.
+    2 - No soundfile, only synthesis.
+    3 - The script must be finite in time, with fade-in and fade-out 
+        to avoid clicks between pieces. Use the DURATION variable.
+
+belangeo - 2014
+
+"""
+from pyo import *
+
+################### USER-DEFINED VARIABLES ###################
+### READY is used to manage the server behaviour depending ###
+### of the context. Set this variable to True when the     ###
+### music is ready for the radio. TITLE and ARTIST are the ###
+### infos shown by the radio player. DURATION set the      ###
+### duration of the audio file generated for the streaming.###
+##############################################################
+READY = False           # Set to True when ready for the radio
+TITLE = "Song Title"    # The title of the music
+ARTIST = "Artist Name"  # Your artist name
+DURATION = 300          # The duration of the music in seconds
+##################### These are optional #####################
+GENRE = "Electronic"    # Kind of your music, if there is any
+DATE = 2014             # Year of creation
+
+####################### SERVER CREATION ######################
+if READY:
+    s = Server(duplex=0, audio="offline").boot()
+    s.recordOptions(dur=DURATION, filename="radiopyo.ogg", fileformat=7)
+else:
+    s = Server(duplex=0).boot()
+
+
+##################### PROCESSING SECTION #####################
+# global volume (should be used to control the overall sound)
+fade = Fader(fadein=0.001, fadeout=10, dur=DURATION).play()
+
+
+###
+### Insert your algorithms here...
+###
+
+
+#################### START THE PROCESSING ###################
+s.start()
+if not READY:
+    s.gui(locals())
diff --git a/scripts/release_builder_OSX.sh b/scripts/release_builder_OSX.sh
new file mode 100755
index 0000000..55b663c
--- /dev/null
+++ b/scripts/release_builder_OSX.sh
@@ -0,0 +1,43 @@
+#!/bin/sh
+
+# macOS release builder.
+
+# Update sources
+git pull
+
+# Build float and double for both python2 and python3
+if [ -d build ]; then
+    sudo rm -rf build/;
+fi    
+
+sudo python2.7 setup.py install --use-coreaudio --use-double
+sudo python3.5 setup.py install --use-coreaudio --use-double
+sudo python3.6 setup.py install --use-coreaudio --use-double
+
+# Compile E-Pyo for both python2 and python3
+cd utils
+
+if [ -d E-Pyo_OSX_py2 ]; then
+   sudo rm -rf E-Pyo_OSX_py2/;
+fi    
+
+if [ -d E-Pyo_OSX_py35 ]; then
+    sudo rm -rf E-Pyo_OSX_py35/;
+fi    
+
+if [ -d E-Pyo_OSX_py36 ]; then
+    sudo rm -rf E-Pyo_OSX_py36/;
+fi    
+
+sh epyo_builder_OSX_py2.sh
+sh epyo_builder_OSX_py3.5.sh
+sh epyo_builder_OSX_py3.6.sh
+
+# Build the packages
+cd ../installers/osx
+
+sudo rm -rf *.dmg
+
+sudo sh release_x86_64_py2.sh
+sudo sh release_x86_64_py3.5.sh
+sudo sh release_x86_64_py3.6.sh
diff --git a/scripts/release_doc_src.sh b/scripts/release_doc_src.sh
old mode 100644
new mode 100755
index 9b8c344..9859557
--- 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.6.8
+version=0.8.7
 replace=XXX
 
 doc_rep=pyo_XXX-doc
@@ -21,6 +21,6 @@ tar -cjvf ${doc_tar/$replace/$version} ${doc_rep/$replace/$version}
 rm -R ${doc_rep/$replace/$version}
 cd ..
 
-svn export . ${src_rep/$replace/$version}
+git checkout-index -a -f --prefix=${src_rep/$replace/$version}/
 tar -cjvf ${src_tar/$replace/$version} ${src_rep/$replace/$version}
 rm -R ${src_rep/$replace/$version}
diff --git a/scripts/retrieve_keywords.py b/scripts/retrieve_keywords.py
index f58ec88..8b2860b 100644
--- a/scripts/retrieve_keywords.py
+++ b/scripts/retrieve_keywords.py
@@ -21,7 +21,7 @@ l.append("Server")
 with open("pyo_keywords.txt", "w") as f:
     for i, word in enumerate(l):
         if word not in t2:
-            print word
+            print(word)
         if (i % 10) == 0:
             f.write("\n")
         f.write(word + " ")
diff --git a/scripts/win/windows-build-routine.txt b/scripts/win/windows-7-build-routine.txt
similarity index 72%
copy from scripts/win/windows-build-routine.txt
copy to scripts/win/windows-7-build-routine.txt
index 2cac5e2..69603aa 100644
--- a/scripts/win/windows-build-routine.txt
+++ b/scripts/win/windows-7-build-routine.txt
@@ -1,16 +1,17 @@
 === STEP 1 ===
---- Install Python (2.5 -> 2.7)
+--- Install Python 2.6 and 2.7.10 and WxPython 3.0.2.0 for each version
 
-=== STEP 2 ===
---- Install Slick SVN (Slick-Subversion-1.6.12-win32.msi)
-http://www.sliksvn.com/pub/Slik-Subversion-1.6.12-win32.msi
+=== STEP 2 (should be git soon) ===
+--- Install Slick SVN 1.8.10
+http://www.sliksvn.com
 
 === STEP 3 ===
---- Install scons 2.2.0 in the Python site-packages:
+--- Install scons 2.3.5 in the Python site-packages:
 http://www.scons.org/download.php
 
 === STEP 4 ===
---- Install MinGW (minimalist) from sourceforge
+--- Install MinGW (minimalist GNU for Windows) from sourceforge
+--- Add ";C:\MinGW\bin;C:\MinGW\mingw32\bin" to the PATH variable
 
 === STEP 5 ===
 --- Install pthreads (just copy files from ftp):
@@ -23,50 +24,11 @@ which may be pre-release or release; currently it is the latest stable release (
 Do not build from sources.
 
 === STEP 7 ===
---- Update liblo tag 0.26 from the tarball at http://liblo.sourceforge.net (not SVN!), 
-copy build/config-msvc.h --> src/config.h,
-and build with this SConstruct:
-
-# S C O N S T R U C T   F O R   L I B L O . D L L
-# Michael Gogins
-# Using hints from: http://clam.iua.upf.edu/wikis/clam/index.php/Devel/Windows_MinGW_cross_compile#liblo
-# Modified by Olivier Belanger on september 2010
-
-environment = Environment(tools = ['mingw'])
-
-sources = '''
-src/address.c
-src/blob.c
-src/bundle.c
-src/message.c
-src/method.c
-src/pattern_match.c
-src/send.c
-src/server.c
-src/server_thread.c
-src/timetag.c
-'''
+--- Update liblo tag 0.28 from the tarball at http://liblo.sourceforge.net (not SVN!), 
 
-cppath = '''
-.
-lo
-C:/pthreads/include
-'''
+Compile with MinGW's pthreads installed and ./configure && make
 
-libpath = '''
-C:/MinGW/lib
-C:/pthreads/lib
-'''
-
-environment.Append(CFLAGS = Split('-O2 -g -DHAVE_CONFIG_H -D_WIN32_WINNT=0x0501'))
-environment.Append(CPPPATH = Split(cppath))
-environment.Append(LIBPATH = Split(libpath))
-environment.Append(LIBS = Split('pthreadvc2 kernel32 gdi32 wsock32 ws2_32 ole32 uuid winmm'))
-environment.Append(LINKFLAGS = ['-Wl,--enable-stdcall-fixup', '-Wl,--export-all-symbols'])
-### -export-all-symbols or -export-dynamic ? ###
-
-liblo = environment.SharedLibrary('lo', Split(sources))
-#######################################################
+If there is a conflict about struct timespec, remove the definition in pthread.h.
 
 === STEP 8 ===
 --- Install Directx 9.0 SDK (april 2007)
@@ -81,7 +43,7 @@ Try the trunk version first, if that doesn't work use the most recent tag.
 --- Copy ASIOSDK to portaudio/src/hostapi/asio
 
 --- Check the pa_win_hostapis.c file and make sure that it is configured to build 
-the DirectSound, WMME, and ASIO drivers:
+the DirectSound, WMME, WDMKS and ASIO drivers. (nothing to do here)
 
 --- Need to removed "volatile" from function definitions in MinGW/include/winbase.h
 
@@ -92,8 +54,8 @@ MinGW SConstruct for PortAudio
 Michael Gogins
 Modified by Olivier Belanger on september 2010
 '''
-print __doc__
-print
+print(__doc__)
+print()
 
 import os
 import string
@@ -113,6 +75,7 @@ commonEnvironment.Append(CPPFLAGS = Split('''
 -DPA_USE_DS
 -DPA_USE_ASIO
 -DPA_USE_WASAPI
+-DPA_USE_WDMKS
 '''))
 
 commonEnvironment.Append(CPPPATH = [".", "src/common", "src/hostapi", "src/os", "src/os/win", "include",
@@ -120,7 +83,7 @@ commonEnvironment.Append(CPPPATH = [".", "src/common", "src/hostapi", "src/os",
 "C:/portaudio/src/hostapi/asio/ASIOSDK/host",
 "C:/portaudio/src/hostapi/asio/ASIOSDK/host/pc",
 "C:/portaudio/src/hostapi/asio/ASIOSDK/common",
-"C:/Program Files/Microsoft DirectX SDK (April 2007)/Include"])
+"C:/Program Files (x86)/Microsoft DirectX SDK (April 2007)/Include"])
 
 commonEnvironment.Append(LIBS=Split('''
 setupapi
@@ -155,6 +118,7 @@ src/hostapi/dsound/pa_win_ds.c
 src/hostapi/dsound/pa_win_ds_dynlink.c
 src/hostapi/wmme/pa_win_wmme.c
 src/hostapi/skeleton/pa_hostapi_skeleton.c
+src/hostapi/wdmks/pa_win_wdmks.c
 src/os/win/pa_win_hostapis.c
 src/os/win/pa_win_util.c
 src/os/win/pa_win_waveformat.c
@@ -175,14 +139,14 @@ portAudio = commonEnvironment.SharedLibrary('portaudio', portAudioSources)
 ##########################################################################
 
 === STEP 11 ===
-4 --- Update the PortMidi library http://portmedia.sourceforge.net from SVN and build it with this SConstruct:
+--- Update the PortMidi library http://portmedia.sourceforge.net from SVN and build it with this SConstruct:
 
 '''
 MinGW SConstruct for PortMidi
 Michael Gogins
 '''
-print __doc__
-print
+print(__doc__)
+print()
 
 import os
 import string
@@ -259,9 +223,7 @@ Depends(test, portmidi)
 [build]
 compiler = mingw32
 
-*** For Python 2.5, comment line 428 to 434 in Python25/include/pyconfig.py
-
 === STEP 13 ===
---- Download pyo sources from svn and build it with:
+--- Download pyo sources from git and build it with:
 
 python setup.py install
diff --git a/scripts/win/windows-build-routine.txt b/scripts/win/windows-build-routine.txt
index 2cac5e2..a5455df 100644
--- a/scripts/win/windows-build-routine.txt
+++ b/scripts/win/windows-build-routine.txt
@@ -92,8 +92,8 @@ MinGW SConstruct for PortAudio
 Michael Gogins
 Modified by Olivier Belanger on september 2010
 '''
-print __doc__
-print
+print(__doc__)
+print()
 
 import os
 import string
@@ -181,8 +181,8 @@ portAudio = commonEnvironment.SharedLibrary('portaudio', portAudioSources)
 MinGW SConstruct for PortMidi
 Michael Gogins
 '''
-print __doc__
-print
+print(__doc__)
+print()
 
 import os
 import string
diff --git a/setup.py b/setup.py
index 92bcd39..f96a0c4 100644
--- a/setup.py
+++ b/setup.py
@@ -1,57 +1,74 @@
 # -*- coding: utf-8 -*-
 """
-Copyright 2010 Olivier Belanger
+Copyright 2009-2015 Olivier Belanger
 
 This file is part of pyo, a python module to help digital signal
 processing script creation.
 
 pyo is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+it under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
 
 pyo is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GNU Lesser General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with pyo.  If not, see <http://www.gnu.org/licenses/>.
+You should have received a copy of the GNU Lesser General Public
+License along with pyo.  If not, see <http://www.gnu.org/licenses/>.
 """
-
+from distutils.sysconfig import get_python_lib
 from distutils.core import setup, Extension
-import os, sys, getopt
-import time
+import os, sys, py_compile, subprocess
 
-pyo_version = "0.6.8"
-build_osx_with_jack_support = False
+if sys.version_info[0] < 3:
+    def tobytes(strng, encoding=None):
+        "Convert unicode string to bytes."
+        return bytes(strng)
+else:
+    def tobytes(strng, encoding="utf-8"):
+        "Convert unicode string to bytes."
+        return bytes(strng, encoding=encoding)
+
+def get_jack_api():
+    try:
+        output = subprocess.Popen(["jackd", "-V"], stdout=subprocess.PIPE)
+    except FileNotFoundError:
+        # jack2-dbus is probably installed instead of jackd.
+        return "JACK_OLD_API"
+
+    text = output.communicate()[0]
+    if text != "":
+        line = text.splitlines()[0]
+        if tobytes("0.124") in line or tobytes("1.9.10") in line:
+            return "JACK_OLD_API"
+        else:
+            return "JACK_NEW_API"
+    else:
+        return "JACK_NEW_API"
+
+pyo_version = "0.8.7"
+build_with_jack_support = False
 compile_externals = False
 
 macros = []
 extension_names = ['_pyo']
 main_modules = ['pyo']
 extra_macros_per_extension = [[]]
+
+if '--use-double' in sys.argv:
+    sys.argv.remove('--use-double') 
+    if not '--only-double' in sys.argv: 
+        extension_names.append('_pyo64')
+        main_modules.append('pyo64')
+        extra_macros_per_extension.append([('USE_DOUBLE',None)])
+
 if '--only-double' in sys.argv:
     sys.argv.remove('--only-double') 
     extension_names = ['_pyo64']
     main_modules = ['pyo64']
     extra_macros_per_extension = [[('USE_DOUBLE',None)]]
-    
-if '--use-double' in sys.argv and not '--only-double' in sys.argv: 
-    sys.argv.remove('--use-double') 
-    extension_names.append('_pyo64')
-    main_modules.append('pyo64')
-    extra_macros_per_extension.append([('USE_DOUBLE',None)])
-    
-if '--use-jack' in sys.argv: 
-    sys.argv.remove('--use-jack') 
-    if sys.platform == "darwin":
-        build_osx_with_jack_support = True
-    macros.append(('USE_JACK',None))
-
-if '--use-coreaudio' in sys.argv: 
-    sys.argv.remove('--use-coreaudio') 
-    macros.append(('USE_COREAUDIO',None))
 
 if '--no-messages' in sys.argv:    
     sys.argv.remove('--no-messages') 
@@ -62,64 +79,135 @@ if '--compile-externals' in sys.argv:
     sys.argv.remove('--compile-externals') 
     macros.append(('COMPILE_EXTERNALS',None))
 
-path = 'src/engine/'
-files = ['pyomodule.c', 'servermodule.c', 'pvstreammodule.c', 'streammodule.c', 'dummymodule.c', 
-        'mixmodule.c', 'inputfadermodule.c', 'interpolation.c', 'fft.c', "wind.c"]
-source_files = [path + f for f in files]
-
-path = 'src/objects/'
-files = ['phasevocmodule.c', 'fftmodule.c', 'oscilmodule.c', 'randommodule.c', 'oscmodule.c','analysismodule.c', 
-        'sfplayermodule.c', 'oscbankmodule.c', 'lfomodule.c', 'tablemodule.c',
-         'matrixmodule.c', 'filtremodule.c', 'noisemodule.c', 'distomodule.c',
-        'inputmodule.c', 'fadermodule.c', 'midimodule.c', 'delaymodule.c','recordmodule.c', 'granulatormodule.c', 
-        'metromodule.c', 'trigmodule.c', 'patternmodule.c', 'bandsplitmodule.c', 'hilbertmodule.c', 'panmodule.c',
-        'selectmodule.c', 'freeverbmodule.c', 'compressmodule.c', 'utilsmodule.c',
-        'convolvemodule.c', 'wgverbmodule.c', 'arithmeticmodule.c', 'sigmodule.c',
-        'matrixprocessmodule.c', 'harmonizermodule.c', 'chorusmodule.c']
+if '--debug' in sys.argv:
+    sys.argv.remove('--debug')
+    gflag = "-g3"
+else:
+    gflag = "-g0"
+
+if '--fast-compile' in sys.argv:
+    sys.argv.remove('--fast-compile')
+    oflag = "-O0"
+else:
+    oflag = "-O3"
+
+# Specific audio drivers source files to compile
+ad_files = []
+obj_files = []
+
+# Special flag to build without portaudio, portmidi and liblo deps.
+if '--minimal' in sys.argv:
+    minimal_build = True
+    sys.argv.remove('--minimal') 
+    libraries = []
+else:
+    minimal_build = False
+    # portaudio
+    macros.append(('USE_PORTAUDIO', None))
+    ad_files.append("ad_portaudio.c")
+    libraries = ["portaudio"]
+    # portmidi
+    macros.append(('USE_PORTMIDI', None))
+    ad_files.append("md_portmidi.c")
+    ad_files.append("midilistenermodule.c")
+    libraries += ["portmidi"]
+    # liblo
+    macros.append(('USE_OSC', None))
+    ad_files.append("osclistenermodule.c")
+    obj_files.append("oscmodule.c")
+    if sys.platform == "win32":
+        libraries += ["liblo-7"]
+    else:
+        libraries += ["lo"]
+
+# Optional Audio / Midi drivers
+if '--use-jack' in sys.argv: 
+    sys.argv.remove('--use-jack') 
+    build_with_jack_support = True
+    macros.append(('USE_JACK', None))
+    macros.append((get_jack_api(), None))
+    ad_files.append("ad_jack.c")
+
+if '--use-coreaudio' in sys.argv: 
+    sys.argv.remove('--use-coreaudio') 
+    macros.append(('USE_COREAUDIO', None))
+    ad_files.append("ad_coreaudio.c")
+
+if sys.platform == "darwin":
+    macros.append(('_OSX_', None))
+
+path = 'src/engine'
+files = ['pyomodule.c', 'streammodule.c', 'servermodule.c', 'pvstreammodule.c', 
+         'dummymodule.c', 'mixmodule.c', 'inputfadermodule.c', 'interpolation.c', 
+         'fft.c', "wind.c"] + ad_files
+source_files = [os.path.join(path, f) for f in files]
+
+path = 'src/objects'
+files = ['filtremodule.c', 'arithmeticmodule.c', 'oscilmodule.c', 
+         'randommodule.c', 'analysismodule.c', 'sfplayermodule.c', 
+         'oscbankmodule.c', 'lfomodule.c', 'exprmodule.c', 'utilsmodule.c', 
+         'granulatormodule.c', 'matrixmodule.c', 'noisemodule.c', 'distomodule.c', 
+         'tablemodule.c', 'wgverbmodule.c', 'inputmodule.c', 'fadermodule.c', 
+         'midimodule.c', 'delaymodule.c','recordmodule.c', 'metromodule.c', 
+         'trigmodule.c', 'patternmodule.c', 'bandsplitmodule.c', 'hilbertmodule.c', 
+         'panmodule.c', 'selectmodule.c', 'compressmodule.c',  'freeverbmodule.c', 
+         'phasevocmodule.c', 'fftmodule.c', 'convolvemodule.c', 'sigmodule.c',
+         'matrixprocessmodule.c', 'harmonizermodule.c', 'chorusmodule.c'] + obj_files
 
 if compile_externals:
-    source_files = source_files + ["externals/externalmodule.c"] + [path + f for f in files]
+    source_files = source_files + \
+                   ["externals/externalmodule.c"] + \
+                   [os.path.join(path, f) for f in files]
 else:
-    source_files = source_files + [path + f for f in files]
+    source_files = source_files + [os.path.join(path, f) for f in files]
 
 # Platform-specific build settings for the pyo extension(s).  
 if sys.platform == "win32":
-    include_dirs = ['C:\portaudio\include', 'C:\Program Files\Mega-Nerd\libsndfile\include',
-                    'C:\portmidi\pm_common', 'C:\liblo', 'C:\pthreads\include', 'include',
-                    'C:\portmidi\porttime']
-    library_dirs = ['C:\portaudio', 'C:/Program Files/Mega-Nerd/libsndfile/bin', 'C:\portmidi', 'C:\liblo', 'C:\pthreads\lib']
-    libraries = ['portaudio', 'portmidi', 'porttime', 'libsndfile-1', 'lo', 'pthreadVC2']
+    include_dirs = ['C:\portaudio\include', 'C:\portmidi\pm_common', 'include',
+                    'C:\Program Files (x86)\Mega-Nerd\libsndfile\include',
+                    'C:\liblo-0.28', 'C:\pthreads\include', 'C:\portmidi\porttime']
+    library_dirs = ['C:\portaudio', 'C:\portmidi', 'C:\liblo-0.28\src\.libs', 'C:\pthreads\lib', 
+                    'C:/Program Files (x86)/Mega-Nerd/libsndfile/bin']
+    libraries += ['libsndfile-1', 'pthreadGC2']
+    if 'portmidi' in libraries:
+        libraries.append('porttime')
 else:
-    tsrt = time.strftime('"%d %b %Y %H:%M:%S"', time.localtime())
-    macros.append(('TIMESTAMP', tsrt))
     include_dirs = ['include', '/usr/local/include']
+    if sys.platform == "darwin":
+        include_dirs.append('/opt/local/include')
     library_dirs = []
-    libraries = ['portaudio', 'portmidi', 'sndfile', 'lo']
-    if build_osx_with_jack_support:
+    libraries += ['sndfile']
+    if build_with_jack_support:
         libraries.append('jack')
 
+libraries += ['m']
+extra_compile_args = ['-Wno-strict-prototypes', '-Wno-strict-aliasing', oflag, gflag]
+
 extensions = []
 for extension_name, extra_macros in zip(extension_names, extra_macros_per_extension):
-    extensions.append(Extension(extension_name, source_files, include_dirs=include_dirs, library_dirs=library_dirs,
-                                libraries=libraries, extra_compile_args=['-Wno-strict-prototypes', '-O3'],
+    extensions.append(Extension(extension_name, source_files, libraries=libraries, 
+                                library_dirs=library_dirs, include_dirs=include_dirs, 
+                                extra_compile_args=extra_compile_args,
                                 define_macros=macros + extra_macros))
 
 if compile_externals:
     include_dirs.append('externals')
     os.system('cp externals/external.py pyolib')
 
+soundfiles = [f for f in os.listdir('pyolib/snds') if f[-3:] in ['aif', 'wav']]
+ldesc = "Python module written in C to help digital signal processing script creation."
 setup(  name = "pyo",
         author = "Olivier Belanger",
         author_email = "belangeo at gmail.com",
         version = pyo_version,
         description = "Python dsp module.",
-        long_description = "pyo is a Python module written in C to help digital signal processing script creation.",
-        url = "http://code.google.com/p/pyo/",
-        license = "GPLv3",
+        long_description = ldesc,
+        url = "https://github.com/belangeo/pyo",
+        license = "LGPLv3+",
         packages = ['pyolib', 'pyolib.snds'],
         py_modules = main_modules,
-        package_data = {'pyolib.snds': [f for f in os.listdir('pyolib/snds') if f.endswith('aif') or f.endswith('wav')]},
-        ext_modules = extensions )
+        package_data = {'pyolib.snds': soundfiles},
+        ext_modules = extensions)
 
 if compile_externals:
     os.system('rm pyolib/external.py')
diff --git a/src/engine/ad_coreaudio.c b/src/engine/ad_coreaudio.c
new file mode 100644
index 0000000..d9fff78
--- /dev/null
+++ b/src/engine/ad_coreaudio.c
@@ -0,0 +1,444 @@
+/**************************************************************************
+ * Copyright 2009-2016 Olivier Belanger                                   *
+ *                                                                        *
+ * This file is part of pyo, a python module to help digital signal       *
+ * processing script creation.                                            *
+ *                                                                        *
+ * pyo is free software: you can redistribute it and/or modify            *
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
+ *                                                                        *
+ * pyo is distributed in the hope that it will be useful,                 *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ * GNU 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/>.   *
+ *************************************************************************/
+
+#include "ad_coreaudio.h"
+
+OSStatus coreaudio_input_callback(AudioDeviceID device, const AudioTimeStamp* inNow,
+                                   const AudioBufferList* inInputData,
+                                   const AudioTimeStamp* inInputTime,
+                                   AudioBufferList* outOutputData,
+                                   const AudioTimeStamp* inOutputTime,
+                                   void* defptr)
+{
+    int i, j, bufchnls, servchnls, off1chnls, off2chnls;
+    Server *server = (Server *) defptr;
+    (void) outOutputData;
+    const AudioBuffer* inputBuf = inInputData->mBuffers;
+    float *bufdata = (float*)inputBuf->mData;
+    bufchnls = inputBuf->mNumberChannels;
+    servchnls = server->ichnls < bufchnls ? server->ichnls : bufchnls;
+    for (i=0; i<server->bufferSize; i++) {
+        off1chnls = i*bufchnls+server->input_offset;
+        off2chnls = i*servchnls;
+        for (j=0; j<servchnls; j++) {
+            server->input_buffer[off2chnls+j] = (MYFLT)bufdata[off1chnls+j];
+        }
+    }
+    return kAudioHardwareNoError;
+}
+
+OSStatus coreaudio_output_callback(AudioDeviceID device, const AudioTimeStamp* inNow,
+                                   const AudioBufferList* inInputData,
+                                   const AudioTimeStamp* inInputTime,
+                                   AudioBufferList* outOutputData,
+                                   const AudioTimeStamp* inOutputTime,
+                                   void* defptr)
+{
+    int i, j, bufchnls, servchnls, off1chnls, off2chnls;
+    Server *server = (Server *) defptr;
+
+    (void) inInputData;
+
+    if (server->withPortMidi == 1) {
+        pyoGetMidiEvents(server);
+    }
+
+    Server_process_buffers(server);
+    AudioBuffer* outputBuf = outOutputData->mBuffers;
+    bufchnls = outputBuf->mNumberChannels;
+    servchnls = server->nchnls < bufchnls ? server->nchnls : bufchnls;
+    float *bufdata = (float*)outputBuf->mData;
+    for (i=0; i<server->bufferSize; i++) {
+        off1chnls = i*bufchnls+server->output_offset;
+        off2chnls = i*servchnls;
+        for(j=0; j<servchnls; j++) {
+            bufdata[off1chnls+j] = server->output_buffer[off2chnls+j];
+        }
+    }
+    server->midi_count = 0;
+
+    return kAudioHardwareNoError;
+}
+
+int
+coreaudio_stop_callback(Server *self)
+{
+    OSStatus err = kAudioHardwareNoError;
+
+    if (self->duplex == 1) {
+        err = AudioDeviceStop(self->input, coreaudio_input_callback);
+        if (err != kAudioHardwareNoError) {
+            Server_error(self, "Input AudioDeviceStop failed %d\n", (int)err);
+            return -1;
+        }
+    }
+
+    err = AudioDeviceStop(self->output, coreaudio_output_callback);
+    if (err != kAudioHardwareNoError) {
+        Server_error(self, "Output AudioDeviceStop failed %d\n", (int)err);
+        return -1;
+    }
+    self->server_started = 0;
+    return 0;
+}
+
+int
+Server_coreaudio_init(Server *self)
+{
+    OSStatus err = kAudioHardwareNoError;
+    UInt32 count, namelen, propertySize;
+    int i, numdevices;
+    char *name;
+    AudioDeviceID mOutputDevice = kAudioDeviceUnknown;
+    AudioDeviceID mInputDevice = kAudioDeviceUnknown;
+    Boolean writable;
+    AudioTimeStamp now;
+
+    now.mFlags = kAudioTimeStampHostTimeValid;
+    now.mHostTime = AudioGetCurrentHostTime();
+
+    /************************************/
+    /* List Coreaudio available devices */
+    /************************************/
+    err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &count, 0);
+    AudioDeviceID *devices = (AudioDeviceID*) malloc(count);
+    err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &count, devices);
+    if (err != kAudioHardwareNoError) {
+        Server_error(self, "Get kAudioHardwarePropertyDevices error %s\n", (char*)&err);
+        free(devices);
+    }
+
+    numdevices = count / sizeof(AudioDeviceID);
+    Server_debug(self, "Coreaudio : Number of devices: %i\n", numdevices);
+
+    for (i=0; i<numdevices; ++i) {
+        err = AudioDeviceGetPropertyInfo(devices[i], 0, false, kAudioDevicePropertyDeviceName, &count, 0);
+        if (err != kAudioHardwareNoError) {
+            Server_error(self, "Info kAudioDevicePropertyDeviceName error %s A %d %08X\n", (char*)&err, i, devices[i]);
+            break;
+        }
+
+        char *name = (char*)malloc(count);
+        err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &count, name);
+        if (err != kAudioHardwareNoError) {
+            Server_error(self, "Get kAudioDevicePropertyDeviceName error %s A %d %08X\n", (char*)&err, i, devices[i]);
+            free(name);
+            break;
+        }
+        Server_debug(self, "   %d : \"%s\"\n", i, name);
+        free(name);
+    }
+
+    /************************************/
+    /* Acquire input and output devices */
+    /************************************/
+    /* Acquire input audio device */
+    if (self->duplex == 1) {
+        if (self->input != -1)
+            mInputDevice = devices[self->input];
+
+        if (mInputDevice==kAudioDeviceUnknown) {
+            count = sizeof(mInputDevice);
+            err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &count, (void *) &mInputDevice);
+            if (err != kAudioHardwareNoError) {
+                Server_error(self, "Get kAudioHardwarePropertyDefaultInputDevice error %s\n", (char*)&err);
+                return -1;
+            }
+        }
+
+        err = AudioDeviceGetPropertyInfo(mInputDevice, 0, false, kAudioDevicePropertyDeviceName, &namelen, 0);
+        if (err != kAudioHardwareNoError) {
+            Server_error(self, "Info kAudioDevicePropertyDeviceName error %s A %08X\n", (char*)&err, mInputDevice);
+        }
+        name = (char*)malloc(namelen);
+        err = AudioDeviceGetProperty(mInputDevice, 0, false, kAudioDevicePropertyDeviceName, &namelen, name);
+        if (err != kAudioHardwareNoError) {
+            Server_error(self, "Get kAudioDevicePropertyDeviceName error %s A %08X\n", (char*)&err, mInputDevice);
+        }
+        Server_debug(self, "Coreaudio : Uses input device : \"%s\"\n", name);
+        self->input = mInputDevice;
+        free(name);
+    }
+
+    /* Acquire output audio device */
+    if (self->output != -1)
+        mOutputDevice = devices[self->output];
+
+    if (mOutputDevice==kAudioDeviceUnknown) {
+        count = sizeof(mOutputDevice);
+        err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &count, (void *) &mOutputDevice);
+        if (err != kAudioHardwareNoError) {
+            Server_error(self, "Get kAudioHardwarePropertyDefaultOutputDevice error %s\n", (char*)&err);
+            return -1;
+        }
+    }
+
+    err = AudioDeviceGetPropertyInfo(mOutputDevice, 0, false, kAudioDevicePropertyDeviceName, &namelen, 0);
+    if (err != kAudioHardwareNoError) {
+        Server_error(self, "Info kAudioDevicePropertyDeviceName error %s A %08X\n", (char*)&err, mOutputDevice);
+    }
+    name = (char*)malloc(namelen);
+    err = AudioDeviceGetProperty(mOutputDevice, 0, false, kAudioDevicePropertyDeviceName, &namelen, name);
+    if (err != kAudioHardwareNoError) {
+        Server_error(self, "Get kAudioDevicePropertyDeviceName error %s A %08X\n", (char*)&err, mOutputDevice);
+    }
+    Server_debug(self, "Coreaudio : Uses output device : \"%s\"\n", name);
+    self->output = mOutputDevice;
+    free(name);
+
+    /*************************************************/
+    /* Get in/out buffer frame and buffer frame size */
+    /*************************************************/
+    UInt32 bufferSize;
+    AudioValueRange range;
+    Float64 sampleRate;
+
+    /* Get input device buffer frame size and buffer frame size range */
+    if (self->duplex == 1) {
+        count = sizeof(UInt32);
+        err = AudioDeviceGetProperty(mInputDevice, 0, false, kAudioDevicePropertyBufferFrameSize, &count, &bufferSize);
+        if (err != kAudioHardwareNoError)
+            Server_error(self, "Get kAudioDevicePropertyBufferFrameSize error %s\n", (char*)&err);
+        Server_debug(self, "Coreaudio : Coreaudio input device buffer size = %ld\n", bufferSize);
+
+        count = sizeof(AudioValueRange);
+        err = AudioDeviceGetProperty(mInputDevice, 0, false, kAudioDevicePropertyBufferSizeRange, &count, &range);
+        if (err != kAudioHardwareNoError)
+            Server_error(self, "Get kAudioDevicePropertyBufferSizeRange error %s\n", (char*)&err);
+        Server_debug(self, "Coreaudio : Coreaudio input device buffer size range = %f -> %f\n", range.mMinimum, range.mMaximum);
+
+        /* Get input device sampling rate */
+        count = sizeof(Float64);
+        err = AudioDeviceGetProperty(mInputDevice, 0, false, kAudioDevicePropertyNominalSampleRate, &count, &sampleRate);
+        if (err != kAudioHardwareNoError)
+            Server_debug(self, "Get kAudioDevicePropertyNominalSampleRate error %s\n", (char*)&err);
+        Server_debug(self, "Coreaudio : Coreaudio input device sampling rate = %.2f\n", sampleRate);
+    }
+
+    /* Get output device buffer frame size and buffer frame size range */
+    count = sizeof(UInt32);
+    err = AudioDeviceGetProperty(mOutputDevice, 0, false, kAudioDevicePropertyBufferFrameSize, &count, &bufferSize);
+    if (err != kAudioHardwareNoError)
+        Server_error(self, "Get kAudioDevicePropertyBufferFrameSize error %s\n", (char*)&err);
+    Server_debug(self, "Coreaudio : Coreaudio output device buffer size = %ld\n", bufferSize);
+
+    count = sizeof(AudioValueRange);
+    err = AudioDeviceGetProperty(mOutputDevice, 0, false, kAudioDevicePropertyBufferSizeRange, &count, &range);
+    if (err != kAudioHardwareNoError)
+        Server_error(self, "Get kAudioDevicePropertyBufferSizeRange error %s\n", (char*)&err);
+    Server_debug(self, "Coreaudio : Coreaudio output device buffer size range = %.2f -> %.2f\n", range.mMinimum, range.mMaximum);
+
+    /* Get output device sampling rate */
+    count = sizeof(Float64);
+    err = AudioDeviceGetProperty(mOutputDevice, 0, false, kAudioDevicePropertyNominalSampleRate, &count, &sampleRate);
+    if (err != kAudioHardwareNoError)
+        Server_debug(self, "Get kAudioDevicePropertyNominalSampleRate error %s\n", (char*)&err);
+    Server_debug(self, "Coreaudio : Coreaudio output device sampling rate = %.2f\n", sampleRate);
+
+
+    /****************************************/
+    /********* Set audio properties *********/
+    /****************************************/
+    /* set/get the buffersize for the devices */
+    count = sizeof(UInt32);
+    err = AudioDeviceSetProperty(mOutputDevice, &now, 0, false, kAudioDevicePropertyBufferFrameSize, count, &self->bufferSize);
+    if (err != kAudioHardwareNoError) {
+        Server_error(self, "set kAudioDevicePropertyBufferFrameSize error %4.4s\n", (char*)&err);
+        self->bufferSize = bufferSize;
+        err = AudioDeviceSetProperty(mOutputDevice, &now, 0, false, kAudioDevicePropertyBufferFrameSize, count, &self->bufferSize);
+        if (err != kAudioHardwareNoError)
+            Server_error(self, "set kAudioDevicePropertyBufferFrameSize error %4.4s\n", (char*)&err);
+        else
+            Server_debug(self, "pyo buffer size set to output device buffer size : %i\n", self->bufferSize);
+    }
+    else
+        Server_debug(self, "Coreaudio : Changed output device buffer size successfully: %i\n", self->bufferSize);
+
+    if (self->duplex == 1) {
+        err = AudioDeviceSetProperty(mInputDevice, &now, 0, false, kAudioDevicePropertyBufferFrameSize, count, &self->bufferSize);
+        if (err != kAudioHardwareNoError) {
+            Server_error(self, "set kAudioDevicePropertyBufferFrameSize error %4.4s\n", (char*)&err);
+        }
+    }
+
+    /* set/get the sampling rate for the devices */
+    count = sizeof(double);
+    double pyoSamplingRate = self->samplingRate;
+    err = AudioDeviceSetProperty(mOutputDevice, &now, 0, false, kAudioDevicePropertyNominalSampleRate, count, &pyoSamplingRate);
+    if (err != kAudioHardwareNoError) {
+        Server_error(self, "set kAudioDevicePropertyNominalSampleRate error %s\n", (char*)&err);
+        self->samplingRate = (double)sampleRate;
+        err = AudioDeviceSetProperty(mOutputDevice, &now, 0, false, kAudioDevicePropertyNominalSampleRate, count, &sampleRate);
+        if (err != kAudioHardwareNoError)
+            Server_error(self, "set kAudioDevicePropertyNominalSampleRate error %s\n", (char*)&err);
+        else
+            Server_debug(self, "pyo sampling rate set to output device sampling rate : %i\n", self->samplingRate);
+    }
+    else
+        Server_debug(self, "Coreaudio : Changed output device sampling rate successfully: %.2f\n", self->samplingRate);
+
+    if (self->duplex ==1) {
+        pyoSamplingRate = self->samplingRate;
+        err = AudioDeviceSetProperty(mInputDevice, &now, 0, false, kAudioDevicePropertyNominalSampleRate, count, &pyoSamplingRate);
+        if (err != kAudioHardwareNoError) {
+            Server_error(self, "set kAudioDevicePropertyNominalSampleRate error %s\n", (char*)&err);
+        }
+    }
+
+
+    /****************************************/
+    /* Input and output stream descriptions */
+    /****************************************/
+    AudioStreamBasicDescription outputStreamDescription;
+    AudioStreamBasicDescription inputStreamDescription;
+
+    // Get input device stream configuration
+    if (self->duplex == 1) {
+        count = sizeof(AudioStreamBasicDescription);
+        err = AudioDeviceGetProperty(mInputDevice, 0, true, kAudioDevicePropertyStreamFormat, &count, &inputStreamDescription);
+        if (err != kAudioHardwareNoError)
+            Server_debug(self, "Get kAudioDevicePropertyStreamFormat error %s\n", (char*)&err);
+
+        /*
+        inputStreamDescription.mSampleRate = (Float64)self->samplingRate;
+
+        err = AudioDeviceSetProperty(mInputDevice, &now, 0, false, kAudioDevicePropertyStreamFormat, count, &inputStreamDescription);
+        if (err != kAudioHardwareNoError)
+            Server_debug(self, "-- Set kAudioDevicePropertyStreamFormat error %s\n", (char*)&err);
+
+        // Print new input stream description
+        err = AudioDeviceGetProperty(mInputDevice, 0, true, kAudioDevicePropertyStreamFormat, &count, &inputStreamDescription);
+        if (err != kAudioHardwareNoError)
+            Server_debug(self, "Get kAudioDevicePropertyNominalSampleRate error %s\n", (char*)&err);
+        */
+        Server_debug(self, "Coreaudio : Coreaudio driver input stream sampling rate = %.2f\n", inputStreamDescription.mSampleRate);
+        Server_debug(self, "Coreaudio : Coreaudio driver input stream bytes per frame = %i\n", inputStreamDescription.mBytesPerFrame);
+        Server_debug(self, "Coreaudio : Coreaudio driver input stream number of channels = %i\n", inputStreamDescription.mChannelsPerFrame);
+    }
+
+    /* Get output device stream configuration */
+    count = sizeof(AudioStreamBasicDescription);
+    err = AudioDeviceGetProperty(mOutputDevice, 0, false, kAudioDevicePropertyStreamFormat, &count, &outputStreamDescription);
+    if (err != kAudioHardwareNoError)
+        Server_debug(self, "Get kAudioDevicePropertyStreamFormat error %s\n", (char*)&err);
+
+    /*
+    outputStreamDescription.mSampleRate = (Float64)self->samplingRate;
+
+    err = AudioDeviceSetProperty(mOutputDevice, &now, 0, false, kAudioDevicePropertyStreamFormat, count, &outputStreamDescription);
+    if (err != kAudioHardwareNoError)
+        Server_debug(self, "Set kAudioDevicePropertyStreamFormat error %s\n", (char*)&err);
+
+    // Print new output stream description
+    err = AudioDeviceGetProperty(mOutputDevice, 0, false, kAudioDevicePropertyStreamFormat, &count, &outputStreamDescription);
+    if (err != kAudioHardwareNoError)
+        Server_debug(self, "Get kAudioDevicePropertyStreamFormat error %s\n", (char*)&err);
+    */
+    Server_debug(self, "Coreaudio : Coreaudio driver output stream sampling rate = %.2f\n", outputStreamDescription.mSampleRate);
+    Server_debug(self, "Coreaudio : Coreaudio driver output stream bytes per frame = %i\n", outputStreamDescription.mBytesPerFrame);
+    Server_debug(self, "Coreaudio : Coreaudio driver output stream number of channels = %i\n", outputStreamDescription.mChannelsPerFrame);
+
+
+    /**************************************************/
+    /********* Set input and output callbacks *********/
+    /**************************************************/
+    if (self->duplex == 1) {
+        err = AudioDeviceAddIOProc(self->input, coreaudio_input_callback, (void *) self);    // setup our device with an IO proc
+        if (err != kAudioHardwareNoError) {
+            Server_error(self, "Input AudioDeviceAddIOProc failed %d\n", (int)err);
+            return -1;
+        }
+        err = AudioDeviceGetPropertyInfo(self->input, 0, true, kAudioDevicePropertyIOProcStreamUsage, &propertySize, &writable);
+        AudioHardwareIOProcStreamUsage *input_su = (AudioHardwareIOProcStreamUsage*)malloc(propertySize);
+        input_su->mIOProc = (void*)coreaudio_input_callback;
+        err = AudioDeviceGetProperty(self->input, 0, true, kAudioDevicePropertyIOProcStreamUsage, &propertySize, input_su);
+        for (i=0; i<inputStreamDescription.mChannelsPerFrame; ++i) {
+            input_su->mStreamIsOn[i] = 1;
+        }
+        err = AudioDeviceSetProperty(self->input, &now, 0, true, kAudioDevicePropertyIOProcStreamUsage, propertySize, input_su);
+    }
+
+    err = AudioDeviceAddIOProc(self->output, coreaudio_output_callback, (void *) self);    // setup our device with an IO proc
+    if (err != kAudioHardwareNoError) {
+        Server_error(self, "Output AudioDeviceAddIOProc failed %d\n", (int)err);
+        return -1;
+    }
+    err = AudioDeviceGetPropertyInfo(self->output, 0, false, kAudioDevicePropertyIOProcStreamUsage, &propertySize, &writable);
+    AudioHardwareIOProcStreamUsage *output_su = (AudioHardwareIOProcStreamUsage*)malloc(propertySize);
+    output_su->mIOProc = (void*)coreaudio_output_callback;
+    err = AudioDeviceGetProperty(self->output, 0, false, kAudioDevicePropertyIOProcStreamUsage, &propertySize, output_su);
+    for (i=0; i<outputStreamDescription.mChannelsPerFrame; ++i) {
+        output_su->mStreamIsOn[i] = 1;
+    }
+    err = AudioDeviceSetProperty(self->output, &now, 0, false, kAudioDevicePropertyIOProcStreamUsage, propertySize, output_su);
+
+    return 0;
+}
+
+int
+Server_coreaudio_deinit(Server *self)
+{
+    OSStatus err = kAudioHardwareNoError;
+
+    if (self->duplex == 1) {
+        err = AudioDeviceRemoveIOProc(self->input, coreaudio_input_callback);
+        if (err != kAudioHardwareNoError) {
+            Server_error(self, "Input AudioDeviceRemoveIOProc failed %d\n", (int)err);
+            return -1;
+        }
+    }
+
+    err = AudioDeviceRemoveIOProc(self->output, coreaudio_output_callback);
+    if (err != kAudioHardwareNoError) {
+        Server_error(self, "Output AudioDeviceRemoveIOProc failed %d\n", (int)err);
+        return -1;
+    }
+
+    return 0;
+}
+
+int
+Server_coreaudio_start(Server *self)
+{
+    OSStatus err = kAudioHardwareNoError;
+
+    if (self->duplex == 1) {
+        err = AudioDeviceStart(self->input, coreaudio_input_callback);
+        if (err != kAudioHardwareNoError) {
+            Server_error(self, "Input AudioDeviceStart failed %d\n", (int)err);
+            return -1;
+        }
+    }
+
+    err = AudioDeviceStart(self->output, coreaudio_output_callback);
+    if (err != kAudioHardwareNoError) {
+        Server_error(self, "Output AudioDeviceStart failed %d\n", (int)err);
+        return -1;
+    }
+    return 0;
+}
+
+int
+Server_coreaudio_stop(Server *self)
+{
+    coreaudio_stop_callback(self);
+    self->server_stopped = 1;
+    return 0;
+}
diff --git a/src/engine/ad_jack.c b/src/engine/ad_jack.c
new file mode 100644
index 0000000..d63ca39
--- /dev/null
+++ b/src/engine/ad_jack.c
@@ -0,0 +1,520 @@
+/**************************************************************************
+ * Copyright 2009-2016 Olivier Belanger                                   *
+ *                                                                        *
+ * This file is part of pyo, a python module to help digital signal       *
+ * processing script creation.                                            *
+ *                                                                        *
+ * pyo is free software: you can redistribute it and/or modify            *
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
+ *                                                                        *
+ * pyo is distributed in the hope that it will be useful,                 *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ * GNU 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/>.   *
+ *************************************************************************/
+
+#include "ad_jack.h"
+#include "py2to3.h"
+
+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];
+
+    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);
+    }
+    for (i = 0; i < server->nchnls; i++) {
+        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++) {
+            for (j=0; j<server->ichnls; j++) {
+                server->input_buffer[(i*server->ichnls)+j] = (MYFLT) in_buffers[j][i];
+            }
+        }
+    }
+    Server_process_buffers(server);
+    for (i=0; i<server->bufferSize; i++) {
+        for (j=0; j<server->nchnls; j++) {
+            out_buffers[j][i] = (jack_default_audio_sample_t) server->output_buffer[(i*server->nchnls)+j];
+        }
+    }
+    server->midi_count = 0;
+    return 0;
+}
+
+int
+jack_transport_cb(jack_transport_state_t state, jack_position_t *pos, void *arg) {
+    Server *server = (Server *) arg;
+
+    if (server->jack_transport_state == state)
+        return 0;
+
+    switch (state) {
+        case JackTransportStopped:
+            if (server->server_started) {
+                PyGILState_STATE s = PyGILState_Ensure();
+                Server_stop(server);
+                PyGILState_Release(s);
+            }
+            break;
+        case JackTransportRolling:
+            if (!server->server_started) {
+                PyGILState_STATE s = PyGILState_Ensure();
+                Server_start(server);
+                PyGILState_Release(s);
+            }
+            break;
+        case JackTransportStarting:
+            break;
+        case JackTransportLooping:
+            break;
+    }
+
+    server->jack_transport_state = state;
+
+    return 0;
+}
+
+int
+jack_srate_cb(jack_nframes_t nframes, void *arg) {
+    Server *server = (Server *) arg;
+    server->samplingRate = (double) nframes;
+
+    PyGILState_STATE s = PyGILState_Ensure();
+    Server_debug(server, "The sample rate is now %lu.\n", (unsigned long) nframes);
+    PyGILState_Release(s);
+
+    return 0;
+}
+
+int
+jack_bufsize_cb(jack_nframes_t nframes, void *arg) {
+    Server *server = (Server *) arg;
+    server->bufferSize = (int) nframes;
+
+    PyGILState_STATE s = PyGILState_Ensure();
+    Server_debug(server, "The buffer size is now %lu.\n", (unsigned long) nframes);
+    PyGILState_Release(s);
+
+    return 0;
+}
+
+void
+jack_error_cb(const char *desc) {
+    PyGILState_STATE s = PyGILState_Ensure();
+    PySys_WriteStdout("JACK error: %s\n", desc);
+    PyGILState_Release(s);
+}
+
+void
+jack_shutdown_cb(void *arg) {
+    Server *server = (Server *) arg;
+
+    PyGILState_STATE s = PyGILState_Ensure();
+    Server_shutdown(server);
+    Server_warning(server, "JACK server shutdown. Pyo Server shut down.\n");
+    PyGILState_Release(s);
+}
+
+void
+Server_jack_autoconnect(Server *self) {
+    const char **ports;
+    char *portname;
+    int i, j, num, err = 0;
+    PyoJackBackendData *be_data = (PyoJackBackendData *) self->audio_be_data;
+
+    if (self->jackautoin) {
+
+        Py_BEGIN_ALLOW_THREADS
+        ports = jack_get_ports(be_data->jack_client, "system", NULL, JackPortIsOutput);
+        Py_END_ALLOW_THREADS
+
+        if (ports == NULL) {
+            Server_error(self, "Jack: Cannot find any physical capture ports called 'system'\n");
+        }
+
+        i = 0;
+        while(ports[i] != NULL && be_data->jack_in_ports[i] != NULL){
+
+            Py_BEGIN_ALLOW_THREADS
+            err = jack_connect(be_data->jack_client, ports[i], jack_port_name(be_data->jack_in_ports[i]));
+            Py_END_ALLOW_THREADS
+
+            if (err) {
+                Server_error(self, "Jack: cannot connect 'system' to input ports\n");
+            }
+            i++;
+        }
+        free(ports);
+    }
+
+    if (self->jackautoout) {
+
+        Py_BEGIN_ALLOW_THREADS
+        ports = jack_get_ports(be_data->jack_client, "system", NULL, JackPortIsInput);
+        Py_END_ALLOW_THREADS
+
+        if (ports == NULL) {
+            Server_error(self, "Jack: Cannot find any physical playback ports called 'system'\n");
+        }
+
+        i = 0;
+        while(ports[i] != NULL && be_data->jack_out_ports[i] != NULL){
+
+            Py_BEGIN_ALLOW_THREADS
+            jack_connect(be_data->jack_client, jack_port_name (be_data->jack_out_ports[i]), ports[i]);
+            Py_END_ALLOW_THREADS
+
+            if (err) {
+                Server_error(self, "Jack: cannot connect output ports to 'system'\n");
+            }
+            i++;
+        }
+        free(ports);
+    }
+
+    num = PyList_Size(self->jackAutoConnectInputPorts);
+    if (num > 0) {
+        if (num != self->ichnls || !PyList_Check(PyList_GetItem(self->jackAutoConnectInputPorts, 0))) {
+            Server_error(self, "Jack: auto-connect input ports list size does not match server.ichnls.\n");
+        } 
+        else {
+            for (j=0; j<self->ichnls; j++) {
+                num = PyList_Size(PyList_GetItem(self->jackAutoConnectInputPorts, j));
+                for (i=0; i<num; i++) {
+                    portname = PY_STRING_AS_STRING(PyList_GetItem(PyList_GetItem(self->jackAutoConnectInputPorts, j), i));
+
+                    if (jack_port_by_name(be_data->jack_client, portname) != NULL) {
+
+                        Py_BEGIN_ALLOW_THREADS
+                        err = jack_connect(be_data->jack_client, portname, jack_port_name(be_data->jack_in_ports[j]));
+                        Py_END_ALLOW_THREADS
+
+                        if (err) {
+                            Server_error(self, "Jack: cannot connect '%s' to input port %d\n", portname, j);
+                        }
+                    }
+                    else {
+                        Server_error(self, "Jack: cannot find port '%s'\n", portname);
+                    }
+                }
+            }
+        }
+    }
+
+    num = PyList_Size(self->jackAutoConnectOutputPorts);
+    if (num > 0) {
+        if (num != self->nchnls || !PyList_Check(PyList_GetItem(self->jackAutoConnectOutputPorts, 0))) {
+            Server_error(self, "Jack: auto-connect output ports list size does not match server.nchnls.\n");
+        } else {
+            for (j=0; j<self->nchnls; j++) {
+                num = PyList_Size(PyList_GetItem(self->jackAutoConnectOutputPorts, j));
+                for (i=0; i<num; i++) {
+                    portname = PY_STRING_AS_STRING(PyList_GetItem(PyList_GetItem(self->jackAutoConnectOutputPorts, j), i));
+                    if (jack_port_by_name(be_data->jack_client, portname) != NULL) {
+
+                        Py_BEGIN_ALLOW_THREADS
+                        jack_connect(be_data->jack_client, jack_port_name(be_data->jack_out_ports[j]), portname);
+                        Py_END_ALLOW_THREADS
+
+                        if (err) {
+                            Server_error(self, "Jack: cannot connect output port %d to '%s'\n", j, portname);
+                        }
+                    }
+                    else {
+                        Server_error(self, "Jack: cannot find port '%s'\n", portname);
+                    }
+                }
+            }
+        }
+    }
+}
+
+int
+Server_jack_init(Server *self) {
+    char client_name[32];
+    char name[16];
+    const char *server_name = "server";
+    jack_options_t options = JackNullOption;
+    jack_status_t status;
+    int sampleRate = 0;
+    int bufferSize = 0;
+    int nchnls = 0;
+    int total_nchnls = 0;
+    int index = 0;
+    int ret = 0;
+    assert(self->audio_be_data == NULL);
+    PyoJackBackendData *be_data = (PyoJackBackendData *) malloc(sizeof(PyoJackBackendData *));
+    self->audio_be_data = (void *) be_data;
+    strncpy(client_name, self->serverName, 32);
+
+    Py_BEGIN_ALLOW_THREADS
+    be_data->jack_in_ports = (jack_port_t **) calloc(self->ichnls + self->input_offset, sizeof(jack_port_t *));
+    be_data->jack_out_ports = (jack_port_t **) calloc(self->nchnls + self->output_offset, sizeof(jack_port_t *));
+    be_data->jack_client = jack_client_open(client_name, options, &status, server_name);
+    Py_END_ALLOW_THREADS
+
+    if (be_data->jack_client == NULL) {
+        Server_error(self, "Jack error: Unable to create JACK client\n");
+        if (status & JackServerFailed) {
+            Server_debug(self, "Jack error: jack_client_open() failed, "
+            "status = 0x%2.0x\n", status);
+        }
+        return -1;
+    }
+    if (status & JackServerStarted) {
+        Server_warning(self, "JACK server started.\n");
+    }
+    if (strcmp(self->serverName, jack_get_client_name(be_data->jack_client)) ) {
+        strcpy(self->serverName, jack_get_client_name(be_data->jack_client));
+        Server_warning(self, "Jack name `%s' assigned\n", self->serverName);
+    }
+
+    sampleRate = jack_get_sample_rate(be_data->jack_client);
+    if (sampleRate != self->samplingRate) {
+        self->samplingRate = (double)sampleRate;
+        Server_warning(self, "Sample rate set to Jack engine sample rate: %" PRIu32 "\n", sampleRate);
+    }
+    else {
+        Server_debug(self, "Jack engine sample rate: %" PRIu32 "\n", sampleRate);
+    }
+    if (sampleRate <= 0) {
+        Server_error(self, "Invalid Jack engine sample rate.");
+
+        Py_BEGIN_ALLOW_THREADS
+        jack_client_close(be_data->jack_client);
+        Py_END_ALLOW_THREADS
+
+        return -1;
+    }
+
+    bufferSize = jack_get_buffer_size(be_data->jack_client);
+    if (bufferSize != self->bufferSize) {
+        self->bufferSize = bufferSize;
+        Server_warning(self, "Buffer size set to Jack engine buffer size: %" PRIu32 "\n", bufferSize);
+    }
+    else {
+        Server_debug(self, "Jack engine buffer size: %" PRIu32 "\n", bufferSize);
+    }
+
+    nchnls = total_nchnls = self->ichnls + self->input_offset;
+    while (nchnls-- > 0) {
+        index = total_nchnls - nchnls - 1;
+        ret = sprintf(name, "input_%i", index + 1);
+        if (ret > 0) {
+
+            Py_BEGIN_ALLOW_THREADS
+            be_data->jack_in_ports[index] = jack_port_register(be_data->jack_client,
+                                                               name,
+                                                               JACK_DEFAULT_AUDIO_TYPE,
+                                                               JackPortIsInput, 0);
+            Py_END_ALLOW_THREADS
+
+        }
+
+        if ((be_data->jack_in_ports[index] == NULL)) {
+            Server_error(self, "Jack: no more JACK input ports available\n");
+            return -1;
+        }
+    }
+
+    nchnls = total_nchnls = self->nchnls + self->output_offset;
+    while (nchnls-- > 0) {
+        index = total_nchnls - nchnls - 1;
+        ret = sprintf(name, "output_%i", index + 1);
+        if (ret > 0) {
+
+            Py_BEGIN_ALLOW_THREADS
+            be_data->jack_out_ports[index] = jack_port_register(be_data->jack_client,
+                                                                name,
+                                                                JACK_DEFAULT_AUDIO_TYPE,
+                                                                JackPortIsOutput, 0);
+            Py_END_ALLOW_THREADS
+
+        }
+        if ((be_data->jack_out_ports[index] == NULL)) {
+            Server_error(self, "Jack: no more JACK output ports available\n");
+            return -1;
+        }
+    }
+    jack_set_error_function(jack_error_cb);
+    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 (self->isJackTransportSlave)
+        jack_set_sync_callback(be_data->jack_client, jack_transport_cb, (void *) self);
+
+    Py_BEGIN_ALLOW_THREADS
+    ret = jack_activate(be_data->jack_client);
+    Py_END_ALLOW_THREADS
+
+    if (ret) {
+        Server_error(self, "Jack error: cannot activate jack client.\n");
+        return -1;
+    }
+
+    Server_jack_autoconnect(self);
+
+    return 0;
+}
+
+int
+Server_jack_deinit(Server *self) {
+    int ret;
+    PyoJackBackendData *be_data = (PyoJackBackendData *) self->audio_be_data;
+
+    Py_BEGIN_ALLOW_THREADS
+    ret = jack_deactivate(be_data->jack_client);
+    Py_END_ALLOW_THREADS
+
+    if (ret)
+        Server_error(self, "Jack error: cannot deactivate jack client.\n");
+
+    Py_BEGIN_ALLOW_THREADS
+    ret = jack_client_close(be_data->jack_client);
+    Py_END_ALLOW_THREADS
+
+    if (ret)
+        Server_error(self, "Jack error: cannot close client.\n");
+
+    free(be_data->jack_in_ports);
+    free(be_data->jack_out_ports);
+    free(self->audio_be_data);
+
+    return ret;
+}
+
+int
+jack_input_port_set_names(Server *self) {
+    int i, err, lsize;
+    char *name;
+    char result[128];
+    PyoJackBackendData *be_data = (PyoJackBackendData *) self->audio_be_data;
+
+    if (PyList_Check(self->jackInputPortNames)) {
+        lsize = PyList_Size(self->jackInputPortNames);
+        for (i=0; i<self->ichnls && i<lsize; i++) {
+            name = PY_STRING_AS_STRING(PyList_GetItem(self->jackInputPortNames, i));
+
+            Py_BEGIN_ALLOW_THREADS
+#ifdef JACK_NEW_API
+            err = jack_port_rename(be_data->jack_client, be_data->jack_in_ports[i], name);
+#else
+            err = jack_port_set_name(be_data->jack_in_ports[i], name);
+#endif
+            Py_END_ALLOW_THREADS
+
+            if (err)
+                Server_error(self, "Jack error: cannot change port short name.\n");
+        }
+    }
+    else if (PY_STRING_CHECK(self->jackInputPortNames)) {
+        name = PY_STRING_AS_STRING(self->jackInputPortNames);
+        for (i=0; i<self->ichnls; i++) {
+            sprintf(result, "%s_%d", name, i);
+
+            Py_BEGIN_ALLOW_THREADS
+#ifdef JACK_NEW_API
+            err = jack_port_rename(be_data->jack_client, be_data->jack_in_ports[i], result);
+#else
+            err = jack_port_set_name(be_data->jack_in_ports[i], result);
+#endif
+            Py_END_ALLOW_THREADS
+
+            if (err)
+                Server_error(self, "Jack error: cannot change port short name.\n");
+        }
+    }
+    else
+        Server_error(self, "Jack error: input port names must be a string or a list of strings.\n");
+
+    return 0;
+}
+
+int
+jack_output_port_set_names(Server *self) {
+    int i, err, lsize;
+    char *name;
+    char result[128];
+    PyoJackBackendData *be_data = (PyoJackBackendData *) self->audio_be_data;
+
+    if (PyList_Check(self->jackOutputPortNames)) {
+        lsize = PyList_Size(self->jackOutputPortNames);
+        for (i=0; i<self->nchnls && i<lsize; i++) {
+            name = PY_STRING_AS_STRING(PyList_GetItem(self->jackOutputPortNames, i));
+
+            Py_BEGIN_ALLOW_THREADS
+#ifdef JACK_NEW_API
+            err = jack_port_rename(be_data->jack_client, be_data->jack_out_ports[i], name);
+#else
+            err = jack_port_set_name(be_data->jack_out_ports[i], name);
+#endif
+            Py_END_ALLOW_THREADS
+
+            if (err)
+                Server_error(self, "Jack error: cannot change port short name.\n");
+        }
+    }
+    else if (PY_STRING_CHECK(self->jackOutputPortNames)) {
+        name = PY_STRING_AS_STRING(self->jackOutputPortNames);
+        for (i=0; i<self->nchnls; i++) {
+            sprintf(result, "%s_%d", name, i);
+
+            Py_BEGIN_ALLOW_THREADS
+#ifdef JACK_NEW_API
+            err = jack_port_rename(be_data->jack_client, be_data->jack_out_ports[i], result);
+#else
+            err = jack_port_set_name(be_data->jack_out_ports[i], result);
+#endif
+            Py_END_ALLOW_THREADS
+
+            if (err)
+                Server_error(self, "Jack error: cannot change port short name.\n");
+        }
+    }
+    else
+        Server_error(self, "Jack error: output port names must be a string or a list of strings.\n");
+
+    return 0;
+}
+
+int
+Server_jack_start(Server *self) {
+    return 0;
+}
+
+int
+Server_jack_stop(Server *self) {
+    return 0;
+}
diff --git a/src/engine/ad_portaudio.c b/src/engine/ad_portaudio.c
new file mode 100644
index 0000000..064210b
--- /dev/null
+++ b/src/engine/ad_portaudio.c
@@ -0,0 +1,802 @@
+/**************************************************************************
+ * Copyright 2009-2016 Olivier Belanger                                   *
+ *                                                                        *
+ * This file is part of pyo, a python module to help digital signal       *
+ * processing script creation.                                            *
+ *                                                                        *
+ * pyo is free software: you can redistribute it and/or modify            *
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
+ *                                                                        *
+ * pyo is distributed in the hope that it will be useful,                 *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ * GNU 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/>.   *
+ *************************************************************************/
+
+#include "ad_portaudio.h"
+#include "py2to3.h"
+
+/* Audio server's functions. */
+
+static void portaudio_assert(PaError ecode, const char* cmdName) {
+    if (ecode != paNoError) {
+        const char* eText = Pa_GetErrorText(ecode);
+        if (!eText) {
+            eText = "???";
+        }
+        PySys_WriteStdout("portaudio error in %s: %s\n", cmdName, eText);
+
+        if (strcmp(cmdName, "Pa_Initialize") != 0) {
+
+            Py_BEGIN_ALLOW_THREADS
+            Pa_Terminate();
+            Py_END_ALLOW_THREADS
+
+        }
+    }
+}
+
+int
+pa_callback_interleaved( const void *inputBuffer, void *outputBuffer,
+                            unsigned long framesPerBuffer,
+                            const PaStreamCallbackTimeInfo* timeInfo,
+                            PaStreamCallbackFlags statusFlags,
+                            void *arg )
+{
+    float *out = (float *)outputBuffer;
+    Server *server = (Server *) arg;
+
+    assert(framesPerBuffer == server->bufferSize);
+    int i, j, bufchnls, index1, index2;
+
+    /* avoid unused variable warnings */
+    (void) timeInfo;
+    (void) statusFlags;
+
+    if (server->withPortMidi == 1) {
+        pyoGetMidiEvents(server);
+    }
+
+    if (server->duplex == 1) {
+        float *in = (float *)inputBuffer;
+        bufchnls = server->ichnls + server->input_offset;
+        for (i=0; i<server->bufferSize; i++) {
+            index1 = i * server->ichnls;
+            index2 = i * bufchnls + server->input_offset;
+            for (j=0; j<server->ichnls; j++) {
+                server->input_buffer[index1+j] = (MYFLT)in[index2+j];
+            }
+        }
+    }
+
+    Server_process_buffers(server);
+    bufchnls = server->nchnls + server->output_offset;
+    for (i=0; i<server->bufferSize; i++) {
+        index1 = i * server->nchnls;
+        index2 = i * bufchnls + server->output_offset;
+        for (j=0; j<server->nchnls; j++) {
+            out[index2+j] = (float) server->output_buffer[index1+j];
+        }
+    }
+    server->midi_count = 0;
+
+#ifdef _OSX_
+    if (server->server_stopped == 1)
+        return paComplete;
+    else
+#endif
+        return paContinue;
+}
+
+int
+pa_callback_nonInterleaved( const void *inputBuffer, void *outputBuffer,
+                        unsigned long framesPerBuffer,
+                        const PaStreamCallbackTimeInfo* timeInfo,
+                        PaStreamCallbackFlags statusFlags,
+                        void *arg )
+{
+    float **out = (float **)outputBuffer;
+    Server *server = (Server *) arg;
+
+    assert(framesPerBuffer == server->bufferSize);
+    int i, j;
+
+    /* avoid unused variable warnings */
+    (void) timeInfo;
+    (void) statusFlags;
+
+    if (server->withPortMidi == 1) {
+        pyoGetMidiEvents(server);
+    }
+
+    if (server->duplex == 1) {
+        float **in = (float **)inputBuffer;
+        for (i=0; i<server->bufferSize; i++) {
+            for (j=0; j<server->ichnls; j++) {
+                server->input_buffer[(i*server->ichnls)+j] = (MYFLT)in[j+server->input_offset][i];
+            }
+        }
+    }
+
+    Server_process_buffers(server);
+    for (i=0; i<server->bufferSize; i++) {
+        for (j=0; j<server->nchnls; j++) {
+            out[j+server->output_offset][i] = (float) server->output_buffer[(i*server->nchnls)+j];
+        }
+    }
+    server->midi_count = 0;
+
+#ifdef _OSX_
+    if (server->server_stopped == 1)
+        return paComplete;
+    else
+#endif
+        return paContinue;
+}
+
+int
+Server_pa_init(Server *self)
+{
+    PaError err;
+    PaStreamParameters outputParameters;
+    PaStreamParameters inputParameters;
+    PaDeviceIndex n, inDevice, outDevice;
+    const PaDeviceInfo *deviceInfo;
+    PaHostApiIndex hostIndex;
+    const PaHostApiInfo *hostInfo;
+    PaHostApiTypeId hostId;
+    PaSampleFormat sampleFormat;
+    PaStreamCallback *streamCallback;
+
+    Py_BEGIN_ALLOW_THREADS
+    err = Pa_Initialize();
+    Py_END_ALLOW_THREADS
+
+    portaudio_assert(err, "Pa_Initialize");
+
+    n = Pa_GetDeviceCount();
+    if (n < 0) {
+        portaudio_assert(n, "Pa_GetDeviceCount");
+    }
+
+    PyoPaBackendData *be_data = (PyoPaBackendData *) malloc(sizeof(PyoPaBackendData *));
+    self->audio_be_data = (void *) be_data;
+
+    if (self->output == -1)
+        outDevice = Pa_GetDefaultOutputDevice(); /* default output device */
+    else
+        outDevice = (PaDeviceIndex) self->output; /* selected output device */
+    if (self->input == -1)
+        inDevice = Pa_GetDefaultInputDevice(); /* default input device */
+    else
+        inDevice = (PaDeviceIndex) self->input; /* selected input device */
+
+    /* Retrieve host api id and define sample and callback format*/
+    deviceInfo = Pa_GetDeviceInfo(outDevice);
+    hostIndex = deviceInfo->hostApi;
+    hostInfo = Pa_GetHostApiInfo(hostIndex);
+    hostId = hostInfo->type;
+    if (hostId == paASIO) {
+        Server_debug(self, "Portaudio uses non-interleaved callback.\n");
+        sampleFormat = paFloat32 | paNonInterleaved;
+        streamCallback = pa_callback_nonInterleaved;
+    }
+    else if (hostId == paALSA) {
+        Server_debug(self, "Portaudio uses interleaved callback.\n");
+        Server_debug(self, "Using ALSA, if no input/output devices are specified, force to devices 0.\n");
+        if (self->input == -1 && self->output == -1) {
+            self->input = self->output = 0;
+            inDevice = outDevice = (PaDeviceIndex) 0;
+        }
+        sampleFormat = paFloat32;
+        streamCallback = pa_callback_interleaved;
+    }
+    else {
+        Server_debug(self, "Portaudio uses interleaved callback.\n");
+        sampleFormat = paFloat32;
+        streamCallback = pa_callback_interleaved;
+    }
+
+
+    /* setup output and input streams */
+    memset(&outputParameters, 0, sizeof(outputParameters));
+    outputParameters.device = outDevice;
+    outputParameters.channelCount = self->nchnls + self->output_offset;
+    outputParameters.sampleFormat = sampleFormat;
+    outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
+    outputParameters.hostApiSpecificStreamInfo = NULL;
+
+    if (self->duplex == 1) {
+        memset(&inputParameters, 0, sizeof(inputParameters));
+        inputParameters.device = inDevice;
+        inputParameters.channelCount = self->ichnls + self->input_offset;
+        inputParameters.sampleFormat = sampleFormat;
+        inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
+        inputParameters.hostApiSpecificStreamInfo = NULL;
+    }
+
+    if (self->input == -1 && self->output == -1) {
+        if (self->duplex == 1) {
+
+            Py_BEGIN_ALLOW_THREADS
+            err = Pa_OpenDefaultStream(&be_data->stream,
+                                       self->ichnls + self->input_offset,
+                                       self->nchnls + self->output_offset,
+                                       sampleFormat,
+                                       self->samplingRate,
+                                       self->bufferSize,
+                                       streamCallback,
+                                       (void *) self);
+            Py_END_ALLOW_THREADS
+
+        }
+        else {
+
+            Py_BEGIN_ALLOW_THREADS
+            err = Pa_OpenDefaultStream(&be_data->stream,
+                                       0,
+                                       self->nchnls + self->output_offset,
+                                       sampleFormat,
+                                       self->samplingRate,
+                                       self->bufferSize,
+                                       streamCallback,
+                                       (void *) self);
+            Py_END_ALLOW_THREADS
+
+        }
+    }
+    else {
+        if (self->duplex == 1) {
+
+            Py_BEGIN_ALLOW_THREADS
+            err = Pa_OpenStream(&be_data->stream,
+                                &inputParameters,
+                                &outputParameters,
+                                self->samplingRate,
+                                self->bufferSize,
+                                paNoFlag,
+                                streamCallback,
+                                (void *) self);
+            Py_END_ALLOW_THREADS
+
+        }
+        else {
+
+            Py_BEGIN_ALLOW_THREADS
+            err = Pa_OpenStream(&be_data->stream,
+                                (PaStreamParameters *) NULL,
+                                &outputParameters,
+                                self->samplingRate,
+                                self->bufferSize,
+                                paNoFlag,
+                                streamCallback,
+                                (void *) self);
+            Py_END_ALLOW_THREADS
+
+        }
+    }
+    portaudio_assert(err, "Pa_OpenStream");
+    if (err < 0) {
+        Server_error(self, "Portaudio error: %s", Pa_GetErrorText(err));
+        return -1;
+    }
+    return 0;
+}
+
+int
+Server_pa_deinit(Server *self)
+{
+    PaError err;
+    PyoPaBackendData *be_data = (PyoPaBackendData *) self->audio_be_data;
+
+    Py_BEGIN_ALLOW_THREADS
+    err = Pa_IsStreamStopped(be_data->stream);
+    Py_END_ALLOW_THREADS
+
+    if (!err) {
+        self->server_started = 0;
+
+        Py_BEGIN_ALLOW_THREADS
+        err = Pa_AbortStream(be_data->stream);
+        Py_END_ALLOW_THREADS
+
+        portaudio_assert(err, "Pa_AbortStream (pa_deinit)");
+    }
+
+    Py_BEGIN_ALLOW_THREADS
+    err = Pa_CloseStream(be_data->stream);
+    Py_END_ALLOW_THREADS
+
+    portaudio_assert(err, "Pa_CloseStream (pa_deinit)");
+
+    Py_BEGIN_ALLOW_THREADS
+    err = Pa_Terminate();
+    Py_END_ALLOW_THREADS
+
+    portaudio_assert(err, "Pa_Terminate (pa_deinit)");
+
+    free(self->audio_be_data);
+    return err;
+}
+
+int
+Server_pa_start(Server *self)
+{
+    PaError err;
+    PyoPaBackendData *be_data = (PyoPaBackendData *) self->audio_be_data;
+
+    Py_BEGIN_ALLOW_THREADS
+    err = Pa_IsStreamStopped(be_data->stream);
+    Py_END_ALLOW_THREADS
+
+    if (!err) {
+
+        Py_BEGIN_ALLOW_THREADS
+        err = Pa_AbortStream(be_data->stream);
+        Py_END_ALLOW_THREADS
+
+        portaudio_assert(err, "Pa_AbortStream (pa_start)");
+    }
+
+    Py_BEGIN_ALLOW_THREADS
+    err = Pa_StartStream(be_data->stream);
+    Py_END_ALLOW_THREADS
+
+    portaudio_assert(err, "Pa_StartStream (pa_start)");
+
+    return err;
+}
+
+int
+Server_pa_stop(Server *self)
+{
+    PaError err;
+    PyoPaBackendData *be_data = (PyoPaBackendData *) self->audio_be_data;
+
+    Py_BEGIN_ALLOW_THREADS
+    err = Pa_IsStreamStopped(be_data->stream);
+    Py_END_ALLOW_THREADS
+
+    if (!err) {
+#ifndef _OSX_
+
+        Py_BEGIN_ALLOW_THREADS
+        err = Pa_AbortStream(be_data->stream);
+        Py_END_ALLOW_THREADS
+
+        portaudio_assert(err, "Pa_AbortStream (pa_stop)");
+#endif
+    }
+
+    self->server_started = 0;
+    self->server_stopped = 1;
+    return 0;
+}
+
+/* Query functions. */
+
+PyObject *
+portaudio_get_version() {
+    return PyInt_FromLong(Pa_GetVersion());
+}
+
+PyObject *
+portaudio_get_version_text() {
+    return PyUnicode_FromString(Pa_GetVersionText());
+}
+
+PyObject *
+portaudio_count_host_apis(){
+    PaError err;
+    PaHostApiIndex numApis;
+
+    Py_BEGIN_ALLOW_THREADS
+    err = Pa_Initialize();
+    Py_END_ALLOW_THREADS
+
+    if (err != paNoError) {
+        portaudio_assert(err, "Pa_Initialize");
+		Py_RETURN_NONE;
+	}
+	else {
+        numApis = Pa_GetHostApiCount();
+        if( numApis < 0 )
+            portaudio_assert(numApis, "Pa_GetHostApiCount");
+
+        Py_BEGIN_ALLOW_THREADS
+        Pa_Terminate();
+        Py_END_ALLOW_THREADS
+
+        return PyInt_FromLong(numApis);
+    }
+}
+
+PyObject *
+portaudio_list_host_apis(){
+    PaError err;
+    PaHostApiIndex n, i;
+
+    Py_BEGIN_ALLOW_THREADS
+    err = Pa_Initialize();
+    Py_END_ALLOW_THREADS
+
+    if (err != paNoError) {
+        portaudio_assert(err, "Pa_Initialize");
+	}
+    else {
+        n = Pa_GetHostApiCount();
+        if (n < 0){
+            portaudio_assert(n, "Pa_GetHostApiCount");
+        }
+        else {
+            for (i=0; i < n; ++i){
+                const PaHostApiInfo *info = Pa_GetHostApiInfo(i);
+                assert(info);
+                PySys_WriteStdout("index: %i, id: %i, name: %s, num devices: %i, default in: %i, default out: %i\n", 
+                                  i, (int)info->type, info->name, (int)info->deviceCount, (int)info->defaultInputDevice, 
+                                  (int)info->defaultOutputDevice);
+            }
+        }
+
+        Py_BEGIN_ALLOW_THREADS
+        Pa_Terminate();
+        Py_END_ALLOW_THREADS
+
+    }
+    Py_RETURN_NONE;
+}
+
+PyObject *
+portaudio_get_default_host_api(){
+    PaError err;
+    PaHostApiIndex i;
+
+    Py_BEGIN_ALLOW_THREADS
+    err = Pa_Initialize();
+    Py_END_ALLOW_THREADS
+
+    if (err != paNoError) {
+        portaudio_assert(err, "Pa_Initialize");
+		Py_RETURN_NONE;
+	}
+    else {
+        i = Pa_GetDefaultHostApi();
+
+        Py_BEGIN_ALLOW_THREADS
+        Pa_Terminate();
+        Py_END_ALLOW_THREADS
+
+        return PyInt_FromLong(i);
+    }
+}
+
+PyObject *
+portaudio_count_devices(){
+    PaError err;
+    PaDeviceIndex numDevices;
+
+    Py_BEGIN_ALLOW_THREADS
+    err = Pa_Initialize();
+    Py_END_ALLOW_THREADS
+
+    if (err != paNoError) {
+        portaudio_assert(err, "Pa_Initialize");
+		Py_RETURN_NONE;
+	}
+	else {
+        numDevices = Pa_GetDeviceCount();
+        if( numDevices < 0 )
+            portaudio_assert(numDevices, "Pa_GetDeviceCount");
+
+        Py_BEGIN_ALLOW_THREADS
+        Pa_Terminate();
+        Py_END_ALLOW_THREADS
+
+        return PyInt_FromLong(numDevices);
+    }
+
+}
+
+PyObject *
+portaudio_list_devices(){
+    PaError err;
+    PaDeviceIndex n, i;
+
+    Py_BEGIN_ALLOW_THREADS
+    err = Pa_Initialize();
+    Py_END_ALLOW_THREADS
+
+    if (err != paNoError) {
+        portaudio_assert(err, "Pa_Initialize");
+		Py_RETURN_NONE;
+	}
+    else {
+        n = Pa_GetDeviceCount();
+        if (n < 0){
+            portaudio_assert(n, "Pa_GetDeviceCount");
+        }
+        else {
+            PySys_WriteStdout("AUDIO devices:\n");
+            for (i=0; i < n; ++i){
+                const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
+                assert(info);
+
+                if (info->maxInputChannels > 0)
+                    PySys_WriteStdout("%i: IN, name: %s, host api index: %i, default sr: %i Hz, latency: %f s\n", 
+                                      i, info->name, (int)info->hostApi, (int)info->defaultSampleRate, 
+                                      (float)info->defaultLowInputLatency);
+
+                if (info->maxOutputChannels > 0)
+                    PySys_WriteStdout("%i: OUT, name: %s, host api index: %i, default sr: %i Hz, latency: %f s\n", 
+                                      i, info->name, (int)info->hostApi, (int)info->defaultSampleRate, 
+                                      (float)info->defaultLowOutputLatency);
+            }
+            PySys_WriteStdout("\n");
+        }
+
+        Py_BEGIN_ALLOW_THREADS
+        Pa_Terminate();
+        Py_END_ALLOW_THREADS
+
+    }
+    Py_RETURN_NONE;
+}
+
+PyObject *
+portaudio_get_devices_infos(){
+    PaError err;
+    PaDeviceIndex n, i;
+    PyObject *inDict, *outDict, *tmpDict;
+    inDict = PyDict_New();
+    outDict = PyDict_New();
+
+    Py_BEGIN_ALLOW_THREADS
+    err = Pa_Initialize();
+    Py_END_ALLOW_THREADS
+
+    if (err != paNoError) {
+        portaudio_assert(err, "Pa_Initialize");
+	}
+    else {
+        n = Pa_GetDeviceCount();
+        if (n < 0){
+            portaudio_assert(n, "Pa_GetDeviceCount");
+        }
+        else {
+            for (i=0; i < n; ++i){
+                const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
+                assert(info);
+                tmpDict = PyDict_New();
+                if (info->maxInputChannels > 0) {
+                    if (PyUnicode_FromString(info->name) == NULL)
+                        PyDict_SetItemString(tmpDict, "name", PyUnicode_FromString("???"));
+                    else
+                        PyDict_SetItemString(tmpDict, "name", PyUnicode_FromString(info->name));
+                    PyDict_SetItemString(tmpDict, "host api index", PyInt_FromLong((int)info->hostApi));
+                    PyDict_SetItemString(tmpDict, "default sr", PyInt_FromLong((int)info->defaultSampleRate));
+                    PyDict_SetItemString(tmpDict, "latency", PyFloat_FromDouble((float)info->defaultLowInputLatency));
+                    PyDict_SetItem(inDict, PyInt_FromLong(i), PyDict_Copy(tmpDict));
+                }
+                if (info->maxOutputChannels > 0) {
+                    if (PyUnicode_FromString(info->name) == NULL)
+                        PyDict_SetItemString(tmpDict, "name", PyUnicode_FromString("???"));
+                    else
+                        PyDict_SetItemString(tmpDict, "name", PyUnicode_FromString(info->name));
+                    PyDict_SetItemString(tmpDict, "host api index", PyInt_FromLong((int)info->hostApi));
+                    PyDict_SetItemString(tmpDict, "default sr", PyInt_FromLong((int)info->defaultSampleRate));
+                    PyDict_SetItemString(tmpDict, "latency", PyFloat_FromDouble((float)info->defaultLowOutputLatency));
+                    PyDict_SetItem(outDict, PyInt_FromLong(i), PyDict_Copy(tmpDict));
+                }
+            }
+        }
+
+        Py_BEGIN_ALLOW_THREADS
+        err = Pa_Terminate();
+        Py_END_ALLOW_THREADS
+
+    }
+    return Py_BuildValue("(OO)", inDict, outDict);
+}
+
+PyObject *
+portaudio_get_output_devices(){
+    PaError err;
+    PaDeviceIndex n, i;
+
+    PyObject *list, *list_index;
+    list = PyList_New(0);
+    list_index = PyList_New(0);
+
+    Py_BEGIN_ALLOW_THREADS
+    err = Pa_Initialize();
+    Py_END_ALLOW_THREADS
+
+    if (err != paNoError) {
+        portaudio_assert(err, "Pa_Initialize");
+	}
+    else {
+        n = Pa_GetDeviceCount();
+        if (n < 0){
+            portaudio_assert(n, "Pa_GetDeviceCount");
+        }
+        else {
+            for (i=0; i < n; ++i){
+                const PaDeviceInfo *info=Pa_GetDeviceInfo(i);
+                assert(info);
+                if (info->maxOutputChannels > 0) {
+                    PyList_Append(list_index, PyInt_FromLong(i));
+                    if (PyUnicode_FromString(info->name) == NULL)
+                        PyList_Append(list, PyUnicode_FromString("???"));
+                    else
+                        PyList_Append(list, PyUnicode_FromString(info->name));
+                }
+            }
+        }
+
+        Py_BEGIN_ALLOW_THREADS
+        Pa_Terminate();
+        Py_END_ALLOW_THREADS
+
+    }
+    return Py_BuildValue("OO", list, list_index);
+}
+
+PyObject *
+portaudio_get_output_max_channels(PyObject *self, PyObject *arg){
+    PaError err;
+    PaDeviceIndex n, i = PyInt_AsLong(arg);
+
+    Py_BEGIN_ALLOW_THREADS
+    err = Pa_Initialize();
+    Py_END_ALLOW_THREADS
+
+    if (err != paNoError) {
+        portaudio_assert(err, "Pa_Initialize");
+		Py_RETURN_NONE;
+	}
+    else {
+        n = Pa_GetDeviceCount();
+        if (n < 0){
+            portaudio_assert(n, "Pa_GetDeviceCount");
+            Py_RETURN_NONE;
+        }
+        else {
+            const PaDeviceInfo *info=Pa_GetDeviceInfo(i);
+
+            Py_BEGIN_ALLOW_THREADS
+            Pa_Terminate();
+            Py_END_ALLOW_THREADS
+
+            assert(info);
+            return PyInt_FromLong(info->maxOutputChannels);
+        }
+    }
+}
+
+PyObject *
+portaudio_get_input_max_channels(PyObject *self, PyObject *arg){
+    PaError err;
+    PaDeviceIndex n, i = PyInt_AsLong(arg);
+
+    Py_BEGIN_ALLOW_THREADS
+    err = Pa_Initialize();
+    Py_END_ALLOW_THREADS
+
+    if (err != paNoError) {
+        portaudio_assert(err, "Pa_Initialize");
+		Py_RETURN_NONE;
+	}
+    else {
+        n = Pa_GetDeviceCount();
+        if (n < 0){
+            portaudio_assert(n, "Pa_GetDeviceCount");
+            Py_RETURN_NONE;
+        }
+        else {
+            const PaDeviceInfo *info=Pa_GetDeviceInfo(i);
+
+            Py_BEGIN_ALLOW_THREADS
+            Pa_Terminate();
+            Py_END_ALLOW_THREADS
+
+            assert(info);
+            return PyInt_FromLong(info->maxInputChannels);
+        }
+    }
+}
+
+PyObject *
+portaudio_get_input_devices(){
+    PaError err;
+    PaDeviceIndex n, i;
+
+    PyObject *list, *list_index;
+    list = PyList_New(0);
+    list_index = PyList_New(0);
+
+    Py_BEGIN_ALLOW_THREADS
+    err = Pa_Initialize();
+    Py_END_ALLOW_THREADS
+
+    if (err != paNoError) {
+        portaudio_assert(err, "Pa_Initialize");
+	}
+    else {
+        n = Pa_GetDeviceCount();
+        if (n < 0){
+            portaudio_assert(n, "Pa_GetDeviceCount");
+        }
+        else {
+            for (i=0; i < n; ++i){
+                const PaDeviceInfo *info=Pa_GetDeviceInfo(i);
+                assert(info);
+                if (info->maxInputChannels > 0) {
+                    PyList_Append(list_index, PyInt_FromLong(i));
+                    if (PyUnicode_FromString(info->name) == NULL)
+                        PyList_Append(list, PyUnicode_FromString("???"));
+                    else
+                        PyList_Append(list, PyUnicode_FromString(info->name));
+                }
+            }
+        }
+
+        Py_BEGIN_ALLOW_THREADS
+        Pa_Terminate();
+        Py_END_ALLOW_THREADS
+
+    }
+    return Py_BuildValue("OO", list, list_index);
+}
+
+PyObject *
+portaudio_get_default_input(){
+    PaError err;
+    PaDeviceIndex i;
+
+    Py_BEGIN_ALLOW_THREADS
+    err = Pa_Initialize();
+    Py_END_ALLOW_THREADS
+
+    if (err != paNoError) {
+        portaudio_assert(err, "Pa_Initialize");
+		Py_RETURN_NONE;
+	}
+    else {
+        i = Pa_GetDefaultInputDevice();
+
+        Py_BEGIN_ALLOW_THREADS
+        Pa_Terminate();
+        Py_END_ALLOW_THREADS
+
+        return PyInt_FromLong(i);
+    }
+}
+
+PyObject *
+portaudio_get_default_output(){
+    PaError err;
+    PaDeviceIndex i;
+
+    Py_BEGIN_ALLOW_THREADS
+    err = Pa_Initialize();
+    Py_END_ALLOW_THREADS
+
+    if (err != paNoError) {
+        portaudio_assert(err, "Pa_Initialize");
+		Py_RETURN_NONE;
+	}
+    else {
+        i = Pa_GetDefaultOutputDevice();
+
+        Py_BEGIN_ALLOW_THREADS
+        Pa_Terminate();
+        Py_END_ALLOW_THREADS
+
+        return PyInt_FromLong(i);
+    }
+}
diff --git a/src/engine/dummymodule.c b/src/engine/dummymodule.c
index f2bcdc5..c10158a 100644
--- a/src/engine/dummymodule.c
+++ b/src/engine/dummymodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
-* Copyright 2010 Olivier Belanger                                        *                  
-*                                                                        * 
-* This file is part of pyo, a python module to help digital signal       *
-* processing script creation.                                            *  
-*                                                                        * 
-* pyo is free software: you can redistribute it and/or modify            *
-* it under the terms of the GNU General Public License as published by   *
-* the Free Software Foundation, either version 3 of the License, or      *
-* (at your option) any later version.                                    * 
-*                                                                        *
-* pyo is distributed in the hope that it will be useful,                 *
-* but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
-* GNU General Public License for more details.                           *
-*                                                                        *
-* You should have received a copy of the GNU General Public License      *
-* along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
-*************************************************************************/
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
+ * This file is part of pyo, a python module to help digital signal       *
+ * processing script creation.                                            *
+ *                                                                        *
+ * pyo is free software: you can redistribute it and/or modify            *
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
+ *                                                                        *
+ * pyo is distributed in the hope that it will be useful,                 *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ * GNU 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/>.   *
+ *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
@@ -43,31 +44,31 @@ Dummy_setProcMode(Dummy *self)
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Dummy_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Dummy_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Dummy_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Dummy_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Dummy_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Dummy_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Dummy_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Dummy_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Dummy_postprocessing_revareva;
             break;
     }
@@ -80,7 +81,7 @@ Dummy_compute_next_data_frame(Dummy *self)
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = in[i];
-    }    
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -93,7 +94,7 @@ Dummy_traverse(Dummy *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Dummy_clear(Dummy *self)
 {
     pyo_CLEAR
@@ -107,24 +108,24 @@ Dummy_dealloc(Dummy* self)
 {
     pyo_DEALLOC
     Dummy_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
-PyObject * 
+PyObject *
 Dummy_initialize(Dummy *self)
 {
     int i;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Dummy_compute_next_data_frame);
     self->mode_func_ptr = Dummy_setProcMode;
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     Stream_setStreamActive(self->stream, 1);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -146,17 +147,17 @@ Dummy_setInput(Dummy *self, PyObject *arg)
     (*self->mode_func_ptr)(self);
 
     Dummy_compute_next_data_frame(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
 static PyObject * Dummy_getServer(Dummy* self) { GET_SERVER };
 static PyObject * Dummy_getStream(Dummy* self) { GET_STREAM };
-static PyObject * Dummy_setMul(Dummy *self, PyObject *arg) { SET_MUL };	
-static PyObject * Dummy_setAdd(Dummy *self, PyObject *arg) { SET_ADD };	
-static PyObject * Dummy_setSub(Dummy *self, PyObject *arg) { SET_SUB };	
-static PyObject * Dummy_setDiv(Dummy *self, PyObject *arg) { SET_DIV };	
+static PyObject * Dummy_setMul(Dummy *self, PyObject *arg) { SET_MUL };
+static PyObject * Dummy_setAdd(Dummy *self, PyObject *arg) { SET_ADD };
+static PyObject * Dummy_setSub(Dummy *self, PyObject *arg) { SET_SUB };
+static PyObject * Dummy_setDiv(Dummy *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Dummy_play(Dummy *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Dummy_out(Dummy *self, PyObject *args, PyObject *kwds) { OUT };
@@ -198,7 +199,7 @@ static PyNumberMethods Dummy_as_number = {
     (binaryfunc)Dummy_add,                         /*nb_add*/
     (binaryfunc)Dummy_sub,                         /*nb_subtract*/
     (binaryfunc)Dummy_multiply,                    /*nb_multiply*/
-    (binaryfunc)Dummy_div,                          /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO   /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -212,16 +213,16 @@ static PyNumberMethods Dummy_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Dummy_inplace_add,                 /*inplace_add*/
     (binaryfunc)Dummy_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Dummy_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Dummy_inplace_div,                  /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO               /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -230,15 +231,14 @@ static PyNumberMethods Dummy_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Dummy_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Dummy_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject DummyType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Dummy_base",                                   /*tp_name*/
     sizeof(Dummy),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -246,7 +246,7 @@ PyTypeObject DummyType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &Dummy_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -302,36 +302,36 @@ static void
 TriggerDummy_setProcMode(TriggerDummy *self) {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = TriggerDummy_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = TriggerDummy_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = TriggerDummy_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = TriggerDummy_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = TriggerDummy_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = TriggerDummy_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = TriggerDummy_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = TriggerDummy_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = TriggerDummy_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
@@ -341,7 +341,7 @@ TriggerDummy_compute_next_data_frame(TriggerDummy *self)
     MYFLT *tmp = TriggerStream_getData((TriggerStream *)self->input_stream);
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = tmp[i];
-    }    
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -354,11 +354,11 @@ TriggerDummy_traverse(TriggerDummy *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 TriggerDummy_clear(TriggerDummy *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->input);    
+    Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
     return 0;
 }
@@ -368,7 +368,7 @@ TriggerDummy_dealloc(TriggerDummy* self)
 {
     pyo_DEALLOC
     TriggerDummy_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -378,34 +378,34 @@ TriggerDummy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp;
     TriggerDummy *self;
     self = (TriggerDummy *)type->tp_alloc(type, 0);
-    
+
     self->modebuffer[0] = 0;
     self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, TriggerDummy_compute_next_data_frame);
     self->mode_func_ptr = TriggerDummy_setProcMode;
 
     static char *kwlist[] = {"input", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &inputtmp))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     INIT_INPUT_TRIGGER_STREAM
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * TriggerDummy_getServer(TriggerDummy* self) { GET_SERVER };
 static PyObject * TriggerDummy_getStream(TriggerDummy* self) { GET_STREAM };
-static PyObject * TriggerDummy_setMul(TriggerDummy *self, PyObject *arg) { SET_MUL };	
-static PyObject * TriggerDummy_setAdd(TriggerDummy *self, PyObject *arg) { SET_ADD };	
-static PyObject * TriggerDummy_setSub(TriggerDummy *self, PyObject *arg) { SET_SUB };	
-static PyObject * TriggerDummy_setDiv(TriggerDummy *self, PyObject *arg) { SET_DIV };	
+static PyObject * TriggerDummy_setMul(TriggerDummy *self, PyObject *arg) { SET_MUL };
+static PyObject * TriggerDummy_setAdd(TriggerDummy *self, PyObject *arg) { SET_ADD };
+static PyObject * TriggerDummy_setSub(TriggerDummy *self, PyObject *arg) { SET_SUB };
+static PyObject * TriggerDummy_setDiv(TriggerDummy *self, PyObject *arg) { SET_DIV };
 
 static PyObject * TriggerDummy_play(TriggerDummy *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * TriggerDummy_stop(TriggerDummy *self) { STOP };
@@ -435,14 +435,14 @@ static PyMethodDef TriggerDummy_methods[] = {
     {"setMul", (PyCFunction)TriggerDummy_setMul, METH_O, "Sets oscillator mul factor."},
     {"setAdd", (PyCFunction)TriggerDummy_setAdd, METH_O, "Sets oscillator add factor."},
     {"setSub", (PyCFunction)TriggerDummy_setSub, METH_O, "Sets inverse add factor."},
-    {"setDiv", (PyCFunction)TriggerDummy_setDiv, METH_O, "Sets inverse mul factor."},        
+    {"setDiv", (PyCFunction)TriggerDummy_setDiv, METH_O, "Sets inverse mul factor."},
     {NULL}  /* Sentinel */
 };
 static PyNumberMethods TriggerDummy_as_number = {
     (binaryfunc)TriggerDummy_add,                         /*nb_add*/
     (binaryfunc)TriggerDummy_sub,                         /*nb_subtract*/
     (binaryfunc)TriggerDummy_multiply,                    /*nb_multiply*/
-    (binaryfunc)TriggerDummy_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -456,16 +456,16 @@ static PyNumberMethods TriggerDummy_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)TriggerDummy_inplace_add,                 /*inplace_add*/
     (binaryfunc)TriggerDummy_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)TriggerDummy_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)TriggerDummy_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -474,15 +474,14 @@ static PyNumberMethods TriggerDummy_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)TriggerDummy_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)TriggerDummy_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject TriggerDummyType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.TriggerDummy_base",         /*tp_name*/
     sizeof(TriggerDummy),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -490,7 +489,7 @@ PyTypeObject TriggerDummyType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &TriggerDummy_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -520,4 +519,4 @@ PyTypeObject TriggerDummyType = {
     0,      /* tp_init */
     0,                         /* tp_alloc */
     TriggerDummy_new,                 /* tp_new */
-};
+};
\ No newline at end of file
diff --git a/src/engine/fft.c b/src/engine/fft.c
index dcaaff3..ebd8530 100644
--- a/src/engine/fft.c
+++ b/src/engine/fft.c
@@ -1,14 +1,33 @@
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
+ * This file is part of pyo, a python module to help digital signal       *
+ * processing script creation.                                            *
+ *                                                                        *
+ * pyo is free software: you can redistribute it and/or modify            *
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
+ *                                                                        *
+ * pyo is distributed in the hope that it will be useful,                 *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ * GNU 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/>.   *
+ *************************************************************************/
 /******************************************************
 **	                 FFT library
 **
-**  (one-dimensional complex and real FFTs for array 
+**  (one-dimensional complex and real FFTs for array
 **  lengths of 2^n)
 **
 **	Author: Toth Laszlo (tothl at inf.u-szeged.hu)
-**  
+**
 **	Research Group on Artificial Intelligence
 **  H-6720 Szeged, Aradi vertanuk tere 1, Hungary
-**	
+**
 **	Last modified: 97.05.29
 **
 **  Modified by belangeo 2011.05.25
@@ -55,12 +74,12 @@ void fft_compute_radix2_twiddle(MYFLT *twiddle, int size) {
 ** Sorensen in-place split-radix FFT for real values
 ** data: array of doubles:
 ** re(0),re(1),re(2),...,re(size-1)
-** 
+**
 ** output:
 ** re(0),re(1),re(2),...,re(size/2),im(size/2-1),...,im(1)
 ** normalized by array length
 **
-** Source: 
+** Source:
 ** Sorensen et al: Real-Valued Fast Fourier Transform Algorithms,
 ** IEEE Trans. ASSP, ASSP-35, No. 6, June 1987
 **************************************************************** */
@@ -83,16 +102,16 @@ void realfft_split(MYFLT *data, MYFLT *outdata, int n, MYFLT **twiddle) {
 	    k = n2;
 	    while (k<=j){
 			j -= k;
-			k >>= 1;	
+			k >>= 1;
 		}
 	    j += k;
     }
-	
+
 	/* length two butterflies */
 	i0 = 0;
 	id = 4;
     do {
-        for (; i0<n4; i0+=id){ 
+        for (; i0<n4; i0+=id){
 		    i1 = i0 + 1;
 			t1 = data[i0];
 			data[i0] = t1 + data[i1];
@@ -105,14 +124,14 @@ void realfft_split(MYFLT *data, MYFLT *outdata, int n, MYFLT **twiddle) {
 
     /* L shaped butterflies */
     n2 = 2;
-    for(k=n; k>2; k>>=1) {  
+    for(k=n; k>2; k>>=1) {
 	    n2 <<= 1; /* power of two from 4 to n */
 	    n4 = n2 >> 2;
 	    n8 = n2 >> 3;
 	    pas = n / n2;
 	    i1 = 0;
 	    id = n2 << 1;
-	    do { 
+	    do {
 	        for (; i1<n; i1+=id){
 			    i2 = i1 + n4;
 			    i3 = i2 + n4;
@@ -138,16 +157,16 @@ void realfft_split(MYFLT *data, MYFLT *outdata, int n, MYFLT **twiddle) {
 	        i1 = id - n2;
 	        id <<= 1;
 	    } while ( i1<n );
-	    for (j=2; j<=n8; j++){ 
+	    for (j=2; j<=n8; j++){
 	        pos = (j-1) * pas;
 	        cc1 = twiddle[0][pos];
 	        ss1 = twiddle[1][pos];
 	        cc3 = twiddle[2][pos];
-	        ss3 = twiddle[3][pos]; 
+	        ss3 = twiddle[3][pos];
 	        i = 0;
 	        id = n2 << 1;
 	        do {
-		        for (; i<n; i+=id){  
+		        for (; i<n; i+=id){
 			        i1 = i + j - 1;
 			        i2 = i1 + n4;
 			        i3 = i2 + n4;
@@ -185,7 +204,7 @@ void realfft_split(MYFLT *data, MYFLT *outdata, int n, MYFLT **twiddle) {
     }
 
 	/* division with array length */
-    for(i=0; i<n; i++) 
+    for(i=0; i<n; i++)
         outdata[i] = data[i] / n;
 }
 
@@ -193,12 +212,12 @@ void realfft_split(MYFLT *data, MYFLT *outdata, int n, MYFLT **twiddle) {
 ** Sorensen in-place inverse split-radix FFT for real values
 ** data: array of doubles:
 ** re(0),re(1),re(2),...,re(size/2),im(size/2-1),...,im(1)
-** 
+**
 ** output:
 ** re(0),re(1),re(2),...,re(size-1)
 ** NOT normalized by array length
 **
-** Source: 
+** Source:
 ** Sorensen et al: Real-Valued Fast Fourier Transform Algorithms,
 ** IEEE Trans. ASSP, ASSP-35, No. 6, June 1987
 ****************************************************************** */
@@ -208,19 +227,19 @@ void irealfft_split(MYFLT *data, MYFLT *outdata, int n, MYFLT **twiddle) {
     int i,j,k,i5,i6,i7,i8,i0,id,i1,i2,i3,i4,n2,n4,n8,n1;
     int pas, pos;
     MYFLT t1,t2,t3,t4,t5,ss1,ss3,cc1,cc3,sqrt2;
-  
+
     sqrt2 = 1.4142135623730951; /* sqrt(2.0) */
-  
+
     n1 = n - 1;
     n2 = n << 1;
-    for(k=n; k>2; k>>=1) {  
+    for(k=n; k>2; k>>=1) {
 	    id = n2;
 	    n2 >>= 1;
 	    n4 = n2 >> 2;
 	    n8 = n2 >> 3;
 	    pas = n / n2;
 	    i1 = 0;
-	    do { 
+	    do {
 	        for (; i1<n; i1+=id) {
 			    i2 = i1 + n4;
 			    i3 = i2 + n4;
@@ -247,7 +266,7 @@ void irealfft_split(MYFLT *data, MYFLT *outdata, int n, MYFLT **twiddle) {
 	        i1 = id - n2;
 	        id <<= 1;
 	    } while ( i1<n1 );
-	    for (j=2; j<=n8; j++) {  
+	    for (j=2; j<=n8; j++) {
 	        pos = (j-1) * pas;
 	        cc1 = twiddle[0][pos];
 	        ss1 = twiddle[1][pos];
@@ -256,7 +275,7 @@ void irealfft_split(MYFLT *data, MYFLT *outdata, int n, MYFLT **twiddle) {
 	        i = 0;
 	        id = n2 << 1;
 	        do {
-		        for (; i<n; i+=id) {  
+		        for (; i<n; i+=id) {
 			        i1 = i + j - 1;
 			        i2 = i1 + n4;
 			        i3 = i2 + n4;
@@ -287,13 +306,13 @@ void irealfft_split(MYFLT *data, MYFLT *outdata, int n, MYFLT **twiddle) {
 		        id <<= 1;
 		    } while(i<n1);
 	    }
-    }	
+    }
 
     /*----------------------*/
 	i0 = 0;
 	id = 4;
     do {
-        for (; i0<n1; i0+=id) { 
+        for (; i0<n1; i0+=id) {
 		    i1 = i0 + 1;
 			t1 = data[i0];
 			data[i0] = t1 + data[i1];
@@ -314,12 +333,12 @@ void irealfft_split(MYFLT *data, MYFLT *outdata, int n, MYFLT **twiddle) {
 	    k = n2;
 	    while (k<=j) {
 			j -= k;
-			k >>= 1;	
+			k >>= 1;
 		}
 	    j += k;
     }
     for (i=0; i<n; i++)
-        outdata[i] = data[i];	
+        outdata[i] = data[i];
 }
 
 /* *****************************************************
@@ -327,7 +346,7 @@ void irealfft_split(MYFLT *data, MYFLT *outdata, int n, MYFLT **twiddle) {
 ** data: array of doubles:
 ** re(0),im(0),re(1),im(1),...,re(size-1),im(size-1)
 ** it means that size=array_length/2 !!
-** 
+**
 ** suggested use:
 ** intput in normal order
 ** output in bit-reversed order
@@ -360,7 +379,7 @@ void dif_butterfly(MYFLT *data, int size, MYFLT *twiddle){
                 *(l1) = xr; *(l1+1) = xi;
                 *(l2) = yr; *(l2+1) = yi;
                 angle += astep;
-		    } 
+		    }
         }
     }
 }
@@ -415,7 +434,7 @@ void inverse_dit_butterfly(MYFLT *data, int size, MYFLT *twiddle){
 ** it means that size=array_length/2 !!
 **
 ** Source: Rabiner-Gold: Theory and Application of DSP,
-** Prentice Hall,1978 
+** Prentice Hall,1978
 ******************************************************* */
 void unshuffle(MYFLT *data, int size){
 
@@ -433,14 +452,14 @@ void unshuffle(MYFLT *data, int size){
         k = m;
         while (k <= j) {
             j -= k;
-            k >>= 1;	
+            k >>= 1;
         }
         j += k;
     }
 }
 
 /* *****************************************************
-** used by realfft 
+** used by realfft
 ** parameters as above
 **
 ** Source: Brigham: The Fast Fourier Transform
@@ -456,7 +475,7 @@ void realize(MYFLT *data, int size) {
     xr = *l1;
     xi = *(l1+1);
     *l1 = xr + xi;
-    *(l1+1) = xr - xi; 
+    *(l1+1) = xr - xi;
 	l1 += 2;
 	astep = PI / size;
     for(ang=astep; l1<=l2; l1+=2, l2-=2, ang+=astep) {
@@ -469,14 +488,14 @@ void realize(MYFLT *data, int size) {
         dr = yr * wr - yi * wi;
         di = yr * wi + yi * wr;
         *l1 = xr + dr;
-        *(l1+1) = xi + di;      
+        *(l1+1) = xi + di;
         *l2 = xr - dr;
         *(l2+1) = -xi + di;
 	}
 }
 
 /* *****************************************************
-** used by inverse realfft 
+** used by inverse realfft
 ** parameters as above
 **
 ** Source: Brigham: The Fast Fourier Transform
@@ -492,7 +511,7 @@ void unrealize(MYFLT *data, int size) {
     xr = (*l1) / 2;
     xi = (*(l1+1)) / 2;
     *l1 = xr + xi;
-    *(l1+1) = xr - xi; 
+    *(l1+1) = xr - xi;
 	l1 += 2;
 	astep = PI / size;
     for(ang=astep; l1<=l2; l1+=2, l2-=2, ang+=astep){
@@ -505,7 +524,7 @@ void unrealize(MYFLT *data, int size) {
         dr = yr * wr - yi * wi;
         di = yr * wi + yi * wr;
         *l2 = xr + dr;
-        *(l1+1) = xi + di;      
+        *(l1+1) = xi + di;
         *l1 = xr - dr;
         *(l2+1) = -xi + di;
 	}
@@ -516,7 +535,7 @@ void unrealize(MYFLT *data, int size) {
 ** (by the so-called "packing method")
 ** data: array of doubles:
 ** re(0),re(1),re(2),...,re(size-1)
-** 
+**
 ** output:
 ** re(0),re(size/2),re(1),im(1),re(2),im(2),...,re(size/2-1),im(size/2-1)
 ** normalized by array length
@@ -541,8 +560,8 @@ void realfft_packed(MYFLT *data, MYFLT *outdata, int size, MYFLT *twiddle) {
 ** in-place Radix-2 inverse FFT for real values
 ** (by the so-called "packing method")
 ** data: array of doubles:
-** re(0),re(size/2),re(1),im(1),re(2),im(2),...,re(size/2-1),im(size/2-1) 
-** 
+** re(0),re(size/2),re(1),im(1),re(2),im(2),...,re(size/2-1),im(size/2-1)
+**
 ** output:
 ** re(0),re(1),re(2),...,re(size-1)
 ** NOT normalized by array length
@@ -562,4 +581,3 @@ void irealfft_packed(MYFLT *data, MYFLT *outdata, int size, MYFLT *twiddle) {
 	for (i=0; i<size; i++)
 	    outdata[i] = data[i] * 2;
 }
-
diff --git a/src/engine/inputfadermodule.c b/src/engine/inputfadermodule.c
index 5f6b44e..1ee5d4d 100644
--- a/src/engine/inputfadermodule.c
+++ b/src/engine/inputfadermodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
@@ -40,40 +41,40 @@ typedef struct {
 
 static void InputFader_setProcMode(InputFader *self) {};
 
-static void InputFader_process_only_first(InputFader *self) 
+static void InputFader_process_only_first(InputFader *self)
 {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input1_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = in[i];
     }
 }
 
-static void InputFader_process_only_second(InputFader *self) 
+static void InputFader_process_only_second(InputFader *self)
 {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input2_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = in[i];
     }
 }
 
-static void InputFader_process_one(InputFader *self) 
+static void InputFader_process_one(InputFader *self)
 {
     int i;
     MYFLT sclfade, val;
     MYFLT *in1 = Stream_getData((Stream *)self->input1_stream);
     MYFLT *in2 = Stream_getData((Stream *)self->input2_stream);
-    
+
     val = 0.0;
     sclfade = 1. / self->fadetime;
     for (i=0; i<self->bufsize; i++) {
         if (self->currentTime < self->fadetime) {
             val = MYSQRT(self->currentTime * sclfade);
             self->currentTime += self->sampleToSec;
-        }    
+        }
         else
             val = 1.;
 
@@ -84,7 +85,7 @@ static void InputFader_process_one(InputFader *self)
 
 }
 
-static void InputFader_process_two(InputFader *self) 
+static void InputFader_process_two(InputFader *self)
 {
     int i;
     MYFLT sclfade, val;
@@ -97,10 +98,10 @@ static void InputFader_process_two(InputFader *self)
         if (self->currentTime < self->fadetime) {
             val = MYSQRT(self->currentTime * sclfade);
             self->currentTime += self->sampleToSec;
-        }    
+        }
         else
             val = 1.;
-        
+
         self->data[i] = in2[i] * val + in1[i] * (1 - val);
     }
     if (val == 1.)
@@ -109,7 +110,7 @@ static void InputFader_process_two(InputFader *self)
 
 static void
 InputFader_compute_next_data_frame(InputFader *self)
-{   
+{
     (*self->proc_func_ptr)(self);
 }
 
@@ -124,7 +125,7 @@ InputFader_traverse(InputFader *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 InputFader_clear(InputFader *self)
 {
     pyo_CLEAR
@@ -140,7 +141,7 @@ InputFader_dealloc(InputFader* self)
 {
     pyo_DEALLOC
     InputFader_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -150,15 +151,15 @@ InputFader_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp=NULL, *streamtmp;
     InputFader *self;
     self = (InputFader *)type->tp_alloc(type, 0);
-    
+
     self->switcher = 0;
     self->fadetime = 0.05;
     self->currentTime = 0.0;
-    
+
     INIT_OBJECT_COMMON
 
     self->sampleToSec = 1. / self->sr;
-    
+
     Stream_setFunctionPtr(self->stream, InputFader_compute_next_data_frame);
     self->mode_func_ptr = InputFader_setProcMode;
     self->proc_func_ptr = InputFader_process_only_first;
@@ -166,14 +167,11 @@ InputFader_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     static char *kwlist[] = {"input", NULL};
 
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &inputtmp))
-        Py_RETURN_NONE; 
+        Py_RETURN_NONE;
 
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "server") == 0 ) {
-        PySys_WriteStderr("TypeError: \"input\" argument must be a PyoObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument must be a PyoObject.\n");
+        Py_RETURN_NONE;
     }
     Py_INCREF(inputtmp);
     Py_XDECREF(self->input1);
@@ -182,9 +180,9 @@ InputFader_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     Py_INCREF(streamtmp);
     Py_XDECREF(self->input1_stream);
     self->input1_stream = (Stream *)streamtmp;
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     return (PyObject *)self;
 }
 
@@ -196,13 +194,13 @@ InputFader_setInput(InputFader *self, PyObject *args, PyObject *kwds)
     static char *kwlist[] = {"input", "fadetime", NULL};
 
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_F, kwlist, &tmp, &self->fadetime))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     self->switcher = (self->switcher + 1) % 2;
     self->currentTime = 0.0;
     if (self->fadetime == 0)
         self->fadetime = 0.0001;
-    
+
     Py_INCREF(tmp);
 
     if (self->switcher == 0) {
@@ -222,11 +220,11 @@ InputFader_setInput(InputFader *self, PyObject *args, PyObject *kwds)
         Py_XDECREF(self->input2_stream);
         self->input2_stream = (Stream *)streamtmp;
         self->proc_func_ptr = InputFader_process_two;
-	}    
-    
+	}
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject * InputFader_getServer(InputFader* self) { GET_SERVER };
 static PyObject * InputFader_getStream(InputFader* self) { GET_STREAM };
@@ -254,8 +252,7 @@ static PyMethodDef InputFader_methods[] = {
 };
 
 PyTypeObject InputFaderType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.InputFader_base",         /*tp_name*/
     sizeof(InputFader),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -263,7 +260,7 @@ PyTypeObject InputFaderType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     0,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -294,4 +291,3 @@ PyTypeObject InputFaderType = {
     0,                         /* tp_alloc */
     InputFader_new,                 /* tp_new */
 };
-
diff --git a/src/engine/interpolation.c b/src/engine/interpolation.c
index a9ee2b5..ac986a0 100644
--- a/src/engine/interpolation.c
+++ b/src/engine/interpolation.c
@@ -1,21 +1,21 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include "interpolation.h"
@@ -36,16 +36,16 @@ MYFLT cosine(MYFLT *buf, int index, MYFLT frac, int size) {
     MYFLT frac2;
     MYFLT x1 = buf[index];
     MYFLT x2 = buf[index+1];
-    
+
     frac2 = (1.0 - MYCOS(frac * M_PI)) * 0.5;
-    return (x1 * (1.0 - frac2) + x2 * frac2);
+    return (x1 + (x2 - x1) * frac2);
 }
 
 MYFLT cubic(MYFLT *buf, int index, MYFLT frac, int size) {
     MYFLT x0, x3, a0, a1, a2, a3;
     MYFLT x1 = buf[index];
     MYFLT x2 = buf[index+1];
-    
+
     if (index == 0) {
         x0 = x1 + (x1 - x2);
         x3 = buf[index + 2];
@@ -53,16 +53,16 @@ MYFLT cubic(MYFLT *buf, int index, MYFLT frac, int size) {
     else if (index >= (size-2)) {
         x0 = buf[index - 1];
         x3 = x2 + (x2 - x1);
-    }    
+    }
     else {
         x0 = buf[index - 1];
         x3 = buf[index + 2];
     }
-    
+
     a3 = frac * frac; a3 -= 1.0; a3 *= (1.0 / 6.0);
     a2 = (frac + 1.0) * 0.5; a0 = a2 - 1.0;
     a1 = a3 * 3.0; a2 -= a1; a0 -= a3; a1 -= frac;
     a0 *= frac; a1 *= frac; a2 *= frac; a3 *= frac; a1 += 1.0;
 
     return (a0*x0+a1*x1+a2*x2+a3*x3);
-}
+}
\ No newline at end of file
diff --git a/src/engine/md_portmidi.c b/src/engine/md_portmidi.c
new file mode 100644
index 0000000..6d8592b
--- /dev/null
+++ b/src/engine/md_portmidi.c
@@ -0,0 +1,560 @@
+/**************************************************************************
+ * Copyright 2009-2016 Olivier Belanger                                   *
+ *                                                                        *
+ * This file is part of pyo, a python module to help digital signal       *
+ * processing script creation.                                            *
+ *                                                                        *
+ * pyo is free software: you can redistribute it and/or modify            *
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
+ *                                                                        *
+ * pyo is distributed in the hope that it will be useful,                 *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ * GNU 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/>.   *
+ *************************************************************************/
+
+#include "md_portmidi.h"
+#include "py2to3.h"
+
+static PyoMidiEvent PmEventToPyoMidiEvent(PmEvent buffer)
+{
+    PyoMidiEvent newbuf;
+    newbuf.message = buffer.message;
+    newbuf.timestamp = buffer.timestamp;
+    return newbuf;
+}
+
+void portmidiGetEvents(Server *self)
+{
+    int i;
+    PmError result, length;
+    PmEvent buffer;
+
+    PyoPmBackendData *be_data = (PyoPmBackendData *) self->midi_be_data;
+
+    for (i=0; i<self->midiin_count; i++) {
+        do {
+            result = Pm_Poll(be_data->midiin[i]);
+            if (result) {
+                length = Pm_Read(be_data->midiin[i], &buffer, 1);
+                if (length > 0)
+                    self->midiEvents[self->midi_count++] = PmEventToPyoMidiEvent(buffer);
+            }
+        } while (result);
+    }
+}
+
+int
+Server_pm_init(Server *self)
+{
+    int i = 0, ret = 0;
+    PmError pmerr;
+
+    if (self->midiActive == 0) {
+        self->withPortMidi = 0;
+        self->withPortMidiOut = 0;
+        return 0;
+    }
+
+    Py_BEGIN_ALLOW_THREADS
+    pmerr = Pm_Initialize();
+    Py_END_ALLOW_THREADS
+
+    if (pmerr) {
+        Server_warning(self, "Portmidi warning: could not initialize Portmidi: %s\n", Pm_GetErrorText(pmerr));
+        self->withPortMidi = 0;
+        self->withPortMidiOut = 0;
+        return -1;
+    }
+    else {
+        Server_debug(self, "Portmidi initialized.\n");
+        self->withPortMidi = 1;
+        self->withPortMidiOut = 1;
+    }
+
+    PyoPmBackendData *be_data = (PyoPmBackendData *) malloc(sizeof(PyoPmBackendData *));
+    self->midi_be_data = (void *) be_data;
+
+    if (self->withPortMidi == 1) {
+        self->midiin_count = self->midiout_count = 0;
+        int num_devices = Pm_CountDevices();
+        Server_debug(self, "Portmidi number of devices: %d.\n", num_devices);
+        if (num_devices > 0) {
+            if (self->midi_input < num_devices) {
+                if (self->midi_input == -1)
+                    self->midi_input = Pm_GetDefaultInputDeviceID();
+                Server_debug(self, "Midi input device : %d.\n", self->midi_input);
+                const PmDeviceInfo *info = Pm_GetDeviceInfo(self->midi_input);
+                if (info != NULL) {
+                    if (info->input) {
+
+                        Py_BEGIN_ALLOW_THREADS
+                        Pt_Start(1, 0, 0); /* start a timer with millisecond accuracy */
+                        pmerr = Pm_OpenInput(&be_data->midiin[0], self->midi_input, NULL, 100, NULL, NULL);
+                        Py_END_ALLOW_THREADS
+
+                        if (pmerr) {
+                            Server_warning(self,
+                                 "Portmidi warning: could not open midi input %d (%s): %s\n",
+                                 self->midi_input, info->name, Pm_GetErrorText(pmerr));
+                            self->withPortMidi = 0;
+                        }
+                        else {
+                            Server_debug(self, "Midi input (%s) opened.\n", info->name);
+                            self->midiin_count = 1;
+                        }
+                    }
+                    else {
+                        Server_warning(self, "Portmidi warning: Midi Device (%s), not an input device!\n", info->name);
+                        self->withPortMidi = 0;
+                    }
+                }
+                else {
+                    Server_debug(self, "Can't get midi input device info : %d.\n", self->midi_input);
+                    self->withPortMidi = 0;
+                }
+            }
+            else if (self->midi_input >= num_devices) {
+                Server_debug(self, "Midi input device : all!\n");
+                self->midiin_count = 0;
+
+                Py_BEGIN_ALLOW_THREADS
+                Pt_Start(1, 0, 0); /* start a timer with millisecond accuracy */
+                Py_END_ALLOW_THREADS
+
+                for (i=0; i<num_devices; i++) {
+                    const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
+                    if (info != NULL) {
+                        if (info->input) {
+
+                            Py_BEGIN_ALLOW_THREADS
+                            pmerr = Pm_OpenInput(&be_data->midiin[self->midiin_count], i, NULL, 100, NULL, NULL);
+                            Py_END_ALLOW_THREADS
+
+                            if (pmerr) {
+                                Server_warning(self,
+                                     "Portmidi warning: could not open midi input %d (%s): %s\n",
+                                     0, info->name, Pm_GetErrorText(pmerr));
+                            }
+                            else {
+                                Server_debug(self, "Midi input (%s) opened.\n", info->name);
+                                self->midiin_count++;
+                            }
+                        }
+                    }
+                }
+                if (self->midiin_count == 0)
+                    self->withPortMidi = 0;
+            }
+            else {
+                    Server_warning(self, "Portmidi warning: no input device!\n");
+                    self->withPortMidi = 0;
+            }
+
+            if (self->midi_output < num_devices) {
+                if (self->midi_output == -1)
+                    self->midi_output = Pm_GetDefaultOutputDeviceID();
+                Server_debug(self, "Midi output device : %d.\n", self->midi_output);
+                const PmDeviceInfo *outinfo = Pm_GetDeviceInfo(self->midi_output);
+                if (outinfo != NULL) {
+                    if ((strcmp(outinfo->name, "Microsoft MIDI Mapper") == 0 || 
+                          strcmp(outinfo->name, "Microsoft GS Wavetable Synth") == 0) && 
+                         self->allowMMMapper == 0) {
+                        self->withPortMidiOut = 0;
+                    }
+                    else if (outinfo->output) {
+
+                        Py_BEGIN_ALLOW_THREADS
+                        if (!Pt_Started())
+                            Pt_Start(1, 0, 0); /* start a timer with millisecond accuracy */
+                        pmerr = Pm_OpenOutput(&be_data->midiout[0], self->midi_output, NULL, 100, NULL, NULL, 1);
+                        Py_END_ALLOW_THREADS
+
+                        if (pmerr) {
+                            Server_warning(self,
+                                     "Portmidi warning: could not open midi output %d (%s): %s\n",
+                                     self->midi_output, outinfo->name, Pm_GetErrorText(pmerr));
+                            self->withPortMidiOut = 0;
+
+                            Py_BEGIN_ALLOW_THREADS
+                            if (Pt_Started())
+                                Pt_Stop();
+                            Py_END_ALLOW_THREADS
+
+                        }
+                        else {
+                            Server_debug(self, "Midi output (%s) opened.\n", outinfo->name);
+                            self->midiout_count = 1;
+                        }
+                    }
+                    else {
+                        Server_warning(self, "Portmidi warning: Midi Device (%s), not an output device!\n", outinfo->name);
+                        self->withPortMidiOut = 0;
+                    }
+                }
+                else {
+                    Server_debug(self, "Can't get midi output device info : %d.\n", self->midi_output);
+                    self->withPortMidiOut = 0;
+                }
+            }
+            else if (self->midi_output >= num_devices) {
+                Server_debug(self, "Midi output device : all!\n");
+                self->midiout_count = 0;
+
+                Py_BEGIN_ALLOW_THREADS
+                if (!Pt_Started())
+                    Pt_Start(1, 0, 0); /* start a timer with millisecond accuracy */
+                Py_END_ALLOW_THREADS
+
+                for (i=0; i<num_devices; i++) {
+                    const PmDeviceInfo *outinfo = Pm_GetDeviceInfo(i);
+                    if (outinfo != NULL) {
+                        if ((strcmp(outinfo->name, "Microsoft MIDI Mapper") == 0 || 
+                              strcmp(outinfo->name, "Microsoft GS Wavetable Synth") == 0) && 
+                             self->allowMMMapper == 0) {
+                            continue;
+                        }
+                        else if (outinfo->output) {
+
+                            Py_BEGIN_ALLOW_THREADS
+                            pmerr = Pm_OpenOutput(&be_data->midiout[self->midiout_count], i, NULL, 100, NULL, NULL, 1);
+                            Py_END_ALLOW_THREADS
+
+                            if (pmerr) {
+                                Server_warning(self,
+                                     "Portmidi warning: could not open midi output %d (%s): %s\n",
+                                     0, outinfo->name, Pm_GetErrorText(pmerr));
+                            }
+                            else {
+                                Server_debug(self, "Midi output (%s) opened.\n", outinfo->name);
+                                self->midiout_count++;
+                            }
+                        }
+                    }
+                }
+                if (self->midiout_count == 0) {
+                    self->withPortMidiOut = 0;
+                }
+            }
+            else {
+                    Server_warning(self, "Portmidi warning: no output device!\n");
+                    self->withPortMidiOut = 0;
+            }
+
+            if (self->withPortMidi == 0 && self->withPortMidiOut == 0) {
+
+                Py_BEGIN_ALLOW_THREADS
+                if (Pt_Started())
+                    Pt_Stop();
+                Pm_Terminate();
+                Py_END_ALLOW_THREADS
+
+                Server_warning(self, "Portmidi closed.\n");
+                ret = -1;
+            }
+        }
+        else {
+            Server_warning(self, "Portmidi warning: no midi device found!\nPortmidi closed.\n");
+            self->withPortMidi = 0;
+            self->withPortMidiOut = 0;
+
+            Py_BEGIN_ALLOW_THREADS
+            Pm_Terminate();
+            Py_END_ALLOW_THREADS
+
+            ret = -1;
+        }
+    }
+    if (self->withPortMidi == 1) {
+        self->midi_count = 0;
+        for (i=0; i<self->midiin_count; i++) {
+            Pm_SetFilter(be_data->midiin[i], PM_FILT_ACTIVE | PM_FILT_CLOCK);
+        }
+    }
+    return ret;
+}
+
+int
+Server_pm_deinit(Server *self)
+{
+    int i = 0;
+
+    PyoPmBackendData *be_data = (PyoPmBackendData *) self->midi_be_data;
+
+    /* An opened stream should be properly closed 
+       but Pm_Close segfaults now and then so...
+       This hack need to be tested on Windows and OSX. */
+
+    if (self->withPortMidi == 1) {
+        for (i=0; i<self->midiin_count; i++) {
+            if (be_data->midiin[i] != NULL) {
+/*
+                Py_BEGIN_ALLOW_THREADS
+                Pm_Close(be_data->midiin[i]);
+                Py_END_ALLOW_THREADS
+*/
+            }
+        }
+    }
+    if (self->withPortMidiOut == 1) {
+        for (i=0; i<self->midiout_count; i++) {
+            if (be_data->midiout[i] != NULL) {
+/*
+                Py_BEGIN_ALLOW_THREADS
+                Pm_Close(be_data->midiout[i]);
+                Py_END_ALLOW_THREADS
+*/
+            }
+        }
+    }
+    if (self->withPortMidi == 1 || self->withPortMidiOut == 1) {
+
+        Py_BEGIN_ALLOW_THREADS
+        if (Pt_Started())
+            Pt_Stop();
+        Pm_Terminate();
+        Py_END_ALLOW_THREADS
+
+    }
+    self->withPortMidi = 0;
+    self->withPortMidiOut = 0;
+    
+    free(self->midi_be_data);
+
+    return 0;
+}
+
+void
+pm_noteout(Server *self, int pit, int vel, int chan, long timestamp)
+{
+    int i, curtime;
+    PmEvent buffer[1];
+
+    PyoPmBackendData *be_data = (PyoPmBackendData *) self->midi_be_data;
+
+    curtime = Pt_Time();
+    buffer[0].timestamp = curtime + timestamp;
+    if (chan == 0)
+        buffer[0].message = Pm_Message(0x90, pit, vel);
+    else
+        buffer[0].message = Pm_Message(0x90 | (chan - 1), pit, vel);
+    for (i=0; i<self->midiout_count; i++) {
+        Pm_Write(be_data->midiout[i], buffer, 1);
+    }
+}
+
+void
+pm_afterout(Server *self, int pit, int vel, int chan, long timestamp)
+{
+    int i, curtime;
+    PmEvent buffer[1];
+
+    PyoPmBackendData *be_data = (PyoPmBackendData *) self->midi_be_data;
+
+    curtime = Pt_Time();
+    buffer[0].timestamp = curtime + timestamp;
+    if (chan == 0)
+        buffer[0].message = Pm_Message(0xA0, pit, vel);
+    else
+        buffer[0].message = Pm_Message(0xA0 | (chan - 1), pit, vel);
+    for (i=0; i<self->midiout_count; i++) {
+        Pm_Write(be_data->midiout[i], buffer, 1);
+    }
+}
+
+void
+pm_ctlout(Server *self, int ctlnum, int value, int chan, long timestamp)
+{
+    int i, curtime;
+    PmEvent buffer[1];
+
+    PyoPmBackendData *be_data = (PyoPmBackendData *) self->midi_be_data;
+
+    curtime = Pt_Time();
+    buffer[0].timestamp = curtime + timestamp;
+    if (chan == 0)
+        buffer[0].message = Pm_Message(0xB0, ctlnum, value);
+    else
+        buffer[0].message = Pm_Message(0xB0 | (chan - 1), ctlnum, value);
+    for (i=0; i<self->midiout_count; i++) {
+        Pm_Write(be_data->midiout[i], buffer, 1);
+    }
+}
+
+void
+pm_programout(Server *self, int value, int chan, long timestamp)
+{
+    int i, curtime;
+    PmEvent buffer[1];
+
+    PyoPmBackendData *be_data = (PyoPmBackendData *) self->midi_be_data;
+
+    curtime = Pt_Time();
+    buffer[0].timestamp = curtime + timestamp;
+    if (chan == 0)
+        buffer[0].message = Pm_Message(0xC0, value, 0);
+    else
+        buffer[0].message = Pm_Message(0xC0 | (chan - 1), value, 0);
+    for (i=0; i<self->midiout_count; i++) {
+        Pm_Write(be_data->midiout[i], buffer, 1);
+    }
+}
+
+void
+pm_pressout(Server *self, int value, int chan, long timestamp)
+{
+    int i, curtime;
+    PmEvent buffer[1];
+
+    PyoPmBackendData *be_data = (PyoPmBackendData *) self->midi_be_data;
+
+    curtime = Pt_Time();
+    buffer[0].timestamp = curtime + timestamp;
+    if (chan == 0)
+        buffer[0].message = Pm_Message(0xD0, value, 0);
+    else
+        buffer[0].message = Pm_Message(0xD0 | (chan - 1), value, 0);
+    for (i=0; i<self->midiout_count; i++) {
+        Pm_Write(be_data->midiout[i], buffer, 1);
+    }
+}
+
+void
+pm_bendout(Server *self, int value, int chan, long timestamp)
+{
+    int i, lsb, msb, curtime;
+    PmEvent buffer[1];
+
+    PyoPmBackendData *be_data = (PyoPmBackendData *) self->midi_be_data;
+
+    curtime = Pt_Time();
+    buffer[0].timestamp = curtime + timestamp;
+    lsb = value & 0x007F;
+    msb = (value & (0x007F << 7)) >> 7;
+    if (chan == 0)
+        buffer[0].message = Pm_Message(0xE0, lsb, msb);
+    else
+        buffer[0].message = Pm_Message(0xE0 | (chan - 1), lsb, msb);
+    for (i=0; i<self->midiout_count; i++) {
+        Pm_Write(be_data->midiout[i], buffer, 1);
+    }
+}
+
+void
+pm_sysexout(Server *self, unsigned char *msg, long timestamp)
+{
+    int i, curtime;
+
+    PyoPmBackendData *be_data = (PyoPmBackendData *) self->midi_be_data;
+
+    curtime = Pt_Time();
+    for (i=0; i<self->midiout_count; i++) {
+        Pm_WriteSysEx(be_data->midiout[i], curtime + timestamp, msg);
+    }
+}
+
+long
+pm_get_current_time()
+{
+    if (Pt_Started())
+        return Pt_Time();
+    else
+        return 0;
+}
+
+/* Query functions. */
+
+PyObject *
+portmidi_count_devices() {
+    int numDevices;
+	numDevices = Pm_CountDevices();
+    return PyInt_FromLong(numDevices);
+}
+
+PyObject *
+portmidi_list_devices() {
+    int i;
+    PySys_WriteStdout("MIDI devices:\n");
+    for (i = 0; i < Pm_CountDevices(); i++) {
+        const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
+        if (info->input && info->output)
+            PySys_WriteStdout("%d: IN/OUT, name: %s, interface: %s\n", i, info->name, info->interf);
+        else if (info->input)
+            PySys_WriteStdout("%d: IN, name: %s, interface: %s\n", i, info->name, info->interf);
+        else if (info->output)
+            PySys_WriteStdout("%d: OUT, name: %s, interface: %s\n", i, info->name, info->interf);
+    }
+    PySys_WriteStdout("\n");
+    Py_RETURN_NONE;
+}
+
+PyObject *
+portmidi_get_input_devices() {
+	int n, i;
+    PyObject *list, *list_index;
+    list = PyList_New(0);
+    list_index = PyList_New(0);
+    n = Pm_CountDevices();
+    if (n < 0){
+        PySys_WriteStdout("Portmidi warning: No Midi interface found\n\n");
+    }
+    else {
+        for (i=0; i < n; i++){
+            const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
+            if (info->input){
+                PyList_Append(list, PyUnicode_FromString(info->name));
+                PyList_Append(list_index, PyInt_FromLong(i));
+            }
+        }
+        PySys_WriteStdout("\n");
+    }
+    return Py_BuildValue("OO", list, list_index);
+}
+
+PyObject *
+portmidi_get_output_devices() {
+	int n, i;
+    PyObject *list, *list_index;
+    list = PyList_New(0);
+    list_index = PyList_New(0);
+    n = Pm_CountDevices();
+    if (n < 0){
+        PySys_WriteStdout("Portmidi warning: No Midi interface found\n\n");
+    }
+    else {
+        for (i=0; i < n; i++){
+            const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
+            if (info->output){
+                PyList_Append(list, PyUnicode_FromString(info->name));
+                PyList_Append(list_index, PyInt_FromLong(i));
+            }
+        }
+        PySys_WriteStdout("\n");
+    }
+    return Py_BuildValue("OO", list, list_index);
+}
+
+PyObject *
+portmidi_get_default_input() {
+    PmDeviceID i;
+
+    i = Pm_GetDefaultInputDeviceID();
+    if (i < 0)
+        PySys_WriteStdout("pm_get_default_input: no midi input device found.\n");
+    return PyInt_FromLong(i);
+}
+
+
+PyObject *
+portmidi_get_default_output() {
+    PmDeviceID i;
+    i = Pm_GetDefaultOutputDeviceID();
+    if (i < 0)
+        PySys_WriteStdout("pm_get_default_output: no midi output device found.\n");
+    return PyInt_FromLong(i);
+}
diff --git a/src/engine/midilistenermodule.c b/src/engine/midilistenermodule.c
new file mode 100644
index 0000000..df3f47d
--- /dev/null
+++ b/src/engine/midilistenermodule.c
@@ -0,0 +1,645 @@
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
+ * This file is part of pyo, a python module to help digital signal       *
+ * processing script creation.                                            *
+ *                                                                        *
+ * pyo is free software: you can redistribute it and/or modify            *
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
+ *                                                                        *
+ * pyo is distributed in the hope that it will be useful,                 *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ * GNU 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/>.   *
+ *************************************************************************/
+
+#include <Python.h>
+#include "py2to3.h"
+#include "structmember.h"
+#include <math.h>
+#include "pyomodule.h"
+#include "portmidi.h"
+#include "porttime.h"
+
+typedef struct {
+    PyObject_HEAD
+    PyObject *midicallable;
+    PmStream *midiin[64];
+    PyObject *mididev;
+    int ids[64];
+    int midicount;
+    int active;
+    int reportdevice;
+} MidiListener;
+
+void process_midi(PtTimestamp timestamp, void *userData)
+{
+    PmError result;
+    PmEvent buffer; /* just one message at a time */
+    int i, status, data1, data2;
+    PyObject *tup = NULL;
+    MidiListener *server = (MidiListener *)userData;
+
+    if (server->active == 0) return;
+
+    PyGILState_STATE s = PyGILState_Ensure();
+    do {
+        for (i=0; i<server->midicount; i++) {
+            result = Pm_Poll(server->midiin[i]);
+            if (result) {
+                if (Pm_Read(server->midiin[i], &buffer, 1) == pmBufferOverflow) 
+                    continue;
+                status = Pm_MessageStatus(buffer.message);
+                data1 = Pm_MessageData1(buffer.message);
+                data2 = Pm_MessageData2(buffer.message);
+                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);
+
+    PyGILState_Release(s);
+}
+
+static int
+MidiListener_traverse(MidiListener *self, visitproc visit, void *arg)
+{
+    Py_VISIT(self->midicallable);
+    Py_VISIT(self->mididev);
+    return 0;
+}
+
+static int
+MidiListener_clear(MidiListener *self)
+{
+    Py_CLEAR(self->midicallable);
+    Py_CLEAR(self->mididev);
+    return 0;
+}
+
+static void
+MidiListener_dealloc(MidiListener* self)
+{
+    if (self->active == 1)
+        PyObject_CallMethod((PyObject *)self, "stop", NULL);
+    MidiListener_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+MidiListener_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    PyObject *midicalltmp=NULL, *mididevtmp=NULL;
+    MidiListener *self;
+
+    self = (MidiListener *)type->tp_alloc(type, 0);
+
+    self->active = self->midicount = self->reportdevice = 0;
+
+    static char *kwlist[] = {"midicallable", "mididevice", "reportdevice", NULL};
+
+    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, lsize, mididev;
+    PmError pmerr;
+
+    Py_BEGIN_ALLOW_THREADS
+    /* always start the timer before you start midi */
+    Pt_Start(1, &process_midi, (void *)self);
+    
+    pmerr = Pm_Initialize();
+    Py_END_ALLOW_THREADS
+
+    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_GetDefaultInputDeviceID();
+                const PmDeviceInfo *info = Pm_GetDeviceInfo(mididev);
+                if (info != NULL) {
+                    if (info->input) {
+
+                        Py_BEGIN_ALLOW_THREADS
+                        pmerr = Pm_OpenInput(&self->midiin[0], mididev, NULL, 100, NULL, NULL);
+                        Py_END_ALLOW_THREADS
+
+                        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 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) {
+
+                            Py_BEGIN_ALLOW_THREADS
+                            pmerr = Pm_OpenInput(&self->midiin[self->midicount], i, NULL, 100, NULL, NULL);
+                            Py_END_ALLOW_THREADS
+
+                            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 {
+            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) {
+
+                        Py_BEGIN_ALLOW_THREADS
+                        pmerr = Pm_OpenInput(&self->midiin[self->midicount], i, NULL, 100, NULL, NULL);
+                        Py_END_ALLOW_THREADS
+
+                        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++;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    for (i=0; i<self->midicount; i++) {
+        Pm_SetFilter(self->midiin[i], PM_FILT_ACTIVE | PM_FILT_CLOCK);
+    }
+
+    if (self->midicount > 0)
+        self->active = 1;
+
+	Py_INCREF(Py_None);
+	return Py_None;
+};
+
+static PyObject * MidiListener_stop(MidiListener *self) { 
+    int i;
+
+    Py_BEGIN_ALLOW_THREADS
+    Pt_Stop();
+    for (i=0; i<self->midicount; i++) {
+        Pm_Close(self->midiin[i]);
+    }
+    Pm_Terminate();
+    Py_END_ALLOW_THREADS
+
+    self->active = 0;
+	Py_INCREF(Py_None);
+	return Py_None;
+};
+
+static PyObject *
+MidiListener_setMidiFunction(MidiListener *self, PyObject *arg)
+{
+	PyObject *tmp;
+
+	if (! PyCallable_Check(arg)) {
+        PyErr_SetString(PyExc_TypeError, "The callable attribute must be a valid Python function.");
+		Py_INCREF(Py_None);
+		return Py_None;
+	}
+
+    tmp = arg;
+    Py_XDECREF(self->midicallable);
+    Py_INCREF(tmp);
+    self->midicallable = tmp;
+
+	Py_INCREF(Py_None);
+	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 = PyUnicode_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 */
+};
+
+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 */
+};
+
+PyTypeObject MidiListenerType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.MidiListener_base",         /*tp_name*/
+    sizeof(MidiListener),         /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)MidiListener_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*/
+    "MidiListener objects. Calls a function with midi data as arguments.",           /* tp_doc */
+    (traverseproc)MidiListener_traverse,   /* tp_traverse */
+    (inquiry)MidiListener_clear,           /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    MidiListener_methods,             /* tp_methods */
+    MidiListener_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 */
+    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;
+
+    Py_BEGIN_ALLOW_THREADS
+    /* always start the timer before you start midi */
+    Pt_Start(1, 0, 0);
+    
+    pmerr = Pm_Initialize();
+    Py_END_ALLOW_THREADS
+
+    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) {
+
+                        Py_BEGIN_ALLOW_THREADS
+                        pmerr = Pm_OpenOutput(&self->midiout[0], mididev, NULL, 100, NULL, NULL, 1);
+                        Py_END_ALLOW_THREADS
+
+                        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) {
+
+                            Py_BEGIN_ALLOW_THREADS
+                            pmerr = Pm_OpenOutput(&self->midiout[self->midicount], i, NULL, 100, NULL, NULL, 1);
+                            Py_END_ALLOW_THREADS
+
+                            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) {
+
+                        Py_BEGIN_ALLOW_THREADS
+                        pmerr = Pm_OpenOutput(&self->midiout[self->midicount], i, NULL, 100, NULL, NULL, 1);
+                        Py_END_ALLOW_THREADS
+
+                        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;
+
+    Py_BEGIN_ALLOW_THREADS
+    Pt_Stop();
+    for (i=0; i<self->midicount; i++) {
+        Pm_Close(self->midiout[i]);
+    }
+    Pm_Terminate();    
+    Py_END_ALLOW_THREADS
+
+    self->active = 0;
+	Py_INCREF(Py_None);
+	return Py_None;
+};
+
+PyObject *
+MidiDispatcher_send(MidiDispatcher *self, PyObject *args)
+{
+    int i, status, data1, data2, device;
+    long 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_sendx(MidiDispatcher *self, PyObject *args)
+{
+    unsigned char *msg;
+    int i, size, device;
+    long curtime;
+    PmTimestamp timestamp;
+
+    if (! PyArg_ParseTuple(args, "s#li", &msg, &size, &timestamp, &device))
+        return PyInt_FromLong(-1);
+
+    curtime = Pt_Time();
+    if (device == -1 && self->midicount > 1) {
+        for (i=0; i<self->midicount; i++) {
+            Pm_WriteSysEx(self->midiout[i], curtime + timestamp, msg);
+        }
+    }
+    else if (self->midicount == 1)
+        Pm_WriteSysEx(self->midiout[0], curtime + timestamp, msg);
+    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_WriteSysEx(self->midiout[device], curtime + timestamp, msg);
+    }
+
+    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 = PyUnicode_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."},
+    {"sendx", (PyCFunction)MidiDispatcher_sendx, METH_VARARGS, "Send a sysex 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/mixmodule.c b/src/engine/mixmodule.c
index 5f40ea0..509f453 100644
--- a/src/engine/mixmodule.c
+++ b/src/engine/mixmodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
@@ -49,39 +50,39 @@ Mix_setProcMode(Mix *self)
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Mix_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Mix_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Mix_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Mix_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Mix_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Mix_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Mix_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Mix_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Mix_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Mix_compute_next_data_frame(Mix *self)
-{   
+{
     int i, j;
     MYFLT old;
     PyObject *stream;
@@ -96,13 +97,13 @@ Mix_compute_next_data_frame(Mix *self)
         for (j=0; j<self->bufsize; j++) {
             old = buffer[j];
             buffer[j] = in[j] + old;
-        }    
-    }    
-    
+        }
+    }
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = buffer[i];
     }
-    
+
     (*self->muladd_func_ptr)(self);
 }
 
@@ -114,7 +115,7 @@ Mix_traverse(Mix *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Mix_clear(Mix *self)
 {
     pyo_CLEAR
@@ -127,7 +128,7 @@ Mix_dealloc(Mix* self)
 {
     pyo_DEALLOC
     Mix_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -148,12 +149,12 @@ Mix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     static char *kwlist[] = {"input", "mul", "add", NULL};
 
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp))
-        Py_RETURN_NONE; 
+        Py_RETURN_NONE;
 
     Py_INCREF(inputtmp);
     Py_XDECREF(self->input);
     self->input = inputtmp;
-    
+
     if (multmp) {
         PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
     }
@@ -161,19 +162,19 @@ Mix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     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 * Mix_getServer(Mix* self) { GET_SERVER };
 static PyObject * Mix_getStream(Mix* self) { GET_STREAM };
-static PyObject * Mix_setMul(Mix *self, PyObject *arg) { SET_MUL };	
-static PyObject * Mix_setAdd(Mix *self, PyObject *arg) { SET_ADD };	
-static PyObject * Mix_setSub(Mix *self, PyObject *arg) { SET_SUB };	
+static PyObject * Mix_setMul(Mix *self, PyObject *arg) { SET_MUL };
+static PyObject * Mix_setAdd(Mix *self, PyObject *arg) { SET_ADD };
+static PyObject * Mix_setSub(Mix *self, PyObject *arg) { SET_SUB };
 static PyObject * Mix_setDiv(Mix *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Mix_play(Mix *self, PyObject *args, PyObject *kwds) { PLAY };
@@ -215,7 +216,7 @@ static PyNumberMethods Mix_as_number = {
     (binaryfunc)Mix_add,                      /*nb_add*/
     (binaryfunc)Mix_sub,                 /*nb_subtract*/
     (binaryfunc)Mix_multiply,                 /*nb_multiply*/
-    (binaryfunc)Mix_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -229,16 +230,16 @@ static PyNumberMethods Mix_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)Mix_inplace_add,              /*inplace_add*/
     (binaryfunc)Mix_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)Mix_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)Mix_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -247,15 +248,14 @@ static PyNumberMethods Mix_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)Mix_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)Mix_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject MixType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Mix_base",         /*tp_name*/
     sizeof(Mix),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -263,7 +263,7 @@ PyTypeObject MixType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &Mix_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -294,4 +294,3 @@ PyTypeObject MixType = {
     0,                         /* tp_alloc */
     Mix_new,                 /* tp_new */
 };
-
diff --git a/src/engine/osclistenermodule.c b/src/engine/osclistenermodule.c
new file mode 100644
index 0000000..050ef2a
--- /dev/null
+++ b/src/engine/osclistenermodule.c
@@ -0,0 +1,244 @@
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
+ * This file is part of pyo, a python module to help digital signal       *
+ * processing script creation.                                            *
+ *                                                                        *
+ * pyo is free software: you can redistribute it and/or modify            *
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
+ *                                                                        *
+ * pyo is distributed in the hope that it will be useful,                 *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ * GNU 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/>.   *
+ *************************************************************************/
+
+#include <Python.h>
+#include "py2to3.h"
+#include "structmember.h"
+#include <math.h>
+#include "pyomodule.h"
+#include "lo/lo.h"
+
+static void error(int num, const char *msg, const char *path)
+{
+    PySys_WriteStdout("liblo server error %d in path %s: %s\n", num, path, msg);
+}
+
+typedef struct {
+    PyObject_HEAD
+    PyObject *osccallable;
+    lo_server osc_server;
+    int oscport;
+} OscListener;
+
+static PyObject *
+OscListener_get(OscListener *self)
+{
+    while (lo_server_recv_noblock(self->osc_server, 0) != 0) {};
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+int process_osc(const char *path, const char *types, lo_arg **argv, int argc,
+                void *data, void *user_data)
+{
+    OscListener *server = (OscListener *)user_data;
+    PyObject *tup;
+    lo_blob *blob = NULL;
+    char *blobdata = NULL;
+    uint32_t blobsize = 0;
+    PyObject *charlist = NULL; 
+    tup = PyTuple_New(argc+1);
+    int i = 0;
+    unsigned int j = 0;
+
+    PyGILState_STATE s = PyGILState_Ensure();
+    PyTuple_SET_ITEM(tup, 0, PyUnicode_FromString(path));
+    for (i=0; i<argc; i++) {
+        switch (types[i]) {
+            case LO_INT32:
+                PyTuple_SET_ITEM(tup, i+1, PyInt_FromLong(argv[i]->i));
+                break;
+            case LO_INT64:
+                PyTuple_SET_ITEM(tup, i+1, PyLong_FromLong(argv[i]->h));
+                break;
+            case LO_FLOAT:
+                PyTuple_SET_ITEM(tup, i+1, PyFloat_FromDouble(argv[i]->f));
+                break;
+            case LO_DOUBLE:
+                PyTuple_SET_ITEM(tup, i+1, PyFloat_FromDouble(argv[i]->d));
+                break;
+            case LO_STRING:
+                PyTuple_SET_ITEM(tup, i+1, PyUnicode_FromString(&argv[i]->s));
+                break;
+            case LO_CHAR:
+                PyTuple_SET_ITEM(tup, i+1, PyUnicode_FromFormat("%c", argv[i]->c));
+                break;
+            case LO_BLOB:
+                blob = (lo_blob)argv[i];
+                blobsize = lo_blob_datasize(blob);
+                blobdata = lo_blob_dataptr(blob);
+                charlist = PyList_New(blobsize);
+                for (j=0; j<blobsize; j++) {
+                    PyList_SET_ITEM(charlist, j, PyUnicode_FromFormat("%c", blobdata[j]));
+                }
+                PyTuple_SET_ITEM(tup, i+1, charlist);
+                break;
+            case LO_MIDI:
+                charlist = PyList_New(4);
+                for (j=0; j<4; j++) {
+                    PyList_SET_ITEM(charlist, j, PyInt_FromLong(argv[i]->m[j]));
+                }
+                PyTuple_SET_ITEM(tup, i+1, charlist);                    
+                break;
+            case LO_NIL:
+                Py_INCREF(Py_None);
+                PyTuple_SET_ITEM(tup, i+1, Py_None);
+                break;
+            case LO_TRUE:
+                Py_INCREF(Py_True);
+                PyTuple_SET_ITEM(tup, i+1, Py_True);
+                break;
+            case LO_FALSE:
+                Py_INCREF(Py_False);
+                PyTuple_SET_ITEM(tup, i+1, Py_False);
+                break;
+            default:
+                break;
+        }
+    }
+    PyObject_Call((PyObject *)server->osccallable, tup, NULL);
+    PyGILState_Release(s);
+    Py_XDECREF(tup);
+
+    return 0;
+}
+
+static int
+OscListener_traverse(OscListener *self, visitproc visit, void *arg)
+{
+    Py_VISIT(self->osccallable);
+    return 0;
+}
+
+static int
+OscListener_clear(OscListener *self)
+{
+    Py_CLEAR(self->osccallable);
+    return 0;
+}
+
+static void
+OscListener_dealloc(OscListener* self)
+{
+    lo_server_free(self->osc_server);
+    OscListener_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+OscListener_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    char buf[20];
+    PyObject *osccalltmp=NULL;
+    OscListener *self;
+
+    self = (OscListener *)type->tp_alloc(type, 0);
+
+    static char *kwlist[] = {"osccallable", "port", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "Oi", kwlist, &osccalltmp, &self->oscport))
+        Py_RETURN_NONE;
+
+    if (osccalltmp) {
+        PyObject_CallMethod((PyObject *)self, "setOscFunction", "O", osccalltmp);
+    }
+
+    sprintf(buf, "%i", self->oscport);
+    self->osc_server = lo_server_new(buf, error);
+    lo_server_add_method(self->osc_server, NULL, NULL, process_osc, (void *)self);
+
+    return (PyObject *)self;
+}
+
+static PyObject *
+OscListener_setOscFunction(OscListener *self, PyObject *arg)
+{
+	PyObject *tmp;
+
+    if (arg == Py_None) {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+
+	if (! PyCallable_Check(arg)) {
+        PyErr_SetString(PyExc_TypeError, "The callable attribute must be a valid Python function.");
+		Py_INCREF(Py_None);
+		return Py_None;
+	}
+
+    tmp = arg;
+    Py_XDECREF(self->osccallable);
+    Py_INCREF(tmp);
+    self->osccallable = tmp;
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyMemberDef OscListener_members[] = {
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef OscListener_methods[] = {
+    {"get", (PyCFunction)OscListener_get, METH_NOARGS, "Check for new osc messages."},
+    {"setOscFunction", (PyCFunction)OscListener_setOscFunction, METH_O, "Sets the function to be called."},
+    {NULL}  /* Sentinel */
+};
+
+PyTypeObject OscListenerType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.OscListener_base",         /*tp_name*/
+    sizeof(OscListener),         /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)OscListener_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*/
+    "OscListener objects. Calls a function with OSC data as arguments.",           /* tp_doc */
+    (traverseproc)OscListener_traverse,   /* tp_traverse */
+    (inquiry)OscListener_clear,           /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    OscListener_methods,             /* tp_methods */
+    OscListener_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 */
+    OscListener_new,                 /* tp_new */
+};
diff --git a/src/engine/pvstreammodule.c b/src/engine/pvstreammodule.c
index 6b183dc..e488af3 100644
--- a/src/engine/pvstreammodule.c
+++ b/src/engine/pvstreammodule.c
@@ -1,21 +1,21 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
@@ -34,7 +34,7 @@ PVStream_dealloc(PVStream* self)
 {
     self->magn = NULL;
     self->freq = NULL;
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 int
@@ -53,7 +53,7 @@ MYFLT **
 PVStream_getMagn(PVStream *self)
 {
     return (MYFLT **)self->magn;
-}    
+}
 
 MYFLT **
 PVStream_getFreq(PVStream *self)
@@ -71,19 +71,19 @@ void
 PVStream_setFFTsize(PVStream *self, int fftsize)
 {
     self->fftsize = fftsize;
-}    
+}
 
 void
 PVStream_setOlaps(PVStream *self, int olaps)
 {
     self->olaps = olaps;
-}    
+}
 
 void
 PVStream_setMagn(PVStream *self, MYFLT **data)
 {
     self->magn = data;
-}    
+}
 
 void
 PVStream_setFreq(PVStream *self, MYFLT **data)
@@ -98,8 +98,7 @@ PVStream_setCount(PVStream *self, int *data)
 }
 
 PyTypeObject PVStreamType = {
-    PyObject_HEAD_INIT(NULL)
-    0, /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "pyo.PVStream", /*tp_name*/
     sizeof(PVStream), /*tp_basicsize*/
     0, /*tp_itemsize*/
@@ -107,7 +106,7 @@ PyTypeObject PVStreamType = {
     0, /*tp_print*/
     0, /*tp_getattr*/
     0, /*tp_setattr*/
-    0, /*tp_compare*/
+    0, /*tp_as_async (tp_compare in Python 2)*/
     0, /*tp_repr*/
     0, /*tp_as_number*/
     0, /*tp_as_sequence*/
@@ -139,4 +138,4 @@ PyTypeObject PVStreamType = {
     0, /* tp_init */
     0, /* tp_alloc */
     0, /* tp_new */
-};
+};
\ No newline at end of file
diff --git a/src/engine/pyomodule.c b/src/engine/pyomodule.c
index 208eff1..1e7d7cc 100644
--- a/src/engine/pyomodule.c
+++ b/src/engine/pyomodule.c
@@ -1,26 +1,26 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
 #include <math.h>
-#include "portaudio.h"
+#include "py2to3.h"
 #include "sndfile.h"
 #include "pyomodule.h"
 #include "servermodule.h"
@@ -30,123 +30,98 @@
 #include "tablemodule.h"
 #include "matrixmodule.h"
 
-/** Note : 
- ** Add an argument to pa_get_* and pm_get_* functions to allow printing to the console
- **/
+#ifdef USE_PORTAUDIO
+#include "ad_portaudio.h"
+PyObject * with_portaudio() { Py_INCREF(Py_True); return Py_True; };
+#else
+#define pa_warning "Pyo built without Portaudio support.\n"
+PyObject * portaudio_get_version() { PySys_WriteStdout(pa_warning); Py_RETURN_NONE; };
+PyObject * portaudio_get_version_text() { PySys_WriteStdout(pa_warning); Py_RETURN_NONE; };
+PyObject * portaudio_count_host_apis() { PySys_WriteStdout(pa_warning); Py_RETURN_NONE; };
+PyObject * portaudio_list_host_apis() { PySys_WriteStdout(pa_warning); Py_RETURN_NONE; };
+PyObject * portaudio_get_default_host_api() { PySys_WriteStdout(pa_warning); Py_RETURN_NONE; };
+PyObject * portaudio_count_devices() { PySys_WriteStdout(pa_warning); Py_RETURN_NONE; };
+PyObject * portaudio_list_devices() { PySys_WriteStdout(pa_warning); Py_RETURN_NONE; };
+PyObject * portaudio_get_devices_infos() { PySys_WriteStdout(pa_warning); Py_RETURN_NONE; };
+PyObject * portaudio_get_output_devices() { PySys_WriteStdout(pa_warning); Py_RETURN_NONE; };
+PyObject * portaudio_get_output_max_channels(PyObject *self, PyObject *arg) { PySys_WriteStdout(pa_warning); Py_RETURN_NONE; };
+PyObject * portaudio_get_input_max_channels(PyObject *self, PyObject *arg) { PySys_WriteStdout(pa_warning); Py_RETURN_NONE; };
+PyObject * portaudio_get_input_devices() { PySys_WriteStdout(pa_warning); Py_RETURN_NONE; };
+PyObject * portaudio_get_default_input() { PySys_WriteStdout(pa_warning); Py_RETURN_NONE; };
+PyObject * portaudio_get_default_output() { PySys_WriteStdout(pa_warning); Py_RETURN_NONE; };
+PyObject * with_portaudio() { Py_INCREF(Py_False); return Py_False; };
+#endif
 
-/****** Portaudio utilities ******/
-static void portaudio_assert(PaError ecode, const char* cmdName) {
-    if (ecode != paNoError) {
-        const char* eText = Pa_GetErrorText(ecode);
-        if (!eText) {
-            eText = "???";
-        }
-        fprintf(stderr, "portaudio error in %s: %s\n", cmdName, eText);
-        Pa_Terminate();
-    }
-}
+#ifdef USE_PORTMIDI
+#include "md_portmidi.h"
+PyObject * with_portmidi() { Py_INCREF(Py_True); return Py_True; };
+#else
+#define pm_warning "Pyo built without Portmidi sipport.\n"
+PyObject * portmidi_count_devices() { PySys_WriteStdout(pm_warning); Py_RETURN_NONE; };
+PyObject * portmidi_list_devices() { PySys_WriteStdout(pm_warning); Py_RETURN_NONE; };
+PyObject * portmidi_get_input_devices() { PySys_WriteStdout(pm_warning); Py_RETURN_NONE; };
+PyObject * portmidi_get_output_devices() { PySys_WriteStdout(pm_warning); Py_RETURN_NONE; };
+PyObject * portmidi_get_default_input() { PySys_WriteStdout(pm_warning); Py_RETURN_NONE; };
+PyObject * portmidi_get_default_output() { PySys_WriteStdout(pm_warning); Py_RETURN_NONE; };
+PyObject * with_portmidi() { Py_INCREF(Py_False); return Py_False; };
+#endif
+
+#ifdef USE_JACK
+PyObject * with_jack() { Py_INCREF(Py_True); return Py_True; };
+#else
+PyObject * with_jack() { Py_INCREF(Py_False); return Py_False; };
+#endif
+
+#ifdef USE_COREAUDIO
+PyObject * with_coreaudio() { Py_INCREF(Py_True); return Py_True; };
+#else
+PyObject * with_coreaudio() { Py_INCREF(Py_False); return Py_False; };
+#endif
+
+#ifdef USE_OSC
+PyObject * with_osc() { Py_INCREF(Py_True); return Py_True; };
+#else
+PyObject * with_osc() { Py_INCREF(Py_False); return Py_False; };
+#endif
+
+/** Portaudio utility functions __doc__ strings. **/
+/**************************************************/
 
 #define portaudio_count_host_apis_info \
 "\nReturns the number of host apis found by Portaudio.\n\n\
 >>> c = pa_count_host_apis()\n\
->>> print c\n\
+>>> print(c)\n\
 1\n\n"
 
-static PyObject *
-portaudio_count_host_apis(){
-    PaError err;
-    PaHostApiIndex numApis; 
-
-    err = Pa_Initialize();
-    if (err != paNoError) {
-        portaudio_assert(err, "Pa_Initialize");
-		Py_RETURN_NONE;
-	}
-	else {
-        numApis = Pa_GetHostApiCount();
-        if( numApis < 0 )
-            portaudio_assert(numApis, "Pa_GetHostApiCount");
-        return PyInt_FromLong(numApis);
-    }
-}
+#define portaudio_get_version_info \
+"\nReturns the version number, as an integer, of the current portaudio installation.\n\n\
+>>> v = pa_get_version()\n\
+>>> print(v)\n\
+1899\n\n"
+
+#define portaudio_get_version_text_info \
+"\nReturns the textual description of the current portaudio installation.\n\n\
+>>> desc = pa_get_version_text()\n\
+>>> print(desc)\n\
+PortAudio V19-devel (built Oct 8 2012 16:25:16)\n\n"
 
 #define portaudio_list_host_apis_info \
 "\nPrints a list of all host apis found by Portaudio.\n\n\
 >>> pa_list_host_apis()\n\
 index: 0, id: 5, name: Core Audio, num devices: 6, default in: 0, default out: 2\n\n"
 
-static PyObject*
-portaudio_list_host_apis(){
-    PaError err;
-    PaHostApiIndex n, i;
-	
-    err = Pa_Initialize();
-    if (err != paNoError) {
-        portaudio_assert(err, "Pa_Initialize");
-	}
-    else {
-        n = Pa_GetHostApiCount();
-        if (n < 0){
-            portaudio_assert(n, "Pa_GetHostApiCount");
-        }
-        else {
-            for (i=0; i < n; ++i){
-                const PaHostApiInfo *info = Pa_GetHostApiInfo(i);
-                assert(info);
-                fprintf(stdout, "index: %i, id: %i, name: %s, num devices: %i, default in: %i, default out: %i\n", i, (int)info->type, info->name, (int)info->deviceCount, (int)info->defaultInputDevice, (int)info->defaultOutputDevice);
-            }
-        }        
-    }
-    Py_RETURN_NONE;
-}
-
 #define portaudio_get_default_host_api_info \
 "\nReturns the index number of Portaudio's default host api.\n\n\
 >>> h = pa_get_default_host_api()\n\
->>> print h\n\
+>>> print(h)\n\
 0\n\n"
 
-static PyObject*
-portaudio_get_default_host_api(){
-    PaError err;
-    PaHostApiIndex i;
-	
-    err = Pa_Initialize();
-    if (err != paNoError) {
-        portaudio_assert(err, "Pa_Initialize");
-		Py_RETURN_NONE;
-	}
-    else {
-        i = Pa_GetDefaultHostApi();
-        return PyInt_FromLong(i);
-    }
-}
-
 #define portaudio_count_devices_info \
 "\nReturns the number of devices found by Portaudio.\n\n\
 >>> c = pa_count_devices()\n\
->>> print c\n\
+>>> print(c)\n\
 6\n\n"
 
-static PyObject*
-portaudio_count_devices(){
-    PaError err;
-    PaDeviceIndex numDevices;
-	
-	err = Pa_Initialize();
-    if (err != paNoError) {
-        portaudio_assert(err, "Pa_Initialize");
-		Py_RETURN_NONE;
-	}
-	else {
-        numDevices = Pa_GetDeviceCount();
-        if( numDevices < 0 )
-            portaudio_assert(numDevices, "Pa_GetDeviceCount");
-        return PyInt_FromLong(numDevices);        
-    }
-
-}
-
 #define portaudio_list_devices_info \
 "\nPrints a list of all devices found by Portaudio.\n\n\
 >>> pa_list_devices()\n\
@@ -161,178 +136,43 @@ AUDIO devices:\n\
 5: IN, name: Soundflower (16ch), host api index: 0, default sr: 44100 Hz, latency: 0.010000 s\n\
 5: OUT, name: Soundflower (16ch), host api index: 0, default sr: 44100 Hz, latency: 0.000000 s\n\n"
 
-static PyObject*
-portaudio_list_devices(){
-    PaError err;
-    PaDeviceIndex n, i;
-	
-	err = Pa_Initialize();
-    if (err != paNoError) {
-        portaudio_assert(err, "Pa_Initialize");
-		Py_RETURN_NONE;
-	}
-    else {
-        n = Pa_GetDeviceCount();
-        if (n < 0){
-            portaudio_assert(n, "Pa_GetDeviceCount");
-        }
-        else {
-            printf("AUDIO devices:\n");
-            for (i=0; i < n; ++i){
-                const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
-                assert(info);
-                
-                if (info->maxInputChannels > 0)
-                    fprintf(stdout, "%i: IN, name: %s, host api index: %i, default sr: %i Hz, latency: %f s\n", i, info->name, (int)info->hostApi, (int)info->defaultSampleRate, (float)info->defaultLowInputLatency);
-                
-                if (info->maxOutputChannels > 0)
-                    fprintf(stdout, "%i: OUT, name: %s, host api index: %i, default sr: %i Hz, latency: %f s\n", i, info->name, (int)info->hostApi, (int)info->defaultSampleRate, (float)info->defaultLowOutputLatency);
-            }
-            printf("\n");
-        }        
-    }
-    Py_RETURN_NONE;
-}
-
 #define portaudio_get_devices_infos_info \
 "\nReturns informations about all devices found by Portaudio.\n\n\
-This function returns two dictionaries, one containing a dictionary for each input device and one containing a dictionary for each output device.\
+This function returns two dictionaries, one containing a dictionary for each input device and one containing a dictionary for each output device. \
 Keys of outer dictionaries are the device index as returned by Portaudio. Keys of inner dictionaries are: 'name', 'host api index', 'default sr' and 'latency'.\n\n\
 >>> inputs, outputs = pa_get_devices_infos()\n\
->>> print '- Inputs:'\n\
+>>> print('- Inputs:')\n\
 >>> for index in sorted(inputs.keys()):\n\
-...     print '  Device index:', index\n\
+...     print('  Device index:', index)\n\
 ...     for key in ['name', 'host api index', 'default sr', 'latency']:\n\
-...         print '    %s:' % key, inputs[index][key]\n\
->>> print '- Outputs:'\n\
+...         print('    %s:' % key, inputs[index][key])\n\
+>>> print('- Outputs:')\n\
 >>> for index in sorted(outputs.keys()):\n\
-...     print '  Device index:', index\n\
+...     print('  Device index:', index)\n\
 ...     for key in ['name', 'host api index', 'default sr', 'latency']:\n\
-...         print '    %s:' % key, outputs[index][key]\n\n"
-
-static PyObject*
-portaudio_get_devices_infos(){
-    PaError err;
-    PaDeviceIndex n, i;
-    PyObject *inDict, *outDict, *tmpDict;
-    inDict = PyDict_New();
-    outDict = PyDict_New();
-
-	err = Pa_Initialize();
-    if (err != paNoError) {
-        portaudio_assert(err, "Pa_Initialize");
-		Py_RETURN_NONE;
-	}
-    else {
-        n = Pa_GetDeviceCount();
-        if (n < 0){
-            portaudio_assert(n, "Pa_GetDeviceCount");
-            Py_RETURN_NONE;
-        }
-        else {
-            for (i=0; i < n; ++i){
-                const PaDeviceInfo *info = Pa_GetDeviceInfo(i);
-                assert(info);
-                tmpDict = PyDict_New();
-                if (info->maxInputChannels > 0) {
-                    PyDict_SetItemString(tmpDict, "name", PyString_FromString(info->name));
-                    PyDict_SetItemString(tmpDict, "host api index", PyInt_FromLong((int)info->hostApi));
-                    PyDict_SetItemString(tmpDict, "default sr", PyInt_FromLong((int)info->defaultSampleRate));
-                    PyDict_SetItemString(tmpDict, "latency", PyFloat_FromDouble((float)info->defaultLowInputLatency));
-                    PyDict_SetItem(inDict, PyInt_FromLong(i), PyDict_Copy(tmpDict));
-                }
-                if (info->maxOutputChannels > 0) {
-                    PyDict_SetItemString(tmpDict, "name", PyString_FromString(info->name));
-                    PyDict_SetItemString(tmpDict, "host api index", PyInt_FromLong((int)info->hostApi));
-                    PyDict_SetItemString(tmpDict, "default sr", PyInt_FromLong((int)info->defaultSampleRate));
-                    PyDict_SetItemString(tmpDict, "latency", PyFloat_FromDouble((float)info->defaultLowOutputLatency));
-                    PyDict_SetItem(outDict, PyInt_FromLong(i), PyDict_Copy(tmpDict));
-                }
-            }
-            return Py_BuildValue("(OO)", inDict, outDict);
-        }        
-    }
-}
+...         print('    %s:' % key, outputs[index][key])\n\n"
 
 #define portaudio_get_output_devices_info \
 "\nReturns output devices (device names, device indexes) found by Portaudio.\n\n`device names` is a list of strings and `device indexes` is a list of the actual\nPortaudio index of each device.\n\n\
 >>> outs = pa_get_output_devices()\n\
->>> print outs\n\
+>>> print(outs)\n\
 (['Built-in Output', 'UA-4FX', 'Soundflower (2ch)', 'Soundflower (16ch)'], [2, 3, 4, 5])\n\n"
 
-static PyObject*
-portaudio_get_output_devices(){
-    PaError err;
-    PaDeviceIndex n, i;
-
-    PyObject *list, *list_index;
-    list = PyList_New(0);
-    list_index = PyList_New(0);
-    	
-	err = Pa_Initialize();
-    if (err != paNoError) {
-        portaudio_assert(err, "Pa_Initialize");
-		Py_RETURN_NONE;
-	}
-    else {
-        n = Pa_GetDeviceCount();
-        if (n < 0){
-            portaudio_assert(n, "Pa_GetDeviceCount");
-            Py_RETURN_NONE;
-        }
-        else {
-            for (i=0; i < n; ++i){
-                const PaDeviceInfo *info=Pa_GetDeviceInfo(i);
-                assert(info);                
-                if (info->maxOutputChannels > 0){
-                    PyList_Append(list, PyString_FromString(info->name));
-                    PyList_Append(list_index, PyInt_FromLong(i));
-                }
-            }
-            return Py_BuildValue("OO", list, list_index);
-        }        
-    }
-}
-
 #define portaudio_get_output_max_channels_info \
 "\nRetrieve the maximum number of output channels for the specified device.\n\n:Args:\n\n    \
 x: int\n        Device index as listed by Portaudio (see pa_get_output_devices).\n\n\
 >>> device = 'HDA Intel PCH: STAC92xx Analog (hw:0,0)'\n\
 >>> dev_list, dev_index =  pa_get_output_devices()\n\
 >>> dev = dev_index[dev_list.index(device)]\n\
->>> print 'Device index:', dev\n\
+>>> print('Device index:', dev)\n\
 >>> maxouts = pa_get_output_max_channels(dev)\n\
 >>> maxins = pa_get_input_max_channels(dev)\n\
->>> print 'Max outputs:', maxouts\n\
->>> print 'Max inputs:', maxins\n\
+>>> print('Max outputs:', maxouts)\n\
+>>> print('Max inputs:', maxins)\n\
 >>> if maxouts >= 2 and maxins >= 2:\n\
 ...     nchnls = 2\n\
 >>> else:\n\
-...     nchnls = 1\n\n" 
-
-static PyObject*
-portaudio_get_output_max_channels(PyObject *self, PyObject *arg){
-    PaError err;
-    PaDeviceIndex n, i = PyInt_AsLong(arg);
-
-	err = Pa_Initialize();
-    if (err != paNoError) {
-        portaudio_assert(err, "Pa_Initialize");
-		Py_RETURN_NONE;
-	}
-    else {
-        n = Pa_GetDeviceCount();
-        if (n < 0){
-            portaudio_assert(n, "Pa_GetDeviceCount");
-            Py_RETURN_NONE;
-        }
-        else {
-            const PaDeviceInfo *info=Pa_GetDeviceInfo(i);
-            assert(info);         
-            return PyInt_FromLong(info->maxOutputChannels);
-        }        
-    }
-}
+...     nchnls = 1\n\n"
 
 #define portaudio_get_input_max_channels_info \
 "\nRetrieve the maximum number of input channels for the specified device.\n\n:Args:\n\n    \
@@ -340,142 +180,45 @@ x: int\n        Device index as listed by Portaudio (see pa_get_input_devices).\
 >>> device = 'HDA Intel PCH: STAC92xx Analog (hw:0,0)'\n\
 >>> dev_list, dev_index =  pa_get_output_devices()\n\
 >>> dev = dev_index[dev_list.index(device)]\n\
->>> print 'Device index:', dev\n\
+>>> print('Device index:', dev)\n\
 >>> maxouts = pa_get_output_max_channels(dev)\n\
 >>> maxins = pa_get_input_max_channels(dev)\n\
->>> print 'Max outputs', maxouts\n\
->>> print 'Max inputs:', maxins\n\
+>>> print('Max outputs', maxouts)\n\
+>>> print('Max inputs:', maxins)\n\
 >>> if maxouts >= 2 and maxins >= 2:\n\
 ...     nchnls = 2\n\
 >>> else:\n\
-...     nchnls = 1\n\n" 
-
-static PyObject*
-portaudio_get_input_max_channels(PyObject *self, PyObject *arg){
-    PaError err;
-    PaDeviceIndex n, i = PyInt_AsLong(arg);
-
-	err = Pa_Initialize();
-    if (err != paNoError) {
-        portaudio_assert(err, "Pa_Initialize");
-		Py_RETURN_NONE;
-	}
-    else {
-        n = Pa_GetDeviceCount();
-        if (n < 0){
-            portaudio_assert(n, "Pa_GetDeviceCount");
-            Py_RETURN_NONE;
-        }
-        else {
-            const PaDeviceInfo *info=Pa_GetDeviceInfo(i);
-            assert(info);         
-            return PyInt_FromLong(info->maxInputChannels);
-        }        
-    }
-}
+...     nchnls = 1\n\n"
 
 #define portaudio_get_input_devices_info \
 "\nReturns input devices (device names, device indexes) found by Portaudio.\n\n`device names` is a list of strings and `device indexes` is a list of the actual\nPortaudio index of each device.\n\n\
 >>> ins = pa_get_input_devices()\n\
->>> print ins\n\
+>>> print(ins)\n\
 (['Built-in Microphone', 'Built-in Input', 'UA-4FX', 'Soundflower (2ch)', 'Soundflower (16ch)'], [0, 1, 3, 4, 5])\n\n"
 
-static PyObject*
-portaudio_get_input_devices(){
-    PaError err;
-    PaDeviceIndex n, i;
-    
-    PyObject *list, *list_index;
-    list = PyList_New(0);
-    list_index = PyList_New(0);
-    
-	err = Pa_Initialize();
-    if (err != paNoError) {
-        portaudio_assert(err, "Pa_Initialize");
-		Py_RETURN_NONE;
-	}
-    else {
-        n = Pa_GetDeviceCount();
-        if (n < 0){
-            portaudio_assert(n, "Pa_GetDeviceCount");
-            Py_RETURN_NONE;
-        }
-        else {
-            for (i=0; i < n; ++i){
-                const PaDeviceInfo *info=Pa_GetDeviceInfo(i);
-                assert(info);                
-                if (info->maxInputChannels > 0){
-                    PyList_Append(list, PyString_FromString(info->name));
-                    PyList_Append(list_index, PyInt_FromLong(i));
-                }
-            }
-            return Py_BuildValue("OO", list, list_index);            
-        }        
-    }
-}
-
 #define portaudio_get_default_input_info \
 "\nReturns the index number of Portaudio's default input device.\n\n\
 >>> names, indexes = pa_get_input_devices()\n\
 >>> name = names[indexes.index(pa_get_default_input())]\n\
->>> print name\n\
+>>> print(name)\n\
 'Built-in Microphone'\n\n"
 
-static PyObject*
-portaudio_get_default_input(){
-    PaError err;
-    PaDeviceIndex i;
-	
-	err = Pa_Initialize();
-    if (err != paNoError) {
-        portaudio_assert(err, "Pa_Initialize");
-		Py_RETURN_NONE;
-	}
-    else {
-        i = Pa_GetDefaultInputDevice();
-        return PyInt_FromLong(i);        
-    }
-
-}
-
 #define portaudio_get_default_output_info \
 "\nReturns the index number of Portaudio's default output device.\n\n\
 >>> names, indexes = pa_get_output_devices()\n\
 >>> name = names[indexes.index(pa_get_default_output())]\n\
->>> print name\n\
+>>> print(name)\n\
 'UA-4FX'\n\n"
 
-static PyObject*
-portaudio_get_default_output(){
-    PaError err;
-    PaDeviceIndex i;
-	
-	err = Pa_Initialize();
-    if (err != paNoError) {
-        portaudio_assert(err, "Pa_Initialize");
-		Py_RETURN_NONE;
-	}
-    else {
-        i = Pa_GetDefaultOutputDevice();
-        return PyInt_FromLong(i);
-        
-    }
-}
+/** Portmidi utility functions __doc__ strings. **/
+/*************************************************/
 
-/****** Portmidi utilities ******/
 #define portmidi_count_devices_info \
 "\nReturns the number of devices found by Portmidi.\n\n\
 >>> c = pm_count_devices()\n\
->>> print c\n\
+>>> print(c)\n\
 6\n\n"
 
-static PyObject *
-portmidi_count_devices(){
-    int numDevices;
-	numDevices = Pm_CountDevices();
-    return PyInt_FromLong(numDevices);
-}
-
 #define portmidi_list_devices_info \
 "\nPrints a list of all devices found by Portmidi.\n\n\
 >>> pm_list_devices()\n\
@@ -487,116 +230,35 @@ MIDI devices:\n\
 4: OUT, name: to MaxMSP 1, interface: CoreMIDI\n\
 5: OUT, name: to MaxMSP 2, interface: CoreMIDI\n\n"
 
-static PyObject *
-portmidi_list_devices(){
-    int i;
-    printf("MIDI devices:\n");
-    for (i = 0; i < Pm_CountDevices(); i++) {
-        const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
-        if (info->input && info->output) 
-            printf("%d: IN/OUT, name: %s, interface: %s\n", i, info->name, info->interf);
-        else if (info->input) 
-            printf("%d: IN, name: %s, interface: %s\n", i, info->name, info->interf);
-        else if (info->output) 
-            printf("%d: OUT, name: %s, interface: %s\n", i, info->name, info->interf);
-    }
-    printf("\n");
-    Py_RETURN_NONE;
-}
-
 #define portmidi_get_input_devices_info \
 "\nReturns midi input devices (device names, device indexes) found by Portmidi.\n\n`device names` is a list of strings and `device indexes` is a list of the actual\nPortmidi index of each device.\n\n\
 >>> ins = pm_get_input_devices()\n\
->>> print ins\n\
+>>> print(ins)\n\
 (['IAC Driver Bus 1', 'from MaxMSP 1', 'from MaxMSP 2'], [0, 1, 2])\n\n"
 
-static PyObject*
-portmidi_get_input_devices(){
-	int n, i;
-    PyObject *list, *list_index;
-    list = PyList_New(0);
-    list_index = PyList_New(0);
-    n = Pm_CountDevices();
-    if (n < 0){
-        printf("Portmidi warning: No Midi interface found\n\n");
-    }
-    else {
-        for (i=0; i < n; i++){
-            const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
-            if (info->input){
-                PyList_Append(list, PyString_FromString(info->name));
-                PyList_Append(list_index, PyInt_FromLong(i));
-            }
-        }
-        printf("\n");
-    }
-    return Py_BuildValue("OO", list, list_index);
-}
-
 #define portmidi_get_output_devices_info \
 "\nReturns midi output devices (device names, device indexes) found by Portmidi.\n\n`device names` is a list of strings and `device indexes` is a list of the actual\nPortmidi index of each device.\n\n\
 >>> outs = pm_get_output_devices()\n\
->>> print outs\n\
+>>> print(outs)\n\
 (['IAC Driver Bus 1', 'to MaxMSP 1', 'to MaxMSP 2'], [3, 4, 5])\n\n"
 
-static PyObject*
-portmidi_get_output_devices(){
-	int n, i;
-    PyObject *list, *list_index;
-    list = PyList_New(0);
-    list_index = PyList_New(0);
-    n = Pm_CountDevices();
-    if (n < 0){
-        printf("Portmidi warning: No Midi interface found\n\n");
-    }
-    else {
-        for (i=0; i < n; i++){
-            const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
-            if (info->output){
-                PyList_Append(list, PyString_FromString(info->name));
-                PyList_Append(list_index, PyInt_FromLong(i));
-            }
-        }
-        printf("\n");
-    }
-    return Py_BuildValue("OO", list, list_index);
-}
-
 #define portmidi_get_default_input_info \
 "\nReturns the index number of Portmidi's default input device.\n\n\
 >>> names, indexes = pm_get_input_devices()\n\
 >>> name = names[indexes.index(pm_get_default_input())]\n\
->>> print name\n\
+>>> print(name)\n\
 'IAC Driver Bus 1'\n\n"
 
-static PyObject *
-portmidi_get_default_input(){
-    PmDeviceID i;
-    
-    i = Pm_GetDefaultInputDeviceID();
-    if (i < 0)
-        printf("pm_get_default_input: no midi input device found.\n");
-    return PyInt_FromLong(i);
-}
-
 #define portmidi_get_default_output_info \
 "\nReturns the index number of Portmidi's default output device.\n\n\
 >>> names, indexes = pm_get_output_devices()\n\
 >>> name = names[indexes.index(pm_get_default_output())]\n\
->>> print name\n\
+>>> print(name)\n\
 'IAC Driver Bus 1'\n\n"
 
-static PyObject *
-portmidi_get_default_output(){
-    PmDeviceID i;
-    i = Pm_GetDefaultOutputDeviceID();
-    if (i < 0)
-        printf("pm_get_default_output: no midi output device found.\n");
-    return PyInt_FromLong(i);
-}
 
 /****** Libsndfile utilities ******/
-static int 
+static int
 libsndfile_get_format(int fileformat, int sampletype) {
     int format = 0;
     switch (fileformat) {
@@ -653,41 +315,23 @@ libsndfile_get_format(int fileformat, int sampletype) {
     return format;
 }
 
-#define sndinfo_info \
-"\nRetrieve informations about a soundfile.\n\n\
-Prints the infos of the given soundfile to the console and returns a tuple containing:\n\n(number of frames, duration in seconds, sampling rate,\nnumber of channels, file format, sample type).\n\n:Args:\n\n    \
-path : string\n        Path of a valid soundfile.\n    \
-print : boolean, optional\n        If True, sndinfo will print sound infos to the console. Defaults to False.\n\n\
->>> path = SNDS_PATH + '/transparent.aif'\n\
->>> print path\n\
-/usr/lib/python2.7/dist-packages/pyolib/snds/transparent.aif\n\
->>> info = sndinfo(path)\n\
->>> print info\n\
-(29877, 0.6774829931972789, 44100.0, 1, 'AIFF', '16 bit int')\n\n"
-
 static PyObject *
-sndinfo(PyObject *self, PyObject *args, PyObject *kwds) {
-    
+p_sndinfo(PyObject *self, PyObject *args, PyObject *kwds) {
     SNDFILE *sf;
     SF_INFO info;
-    char *pathtmp;
     char *path;
     char fileformat[5];
-    char *sampletype;
-    int format;
-    int subformat;
-    int print = 0;
+    char sampletype[16];
+    int format, subformat, print = 0;
+    Py_ssize_t psize;
 
     static char *kwlist[] = {"path", "print", NULL};
 
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwlist, &pathtmp, &print)) {
-        PySys_WriteStderr("sndinfo: failed to open the file.\n");
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "s#|i", kwlist, &path, &psize, &print)) {
+        PySys_WriteStderr("sndinfo: called with wrong arguments.\n");
         Py_RETURN_NONE;
     }
 
-    path = malloc(strlen(pathtmp)+1);
-    strcpy(path, pathtmp);
-
     /* Open the sound file. */
     info.format = 0;
     sf = sf_open(path, SFM_READ, &info);
@@ -695,149 +339,68 @@ sndinfo(PyObject *self, PyObject *args, PyObject *kwds) {
         PySys_WriteStderr("sndinfo: failed to open the file.\n");
         Py_RETURN_NONE;
     }
-    else {
-        /* Retrieve file format */
-        format = (int)info.format;
-        if (format > SF_FORMAT_WAV && format < SF_FORMAT_AIFF) {
-            strcpy(fileformat, "WAVE");
-            subformat = format - SF_FORMAT_WAV;
-        }
-        else if (format > SF_FORMAT_AIFF && format < SF_FORMAT_AU) {
-            strcpy(fileformat, "AIFF");
-            subformat = format - SF_FORMAT_AIFF;
-        }
-        else if (format > SF_FORMAT_AU && format < SF_FORMAT_RAW) {
-            strcpy(fileformat, "AU");
-            subformat = format - SF_FORMAT_AU;
-        }
-        else if (format > SF_FORMAT_RAW && format < SF_FORMAT_PAF) {
-            strcpy(fileformat, "RAW");
-            subformat = format - SF_FORMAT_RAW;
-        }
-        else if (format > SF_FORMAT_SD2 && format < SF_FORMAT_FLAC) {
-            strcpy(fileformat, "SD2");
-            subformat = format - SF_FORMAT_SD2;
-        }
-        else if (format > SF_FORMAT_FLAC && format < SF_FORMAT_CAF) {
-            strcpy(fileformat, "FLAC");
-            subformat = format - SF_FORMAT_FLAC;
-        }
-        else if (format > SF_FORMAT_CAF && format < SF_FORMAT_WVE) {
-            strcpy(fileformat, "CAF");
-            subformat = format - SF_FORMAT_CAF;
-        }
-        else if (format > SF_FORMAT_OGG && format < SF_FORMAT_MPC2K) {
-            strcpy(fileformat, "OGG");
-            subformat = format - SF_FORMAT_OGG;
-        }
-        else if (format > SF_FORMAT_RF64 && format < 0x230000) {
-            strcpy(fileformat, "RF64");
-            subformat = format - SF_FORMAT_RF64;
-        }
-        else {
-            strcpy(fileformat, "????");
-            subformat = -1;
-        }
-        /* Retrieve sample type */
-        if (subformat != -1) {
-            switch (subformat) {
-                case SF_FORMAT_PCM_S8:
-                    sampletype = malloc(strlen("s8 bit int") + 1);
-                    strcpy(sampletype, "s8 bit int");
-                    break;
-                case SF_FORMAT_PCM_U8:
-                    sampletype = malloc(strlen("u8 bit int") + 1);
-                    strcpy(sampletype, "u8 bit int");
-                    break;
-                case SF_FORMAT_PCM_16:
-                    sampletype = malloc(strlen("16 bit int") + 1);
-                    strcpy(sampletype, "16 bit int");
-                    break;
-                case SF_FORMAT_PCM_24:
-                    sampletype = malloc(strlen("24 bit int") + 1);
-                    strcpy(sampletype, "24 bit int");
-                    break;
-                case SF_FORMAT_PCM_32:
-                    sampletype = malloc(strlen("32 bit int") + 1);
-                    strcpy(sampletype, "32 bit int");
-                    break;
-                case SF_FORMAT_FLOAT:
-                    sampletype = malloc(strlen("32 bit float") + 1);
-                    strcpy(sampletype, "32 bit float");
-                    break;
-                case SF_FORMAT_DOUBLE:
-                    sampletype = malloc(strlen("64 bit float") + 1);
-                    strcpy(sampletype, "64 bit float");
-                    break;
-                case SF_FORMAT_ULAW:
-                    sampletype = malloc(strlen("U-Law encoded") + 1);
-                    strcpy(sampletype, "U-Law encoded");
-                    break;
-                case SF_FORMAT_ALAW:
-                    sampletype = malloc(strlen("A-Law encoded") + 1);
-                    strcpy(sampletype, "A-Law encoded");
-                    break;
-                case SF_FORMAT_VORBIS:
-                    sampletype = malloc(strlen("vorbis encoding") + 1);
-                    strcpy(sampletype, "vorbis encoding");
-                    break;
-                default:
-                    /* printf("%d\n", subformat); */
-                    sampletype = malloc(strlen("Unknown...") + 1);
-                    strcpy(sampletype, "Unknown...");
-                    break;
-            }
-        }
-        else {
-            sampletype = malloc(strlen("Unknown...") + 1);
-            strcpy(sampletype, "Unknown...");
-        }
-    
-        if (print)
-            fprintf(stdout, "name: %s\nnumber of frames: %i\nduration: %.4f sec\nsr: %.2f\nchannels: %i\nformat: %s\nsample type: %s\n", 
-                    path, (int)info.frames, ((float)info.frames / info.samplerate), (float)info.samplerate, (int)info.channels, fileformat, sampletype);
-        PyObject *sndinfo = PyTuple_Pack(6, PyInt_FromLong(info.frames), PyFloat_FromDouble((float)info.frames / info.samplerate), 
-            PyFloat_FromDouble(info.samplerate), PyInt_FromLong(info.channels), PyString_FromString(fileformat), PyString_FromString(sampletype));
-        sf_close(sf);
-        free(path);
-        free(sampletype);
-        return sndinfo;
-    }
-}    
-
-#define savefile_info \
-"\nCreates an audio file from a list of floats.\n\n:Args:\n\n    \
-samples : list of floats\n        list of samples data, or list of list of samples data if more than 1 channels.\n    \
-path : string\n        Full path (including extension) of the new file.\n    \
-sr : int, optional\n        Sampling rate of the new file. Defaults to 44100.\n    \
-channels : int, optional\n        number of channels of the new file. Defaults to 1.\n    \
-fileformat : int, optional\n        Format type of the new file. Defaults to 0. Supported formats are:\n            \
-0. WAVE - Microsoft WAV format (little endian) {.wav, .wave}\n            \
-1. AIFF - Apple/SGI AIFF format (big endian) {.aif, .aiff}\n            \
-2. AU - Sun/NeXT AU format (big endian) {.au}\n            \
-3. RAW - RAW PCM data {no extension}\n            \
-4. SD2 - Sound Designer 2 {.sd2}\n            \
-5. FLAC - FLAC lossless file format {.flac}\n            \
-6. CAF - Core Audio File format {.caf}\n            \
-7. OGG - Xiph OGG container {.ogg}\n    \
-sampletype ; int, optional\n        Bit depth encoding of the audio file. Defaults to 0.\n        \
-SD2 and FLAC only support 16 or 24 bit int. Supported types are:\n            \
-0. 16 bit int\n            \
-1. 24 bit int\n            \
-2. 32 bit int\n            \
-3. 32 bit float\n            \
-4. 64 bit float\n            \
-5. U-Law encoded\n            \
-6. A-Law encoded\n\n\
->>> from random import uniform\n\
->>> import os\n\
->>> home = os.path.expanduser('~')\n\
->>> sr, dur, chnls, path = 44100, 5, 2, os.path.join(home, 'noise.aif')\n\
->>> samples = [[uniform(-0.5,0.5) for i in range(sr*dur)] for i in range(chnls)]\n\
->>> savefile(samples=samples, path=path, sr=sr, channels=chnls, fileformat=1, sampletype=1)\n\n"
+
+    /* Retrieve file format */
+    format = (int)info.format & SF_FORMAT_TYPEMASK;
+    subformat = (int)info.format & SF_FORMAT_SUBMASK;
+    if (format == SF_FORMAT_WAV)
+        strcpy(fileformat, "WAVE");
+    else if (format == SF_FORMAT_AIFF)
+        strcpy(fileformat, "AIFF");
+    else if (format == SF_FORMAT_AU)
+        strcpy(fileformat, "AU");
+    else if (format == SF_FORMAT_RAW)
+        strcpy(fileformat, "RAW");
+    else if (format == SF_FORMAT_SD2)
+        strcpy(fileformat, "SD2");
+    else if (format == SF_FORMAT_FLAC)
+        strcpy(fileformat, "FLAC");
+    else if (format == SF_FORMAT_CAF)
+        strcpy(fileformat, "CAF");
+    else if (format == SF_FORMAT_OGG)
+        strcpy(fileformat, "OGG");
+    else if (format == SF_FORMAT_RF64)
+        strcpy(fileformat, "RF64");
+    else
+        strcpy(fileformat, "????");
+
+    /* Retrieve sample type */
+    if (subformat == SF_FORMAT_PCM_S8)
+        strcpy(sampletype, "s8 bit int");
+    else if (subformat == SF_FORMAT_PCM_U8)
+        strcpy(sampletype, "u8 bit int");
+    else if (subformat == SF_FORMAT_PCM_16)
+        strcpy(sampletype, "16 bit int");
+    else if (subformat == SF_FORMAT_PCM_24)
+        strcpy(sampletype, "24 bit int");
+    else if (subformat == SF_FORMAT_PCM_32)
+        strcpy(sampletype, "32 bit int");
+    else if (subformat == SF_FORMAT_FLOAT)
+        strcpy(sampletype, "32 bit float");
+    else if (subformat == SF_FORMAT_DOUBLE)
+        strcpy(sampletype, "64 bit float");
+    else if (subformat == SF_FORMAT_ULAW)
+        strcpy(sampletype, "U-Law encoded");
+    else if (subformat == SF_FORMAT_ALAW)
+        strcpy(sampletype, "A-Law encoded");
+    else if (subformat == SF_FORMAT_VORBIS)
+        strcpy(sampletype, "vorbis encoding");
+    else
+        strcpy(sampletype, "Unknown...");
+
+    if (print)
+        PySys_WriteStdout("name: %s\nnumber of frames: %i\nduration: %.4f sec\nsr: %.2f\nchannels: %i\nformat: %s\nsample type: %s\n",
+                          path, (int)info.frames, ((float)info.frames / info.samplerate), (float)info.samplerate, (int)info.channels, 
+                          fileformat, sampletype);
+    PyObject *sndinfos = PyTuple_Pack(6, PyInt_FromLong(info.frames), PyFloat_FromDouble((float)info.frames / info.samplerate),
+                                        PyFloat_FromDouble(info.samplerate), PyInt_FromLong(info.channels), 
+                                        PyUnicode_FromString(fileformat), PyUnicode_FromString(sampletype));
+    sf_close(sf);
+    return sndinfos;
+}
 
 static PyObject *
-savefile(PyObject *self, PyObject *args, PyObject *kwds) {
+p_savefile(PyObject *self, PyObject *args, PyObject *kwds) {
     int i, j, size;
     char *recpath;
     PyObject *samples;
@@ -846,13 +409,15 @@ savefile(PyObject *self, PyObject *args, PyObject *kwds) {
     int channels = 1;
     int fileformat = 0;
     int sampletype = 0;
+    double quality = 0.4;
     SNDFILE *recfile;
     SF_INFO recinfo;
-    static char *kwlist[] = {"samples", "path", "sr", "channels", "fileformat", "sampletype", NULL};
+    Py_ssize_t psize;
+    static char *kwlist[] = {"samples", "path", "sr", "channels", "fileformat", "sampletype", "quality", NULL};
 
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "Os|iiii", kwlist, &samples, &recpath, &sr, &channels, &fileformat, &sampletype))
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "Os#|iiiid", kwlist, &samples, &recpath, &psize, &sr, &channels, &fileformat, &sampletype, &quality))
         return PyInt_FromLong(-1);
-    
+
     recinfo.samplerate = sr;
     recinfo.channels = channels;
     recinfo.format = libsndfile_get_format(fileformat, sampletype);
@@ -861,64 +426,41 @@ savefile(PyObject *self, PyObject *args, PyObject *kwds) {
         size = PyList_Size(samples);
         sampsarray = (MYFLT *)malloc(size * sizeof(MYFLT));
         for (i=0; i<size; i++) {
-            sampsarray[i] = PyFloat_AS_DOUBLE(PyList_GET_ITEM(samples, i));
+            sampsarray[i] = PyFloat_AsDouble(PyList_GET_ITEM(samples, i));
         }
     }
     else {
         if (PyList_Size(samples) != channels) {
-            printf("savefile: samples list size and channels must be the same!\n");
+            PySys_WriteStdout("savefile: samples list size and channels must be the same!\n");
             return PyInt_FromLong(-1);
         }
         size = PyList_Size(PyList_GET_ITEM(samples, 0)) * channels;
         sampsarray = (MYFLT *)malloc(size * sizeof(MYFLT));
         for (i=0; i<(size/channels); i++) {
             for (j=0; j<channels; j++) {
-                sampsarray[i*channels+j] = PyFloat_AS_DOUBLE(PyList_GET_ITEM(PyList_GET_ITEM(samples, j), i));
+                sampsarray[i*channels+j] = PyFloat_AsDouble(PyList_GET_ITEM(PyList_GET_ITEM(samples, j), i));
             }
-        }    
-    }    
+        }
+    }
     if (! (recfile = sf_open(recpath, SFM_WRITE, &recinfo))) {
-        printf ("savefile: failed to open output file %s.\n", recpath);
+        PySys_WriteStdout("savefile: failed to open output file %s.\n", recpath);
         return PyInt_FromLong(-1);
     }
+
+    // Sets the encoding quality for FLAC and OGG compressed formats
+    if (fileformat == 5 || fileformat == 7) {
+        sf_command(recfile, SFC_SET_VBR_ENCODING_QUALITY, &quality, sizeof(double));
+    }
+
     SF_WRITE(recfile, sampsarray, size);
     sf_close(recfile);
     free(sampsarray);
-    
-    Py_RETURN_NONE;    
-}
 
-#define savefileFromTable_info \
-"\nCreates an audio file from the content of a table.\n\n:Args:\n\n    \
-table : PyoTableObject\n        table from which to retrieve samples to write.\n    \
-path : string\n        Full path (including extension) of the new file.\n    \
-fileformat : int, optional\n        Format type of the new file. Defaults to 0. Supported formats are:\n            \
-0. WAVE - Microsoft WAV format (little endian) {.wav, .wave}\n            \
-1. AIFF - Apple/SGI AIFF format (big endian) {.aif, .aiff}\n            \
-2. AU - Sun/NeXT AU format (big endian) {.au}\n            \
-3. RAW - RAW PCM data {no extension}\n            \
-4. SD2 - Sound Designer 2 {.sd2}\n            \
-5. FLAC - FLAC lossless file format {.flac}\n            \
-6. CAF - Core Audio File format {.caf}\n            \
-7. OGG - Xiph OGG container {.ogg}\n    \
-sampletype ; int, optional\n        Bit depth encoding of the audio file. Defaults to 0.\n        \
-SD2 and FLAC only support 16 or 24 bit int. Supported types are:\n            \
-0. 16 bit int\n            \
-1. 24 bit int\n            \
-2. 32 bit int\n            \
-3. 32 bit float\n            \
-4. 64 bit float\n            \
-5. U-Law encoded\n            \
-6. A-Law encoded\n\n\
->>> import os\n\
->>> home = os.path.expanduser('~')\n\
->>> path1 = SNDS_PATH + '/transparent.aif'\n\
->>> path2 = os.path.join(home, '/transparent2.aif')\n\
->>> t = SndTable(path1)\n\
->>> savefileFromTable(table=t, path=path, fileformat=1, sampletype=1)\n\n"
+    Py_RETURN_NONE;
+}
 
 static PyObject *
-savefileFromTable(PyObject *self, PyObject *args, PyObject *kwds) {
+p_savefileFromTable(PyObject *self, PyObject *args, PyObject *kwds) {
     int i, j, size;
     char *recpath;
     PyObject *table;
@@ -929,15 +471,17 @@ savefileFromTable(PyObject *self, PyObject *args, PyObject *kwds) {
     int channels = 1;
     int fileformat = 0;
     int sampletype = 0;
+    double quality = 0.4;
     int count = 0;
     int num_items = 0;
     SNDFILE *recfile;
     SF_INFO recinfo;
-    static char *kwlist[] = {"table", "path", "fileformat", "sampletype", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "Os|ii", kwlist, &table, &recpath, &fileformat, &sampletype))
+    Py_ssize_t psize;
+    static char *kwlist[] = {"table", "path", "fileformat", "sampletype", "quality", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "Os#|iid", kwlist, &table, &recpath, &psize, &fileformat, &sampletype, &quality))
         return PyInt_FromLong(-1);
-    
+
     base_objs = PyObject_GetAttrString(table, "_base_objs");
     channels = PyList_Size(base_objs);
     tablestreamlist = PyList_New(channels);
@@ -946,18 +490,23 @@ savefileFromTable(PyObject *self, PyObject *args, PyObject *kwds) {
     }
     sr = (int)TableStream_getSamplingRate((PyObject *)PyList_GetItem(tablestreamlist, 0));
     size = TableStream_getSize((PyObject *)PyList_GetItem(tablestreamlist, 0));
-    
+
     recinfo.samplerate = sr;
     recinfo.channels = channels;
     recinfo.format = libsndfile_get_format(fileformat, sampletype);
 
     if (! (recfile = sf_open(recpath, SFM_WRITE, &recinfo))) {
-        printf ("savefileFromTable: failed to open output file %s.\n", recpath);
+        PySys_WriteStdout("savefileFromTable: failed to open output file %s.\n", recpath);
         Py_XDECREF(base_objs);
         Py_XDECREF(tablestreamlist);
         return PyInt_FromLong(-1);
     }
-    
+
+    // Sets the encoding quality for FLAC and OGG compressed formats
+    if (fileformat == 5 || fileformat == 7) {
+        sf_command(recfile, SFC_SET_VBR_ENCODING_QUALITY, &quality, sizeof(double));
+    }
+
     if (channels == 1) {
         MYFLT *data;
         if (size < (sr * 60)) {
@@ -1014,48 +563,17 @@ savefileFromTable(PyObject *self, PyObject *args, PyObject *kwds) {
                 SF_WRITE(recfile, sampsarray, num_items * channels);
             } while (num_items == (sr * 30));
         }
-    }    
+    }
 
     sf_close(recfile);
     free(sampsarray);
     Py_XDECREF(base_objs);
     Py_XDECREF(tablestreamlist);
-    
-    Py_RETURN_NONE;    
+
+    Py_RETURN_NONE;
 }
 
 /****** Sampling rate conversions ******/
-#define upsamp_info \
-"\nIncreases the sampling rate of an audio file.\n\n:Args:\n\n    \
-path : string\n        Full path (including extension) of the audio file to convert.\n    \
-outfile : string\n        Full path (including extension) of the new file.\n    \
-up : int, optional\n        Upsampling factor. Defaults to 4.\n    \
-order : int, optional\n        Length, in samples, of the anti-aliasing lowpass filter. Defaults to 128.\n\n\
->>> import os\n\
->>> home = os.path.expanduser('~')\n\
->>> f = SNDS_PATH+'/transparent.aif'\n\
->>> # upsample a signal 3 times\n\
->>> upfile = os.path.join(home, 'trans_upsamp_2.aif')\n\
->>> upsamp(f, upfile, 2, 256)\n\
->>> # downsample the upsampled signal 3 times\n\
->>> downfile = os.path.join(home, 'trans_downsamp_3.aif')\n\
->>> downsamp(upfile, downfile, 3, 256)\n\n"
-
-#define downsamp_info \
-"\nDecreases the sampling rate of an audio file.\n\n:Args:\n\n    \
-path : string\n        Full path (including extension) of the audio file to convert.\n    \
-outfile : string\n        Full path (including extension) of the new file.\n    \
-down : int, optional\n        Downsampling factor. Defaults to 4.\n    \
-order : int, optional\n        Length, in samples, of the anti-aliasing lowpass filter. Defaults to 128.\n\n\
->>> import os\n\
->>> home = os.path.expanduser('~')\n\
->>> f = SNDS_PATH+'/transparent.aif'\n\
->>> # upsample a signal 3 times\n\
->>> upfile = os.path.join(home, 'trans_upsamp_2.aif')\n\
->>> upsamp(f, upfile, 2, 256)\n\
->>> # downsample the upsampled signal 3 times\n\
->>> downfile = os.path.join(home, 'trans_downsamp_3.aif')\n\
->>> downsamp(upfile, downfile, 3, 256)\n\n"
 
 MYFLT HALF_BLACKMAN[513] = {5.999999848427251e-05, 6.0518785176100209e-05, 6.2141079979483038e-05, 6.4805892179720104e-05, 6.8557070335373282e-05, 7.335994450841099e-05, 7.9284000094048679e-05, 8.6251806351356208e-05, 9.4344803073909134e-05, 0.00010353395919082686, 0.0001138320003519766, 0.0001252776273759082, 0.00013784394832327962, 0.00015158756286837161, 0.00016646583389956504, 0.00018252100562676787, 0.00019978794443886727, 0.00021828405442647636, 0.00023800843337085098, 0.00025901006301864982, 0.0002812814200296998, 0.00030484798480756581, 0.00032972017652355134, 0.00035596732050180435, 0.00038358545862138271, 0.0004126313142478466, 0.00044307118514552712, 0.00047501336666755378, 0.00050844199722632766, 0.00054337596520781517, 0.00057988864136859775, 0.00061800965340808034, 0.00065775914117693901, 0.000699152413289994, 0.00074227934237569571, 0.00078715570271015167, 0.00083377416012808681, 0.00088227324886247516, 0.0009326221770606935, 0.00098489224910736084, 0.0010391034884378314, 0.0010953464079648256, 0.001153626712039113, 0.0012140328763052821, 0.0012765693245455623, 0.001341317780315876, 0.0014083425048738718, 0.0014776336029171944, 0.001549328095279634, 0.0016234172508120537, 0.0017000052612274885, 0.0017791179707273841, 0.0018608199898153543, 0.0019451823318377137, 0.0020322385244071484, 0.0021220885682851076, 0.0022147782146930695, 0.0023103870917111635, 0.0024089745711535215, 0.0025105655658990145, 0.0026152802165597677, 0.0027231767307966948, 0.0028343265876173973, 0.0029487889260053635, 0.0030666270758956671, 0.0031879479065537453, 0.0033128033392131329, 0.0034412886016070843, 0.0035734693519771099, 0.0037094042636454105, 0.0038491983432322741, 0.0039929361082613468, 0.0041406778618693352, 0.004292510449886322, 0.0044485158286988735, 0.004608803428709507, 0.0047734435647726059, 0.0049425391480326653, 0.005116121843457222, 0.0052943285554647446, 0.0054772454313933849, 0.0056649716570973396, 0.0058575910516083241, 0.0060551739297807217, 0.0062578483484685421, 0.0064656869508326054, 0.0066788033582270145, 0.0068972636945545673, 0.0071212123148143291, 0.0073507223278284073, 0.007585874292999506, 0.0078268209472298622, 0.0080736298114061356, 0.0083263935521245003, 0.0085852388292551041, 0.0088502718135714531, 0.0091215828433632851, 0.0093993041664361954, 0.0096835149452090263, 0.0099743194878101349, 0.010271874256432056, 0.010576239787042141, 0.010887577198445797, 0.01120593398809433, 0.01153149176388979, 0.011864298023283482, 0.012204526923596859, 0.012552268803119659, 0.012907638214528561, 0.013270745985209942, 0.013641729019582272, 0.014020670205354691, 0.014407743699848652, 0.014803030528128147, 0.015206646174192429, 0.015618747100234032, 0.016039434820413589, 0.0164688341319561, 0.01690707728266716, 0.017354268580675125, 0.017810540273785591, 0.018276045098900795, 0.018750874325633049, 0.019235162064433098, 0.01972905732691288, 0.020232660695910454, 0.020746102556586266, 0.021269544959068298, 0.021803082898259163, 0.022346852347254753, 0.022900991141796112, 0.023465657606720924, 0.024040926247835159, 0.024626968428492546, 0.025223886594176292, 0.025831848382949829, 0.026450937613844872, 0.02708134613931179, 0.027723187580704689, 0.02837657742202282, 0.029041649773716927, 0.029718579724431038, 0.030407454818487167, 0.03110840916633606, 0.03182162344455719, 0.032547183334827423, 0.033285260200500488, 0.034035947173833847, 0.034799445420503616, 0.035575807094573975, 0.036365248262882233, 0.037167854607105255, 0.037983741611242294, 0.038813117891550064, 0.039656046777963638, 0.040512733161449432, 0.041383236646652222, 0.042267743498086929, 0.043166369199752808, 0.044079229235649109, 0.045006513595581055, 0.045948274433612823, 0.046904727816581726, 0.047875978052616119, 0.048862140625715256, 0.049863360822200775, 0.050879742950201035, 0.051911454647779465, 0.052958611398935318, 0.054021358489990234, 0.055099856108427048, 0.056194130331277847, 0.057304393500089645, 0.0584307461977005, 0.059573329985141754, 0.060732249170541763, 0.061907690018415451, 0.063099689781665802, 0.064308419823646545, 0.065534010529518127, 0.066776573657989502, 0.068036213517189026, 0.069313108921051025, 0.070607319474220276, 0.071918979287147522, 0.073248207569122314, 0.074595145881175995, 0.075959883630275726, 0.07734256237745285, 0.078743241727352142, 0.080162093043327332, 0.08159918338060379, 0.083054669201374054, 0.084528610110282898, 0.086021184921264648, 0.087532415986061096, 0.089062459766864777, 0.090611375868320465, 0.092179328203201294, 0.093766368925571442, 0.095372647047042847, 0.096998192369937897, 0.098643146455287933, 0.10030759125947952, 0.10199161618947983, 0.10369531810283661, 0.10541882365942001, 0.10716214776039124, 0.10892540961503983, 0.11070869863033295, 0.11251209676265717, 0.11433566361665726, 0.11617954820394516, 0.11804373562335968, 0.11992833018302917, 0.12183342128992081, 0.12375906854867935, 0.12570534646511078, 0.12767235934734344, 0.12966008484363556, 0.13166864216327667, 0.13369807600975037, 0.13574843108654022, 0.13781978189945221, 0.13991223275661469, 0.14202572405338287, 0.14416038990020752, 0.14631621539592743, 0.14849328994750977, 0.15069162845611572, 0.15291133522987366, 0.15515235066413879, 0.15741473436355591, 0.15969853103160858, 0.1620037853717804, 0.16433051228523254, 0.16667875647544861, 0.16904847323894501, 0.17143970727920532, 0.17385250329971313, 0.17628686130046844, 0.17874275147914886, 0.18122029304504395, 0.18371935188770294, 0.18623997271060944, 0.18878217041492462, 0.1913459450006485, 0.19393126666545868, 0.19653819501399994, 0.19916661083698273, 0.20181652903556824, 0.20448794960975647, 0.20718084275722504, 0.20989517867565155, 0.2126309871673584, 0.21538813412189484, 0.21816661953926086, 0.2209663987159729, 0.22378745675086975, 0.22662979364395142, 0.22949324548244476, 0.23237781226634979, 0.23528343439102173, 0.23821006715297699, 0.24115763604640961, 0.24412614107131958, 0.24711540341377258, 0.25012537837028503, 0.25315603613853455, 0.25620725750923157, 0.25927898287773132, 0.26237118244171143, 0.26548364758491516, 0.26861634850502014, 0.27176916599273682, 0.27494201064109802, 0.2781347930431366, 0.28134745359420776, 0.28457978367805481, 0.28783169388771057, 0.29110309481620789, 0.29439383745193481, 0.29770383238792419, 0.30103299021720886, 0.30438104271888733, 0.30774796009063721, 0.31113356351852417, 0.31453773379325867, 0.31796032190322876, 0.3214012086391449, 0.32486018538475037, 0.32833707332611084, 0.33183175325393677, 0.33534407615661621, 0.33887386322021484, 0.34242099523544312, 0.34598517417907715, 0.34956631064414978, 0.35316416621208191, 0.35677862167358398, 0.3604094386100769, 0.36405652761459351, 0.36771953105926514, 0.37139829993247986, 0.37509268522262573, 0.37880244851112366, 0.38252738118171692, 0.38626736402511597, 0.39002197980880737, 0.39379113912582397, 0.39757457375526428, 0.40137210488319397, 0.40518343448638916, 0.40900847315788269, 0.41284680366516113, 0.41669824719429016, 0.42056256532669067, 0.42443951964378357, 0.42832884192466736, 0.4322303831577301, 0.43614372611045837, 0.44006863236427307, 0.44400492310523987, 0.4479522705078125, 0.45191043615341187, 0.45587921142578125, 0.45985805988311768, 0.46384698152542114, 0.46784573793411255, 0.47185373306274414, 0.47587084770202637, 0.47989678382873535, 0.48393124341964722, 0.48797392845153809, 0.49202454090118408, 0.49608278274536133, 0.50014835596084595, 0.50422090291976929, 0.50830012559890747, 0.5123857855796814, 0.51647758483886719, 0.52057504653930664, 0.52467787265777588, 0.5287858247756958, 0.53289848566055298, 0.53701561689376831, 0.54113680124282837, 0.54526180028915405, 0.54939013719558716, 0.55352163314819336, 0.55765581130981445, 0.56179243326187134, 0.56593120098114014, 0.57007157802581787, 0.57421320676803589, 0.57835590839385986, 0.58249920606613159, 0.58664274215698242, 0.59078621864318848, 0.59492921829223633, 0.5990714430809021, 0.60321247577667236, 0.60735195875167847, 0.61148953437805176, 0.61562496423721313, 0.61975759267807007, 0.62388718128204346, 0.62801331281661987, 0.63213574886322021, 0.6362539529800415, 0.64036762714385986, 0.64447635412216187, 0.64857983589172363, 0.65267753601074219, 0.65676921606063843, 0.66085445880889893, 0.6649329662322998, 0.66900408267974854, 0.67306756973266602, 0.67712306976318359, 0.68117010593414307, 0.68520838022232056, 0.68923747539520264, 0.69325697422027588, 0.69726645946502686, 0.70126563310623169, 0.70525401830673218, 0.70923143625259399, 0.71319711208343506, 0.71715086698532104, 0.72109222412109375, 0.7250208854675293, 0.72893643379211426, 0.73283845186233521, 0.73672652244567871, 0.74060028791427612, 0.74445939064025879, 0.74830329418182373, 0.75213176012039185, 0.75594443082809448, 0.75974071025848389, 0.76352030038833618, 0.76728278398513794, 0.77102780342102051, 0.77475500106811523, 0.77846395969390869, 0.78215426206588745, 0.78582549095153809, 0.78947734832763672, 0.79310941696166992, 0.79672133922576904, 0.80031275749206543, 0.80388307571411133, 0.80743205547332764, 0.8109593391418457, 0.81446456909179688, 0.81794726848602295, 0.82140713930130005, 0.82484376430511475, 0.82825678586959839, 0.83164584636688232, 0.8350105881690979, 0.83835059404373169, 0.84166562557220459, 0.84495508670806885, 0.84821879863739014, 0.85145628452301025, 0.8546673059463501, 0.85785144567489624, 0.86100828647613525, 0.86413758993148804, 0.86723899841308594, 0.87031209468841553, 0.87335652112960815, 0.87637203931808472, 0.87935841083526611, 0.88231492042541504, 0.88524156808853149, 0.88813787698745728, 0.89100354909896851, 0.89383822679519653, 0.89664167165756226, 0.89941352605819702, 0.90215343236923218, 0.90486115217208862, 0.90753632783889771, 0.91017866134643555, 0.91278791427612305, 0.91536372900009155, 0.91790568828582764, 0.92041373252868652, 0.92288732528686523, 0.92532640695571899, 0.92773056030273438, 0.93009954690933228, 0.93243312835693359, 0.93473094701766968, 0.93699288368225098, 0.93921846151351929, 0.94140768051147461, 0.94356006383895874, 0.94567543268203735, 0.94775348901748657, 0.94979411363601685, 0.95179694890975952, 0.95376187562942505, 0.95568859577178955, 0.95757681131362915, 0.95942646265029907, 0.96123719215393066, 0.9630088210105896, 0.96474123001098633, 0.96643412113189697, 0.96808725595474243, 0.96970051527023315, 0.97127372026443481, 0.97280663251876831, 0.97429907321929932, 0.97575092315673828, 0.9771619439125061, 0.97853195667266846, 0.97986090183258057, 0.98114854097366333, 0.98239481449127197, 0.98359936475753784, 0.98476219177246094, 0.98588317632675171, 0.98696213960647583, 0.98799896240234375, 0.98899352550506592, 0.98994570970535278, 0.99085539579391479, 0.9917224645614624, 0.99254685640335083, 0.99332839250564575, 0.99406707286834717, 0.99476277828216553, 0.99541538953781128, 0.99602478742599487, 0.99659103155136108, 0.99711394309997559, 0.99759352207183838, 0.99802964925765991, 0.99842232465744019, 0.9987715482711792, 0.99907714128494263, 0.99933922290802002, 0.99955761432647705, 0.9997323751449585, 0.99986344575881958, 0.9999508261680603, 0.99999451637268066, 0.99999451637268066};
 /*
@@ -1071,7 +589,7 @@ void gen_lp_impulse(MYFLT *array, int size, float freq) {
     MYFLT vsum = 0.0;
     MYFLT envPointerScaling = 1.0 / (size + 1) * 1024.0;
     MYFLT sincScaling = (MYFLT)half;
-    
+
     for (i=0; i<half; i++) {
         pp = i * envPointerScaling;
         ppi = (int)pp;
@@ -1092,14 +610,14 @@ void gen_lp_impulse(MYFLT *array, int size, float freq) {
     }
     for (i=1; i<half; i++) {
         array[half+i] = array[half-i];
-    }    
+    }
 }
 
 /*
  lp_conv -> convolution lowpass filter.
  samples is the samples array to filter.
  impulse is the impulse response array.
- num_samps is the number od samples to filter.
+ num_samps is the number of samples to filter.
  size is the filter order. Minimum suggested = 16, ideal = 128 or higher.
  gain is the gain of the filter.
 */
@@ -1107,7 +625,7 @@ void lp_conv(MYFLT *samples, MYFLT *impulse, int num_samps, int size, int gain)
     int i, j, count, tmp_count;
     MYFLT val;
     MYFLT intmp[size];
-    
+
     for (i=0; i<size; i++) {
         intmp[i] = 0.0;
     }
@@ -1129,30 +647,31 @@ void lp_conv(MYFLT *samples, MYFLT *impulse, int num_samps, int size, int gain)
 }
 
 static PyObject *
-upsamp(PyObject *self, PyObject *args, PyObject *kwds)
+p_upsamp(PyObject *self, PyObject *args, PyObject *kwds)
 {
-    int i, j, k;
+    unsigned int i, j, k;
     char *inpath;
     char *outpath;
     SNDFILE *sf;
     SF_INFO info;
+    Py_ssize_t psize, psize2;
     unsigned int snd_size, snd_sr, snd_chnls, num_items;
     MYFLT *sincfunc;
     MYFLT *tmp;
     MYFLT **samples;
     MYFLT **upsamples;
-    int up = 4;
+    unsigned int up = 4;
     int order = 128;
     static char *kwlist[] = {"path", "outfile", "up", "order", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "ss|ii", kwlist, &inpath, &outpath, &up, &order))
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "s#s#|ii", kwlist, &inpath, &psize, &outpath, &psize2, &up, &order))
         return PyInt_FromLong(-1);
-    
+
     /* opening input soundfile */
     info.format = 0;
     sf = sf_open(inpath, SFM_READ, &info);
     if (sf == NULL) {
-        printf("upsamp: failed to open the input file %s.\n", inpath);
+        PySys_WriteStdout("upsamp: failed to open the input file %s.\n", inpath);
         return PyInt_FromLong(-1);
     }
     snd_size = info.frames;
@@ -1166,16 +685,16 @@ upsamp(PyObject *self, PyObject *args, PyObject *kwds)
     samples = (MYFLT **)malloc(snd_chnls * sizeof(MYFLT *));
     for(i=0; i<snd_chnls; i++)
         samples[i] = (MYFLT *)malloc(snd_size * sizeof(MYFLT));
-    
+
     for (i=0; i<num_items; i++)
         samples[i%snd_chnls][(int)(i/snd_chnls)] = tmp[i];
     free(tmp);
-    
+
     /* upsampling */
     upsamples = (MYFLT **)malloc(snd_chnls * sizeof(MYFLT *));
     for(i=0; i<snd_chnls; i++)
         upsamples[i] = (MYFLT *)malloc(snd_size * up * sizeof(MYFLT));
-    
+
     for (i=0; i<snd_size; i++) {
         for (j=0; j<snd_chnls; j++) {
             upsamples[j][i*up] = samples[j][i];
@@ -1184,7 +703,7 @@ upsamp(PyObject *self, PyObject *args, PyObject *kwds)
             }
         }
     }
-    
+
     if (order > 2) {
         /* apply lowpass filter */
         sincfunc = (MYFLT *)malloc(order * sizeof(MYFLT));
@@ -1194,7 +713,7 @@ upsamp(PyObject *self, PyObject *args, PyObject *kwds)
         }
         free(sincfunc);
     }
-    
+
     /* save upsampled file */
     info.samplerate = snd_sr * up;
     tmp = (MYFLT *)malloc(num_items * up * sizeof(MYFLT));
@@ -1202,10 +721,10 @@ upsamp(PyObject *self, PyObject *args, PyObject *kwds)
         for (j=0; j<snd_chnls; j++) {
             tmp[i*snd_chnls+j] = upsamples[j][i];
         }
-    }    
-    
+    }
+
     if (! (sf = sf_open(outpath, SFM_WRITE, &info))) {
-        printf ("upsamp: failed to open output file %s.\n", outpath);
+        PySys_WriteStdout("upsamp: failed to open output file %s.\n", outpath);
         free(tmp);
         for (i=0; i<snd_chnls; i++) {
             free(samples[i]);
@@ -1218,7 +737,7 @@ upsamp(PyObject *self, PyObject *args, PyObject *kwds)
 
     SF_WRITE(sf, tmp, num_items * up);
     sf_close(sf);
-    
+
     /* clean-up */
     free(tmp);
     for (i=0; i<snd_chnls; i++) {
@@ -1227,18 +746,19 @@ upsamp(PyObject *self, PyObject *args, PyObject *kwds)
     }
     free(samples);
     free(upsamples);
-    
-    Py_RETURN_NONE;    
+
+    Py_RETURN_NONE;
 }
 
 static PyObject *
-downsamp(PyObject *self, PyObject *args, PyObject *kwds)
+p_downsamp(PyObject *self, PyObject *args, PyObject *kwds)
 {
-    int i, j;
+    unsigned int i, j;
     char *inpath;
     char *outpath;
     SNDFILE *sf;
     SF_INFO info;
+    Py_ssize_t psize, psize2;
     unsigned int snd_size, snd_sr, snd_chnls, num_items, samples_per_channels;
     MYFLT *sincfunc;
     MYFLT *tmp;
@@ -1247,15 +767,15 @@ downsamp(PyObject *self, PyObject *args, PyObject *kwds)
     int down = 4;
     int order = 128;
     static char *kwlist[] = {"path", "outfile", "down", "order", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "ss|ii", kwlist, &inpath, &outpath, &down, &order))
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "s#s#|ii", kwlist, &inpath, &psize, &outpath, &psize2, &down, &order))
         return PyInt_FromLong(-1);
-    
+
     /* opening input soundfile */
     info.format = 0;
     sf = sf_open(inpath, SFM_READ, &info);
     if (sf == NULL) {
-        printf("downsamp: failed to open the input file %s.\n", inpath);
+        PySys_WriteStdout("downsamp: failed to open the input file %s.\n", inpath);
         return PyInt_FromLong(-1);
     }
     snd_size = info.frames;
@@ -1269,7 +789,7 @@ downsamp(PyObject *self, PyObject *args, PyObject *kwds)
     samples = (MYFLT **)malloc(snd_chnls * sizeof(MYFLT *));
     for(i=0; i<snd_chnls; i++)
         samples[i] = (MYFLT *)malloc(snd_size * sizeof(MYFLT));
-    
+
     for (i=0; i<num_items; i++)
         samples[i%snd_chnls][(int)(i/snd_chnls)] = tmp[i];
     free(tmp);
@@ -1283,7 +803,7 @@ downsamp(PyObject *self, PyObject *args, PyObject *kwds)
         }
         free(sincfunc);
     }
-    
+
     /* downsampling */
     samples_per_channels = (snd_size / down) + (snd_size % down);
     downsamples = (MYFLT **)malloc(snd_chnls * sizeof(MYFLT *));
@@ -1296,10 +816,10 @@ downsamp(PyObject *self, PyObject *args, PyObject *kwds)
 
     for (i=0; i<samples_per_channels; i++) {
         for (j=0; j<snd_chnls; j++) {
-            if (i < snd_size)
+            if (i*down < snd_size)
                 downsamples[j][i] = samples[j][i*down];
             else
-                downsamples[j][i] = 0.0;            
+                downsamples[j][i] = 0.0;
         }
     }
 
@@ -1311,9 +831,9 @@ downsamp(PyObject *self, PyObject *args, PyObject *kwds)
             tmp[i*snd_chnls+j] = downsamples[j][i];
         }
     }
-       
+
     if (! (sf = sf_open(outpath, SFM_WRITE, &info))) {
-        printf("downsamp: failed to open the output file %s.\n", outpath);
+        PySys_WriteStdout("downsamp: failed to open the output file %s.\n", outpath);
         free(tmp);
         for (i=0; i<snd_chnls; i++) {
             free(samples[i]);
@@ -1323,10 +843,10 @@ downsamp(PyObject *self, PyObject *args, PyObject *kwds)
         free(downsamples);
         return PyInt_FromLong(-1);
     }
-    
+
     SF_WRITE(sf, tmp, snd_chnls * samples_per_channels);
     sf_close(sf);
-    
+
     /* clean-up */
     free(tmp);
     for (i=0; i<snd_chnls; i++) {
@@ -1335,8 +855,8 @@ downsamp(PyObject *self, PyObject *args, PyObject *kwds)
     }
     free(samples);
     free(downsamples);
-    
-    Py_RETURN_NONE;    
+
+    Py_RETURN_NONE;
 }
 
 /****** Algorithm utilities ******/
@@ -1346,8 +866,8 @@ This function receives a list of points as input and returns a simplified list b
 A point is a tuple (or a list) of two floats, time and value. A list of points looks like:\n\n        \
 [ (0, 0), (0.1, 0.7), (0.2, 0.5), ... ] \n\n\
 :Args:\n\n    \
-pointlist : list of lists or list of tuples\n        List of points (time, value) to filter.\n    \
-tolerance : float, optional\n        Normalized distance threshold under which a point is\n        excluded from the list. Defaults to 0.02."
+pointlist: list of lists or list of tuples\n        List of points (time, value) to filter.\n    \
+tolerance: float, optional\n        Normalized distance threshold under which a point is\n        excluded from the list. Defaults to 0.02."
 
 typedef struct STACK_RECORD {
     int nAnchorIndex;
@@ -1396,32 +916,32 @@ reducePoints(PyObject *self, PyObject *args, PyObject *kwds)
     int *pnUseFlag;
     MYFLT dTolerance = .02;
         MYFLT xMax, yMin, yMax;
-        
+
         static char *kwlist[] = {"pointlist", "tolerance", NULL};
-        
+
         if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_F, kwlist, &pointlist, &dTolerance))
             return PyInt_FromLong(-1);
-        
+
         nPointsCount = PyList_Size(pointlist);
-        
+
         pPointsX = (MYFLT *)malloc(nPointsCount * sizeof(MYFLT));
         pPointsY = (MYFLT *)malloc(nPointsCount * sizeof(MYFLT));
         pnUseFlag = (int *)malloc(nPointsCount * sizeof(int));
-        
+
         tup = PyList_GET_ITEM(pointlist, 0);
         if (PyTuple_Check(tup) == 1) {
             for (i=0; i<nPointsCount; i++) {
                 tup = PyList_GET_ITEM(pointlist, i);
-                pPointsX[i] = PyFloat_AsDouble(PyNumber_Float(PyTuple_GET_ITEM(tup, 0)));
-                pPointsY[i] = PyFloat_AsDouble(PyNumber_Float(PyTuple_GET_ITEM(tup, 1)));
+                pPointsX[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 0));
+                pPointsY[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 1));
                 pnUseFlag[i] = 0;
             }
         }
         else {
             for (i=0; i<nPointsCount; i++) {
                 tup = PyList_GET_ITEM(pointlist, i);
-                pPointsX[i] = PyFloat_AsDouble(PyNumber_Float(PyList_GET_ITEM(tup, 0)));
-                pPointsY[i] = PyFloat_AsDouble(PyNumber_Float(PyList_GET_ITEM(tup, 1)));
+                pPointsX[i] = PyFloat_AsDouble(PyList_GET_ITEM(tup, 0));
+                pPointsY[i] = PyFloat_AsDouble(PyList_GET_ITEM(tup, 1));
                 pnUseFlag[i] = 0;
             }
         }
@@ -1434,7 +954,7 @@ reducePoints(PyObject *self, PyObject *args, PyObject *kwds)
                 yMin = pPointsY[i];
             else if (pPointsY[i] > yMax)
                 yMax = pPointsY[i];
-        }    
+        }
     for (i=0; i<nPointsCount; i++) {
         pPointsX[i] = pPointsX[i] / xMax;
         pPointsY[i] = (pPointsY[i] - yMin) / yMax;
@@ -1494,15 +1014,15 @@ reducePoints(PyObject *self, PyObject *args, PyObject *kwds)
             StackPush( nVertexIndexMaxDistance, nFloaterIndex );
         }
     }
-    
-    pPointsOut = PyList_New(0);    
+
+    pPointsOut = PyList_New(0);
     for (i=0; i<nPointsCount; i++) {
         if (pnUseFlag[i] == 1) {
             PyList_Append(pPointsOut, PyList_GET_ITEM(pointlist, i));
         }
-    }        
+    }
 
-    return pPointsOut;    
+    return pPointsOut;
 }
 
 #define distanceToSegment_info \
@@ -1510,15 +1030,15 @@ reducePoints(PyObject *self, PyObject *args, PyObject *kwds)
 This function returns the shortest distance from a point to a line segment\nnormalized between 0 and 1.\n\n\
 A point is a tuple (or a list) of two floats, time and value. `p` is the point for which\nto find the distance from line `p1` to `p2`.\n\n\
 :Args:\n\n    \
-p : list or tuple\n        Point for which to find the distance.\n    \
-p1 : list or tuple\n        First point of the segment.\n    \
-p2 : list or tuple\n        Second point of the segment.\n    \
-xmin : float, optional\n        Minimum value on the X axis.\n    \
-xmax : float, optional\n        Maximum value on the X axis.\n    \
-ymin : float, optional\n        Minimum value on the Y axis.\n    \
-ymax : float, optional\n        Maximum value on the Y axis.\n    \
-xlog : boolean, optional\n        Set this argument to True if X axis has a logarithmic scaling.\n    \
-ylog : boolean, optional\n        Set this argument to True if Y axis has a logarithmic scaling."
+p: list or tuple\n        Point for which to find the distance.\n    \
+p1: list or tuple\n        First point of the segment.\n    \
+p2: list or tuple\n        Second point of the segment.\n    \
+xmin: float, optional\n        Minimum value on the X axis.\n    \
+xmax: float, optional\n        Maximum value on the X axis.\n    \
+ymin: float, optional\n        Minimum value on the Y axis.\n    \
+ymax: float, optional\n        Maximum value on the Y axis.\n    \
+xlog: boolean, optional\n        Set this argument to True if X axis has a logarithmic scaling.\n    \
+ylog: boolean, optional\n        Set this argument to True if Y axis has a logarithmic scaling."
 
 static PyObject *
 distanceToSegment(PyObject *self, PyObject *args, PyObject *kwds)
@@ -1532,9 +1052,9 @@ distanceToSegment(PyObject *self, PyObject *args, PyObject *kwds)
     int xlog = 0;
     int ylog = 0;
     MYFLT xp[2], xp1[2], xp2[2], closest[2];
-    
+
     static char *kwlist[] = {"p", "p1", "p2", "xmin", "xmax", "ymin", "ymax", "xlog", "ylog", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_OOO_FFFFII, kwlist, &p, &p1, &p2, &xmin, &xmax, &ymin, &ymax, &xlog, &ylog))
         return PyInt_FromLong(-1);
 
@@ -1543,27 +1063,27 @@ distanceToSegment(PyObject *self, PyObject *args, PyObject *kwds)
     pf2 = PySequence_Fast(p2, NULL);
     if (xlog == 0) {
         xscale = xmax - xmin;
-        xp[0] = PyFloat_AsDouble(PyNumber_Float(PySequence_Fast_GET_ITEM(pf, 0))) / xscale;
-        xp1[0] = PyFloat_AsDouble(PyNumber_Float(PySequence_Fast_GET_ITEM(pf1, 0))) / xscale;
-        xp2[0] = PyFloat_AsDouble(PyNumber_Float(PySequence_Fast_GET_ITEM(pf2, 0))) / xscale;
+        xp[0] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(pf, 0)) / xscale;
+        xp1[0] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(pf1, 0)) / xscale;
+        xp2[0] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(pf2, 0)) / xscale;
     }
     else {
         xscale = MYLOG10(xmax / xmin);
-        xp[0] = MYLOG10(PyFloat_AsDouble(PyNumber_Float(PySequence_Fast_GET_ITEM(pf, 0))) / xmin) / xscale;
-        xp1[0] = MYLOG10(PyFloat_AsDouble(PyNumber_Float(PySequence_Fast_GET_ITEM(pf1, 0))) / xmin) / xscale;
-        xp2[0] = MYLOG10(PyFloat_AsDouble(PyNumber_Float(PySequence_Fast_GET_ITEM(pf2, 0))) / xmin) / xscale;
+        xp[0] = MYLOG10(PyFloat_AsDouble(PySequence_Fast_GET_ITEM(pf, 0)) / xmin) / xscale;
+        xp1[0] = MYLOG10(PyFloat_AsDouble(PySequence_Fast_GET_ITEM(pf1, 0)) / xmin) / xscale;
+        xp2[0] = MYLOG10(PyFloat_AsDouble(PySequence_Fast_GET_ITEM(pf2, 0)) / xmin) / xscale;
     }
     if (ylog == 0) {
         yscale = ymax - ymin;
-        xp[1] = PyFloat_AsDouble(PyNumber_Float(PySequence_Fast_GET_ITEM(pf, 1))) / yscale;
-        xp1[1] = PyFloat_AsDouble(PyNumber_Float(PySequence_Fast_GET_ITEM(pf1, 1))) / yscale;
-        xp2[1] = PyFloat_AsDouble(PyNumber_Float(PySequence_Fast_GET_ITEM(pf2, 1))) / yscale;        
+        xp[1] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(pf, 1)) / yscale;
+        xp1[1] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(pf1, 1)) / yscale;
+        xp2[1] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(pf2, 1)) / yscale;
     }
     else {
         yscale = MYLOG10(ymax / ymin);
-        xp[1] = MYLOG10(PyFloat_AsDouble(PyNumber_Float(PySequence_Fast_GET_ITEM(pf, 1))) / ymin) / yscale;
-        xp1[1] = MYLOG10(PyFloat_AsDouble(PyNumber_Float(PySequence_Fast_GET_ITEM(pf1, 1))) / ymin) / yscale;
-        xp2[1] = MYLOG10(PyFloat_AsDouble(PyNumber_Float(PySequence_Fast_GET_ITEM(pf2, 1))) / ymin) / yscale;        
+        xp[1] = MYLOG10(PyFloat_AsDouble(PySequence_Fast_GET_ITEM(pf, 1)) / ymin) / yscale;
+        xp1[1] = MYLOG10(PyFloat_AsDouble(PySequence_Fast_GET_ITEM(pf1, 1)) / ymin) / yscale;
+        xp2[1] = MYLOG10(PyFloat_AsDouble(PySequence_Fast_GET_ITEM(pf2, 1)) / ymin) / yscale;
     }
 
     xDelta = xp2[0] - xp1[0]; yDelta = xp2[1] - xp1[1];
@@ -1585,11 +1105,11 @@ distanceToSegment(PyObject *self, PyObject *args, PyObject *kwds)
 #define linToCosCurve_info \
 "\nCreates a cosinus interpolated curve from a list of points.\n\n\
 A point is a tuple (or a list) of two floats, time and value.\n\n:Args:\n\n    \
-data : list of points\n        Set of points between which will be inserted interpolated segments.\n    \
-yrange : list of 2 floats, optional\n        Minimum and maximum values on the Y axis. Defaults to [0., 1.].\n    \
-totaldur : float, optional\n        X axis duration. Defaults to 1.\n    \
-points : int, optional\n        Number of points in the output list. Defaults to 1024.\n    \
-log : boolean, optional\n        Set this value to True if the Y axis has a logarithmic scale. Defaults to False\n\n\
+data: list of points\n        Set of points between which will be inserted interpolated segments.\n    \
+yrange: list of 2 floats, optional\n        Minimum and maximum values on the Y axis. Defaults to [0., 1.].\n    \
+totaldur: float, optional\n        X axis duration. Defaults to 1.\n    \
+points: int, optional\n        Number of points in the output list. Defaults to 1024.\n    \
+log: boolean, optional\n        Set this value to True if the Y axis has a logarithmic scale. Defaults to False\n\n\
 >>> s = Server().boot()\n\
 >>> a = [(0,0), (0.25, 1), (0.33, 1), (1,0)]\n\
 >>> b = linToCosCurve(a, yrange=[0, 1], totaldur=1, points=8192)\n\
@@ -1600,7 +1120,7 @@ static PyObject *
 linToCosCurve(PyObject *self, PyObject *args, PyObject *kwds)
 {
     PyObject *data, *fdata, *out, *inout, *ftup, *yrange=NULL, *fyrange=NULL;
-    int i, j, datasize, steps; 
+    int i, j, datasize, steps;
     double tmp, x1, x2, y1, y2, mu, ydiff, log10ymin, log10ymax;
     double *xdata, *ydata, *cxdata, *cydata;
     double totaldur = 1.0;
@@ -1610,49 +1130,49 @@ linToCosCurve(PyObject *self, PyObject *args, PyObject *kwds)
     double inc = 1.0 / num;
     int log = 0;
     int count = 0;
-    
+
     static char *kwlist[] = {"data", "yrange", "totaldur", "points", "log", NULL};
 
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|Odii", kwlist, &data, &yrange, &totaldur, &num, &log))
         Py_RETURN_NONE;
-    
+
     if (yrange) {
         fyrange = PySequence_Fast(yrange, NULL);
-        ymin = PyFloat_AsDouble(PyNumber_Float(PySequence_Fast_GET_ITEM(fyrange, 0)));
-        ymax = PyFloat_AsDouble(PyNumber_Float(PySequence_Fast_GET_ITEM(fyrange, 1)));
+        ymin = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(fyrange, 0));
+        ymax = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(fyrange, 1));
     }
     ydiff = ymax - ymin;
     log10ymin = log10(ymin);
     log10ymax = log10(ymax);
-    
+
     fdata = PySequence_Fast(data, NULL);
     datasize = PySequence_Size(fdata);
     xdata = (double *)malloc(datasize * sizeof(double));
     ydata = (double *)malloc(datasize * sizeof(double));
-    
+
     /* acquire data + normalization */
     if (log == 0) {
         for (i=0; i<datasize; i++) {
             ftup = PySequence_Fast(PySequence_Fast_GET_ITEM(fdata, i), NULL);
-            tmp = PyFloat_AsDouble(PyNumber_Float(PySequence_Fast_GET_ITEM(ftup, 0)));
+            tmp = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(ftup, 0));
             xdata[i] = tmp / totaldur;
-            tmp = PyFloat_AsDouble(PyNumber_Float(PySequence_Fast_GET_ITEM(ftup, 1)));
+            tmp = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(ftup, 1));
             ydata[i] = (tmp - ymin) / ydiff;
         }
     }
     else {
         for (i=0; i<datasize; i++) {
             ftup = PySequence_Fast(PySequence_Fast_GET_ITEM(fdata, i), NULL);
-            tmp = PyFloat_AsDouble(PyNumber_Float(PySequence_Fast_GET_ITEM(ftup, 0)));
+            tmp = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(ftup, 0));
             xdata[i] = tmp / totaldur;
-            tmp = PyFloat_AsDouble(PyNumber_Float(PySequence_Fast_GET_ITEM(ftup, 1)));
+            tmp = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(ftup, 1));
             ydata[i] = log10(tmp / ymin) / log10(ymax / ymin);
-        }        
+        }
     }
 
     cxdata = (double *)malloc((num+5) * sizeof(double));
     cydata = (double *)malloc((num+5) * sizeof(double));
-    
+
     /* generates cos interpolation */
     for (i=0; i<(datasize-1); i++) {
         x1 = xdata[i];
@@ -1670,7 +1190,7 @@ linToCosCurve(PyObject *self, PyObject *args, PyObject *kwds)
     }
     cxdata[count] = xdata[datasize-1];
     cydata[count++] = ydata[datasize-1];
-    
+
     /* denormalization */
     if (log == 0) {
         for (i=0; i<count; i++) {
@@ -1682,7 +1202,7 @@ linToCosCurve(PyObject *self, PyObject *args, PyObject *kwds)
         for (i=0; i<count; i++) {
             cxdata[i] *= totaldur;
             cydata[i] = pow(10.0, cydata[i] * (log10ymax - log10ymin) + log10ymin);
-        }        
+        }
     }
 
     /* output Python's list of lists */
@@ -1693,7 +1213,7 @@ linToCosCurve(PyObject *self, PyObject *args, PyObject *kwds)
         PyList_SET_ITEM(inout, 1, PyFloat_FromDouble(cydata[i]));
         PyList_SET_ITEM(out, i, inout);
     }
-    
+
     free(xdata);
     free(ydata);
     free(cxdata);
@@ -1706,20 +1226,20 @@ linToCosCurve(PyObject *self, PyObject *args, PyObject *kwds)
 This function takes data in the range `xmin` - `xmax` and returns corresponding values\nin the range `ymin` - `ymax`.\n\n\
 `data` can be either a number or a list. Return value is of the same type as `data`\nwith all values rescaled.\n\n\
 :Argss:\n\n    \
-data : float or list of floats\n        Values to convert.\n    \
-xmin : float, optional\n        Minimum value of the input range.\n    \
-xmax : float, optional\n        Maximum value of the input range.\n    \
-ymin : float, optional\n        Minimum value of the output range.\n    \
-ymax : float, optional\n        Maximum value of the output range.\n    \
-xlog : boolean, optional\n        Set this argument to True if the input range has a logarithmic scaling.\n    \
-ylog : boolean, optional\n        Set this argument to True if the output range has a logarithmic scaling.\n\n\
+data: float or list of floats\n        Values to convert.\n    \
+xmin: float, optional\n        Minimum value of the input range.\n    \
+xmax: float, optional\n        Maximum value of the input range.\n    \
+ymin: float, optional\n        Minimum value of the output range.\n    \
+ymax: float, optional\n        Maximum value of the output range.\n    \
+xlog: boolean, optional\n        Set this argument to True if the input range has a logarithmic scaling.\n    \
+ylog: boolean, optional\n        Set this argument to True if the output range has a logarithmic scaling.\n\n\
 >>> a = 0.5\n\
 >>> b = rescale(a, 0, 1, 20, 20000, False, True)\n\
->>> print b\n\
+>>> print(b)\n\
 632.453369141\n\
 >>> a = [0, .4, .8]\n\
 >>> b = rescale(a, 0, 1, 20, 20000, False, True)\n\
->>> print b\n\
+>>> print(b)\n\
 [20.000001907348633, 316.97738647460938, 5023.7705078125]\n\n"
 
 static PyObject *
@@ -1735,9 +1255,9 @@ rescale(PyObject *self, PyObject *args, PyObject *kwds)
     int ylog = 0;
     int i, cnt;
     int type; // 0 = float, 1 = list of floats
-    
+
     static char *kwlist[] = {"data", "xmin", "xmax", "ymin", "ymax", "xlog", "ylog", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_FFFFII, kwlist, &data, &xmin, &xmax, &ymin, &ymax, &xlog, &ylog))
         return PyInt_FromLong(-1);
 
@@ -1745,26 +1265,27 @@ rescale(PyObject *self, PyObject *args, PyObject *kwds)
         type = 0;
     else if (PyList_Check(data))
         type = 1;
-    else
-        Py_RETURN_NONE;
-
+    else {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
     if (xlog == 0 && ylog == 0) {
         datascl = xmax - xmin;
         curscl = ymax - ymin;
         curscl /= datascl;
         if (type == 0) {
-            val = PyFloat_AsDouble(PyNumber_Float(data));
+            val = PyFloat_AsDouble(data);
             return Py_BuildValue("d", (val - xmin) * curscl + ymin);
         }
         else if (type == 1) {
             cnt = PyList_Size(data);
             out = PyList_New(cnt);
             for (i=0; i<cnt; i++) {
-                val = PyFloat_AsDouble(PyNumber_Float(PyList_GET_ITEM(data, i)));
+                val = PyFloat_AsDouble(PyList_GET_ITEM(data, i));
                 PyList_SET_ITEM(out, i, PyFloat_FromDouble((val - xmin) * curscl + ymin));
             }
             return out;
-        }        
+        }
     }
     else if (xlog == 0 && ylog == 1) {
         if (xmin == 0)
@@ -1773,7 +1294,7 @@ rescale(PyObject *self, PyObject *args, PyObject *kwds)
         curscl = MYLOG10(ymax / ymin);
         ymin = MYLOG10(ymin);
         if (type == 0) {
-            val = PyFloat_AsDouble(PyNumber_Float(data));
+            val = PyFloat_AsDouble(data);
             if (val == 0)
                 val = 0.000001;
             val = (val - xmin) / datascl;
@@ -1783,20 +1304,20 @@ rescale(PyObject *self, PyObject *args, PyObject *kwds)
             cnt = PyList_Size(data);
             out = PyList_New(cnt);
             for (i=0; i<cnt; i++) {
-                val = PyFloat_AsDouble(PyNumber_Float(PyList_GET_ITEM(data, i)));
+                val = PyFloat_AsDouble(PyList_GET_ITEM(data, i));
                 if (val == 0)
                     val = 0.000001;
                 val = (val - xmin) / datascl;
                 PyList_SET_ITEM(out, i, PyFloat_FromDouble(MYPOW(10.0, val * curscl + ymin)));
             }
             return out;
-        }        
+        }
     }
     else if (xlog == 1 && ylog == 0) {
         datascl = MYLOG10(xmax / xmin);
         curscl = ymax - ymin;
         if (type == 0) {
-            val = PyFloat_AsDouble(PyNumber_Float(data));
+            val = PyFloat_AsDouble(data);
             val = MYLOG10(val / xmin) / datascl;
             return Py_BuildValue("d", val * curscl + ymin);
         }
@@ -1804,19 +1325,19 @@ rescale(PyObject *self, PyObject *args, PyObject *kwds)
             cnt = PyList_Size(data);
             out = PyList_New(cnt);
             for (i=0; i<cnt; i++) {
-                val = PyFloat_AsDouble(PyNumber_Float(PyList_GET_ITEM(data, i)));
+                val = PyFloat_AsDouble(PyList_GET_ITEM(data, i));
                 val = MYLOG10(val / xmin) / datascl;
                 PyList_SET_ITEM(out, i, PyFloat_FromDouble(val * curscl + ymin));
             }
             return out;
-        }        
+        }
     }
     else if (xlog == 1 && ylog == 1) {
         datascl = MYLOG10(xmax / xmin);
         curscl = MYLOG10(ymax / ymin);
         ymin = MYLOG10(ymin);
         if (type == 0) {
-            val = PyFloat_AsDouble(PyNumber_Float(data));
+            val = PyFloat_AsDouble(data);
             val = MYLOG10(val / xmin) / datascl;
             return Py_BuildValue("d", MYPOW(10.0, val * curscl + ymin));
         }
@@ -1824,33 +1345,71 @@ rescale(PyObject *self, PyObject *args, PyObject *kwds)
             cnt = PyList_Size(data);
             out = PyList_New(cnt);
             for (i=0; i<cnt; i++) {
-                val = PyFloat_AsDouble(PyNumber_Float(PyList_GET_ITEM(data, i)));
+                val = PyFloat_AsDouble(PyList_GET_ITEM(data, i));
                 val = MYLOG10(val / xmin) / datascl;
                 PyList_SET_ITEM(out, i, PyFloat_FromDouble(MYPOW(10.0, val * curscl + ymin)));
             }
             return out;
-        }        
+        }
     }
     else {
-        Py_RETURN_NONE;
+        Py_INCREF(Py_None);
+        return Py_None;
     }
-    Py_RETURN_NONE;
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+#define floatmap_info \
+"\nConverts values from a 0-1 range to an output range.\n\n\
+This function takes data in the range `0` - `1` and returns corresponding values\nin the range `min` - `max`.\n\n\
+:Argss:\n\n    \
+x: float\n        Value to convert, in the range 0 to 1.\n    \
+min: float, optional\n        Minimum value of the output range. Defaults to 0.\n    \
+max: float, optional\n        Maximum value of the output range. Defaults to 1.\n    \
+exp: float, optional\n        Power factor (1 (default) is linear, les than 1 is logarithmic, greter than 1 is exponential).\n\n\
+>>> a = 0.5\n\
+>>> b = floatmap(a, 0, 1, 4)\n\
+>>> print(b)\n\
+0.0625\n\n"
+
+static PyObject *
+floatmap(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    MYFLT x = 0.0;
+    MYFLT min = 0.0;
+    MYFLT max = 1.0;
+    MYFLT exp = 1.0;
+
+    static char *kwlist[] = {"x", "min", "max", "exp", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_F_FFF, kwlist, &x, &min, &max, &exp))
+        return PyInt_FromLong(-1);
+
+    if (x < 0.0)
+        x = 0.0;
+    else if (x > 1.0)
+        x = 1.0;
+    if (exp != 1.0)
+        x = MYPOW(x, exp);
+
+    return Py_BuildValue("d", x * (max - min) + min);
 }
 
 /****** Conversion utilities ******/
 #define midiToHz_info \
 "\nConverts a midi note value to frequency in Hertz.\n\n:Args:\n\n    \
-x : int or float\n        Midi note. `x` can be a number, a list or a tuple, otherwise the function returns None.\n\n\
+x: int or float\n        Midi note. `x` can be a number, a list or a tuple, otherwise the function returns None.\n\n\
 >>> a = (48, 60, 62, 67)\n\
 >>> b = midiToHz(a)\n\
->>> print b\n\
+>>> print(b)\n\
 (130.8127826503271, 261.62556530066814, 293.66476791748823, 391.9954359818656)\n\
 >>> a = [48, 60, 62, 67]\n\
 >>> b = midiToHz(a)\n\
->>> print b\n\
+>>> print(b)\n\
 [130.8127826503271, 261.62556530066814, 293.66476791748823, 391.9954359818656]\n\
 >>> b = midiToHz(60.0)\n\
->>> print b\n\
+>>> print(b)\n\
 261.625565301\n\n"
 
 static PyObject *
@@ -1860,13 +1419,13 @@ midiToHz(PyObject *self, PyObject *arg) {
     double x = 0.0;
     PyObject *newseq = NULL;
     if (PyNumber_Check(arg))
-        return Py_BuildValue("d", 8.1757989156437 * pow(1.0594630943593, PyFloat_AsDouble(PyNumber_Float(arg))));
+        return Py_BuildValue("d", 440.0 * MYPOW(2.0, (PyFloat_AsDouble(arg) - 69) / 12.0));
     else if (PyList_Check(arg)) {
         count = PyList_Size(arg);
         newseq = PyList_New(count);
         for (i=0; i<count; i++) {
-            x = PyFloat_AsDouble(PyNumber_Float(PyList_GET_ITEM(arg, i)));
-            PyList_SET_ITEM(newseq, i, PyFloat_FromDouble(8.1757989156437 * pow(1.0594630943593, x)));
+            x = PyFloat_AsDouble(PyList_GET_ITEM(arg, i));
+            PyList_SET_ITEM(newseq, i, PyFloat_FromDouble(440.0 * MYPOW(2.0, (x - 69) / 12.0)));
         }
         return newseq;
     }
@@ -1874,28 +1433,73 @@ midiToHz(PyObject *self, PyObject *arg) {
         count = PyTuple_Size(arg);
         newseq = PyTuple_New(count);
         for (i=0; i<count; i++) {
-            x = PyFloat_AsDouble(PyNumber_Float(PyTuple_GET_ITEM(arg, i)));
-            PyTuple_SET_ITEM(newseq, i, PyFloat_FromDouble(8.1757989156437 * pow(1.0594630943593, x)));
+            x = PyFloat_AsDouble(PyTuple_GET_ITEM(arg, i));
+            PyTuple_SET_ITEM(newseq, i, PyFloat_FromDouble(440.0 * MYPOW(2.0, (x - 69) / 12.0)));
         }
         return newseq;
     }
     else
         Py_RETURN_NONE;
-}    
+}
+
+#define hzToMidi_info \
+"\nConverts a frequency in Hertz to a midi note value.\n\n:Args:\n\n    \
+x: float\n        Frequency in Hertz. `x` can be a number, a list or a tuple, otherwise the function returns None.\n\n\
+>>> a = (110.0, 220.0, 440.0, 880.0)\n\
+>>> b = hzToMidi(a)\n\
+>>> print(b)\n\
+(45.0, 57.0, 69.0, 81.0)\n\
+>>> a = [110.0, 220.0, 440.0, 880.0]\n\
+>>> b = hzToMidi(a)\n\
+>>> print(b)\n\
+[45.0, 57.0, 69.0, 81.0]\n\
+>>> b = hzToMidi(440.0)\n\
+>>> print(b)\n\
+69.0\n\n"
+
+static PyObject *
+hzToMidi(PyObject *self, PyObject *arg) {
+    int count = 0;
+    int i = 0;
+    double x = 0.0;
+    PyObject *newseq = NULL;
+    if (PyNumber_Check(arg))
+        return Py_BuildValue("d", 12.0 * MYLOG2(PyFloat_AsDouble(arg) / 440.0) + 69);
+    else if (PyList_Check(arg)) {
+        count = PyList_Size(arg);
+        newseq = PyList_New(count);
+        for (i=0; i<count; i++) {
+            x = PyFloat_AsDouble(PyList_GET_ITEM(arg, i));
+            PyList_SET_ITEM(newseq, i, PyFloat_FromDouble(12.0 * MYLOG2(x / 440.0) + 69));
+        }
+        return newseq;
+    }
+    else if (PyTuple_Check(arg)) {
+        count = PyTuple_Size(arg);
+        newseq = PyTuple_New(count);
+        for (i=0; i<count; i++) {
+            x = PyFloat_AsDouble(PyTuple_GET_ITEM(arg, i));
+            PyTuple_SET_ITEM(newseq, i, PyFloat_FromDouble(12.0 * MYLOG2(x / 440.0) + 69));
+        }
+        return newseq;
+    }
+    else
+        Py_RETURN_NONE;
+}
 
 #define midiToTranspo_info \
 "\nConverts a midi note value to transposition factor (central key = 60).\n\n:Args:\n\n    \
-x : int or float\n        Midi note. `x` can be a number, a list or a tuple, otherwise the function returns None.\n\n\
+x: int or float\n        Midi note. `x` can be a number, a list or a tuple, otherwise the function returns None.\n\n\
 >>> a = (48, 60, 62, 67)\n\
 >>> b = midiToTranspo(a)\n\
->>> print b\n    \
+>>> print(b)\n    \
 (0.49999999999997335, 1.0, 1.122462048309383, 1.4983070768767281)\n\
 >>> a = [48, 60, 62, 67]\n\
 >>> b = midiToTranspo(a)\n\
->>> print b\n\
+>>> print(b)\n\
 [0.49999999999997335, 1.0, 1.122462048309383, 1.4983070768767281]\n\
 >>> b = midiToTranspo(60.0)\n\
->>> print b\n\
+>>> print(b)\n\
 1.0\n\n"
 
 static PyObject *
@@ -1905,12 +1509,12 @@ midiToTranspo(PyObject *self, PyObject *arg) {
     double x = 0.0;
     PyObject *newseq = NULL;
     if (PyNumber_Check(arg))
-        return Py_BuildValue("d", pow(1.0594630943593, PyFloat_AsDouble(PyNumber_Float(arg))-60.0));
+        return Py_BuildValue("d", pow(1.0594630943593, PyFloat_AsDouble(arg)-60.0));
     else if (PyList_Check(arg)) {
         count = PyList_Size(arg);
         newseq = PyList_New(count);
         for (i=0; i<count; i++) {
-            x = PyFloat_AsDouble(PyNumber_Float(PyList_GET_ITEM(arg, i)));
+            x = PyFloat_AsDouble(PyList_GET_ITEM(arg, i));
             PyList_SET_ITEM(newseq, i, PyFloat_FromDouble(pow(1.0594630943593, x-60.0)));
         }
         return newseq;
@@ -1919,36 +1523,36 @@ midiToTranspo(PyObject *self, PyObject *arg) {
         count = PyTuple_Size(arg);
         newseq = PyTuple_New(count);
         for (i=0; i<count; i++) {
-            x = PyFloat_AsDouble(PyNumber_Float(PyTuple_GET_ITEM(arg, i)));
+            x = PyFloat_AsDouble(PyTuple_GET_ITEM(arg, i));
             PyTuple_SET_ITEM(newseq, i, PyFloat_FromDouble(pow(1.0594630943593, x-60.0)));
         }
         return newseq;
     }
     else
         Py_RETURN_NONE;
-}    
+}
 
 #define sampsToSec_info \
 "\nReturns the duration in seconds equivalent to the number of samples given as an argument.\n\n:Args:\n\n    \
-x : int or float\n        Duration in samples. `x` can be a number, a list or a tuple, otherwise function returns None.\n\n\
+x: int or float\n        Duration in samples. `x` can be a number, a list or a tuple, otherwise function returns None.\n\n\
 >>> s = Server().boot()\n\
 >>> a = (64, 128, 256)\n\
 >>> b = sampsToSec(a)\n\
->>> print b\n\
+>>> print(b)\n\
 (0.0014512471655328798, 0.0029024943310657597, 0.0058049886621315194)\n\
 >>> a = [64, 128, 256]\n\
 >>> b = sampsToSec(a)\n\
->>> print b\n\
+>>> print(b)\n\
 [0.0014512471655328798, 0.0029024943310657597, 0.0058049886621315194]\n\
 >>> b = sampsToSec(8192)\n\
->>> print b\n\
+>>> print(b)\n\
 0.185759637188\n\n"
 
 static PyObject *
 sampsToSec(PyObject *self, PyObject *arg) {
     PyObject *server = PyServer_get_server();
     if (server == NULL) {
-        printf("Warning: A Server must be booted before calling `sampsToSec` function.\n");
+        PySys_WriteStdout("Warning: A Server must be booted before calling `sampsToSec` function.\n");
         Py_RETURN_NONE;
     }
     double sr = PyFloat_AsDouble(PyObject_CallMethod(server, "getSamplingRate", NULL));
@@ -1957,12 +1561,12 @@ sampsToSec(PyObject *self, PyObject *arg) {
     double x = 0.0;
     PyObject *newseq = NULL;
     if (PyNumber_Check(arg))
-        return Py_BuildValue("d", PyFloat_AsDouble(PyNumber_Float(arg)) / sr);
+        return Py_BuildValue("d", PyFloat_AsDouble(arg) / sr);
     else if (PyList_Check(arg)) {
         count = PyList_Size(arg);
         newseq = PyList_New(count);
         for (i=0; i<count; i++) {
-            x = PyFloat_AsDouble(PyNumber_Float(PyList_GET_ITEM(arg, i)));
+            x = PyFloat_AsDouble(PyList_GET_ITEM(arg, i));
             PyList_SET_ITEM(newseq, i, PyFloat_FromDouble(x / sr));
         }
         return newseq;
@@ -1971,36 +1575,36 @@ sampsToSec(PyObject *self, PyObject *arg) {
         count = PyTuple_Size(arg);
         newseq = PyTuple_New(count);
         for (i=0; i<count; i++) {
-            x = PyFloat_AsDouble(PyNumber_Float(PyTuple_GET_ITEM(arg, i)));
+            x = PyFloat_AsDouble(PyTuple_GET_ITEM(arg, i));
             PyTuple_SET_ITEM(newseq, i, PyFloat_FromDouble(x / sr));
         }
         return newseq;
     }
     else
         Py_RETURN_NONE;
-}                         
+}
 
 #define secToSamps_info \
 "\nReturns the number of samples equivalent to the duration in seconds given as an argument.\n\n:Args:\n\n    \
-x : int or float\n        Duration in seconds. `x` can be a number, a list or a tuple, otherwise function returns None.\n\n\
+x: int or float\n        Duration in seconds. `x` can be a number, a list or a tuple, otherwise function returns None.\n\n\
 >>> s = Server().boot()\n\
 >>> a = (0.1, 0.25, 0.5, 1)\n\
 >>> b = secToSamps(a)\n\
->>> print b\n\
+>>> print(b)\n\
 (4410, 11025, 22050, 44100)\n\
 >>> a = [0.1, 0.25, 0.5, 1]\n\
 >>> b = secToSamps(a)\n\
->>> print b\n\
+>>> print(b)\n\
 [4410, 11025, 22050, 44100]\n\
 >>> b = secToSamps(2.5)\n\
->>> print b\n\
+>>> print(b)\n\
 110250\n\n"
 
 static PyObject *
 secToSamps(PyObject *self, PyObject *arg) {
     PyObject *server = PyServer_get_server();
     if (server == NULL) {
-        printf("Warning: A Server must be booted before calling `secToSamps` function.\n");
+        PySys_WriteStdout("Warning: A Server must be booted before calling `secToSamps` function.\n");
         Py_RETURN_NONE;
     }
     double sr = PyFloat_AsDouble(PyObject_CallMethod(server, "getSamplingRate", NULL));
@@ -2009,12 +1613,12 @@ secToSamps(PyObject *self, PyObject *arg) {
     double x = 0.0;
     PyObject *newseq = NULL;
     if (PyNumber_Check(arg))
-        return Py_BuildValue("l", (long)(PyFloat_AsDouble(PyNumber_Float(arg)) * sr));
+        return Py_BuildValue("l", (long)(PyFloat_AsDouble(arg) * sr));
     else if (PyList_Check(arg)) {
         count = PyList_Size(arg);
         newseq = PyList_New(count);
         for (i=0; i<count; i++) {
-            x = PyFloat_AsDouble(PyNumber_Float(PyList_GET_ITEM(arg, i)));
+            x = PyFloat_AsDouble(PyList_GET_ITEM(arg, i));
             PyList_SET_ITEM(newseq, i, PyInt_FromLong((long)(x * sr)));
         }
         return newseq;
@@ -2023,39 +1627,43 @@ secToSamps(PyObject *self, PyObject *arg) {
         count = PyTuple_Size(arg);
         newseq = PyTuple_New(count);
         for (i=0; i<count; i++) {
-            x = PyFloat_AsDouble(PyNumber_Float(PyTuple_GET_ITEM(arg, i)));
+            x = PyFloat_AsDouble(PyTuple_GET_ITEM(arg, i));
             PyTuple_SET_ITEM(newseq, i, PyInt_FromLong((long)(x * sr)));
         }
         return newseq;
     }
     else
         Py_RETURN_NONE;
-}                         
+}
 
 /************* Server quieries *************/
 #define serverCreated_info \
 "\nReturns True if a Server object is already created, otherwise, returns False.\n\n\
->>> print serverCreated()\n\
+>>> print(serverCreated())\n\
 False\n\
 >>> s = Server()\n\
->>> print serverCreated()\n\
+>>> print(serverCreated())\n\
 True\n\n"
 
 static PyObject *
 serverCreated(PyObject *self) {
-    if (PyServer_get_server() != NULL)
-        Py_RETURN_TRUE;
-    else
-        Py_RETURN_FALSE;
+    if (PyServer_get_server() != NULL) {
+        Py_INCREF(Py_True);
+        return Py_True;
+    }
+    else {
+        Py_INCREF(Py_False);
+        return Py_False;
+    }
 }
 
 #define serverBooted_info \
 "\nReturns True if an already created Server is booted, otherwise, returns False.\n\n\
 >>> s = Server()\n\
->>> print serverBooted()\n\
+>>> print(serverBooted())\n\
 False\n\
 >>> s.boot()\n\
->>> print serverBooted()\n\
+>>> print(serverBooted())\n\
 True\n\n"
 
 static PyObject *
@@ -2065,18 +1673,25 @@ serverBooted(PyObject *self) {
     if (PyServer_get_server() != NULL) {
         server = PyServer_get_server();
         boot = PyInt_AsLong(PyObject_CallMethod(server, "getIsBooted", NULL));
-        if (boot == 0)
-            Py_RETURN_FALSE;
-        else
-            Py_RETURN_TRUE;
+        if (boot == 0) {
+            Py_INCREF(Py_False);
+            return Py_False;
+        }
+        else {
+            Py_INCREF(Py_True);
+            return Py_True;
+        }
     }
     else {
-        printf("Warning: A Server must be created before calling `serverBooted` function.\n");
-        Py_RETURN_FALSE;
+        PySys_WriteStdout("Warning: A Server must be created before calling `serverBooted` function.\n");
+        Py_INCREF(Py_False);
+        return Py_False;
     }
 }
 
 static PyMethodDef pyo_functions[] = {
+{"pa_get_version", (PyCFunction)portaudio_get_version, METH_NOARGS, portaudio_get_version_info},
+{"pa_get_version_text", (PyCFunction)portaudio_get_version_text, METH_NOARGS, portaudio_get_version_text_info},
 {"pa_count_devices", (PyCFunction)portaudio_count_devices, METH_NOARGS, portaudio_count_devices_info},
 {"pa_count_host_apis", (PyCFunction)portaudio_count_host_apis, METH_NOARGS, portaudio_count_host_apis_info},
 {"pa_list_devices", (PyCFunction)portaudio_list_devices, METH_NOARGS, portaudio_list_devices_info},
@@ -2095,24 +1710,47 @@ static PyMethodDef pyo_functions[] = {
 {"pm_get_default_input", (PyCFunction)portmidi_get_default_input, METH_NOARGS, portmidi_get_default_input_info},
 {"pm_get_output_devices", (PyCFunction)portmidi_get_output_devices, METH_NOARGS, portmidi_get_output_devices_info},
 {"pm_get_default_output", (PyCFunction)portmidi_get_default_output, METH_NOARGS, portmidi_get_default_output_info},
-{"sndinfo", (PyCFunction)sndinfo, METH_VARARGS|METH_KEYWORDS, sndinfo_info},
-{"savefile", (PyCFunction)savefile, METH_VARARGS|METH_KEYWORDS, savefile_info},
-{"savefileFromTable", (PyCFunction)savefileFromTable, METH_VARARGS|METH_KEYWORDS, savefileFromTable_info},
-{"upsamp", (PyCFunction)upsamp, METH_VARARGS|METH_KEYWORDS, upsamp_info},
-{"downsamp", (PyCFunction)downsamp, METH_VARARGS|METH_KEYWORDS, downsamp_info},
+{"p_sndinfo", (PyCFunction)p_sndinfo, METH_VARARGS|METH_KEYWORDS, ""},
+{"p_savefile", (PyCFunction)p_savefile, METH_VARARGS|METH_KEYWORDS, ""},
+{"p_savefileFromTable", (PyCFunction)p_savefileFromTable, METH_VARARGS|METH_KEYWORDS, ""},
+{"p_upsamp", (PyCFunction)p_upsamp, METH_VARARGS|METH_KEYWORDS, ""},
+{"p_downsamp", (PyCFunction)p_downsamp, METH_VARARGS|METH_KEYWORDS, ""},
 {"reducePoints", (PyCFunction)reducePoints, METH_VARARGS|METH_KEYWORDS, reducePoints_info},
 {"distanceToSegment", (PyCFunction)distanceToSegment, METH_VARARGS|METH_KEYWORDS, distanceToSegment_info},
 {"rescale", (PyCFunction)rescale, METH_VARARGS|METH_KEYWORDS, rescale_info},
+{"floatmap", (PyCFunction)floatmap, METH_VARARGS|METH_KEYWORDS, floatmap_info},
 {"linToCosCurve", (PyCFunction)linToCosCurve, METH_VARARGS|METH_KEYWORDS, linToCosCurve_info},
 {"midiToHz", (PyCFunction)midiToHz, METH_O, midiToHz_info},
+{"hzToMidi", (PyCFunction)hzToMidi, METH_O, hzToMidi_info},
 {"midiToTranspo", (PyCFunction)midiToTranspo, METH_O, midiToTranspo_info},
 {"sampsToSec", (PyCFunction)sampsToSec, METH_O, sampsToSec_info},
 {"secToSamps", (PyCFunction)secToSamps, METH_O, secToSamps_info},
 {"serverCreated", (PyCFunction)serverCreated, METH_NOARGS, serverCreated_info},
 {"serverBooted", (PyCFunction)serverBooted, METH_NOARGS, serverBooted_info},
+{"withPortaudio", (PyCFunction)with_portaudio, METH_NOARGS, "Returns True if pyo is built with portaudio support."},
+{"withPortmidi", (PyCFunction)with_portmidi, METH_NOARGS, "Returns True if pyo is built with portmidi support."},
+{"withJack", (PyCFunction)with_jack, METH_NOARGS, "Returns True if pyo is built with jack support."},
+{"withCoreaudio", (PyCFunction)with_coreaudio, METH_NOARGS, "Returns True if pyo is built with coreaudio support."},
+{"withOSC", (PyCFunction)with_osc, METH_NOARGS, "Returns True if pyo is built with OSC (Open Sound Control) support."},
 {NULL, NULL, 0, NULL},
 };
 
+#if PY_MAJOR_VERSION >= 3
+// TODO: Pyo likely has a bunch of state stored in global variables right now, they should ideally be stored
+// in an interpreter specific struct as described in https://docs.python.org/3/howto/cporting.html
+static struct PyModuleDef pyo_moduledef = {
+    PyModuleDef_HEAD_INIT,
+    LIB_BASE_NAME,/* m_name */
+    "Python digital signal processing module.",/* m_doc */
+    0,/* m_size */
+    pyo_functions,/* m_methods */
+    NULL,/* m_reload */
+    NULL,/* m_traverse */
+    NULL,/* m_clear */
+    NULL,/* m_free */
+};
+#endif
+
 static PyObject *
 module_add_object(PyObject *module, const char *name, PyTypeObject *type) {
     if (PyType_Ready(type) < 0)
@@ -2123,25 +1761,52 @@ module_add_object(PyObject *module, const char *name, PyTypeObject *type) {
 }
 
 PyMODINIT_FUNC
+#if PY_MAJOR_VERSION >= 3
+#ifndef USE_DOUBLE
+PyInit__pyo(void)
+#else
+PyInit__pyo64(void)
+#endif
+#else
 #ifndef USE_DOUBLE
 init_pyo(void)
 #else
 init_pyo64(void)
 #endif
+#endif
+
 {
     PyObject *m;
-    
+
+#if PY_MAJOR_VERSION >= 3
+    m = PyModule_Create(&pyo_moduledef);
+#else
     m = Py_InitModule3(LIB_BASE_NAME, pyo_functions, "Python digital signal processing module.");
+#endif
 
 #ifndef NO_MESSAGES
 #ifndef USE_DOUBLE
-    printf("pyo version %s (uses single precision)\n", PYO_VERSION);
+    PySys_WriteStdout("pyo version %s (uses single precision)\n", PYO_VERSION);
 #else
-    printf("pyo version %s (uses double precision)\n", PYO_VERSION);
+    PySys_WriteStdout("pyo version %s (uses double precision)\n", PYO_VERSION);
 #endif
 #endif
 
     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);
+    module_add_object(m, "OscSend_base", &OscSendType);
+    module_add_object(m, "OscDataSend_base", &OscDataSendType);
+    module_add_object(m, "OscReceive_base", &OscReceiveType);
+    module_add_object(m, "OscReceiver_base", &OscReceiverType);
+    module_add_object(m, "OscListReceive_base", &OscListReceiveType);
+    module_add_object(m, "OscListReceiver_base", &OscListReceiverType);
+    module_add_object(m, "OscDataReceive_base", &OscDataReceiveType);
+#endif
     module_add_object(m, "Stream", &StreamType);
     module_add_object(m, "TriggerStream", &TriggerStreamType);
     module_add_object(m, "PVStream", &PVStreamType);
@@ -2183,6 +1848,7 @@ init_pyo64(void)
     module_add_object(m, "TableMorph_base", &TableMorphType);
     module_add_object(m, "TrigTableRec_base", &TrigTableRecType);
     module_add_object(m, "TrigTableRecTimeStream_base", &TrigTableRecTimeStreamType);
+    module_add_object(m, "TableWrite_base", &TableWriteType);
     module_add_object(m, "TablePut_base", &TablePutType);
     module_add_object(m, "NewMatrix_base", &NewMatrixType);
     module_add_object(m, "MatrixPointer_base", &MatrixPointerType);
@@ -2227,6 +1893,7 @@ init_pyo64(void)
     module_add_object(m, "TableRead_base", &TableReadType);
     module_add_object(m, "Pulsar_base", &PulsarType);
     module_add_object(m, "Sine_base", &SineType);
+    module_add_object(m, "FastSine_base", &FastSineType);
     module_add_object(m, "SineLoop_base", &SineLoopType);
     module_add_object(m, "Fm_base", &FmType);
     module_add_object(m, "CrossFm_base", &CrossFmType);
@@ -2236,6 +1903,8 @@ init_pyo64(void)
     module_add_object(m, "RosslerAlt_base", &RosslerAltType);
     module_add_object(m, "Lorenz_base", &LorenzType);
     module_add_object(m, "LorenzAlt_base", &LorenzAltType);
+    module_add_object(m, "ChenLee_base", &ChenLeeType);
+    module_add_object(m, "ChenLeeAlt_base", &ChenLeeAltType);
     module_add_object(m, "Phasor_base", &PhasorType);
     module_add_object(m, "SuperSaw_base", &SuperSawType);
     module_add_object(m, "Pointer_base", &PointerType);
@@ -2275,18 +1944,12 @@ init_pyo64(void)
     module_add_object(m, "CtlScan2_base", &CtlScan2Type);
     module_add_object(m, "MidiNote_base", &MidiNoteType);
     module_add_object(m, "Notein_base", &NoteinType);
+    module_add_object(m, "NoteinTrig_base", &NoteinTrigType);
     module_add_object(m, "Bendin_base", &BendinType);
     module_add_object(m, "Touchin_base", &TouchinType);
     module_add_object(m, "Programin_base", &PrograminType);
     module_add_object(m, "MidiAdsr_base", &MidiAdsrType);
     module_add_object(m, "MidiDelAdsr_base", &MidiDelAdsrType);
-    module_add_object(m, "OscSend_base", &OscSendType);
-    module_add_object(m, "OscDataSend_base", &OscDataSendType);
-    module_add_object(m, "OscReceive_base", &OscReceiveType);
-    module_add_object(m, "OscReceiver_base", &OscReceiverType);
-    module_add_object(m, "OscListReceive_base", &OscListReceiveType);
-    module_add_object(m, "OscListReceiver_base", &OscListReceiverType);
-    module_add_object(m, "OscDataReceive_base", &OscDataReceiveType);
     module_add_object(m, "TrigRand_base", &TrigRandType);
     module_add_object(m, "TrigRandInt_base", &TrigRandIntType);
     module_add_object(m, "TrigVal_base", &TrigValType);
@@ -2337,6 +2000,7 @@ init_pyo64(void)
     module_add_object(m, "IRFM_base", &IRFMType);
     module_add_object(m, "Granulator_base", &GranulatorType);
     module_add_object(m, "Looper_base", &LooperType);
+    module_add_object(m, "LooperTimeStream_base", &LooperTimeStreamType);
     module_add_object(m, "Harmonizer_base", &HarmonizerType);
     module_add_object(m, "Print_base", &PrintType);
     module_add_object(m, "M_Sin_base", &M_SinType);
@@ -2352,6 +2016,8 @@ init_pyo64(void)
     module_add_object(m, "M_Floor_base", &M_FloorType);
     module_add_object(m, "M_Ceil_base", &M_CeilType);
     module_add_object(m, "M_Round_base", &M_RoundType);
+    module_add_object(m, "M_Tanh_base", &M_TanhType);
+    module_add_object(m, "M_Exp_base", &M_ExpType);
     module_add_object(m, "Snap_base", &SnapType);
     module_add_object(m, "Interp_base", &InterpType);
     module_add_object(m, "SampHold_base", &SampHoldType);
@@ -2361,6 +2027,7 @@ init_pyo64(void)
     module_add_object(m, "CentsToTranspo_base", &CentsToTranspoType);
     module_add_object(m, "TranspoToCents_base", &TranspoToCentsType);
     module_add_object(m, "MToF_base", &MToFType);
+    module_add_object(m, "FToM_base", &FToMType);
     module_add_object(m, "MToT_base", &MToTType);
     module_add_object(m, "FFTMain_base", &FFTMainType);
     module_add_object(m, "FFT_base", &FFTType);
@@ -2388,6 +2055,7 @@ init_pyo64(void)
     module_add_object(m, "ButHP_base", &ButHPType);
     module_add_object(m, "ButBP_base", &ButBPType);
     module_add_object(m, "ButBR_base", &ButBRType);
+    module_add_object(m, "MoogLP_base", &MoogLPType);
     module_add_object(m, "PVAnal_base", &PVAnalType);
     module_add_object(m, "PVSynth_base", &PVSynthType);
     module_add_object(m, "PVTranspose_base", &PVTransposeType);
@@ -2408,6 +2076,35 @@ init_pyo64(void)
     module_add_object(m, "PVMix_base", &PVMixType);
     module_add_object(m, "Granule_base", &GranuleType);
     module_add_object(m, "TableScale_base", &TableScaleType);
+    module_add_object(m, "TrackHold_base", &TrackHoldType);
+    module_add_object(m, "ComplexRes_base", &ComplexResType);
+    module_add_object(m, "STReverb_base", &STReverbType);
+    module_add_object(m, "STRev_base", &STRevType);
+    module_add_object(m, "Pointer2_base", &Pointer2Type);
+    module_add_object(m, "Centroid_base", &CentroidType);
+    module_add_object(m, "AttackDetector_base", &AttackDetectorType);
+    module_add_object(m, "SmoothDelay_base", &SmoothDelayType);
+    module_add_object(m, "TrigBurster_base", &TrigBursterType);
+    module_add_object(m, "TrigBurst_base", &TrigBurstType);
+    module_add_object(m, "TrigBurstTapStream_base", &TrigBurstTapStreamType);
+    module_add_object(m, "TrigBurstAmpStream_base", &TrigBurstAmpStreamType);
+    module_add_object(m, "TrigBurstDurStream_base", &TrigBurstDurStreamType);
+    module_add_object(m, "TrigBurstEndStream_base", &TrigBurstEndStreamType);
+    module_add_object(m, "Scope_base", &ScopeType);
+    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
@@ -2421,4 +2118,8 @@ init_pyo64(void)
 #else
     PyModule_AddIntConstant(m, "USE_DOUBLE", 1);
 #endif
+
+#if PY_MAJOR_VERSION >= 3
+    return m;
+#endif
 }
diff --git a/src/engine/servermodule.c b/src/engine/servermodule.c
index 9148323..0f9f68c 100644
--- a/src/engine/servermodule.c
+++ b/src/engine/servermodule.c
@@ -1,25 +1,21 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
- *                                                                        *
- * Octobre 2013 : Multiple servers facility and embeded backend added by  *
- * Guillaume Barrette. See embeded possibilities at:                      *
- * https://github.com/guibarrette/PyoPlug                                 *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
@@ -30,43 +26,94 @@
 #include <stdlib.h>
 #include <pthread.h>
 
+#include "py2to3.h"
 #include "structmember.h"
-#include "portaudio.h"
-#include "portmidi.h"
-#include "porttime.h"
 #include "sndfile.h"
 #include "streammodule.h"
 #include "pyomodule.h"
 #include "servermodule.h"
 
+#ifdef USE_PORTAUDIO
+#include "ad_portaudio.h"
+#else
+int Server_pa_init(Server *self) { return -10; };
+int Server_pa_deinit(Server *self) { return 0; };
+int Server_pa_start(Server *self) { return 0; };
+int Server_pa_stop(Server *self) { return 0; };
+#endif
+
+#ifdef USE_JACK
+#include "ad_jack.h"
+#else
+int Server_jack_init(Server *self) { return -10; };
+int Server_jack_deinit(Server *self) { return 0; };
+int Server_jack_start(Server *self) { return 0; };
+int Server_jack_stop(Server *self) { return 0; };
+int jack_input_port_set_names(Server *self) { return 0; };
+int jack_output_port_set_names(Server *self) { return 0; };
+
+#endif
+
+#ifdef USE_COREAUDIO
+#include "ad_coreaudio.h"
+#else
+int Server_coreaudio_init(Server *self) { return -10; };
+int Server_coreaudio_deinit(Server *self) { return 0; };
+int Server_coreaudio_start(Server *self) { return 0; };
+int Server_coreaudio_stop(Server *self) { return 0; };
+#endif
+
+#ifdef USE_PORTMIDI
+#include "md_portmidi.h"
+#else
+void portmidiGetEvents(Server *self) {};
+int Server_pm_init(Server *self) { return -10; };
+int Server_pm_deinit(Server *self) { return 0; };
+void pm_noteout(Server *self, int pit, int vel, int chan, long timestamp) {};
+void pm_afterout(Server *self, int pit, int vel, int chan, long timestamp) {};
+void pm_ctlout(Server *self, int ctlnum, int value, int chan, long timestamp) {};
+void pm_programout(Server *self, int value, int chan, long timestamp) {};
+void pm_pressout(Server *self, int value, int chan, long timestamp) {};
+void pm_bendout(Server *self, int value, int chan, long timestamp) {};
+void pm_sysexout(Server *self, unsigned char *msg, long timestamp) {};
+long pm_get_current_time() { return 0; };
+#endif
+
+/** Array of Server objects. **/
+/******************************/
 
 #define MAX_NBR_SERVER 256
 
 static Server *my_server[MAX_NBR_SERVER];
 static int serverID = 0;
 
-static PyObject *Server_shut_down(Server *self);
-static PyObject *Server_stop(Server *self);
-static void Server_process_gui(Server *server);
-static void Server_process_time(Server *server);
-static inline void Server_process_buffers(Server *server);
-static int Server_start_rec_internal(Server *self, char *filename);
+/* Function called by any new pyo object to get a pointer to the current server. */
+PyObject * PyServer_get_server() { return (PyObject *)my_server[serverID]; };
 
-/* random objects count and multiplier to assign different seed to each instance. */
-#define num_rnd_objs 27
+/** Random generator and object seeds. **/
+/****************************************/
 
-int rnd_objs_count[num_rnd_objs] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+#define num_rnd_objs 29
+
+int rnd_objs_count[num_rnd_objs] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
 int rnd_objs_mult[num_rnd_objs] = {1993,1997,1999,2003,2011,2017,2027,2029,2039,2053,2063,2069,
-                         2081,2083,2087,2089,2099,2111,2113,2129,2131,2137,2141,2143,2153, 2161,2179};
+                                   2081,2083,2087,2089,2099,2111,2113,2129,2131,2137,2141,2143,
+                                   2153,2161,2179,2203,2207};
 
-#ifdef USE_COREAUDIO
-static int coreaudio_stop_callback(Server *self);
-#endif
+/* Linear congruential pseudo-random generator. */
+static unsigned int PYO_RAND_SEED = 1u;
+unsigned int pyorand() {
+    PYO_RAND_SEED = (PYO_RAND_SEED * 1664525 + 1013904223) % PYO_RAND_MAX;
+    return PYO_RAND_SEED;
+}
+
+/** Logging levels. **/
+/*********************/
 
+/* Errors should indicate failure to execute a request. */
 void
 Server_error(Server *self, char * format, ...)
 {
-    // Errors should indicate failure to execute a request
     if (self->verbosity & 1) {
         char buffer[256];
         va_list args;
@@ -74,14 +121,15 @@ Server_error(Server *self, char * format, ...)
         vsprintf (buffer,format, args);
         va_end (args);
 
-        printf("%s",buffer);
+        PySys_WriteStdout("%s",buffer);
     }
 }
 
+/* Messages should print useful or relevant information, or 
+   information requested by the user. */
 void
 Server_message(Server *self, char * format, ...)
 {
-    // Messages should print useful or relevant information, or information requested by the user
     if (self->verbosity & 2) {
         char buffer[256];
         va_list args;
@@ -89,14 +137,15 @@ Server_message(Server *self, char * format, ...)
         vsprintf (buffer,format, args);
         va_end (args);
 
-        printf("%s",buffer);
+        PySys_WriteStdout("%s",buffer);
     }
 }
 
+/* Warnings should be used when an unexpected or unusual 
+   choice was made by pyo. */
 void
 Server_warning(Server *self, char * format, ...)
 {
-    // Warnings should be used when an unexpected or unusual choice was made by pyo
 #ifndef NO_MESSAGES
     if (self->verbosity & 4) {
         char buffer[256];
@@ -104,15 +153,16 @@ Server_warning(Server *self, char * format, ...)
         va_start (args, format);
         vsprintf (buffer,format, args);
         va_end (args);
-        printf("%s",buffer);
+        PySys_WriteStdout("%s",buffer);
     }
 #endif
 }
 
+/* Debug messages should print internal information which 
+   might be necessary for debugging internal conditions. */
 void
 Server_debug(Server *self, char * format, ...)
-{    
-    // Debug messages should print internal information which might be necessary for debugging internal conditions.
+{
     if (self->verbosity & 8) {
         char buffer[256];
         va_list args;
@@ -120,1005 +170,32 @@ Server_debug(Server *self, char * format, ...)
         vsprintf (buffer,format, args);
         va_end (args);
 
-        printf("%s",buffer);
-    }
-}
-
-/* Portmidi get input events */
-static void portmidiGetEvents(Server *self) 
-{
-    PmError result;
-    PmEvent buffer;
-
-    do {
-        result = Pm_Poll(self->in);
-        if (result) {
-            if (Pm_Read(self->in, &buffer, 1) == pmBufferOverflow) 
-                continue;
-            self->midiEvents[self->midi_count++] = buffer;
-        }    
-    } while (result);
-}
-
-/* Portaudio stuff */
-static void portaudio_assert(PaError ecode, const char* cmdName) {
-    if (ecode != paNoError) {
-        const char* eText = Pa_GetErrorText(ecode);
-        if (!eText) {
-            eText = "???";
-        }
-        printf("portaudio error in %s: %s\n", cmdName, eText);
-        Pa_Terminate();
-    }
-}
-
-/* Portaudio callback function */
-static int 
-pa_callback_interleaved( const void *inputBuffer, void *outputBuffer,
-                            unsigned long framesPerBuffer,
-                            const PaStreamCallbackTimeInfo* timeInfo,
-                            PaStreamCallbackFlags statusFlags,
-                            void *arg )
-{
-    float *out = (float *)outputBuffer;
-    Server *server = (Server *) arg;
-
-    assert(framesPerBuffer == server->bufferSize);
-    int i, j, bufchnls, index1, index2;
-    
-    /* avoid unused variable warnings */
-    (void) timeInfo;
-    (void) statusFlags;
-
-    if (server->withPortMidi == 1) {
-        portmidiGetEvents(server);
-    }
-    
-    if (server->duplex == 1) {
-        float *in = (float *)inputBuffer;
-        bufchnls = server->nchnls + server->input_offset;
-        for (i=0; i<server->bufferSize; i++) {
-            index1 = i * server->nchnls;
-            index2 = i * bufchnls + server->input_offset;
-            for (j=0; j<server->nchnls; j++) {
-                server->input_buffer[index1+j] = (MYFLT)in[index2+j];
-            }
-        }
-    }
-
-    Server_process_buffers(server);
-    bufchnls = server->nchnls + server->output_offset;
-    for (i=0; i<server->bufferSize; i++) {
-        index1 = i * server->nchnls;
-        index2 = i * bufchnls + server->output_offset;
-        for (j=0; j<server->nchnls; j++) {
-            out[index2+j] = (float) server->output_buffer[index1+j];
-        }
-    }
-    server->midi_count = 0;
-    
-    if (server->server_started == 1) {
-        if (server->server_stopped == 1 && server->currentAmp < 0.0001)
-            server->server_started = 0;
-        return paContinue;
-    }    
-    else {
-        return paComplete;
-    }
-}
-
-static int 
-pa_callback_nonInterleaved( const void *inputBuffer, void *outputBuffer,
-                        unsigned long framesPerBuffer,
-                        const PaStreamCallbackTimeInfo* timeInfo,
-                        PaStreamCallbackFlags statusFlags,
-                        void *arg )
-{
-    float **out = (float **)outputBuffer;
-    Server *server = (Server *) arg;
-    
-    assert(framesPerBuffer == server->bufferSize);
-    int i, j;
-    
-    /* avoid unused variable warnings */
-    (void) timeInfo;
-    (void) statusFlags;
-    
-    if (server->withPortMidi == 1) {
-        portmidiGetEvents(server);
-    }
-
-    if (server->duplex == 1) {
-        float **in = (float **)inputBuffer;
-        for (i=0; i<server->bufferSize; i++) {
-            for (j=0; j<server->nchnls; j++) {
-                server->input_buffer[(i*server->nchnls)+j] = (MYFLT)in[j+server->input_offset][i];
-            }
-        }
-    }
-
-    Server_process_buffers(server);
-    for (i=0; i<server->bufferSize; i++) {
-        for (j=0; j<server->nchnls; j++) {
-            out[j+server->output_offset][i] = (float) server->output_buffer[(i*server->nchnls)+j];
-        }
-    }
-    server->midi_count = 0;
-    
-    if (server->server_started == 1) {
-        if (server->server_stopped == 1 && server->currentAmp < 0.0001)
-            server->server_started = 0;
-        return paContinue;
-    }    
-    else {
-        return paComplete;
-    }
-}
-
-#ifdef USE_JACK
-/* Jack callbacks */
-
-static 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->nchnls], *out_buffers[server->nchnls];
-
-    if (server->withPortMidi == 1) {
-        portmidiGetEvents(server);
-    }
-    PyoJackBackendData *be_data = (PyoJackBackendData *) server->audio_be_data;
-    for (i = 0; i < server->nchnls; i++) {
-        in_buffers[i] = jack_port_get_buffer (be_data->jack_in_ports[i+server->input_offset], server->bufferSize);
-    }
-    for (i = 0; i < server->nchnls; i++) {
-        out_buffers[i] = jack_port_get_buffer (be_data->jack_out_ports[i+server->output_offset], server->bufferSize);
-        
-    }
-    /* jack audio data is not interleaved */
-    if (server->duplex == 1) {
-        for (i=0; i<server->bufferSize; i++) {
-            for (j=0; j<server->nchnls; j++) {
-                server->input_buffer[(i*server->nchnls)+j] = (MYFLT) in_buffers[j][i];
-            }
-        }
-    }
-    Server_process_buffers(server);
-    for (i=0; i<server->bufferSize; i++) {
-        for (j=0; j<server->nchnls; j++) {
-            out_buffers[j][i] = (jack_default_audio_sample_t) server->output_buffer[(i*server->nchnls)+j];
-        }
+        PySys_WriteStdout("%s",buffer);
     }
-    server->midi_count = 0;
-    return 0;    
 }
 
-static int
-jack_srate_cb (jack_nframes_t nframes, void *arg)
-{
-    Server *s = (Server *) arg;
-    s->samplingRate = (double) nframes;
-    Server_debug(s, "The sample rate is now %lu/sec\n", (unsigned long) nframes);
-    return 0;
-}
-
-static int
-jack_bufsize_cb (jack_nframes_t nframes, void *arg)
-{
-    Server *s = (Server *) arg;
-    s->bufferSize = (int) nframes;
-    Server_debug(s, "The buffer size is now %lu/sec\n", (unsigned long) nframes);
-    return 0;
-}
-
-static void
-jack_error_cb (const char *desc)
-{
-    printf("JACK error: %s\n", desc);
-}
-
-static void
-jack_shutdown_cb (void *arg)
-{
-    Server *s = (Server *) arg;
-    Server_shut_down(s);
-    Server_warning(s, "JACK server shutdown. Pyo Server shut down.\n");
-}
-
-#endif
-
-#ifdef USE_COREAUDIO
-/* Coreaudio callbacks */
-
-OSStatus coreaudio_input_callback(AudioDeviceID device, const AudioTimeStamp* inNow,
-                                   const AudioBufferList* inInputData,
-                                   const AudioTimeStamp* inInputTime,
-                                   AudioBufferList* outOutputData,
-                                   const AudioTimeStamp* inOutputTime,
-                                   void* defptr)
-{
-    int i, j, bufchnls, servchnls, off1chnls, off2chnls;
-    Server *server = (Server *) defptr;
-    (void) outOutputData;
-    const AudioBuffer* inputBuf = inInputData->mBuffers;
-    float *bufdata = (float*)inputBuf->mData;
-    bufchnls = inputBuf->mNumberChannels;
-    servchnls = server->nchnls < bufchnls ? server->nchnls : bufchnls;
-    for (i=0; i<server->bufferSize; i++) {
-        off1chnls = i*bufchnls+server->input_offset;
-        off2chnls = i*servchnls;
-        for (j=0; j<servchnls; j++) {
-            server->input_buffer[off2chnls+j] = (MYFLT)bufdata[off1chnls+j];
-        }
-    }    
-    return kAudioHardwareNoError;     
-} 
-
-OSStatus coreaudio_output_callback(AudioDeviceID device, const AudioTimeStamp* inNow,
-                                   const AudioBufferList* inInputData,
-                                   const AudioTimeStamp* inInputTime,
-                                   AudioBufferList* outOutputData,
-                                   const AudioTimeStamp* inOutputTime,
-                                   void* defptr)
-{
-    int i, j, bufchnls, servchnls, off1chnls, off2chnls;
-    Server *server = (Server *) defptr;
-
-    (void) inInputData;
-
-    if (server->withPortMidi == 1) {
-        portmidiGetEvents(server);
-    }
-    
-    Server_process_buffers(server);
-    AudioBuffer* outputBuf = outOutputData->mBuffers;
-    bufchnls = outputBuf->mNumberChannels;
-    servchnls = server->nchnls < bufchnls ? server->nchnls : bufchnls;
-    float *bufdata = (float*)outputBuf->mData;
-    for (i=0; i<server->bufferSize; i++) {
-        off1chnls = i*bufchnls+server->output_offset;
-        off2chnls = i*servchnls;
-        for(j=0; j<servchnls; j++) {
-            bufdata[off1chnls+j] = server->output_buffer[off2chnls+j];
-        }    
-    }
-    server->midi_count = 0;
-
-    if (server->server_started == 1) {
-        if (server->server_stopped == 1 && server->currentAmp < 0.0001)
-            coreaudio_stop_callback(server);
-    }        
-
-    return kAudioHardwareNoError;
-}    
-
-int
-coreaudio_stop_callback(Server *self) 
-{
-    OSStatus err = kAudioHardwareNoError;
-    
-    if (self->duplex == 1) {
-        err = AudioDeviceStop(self->input, coreaudio_input_callback);
-        if (err != kAudioHardwareNoError) {
-            Server_error(self, "Input AudioDeviceStop failed %d\n", (int)err);
-            return -1;
-        }        
-    }
-    
-    err = AudioDeviceStop(self->output, coreaudio_output_callback);
-    if (err != kAudioHardwareNoError) {
-        Server_error(self, "Output AudioDeviceStop failed %d\n", (int)err);
-        return -1;
-    }
-    self->server_started = 0;
-    return 0;
-}
-
-#endif
+/** Offline server. **/
+/*********************/
 
 static int
 offline_process_block(Server *arg)
-{    
+{
     Server *server = (Server *) arg;
     Server_process_buffers(server);
     return 0;
 }
 
-/* Server audio backend init functions */
-
-int
-Server_pa_init(Server *self)
-{
-    PaError err;
-    PaStreamParameters outputParameters;
-    PaStreamParameters inputParameters;
-    PaDeviceIndex n, inDevice, outDevice;
-    const PaDeviceInfo *deviceInfo;
-    PaHostApiIndex hostIndex;
-    const PaHostApiInfo *hostInfo;
-    PaHostApiTypeId hostId;
-    PaSampleFormat sampleFormat;
-    PaStreamCallback *streamCallback;
-
-    err = Pa_Initialize();
-    portaudio_assert(err, "Pa_Initialize");
-
-    n = Pa_GetDeviceCount();
-    if (n < 0) {
-        portaudio_assert(n, "Pa_GetDeviceCount");
-    }
-
-    PyoPaBackendData *be_data = (PyoPaBackendData *) malloc(sizeof(PyoPaBackendData *));
-    self->audio_be_data = (void *) be_data;
-
-    if (self->output == -1)
-        outDevice = Pa_GetDefaultOutputDevice(); /* default output device */
-    else
-        outDevice = (PaDeviceIndex) self->output; /* selected output device */ 
-    if (self->input == -1)
-        inDevice = Pa_GetDefaultInputDevice(); /* default input device */
-    else
-        inDevice = (PaDeviceIndex) self->input; /* selected input device */
-
-    /* Retrieve host api id and define sample and callback format*/
-    deviceInfo = Pa_GetDeviceInfo(outDevice);
-    hostIndex = deviceInfo->hostApi;
-    hostInfo = Pa_GetHostApiInfo(hostIndex);
-    hostId = hostInfo->type;
-    if (hostId == paASIO) {
-        Server_debug(self, "Portaudio uses non-interleaved callback.\n");
-        sampleFormat = paFloat32 | paNonInterleaved;
-        streamCallback = pa_callback_nonInterleaved;
-    }
-    else if (hostId == paALSA) {
-        Server_debug(self, "Portaudio uses interleaved callback.\n");
-        Server_debug(self, "Using ALSA, if no input/output devices are specified, force to devices 0.\n");
-        if (self->input == -1 && self->output == -1) {
-            self->input = self->output = 0;
-            inDevice = outDevice = (PaDeviceIndex) 0;
-        }
-        sampleFormat = paFloat32;
-        streamCallback = pa_callback_interleaved;
-    }
-     else {
-        Server_debug(self, "Portaudio uses interleaved callback.\n");
-        sampleFormat = paFloat32;
-        streamCallback = pa_callback_interleaved;
-    }
-    
-
-    /* setup output and input streams */
-    memset(&outputParameters, 0, sizeof(outputParameters));
-    outputParameters.device = outDevice;
-    outputParameters.channelCount = self->nchnls + self->output_offset;
-    outputParameters.sampleFormat = sampleFormat;
-    outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultHighOutputLatency;
-    outputParameters.hostApiSpecificStreamInfo = NULL;
-
-    if (self->duplex == 1) {
-        memset(&inputParameters, 0, sizeof(inputParameters));
-        inputParameters.device = inDevice;
-        inputParameters.channelCount = self->nchnls + self->input_offset;
-        inputParameters.sampleFormat = sampleFormat;
-        inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultHighInputLatency ;
-        inputParameters.hostApiSpecificStreamInfo = NULL;
-    }
-
-    if (self->input == -1 && self->output == -1) {
-        if (self->duplex == 1)
-            err = Pa_OpenDefaultStream(&be_data->stream, self->nchnls + self->input_offset, self->nchnls + self->output_offset, sampleFormat, self->samplingRate, self->bufferSize, streamCallback, (void *) self);
-        else
-            err = Pa_OpenDefaultStream(&be_data->stream, 0, self->nchnls + self->output_offset, sampleFormat, self->samplingRate, self->bufferSize, streamCallback, (void *) self);
-    }
-    else {
-        if (self->duplex == 1)
-            err = Pa_OpenStream(&be_data->stream, &inputParameters, &outputParameters, self->samplingRate, self->bufferSize, paNoFlag, streamCallback,  (void *) self);
-        else
-            err = Pa_OpenStream(&be_data->stream, (PaStreamParameters *) NULL, &outputParameters, self->samplingRate, self->bufferSize, paNoFlag, streamCallback,  (void *) self);
-    }        
-    portaudio_assert(err, "Pa_OpenStream");
-    if (err < 0) {
-        Server_error(self, "Portaudio error: %s", Pa_GetErrorText(err));
-        return -1;
-    }
-    return 0;
-}
-
-int
-Server_pa_deinit(Server *self)
-{
-    PaError err;
-    PyoPaBackendData *be_data = (PyoPaBackendData *) self->audio_be_data;
-
-    if (Pa_IsStreamActive(be_data->stream) || ! Pa_IsStreamStopped(be_data->stream)) {
-        self->server_started = 0;
-        err = Pa_StopStream(be_data->stream);
-        portaudio_assert(err, "Pa_StopStream");
-    }
-    
-    err = Pa_CloseStream(be_data->stream);
-    portaudio_assert(err, "Pa_CloseStream");
-    
-    err = Pa_Terminate();
-    portaudio_assert(err, "Pa_Terminate");
-    
-    free(self->audio_be_data);
-    return err;
-}
-
-int 
-Server_pa_start(Server *self)
-{
-    PaError err;
-    PyoPaBackendData *be_data = (PyoPaBackendData *) self->audio_be_data;
-
-    if (Pa_IsStreamActive(be_data->stream) || ! Pa_IsStreamStopped(be_data->stream)) {
-        err = Pa_StopStream(be_data->stream);
-        portaudio_assert(err, "Pa_StopStream");
-    }
-    err = Pa_StartStream(be_data->stream);
-    portaudio_assert(err, "Pa_StartStream");
-    return err;
-}
-
-int 
-Server_pa_stop(Server *self)
-{
-    self->timeStep = (int)(0.1 * self->samplingRate);
-    self->amp = 0.;
-    self->server_stopped = 1;
-    return 0;
-}
-
-#ifdef USE_JACK
-
-int
-Server_jack_autoconnect (Server *self)
-{
-    const char **ports;
-    int i, ret = 0;
-    PyoJackBackendData *be_data = (PyoJackBackendData *) self->audio_be_data;
-    
-    if (self->jackautoin) {
-        if ((ports = jack_get_ports (be_data->jack_client, NULL, NULL, JackPortIsOutput)) == NULL) {
-            Server_error(self, "Jack: Cannot find any physical capture ports\n");
-            ret = -1;
-        }
-
-        i=0;
-        while(ports[i]!=NULL && be_data->jack_in_ports[i] != NULL){
-            if (jack_connect (be_data->jack_client, ports[i], jack_port_name(be_data->jack_in_ports[i]))) {
-                Server_error(self, "Jack: cannot connect input ports\n");
-                ret = -1;
-            }
-            i++;
-        }
-        free (ports);
-    }
-    
-    if (self->jackautoout) {
-        if ((ports = jack_get_ports (be_data->jack_client, NULL, NULL, JackPortIsInput)) == NULL) {
-            Server_error(self, "Jack: Cannot find any physical playback ports\n");
-            ret = -1;
-        }
-        
-        i=0;
-        while(ports[i]!=NULL && be_data->jack_out_ports[i] != NULL){
-            if (jack_connect (be_data->jack_client, jack_port_name (be_data->jack_out_ports[i]), ports[i])) {
-                Server_error(self, "Jack: cannot connect output ports\n");
-                ret = -1;
-            }
-            i++;
-        }
-        free (ports);
-    }
-    return ret;
-}
-
-int
-Server_jack_init (Server *self)
-{   
-    char client_name[32];
-    char name[16];
-    const char *server_name = "server";
-    jack_options_t options = JackNullOption;
-    jack_status_t status;
-    int sampleRate = 0;
-    int bufferSize = 0;
-    int nchnls = 0;
-    int total_nchnls = 0;
-    int index = 0;
-    int ret = 0;
-    assert(self->audio_be_data == NULL);
-    PyoJackBackendData *be_data = (PyoJackBackendData *) malloc(sizeof(PyoJackBackendData *));
-    self->audio_be_data = (void *) be_data;
-    be_data->jack_in_ports = (jack_port_t **) calloc(self->nchnls + self->input_offset, sizeof(jack_port_t *));
-    be_data->jack_out_ports = (jack_port_t **) calloc(self->nchnls + self->output_offset, sizeof(jack_port_t *));
-    strncpy(client_name,self->serverName, 32);
-    be_data->jack_client = jack_client_open (client_name, options, &status, server_name);
-    if (be_data->jack_client == NULL) {
-        Server_error(self, "Jack error: Unable to create JACK client\n");
-        if (status & JackServerFailed) {
-            Server_debug(self, "Jack error: jack_client_open() failed, "
-            "status = 0x%2.0x\n", status);
-        }
-        return -1;
-    }
-    if (status & JackServerStarted) {
-        Server_warning(self, "JACK server started.\n");
-    }
-    if (strcmp(self->serverName, jack_get_client_name(be_data->jack_client)) ) {
-        strcpy(self->serverName, jack_get_client_name(be_data->jack_client));
-        Server_warning(self, "Jack name `%s' assigned\n", self->serverName);
-    }
-    
-    sampleRate = jack_get_sample_rate (be_data->jack_client);
-    if (sampleRate != self->samplingRate) {
-        self->samplingRate = (double)sampleRate;
-        Server_warning(self, "Sample rate set to Jack engine sample rate: %" PRIu32 "\n", sampleRate);
-    }
-    else {
-        Server_debug(self, "Jack engine sample rate: %" PRIu32 "\n", sampleRate);
-    }
-    if (sampleRate <= 0) {
-        Server_error(self, "Invalid Jack engine sample rate.");
-        jack_client_close (be_data->jack_client);
-        return -1;
-    }
-    bufferSize = jack_get_buffer_size(be_data->jack_client);
-    if (bufferSize != self->bufferSize) {
-        self->bufferSize = bufferSize;
-        Server_warning(self, "Buffer size set to Jack engine buffer size: %" PRIu32 "\n", bufferSize);
-    }
-    else {
-        Server_debug(self, "Jack engine buffer size: %" PRIu32 "\n", bufferSize);
-    }
-
-    nchnls = total_nchnls = self->nchnls + self->input_offset;
-    while (nchnls-- > 0) {
-        index = total_nchnls - nchnls - 1;
-        ret = sprintf(name, "input_%i", index + 1);
-        if (ret > 0) {
-            be_data->jack_in_ports[index]
-            = jack_port_register (be_data->jack_client, name, 
-                                  JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
-        }
+int Server_offline_init(Server *self) { return 0; };
+int Server_offline_deinit(Server *self) { return 0; };
 
-        if ((be_data->jack_in_ports[index] == NULL)) {
-            Server_error(self, "Jack: no more JACK input ports available\n");
-            return -1;
-        }
-    }
-
-    nchnls = total_nchnls = self->nchnls + self->output_offset;
-    while (nchnls-- > 0) {
-        index = total_nchnls - nchnls - 1;
-        ret = sprintf(name, "output_%i", index + 1);
-        if (ret > 0) {
-            be_data->jack_out_ports[index] 
-            = jack_port_register (be_data->jack_client, name, 
-                                  JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
-        }
-        if ((be_data->jack_out_ports[index] == NULL)) {
-            Server_error(self, "Jack: no more JACK output ports available\n");
-            return -1;
-        }
-    }
-    jack_set_error_function (jack_error_cb);
-    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);
-    return 0;
-}
-
-int 
-Server_jack_deinit (Server *self)
-{
-    int ret = 0;
-    PyoJackBackendData *be_data = (PyoJackBackendData *) self->audio_be_data;
-    ret = jack_client_close(be_data->jack_client);
-    free(be_data->jack_in_ports);
-    free(be_data->jack_out_ports);
-    free(self->audio_be_data);
-    return ret;
-}
-
-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;
-    }
-    //if (self->jackauto)
-    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);
-    self->server_started = 0;
-    return ret;
-}
-
-#endif
-
-#ifdef USE_COREAUDIO
-int
-Server_coreaudio_init(Server *self)
-{
-    OSStatus err = kAudioHardwareNoError;
-    UInt32 count, namelen, propertySize;
-    int i, numdevices;
-    char *name;
-    AudioDeviceID mOutputDevice = kAudioDeviceUnknown;
-    AudioDeviceID mInputDevice = kAudioDeviceUnknown;
-    Boolean writable;
-    AudioTimeStamp now;
-    
-    now.mFlags = kAudioTimeStampHostTimeValid;
-    now.mHostTime = AudioGetCurrentHostTime();
-
-    /************************************/
-    /* List Coreaudio available devices */
-    /************************************/    
-    err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &count, 0);
-    AudioDeviceID *devices = (AudioDeviceID*) malloc(count);    
-    err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &count, devices);
-    if (err != kAudioHardwareNoError) {
-        Server_error(self, "Get kAudioHardwarePropertyDevices error %s\n", (char*)&err);
-        free(devices);
-    }
-
-    numdevices = count / sizeof(AudioDeviceID);
-    Server_debug(self, "Coreaudio : Number of devices: %i\n", numdevices);
-
-    for (i=0; i<numdevices; ++i) {
-        err = AudioDeviceGetPropertyInfo(devices[i], 0, false, kAudioDevicePropertyDeviceName, &count, 0);
-        if (err != kAudioHardwareNoError) {
-            Server_error(self, "Info kAudioDevicePropertyDeviceName error %s A %d %08X\n", (char*)&err, i, devices[i]);
-            break;
-        }
-        
-        char *name = (char*)malloc(count);
-        err = AudioDeviceGetProperty(devices[i], 0, false, kAudioDevicePropertyDeviceName, &count, name);
-        if (err != kAudioHardwareNoError) {
-            Server_error(self, "Get kAudioDevicePropertyDeviceName error %s A %d %08X\n", (char*)&err, i, devices[i]);
-            free(name);
-            break;
-        }
-        Server_debug(self, "   %d : \"%s\"\n", i, name);
-        free(name);
-    }    
-    
-    /************************************/
-    /* Acquire input and output devices */
-    /************************************/    
-    /* Acquire input audio device */    
-    if (self->duplex == 1) {
-        if (self->input != -1)
-            mInputDevice = devices[self->input];
-        
-        if (mInputDevice==kAudioDeviceUnknown) {
-            count = sizeof(mInputDevice);
-            err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &count, (void *) &mInputDevice);
-            if (err != kAudioHardwareNoError) {
-                Server_error(self, "Get kAudioHardwarePropertyDefaultInputDevice error %s\n", (char*)&err);
-                return -1;
-            }
-        }     
-        
-        err = AudioDeviceGetPropertyInfo(mInputDevice, 0, false, kAudioDevicePropertyDeviceName, &namelen, 0);
-        if (err != kAudioHardwareNoError) {
-            Server_error(self, "Info kAudioDevicePropertyDeviceName error %s A %08X\n", (char*)&err, mInputDevice);
-        }    
-        name = (char*)malloc(namelen);
-        err = AudioDeviceGetProperty(mInputDevice, 0, false, kAudioDevicePropertyDeviceName, &namelen, name);
-        if (err != kAudioHardwareNoError) {
-            Server_error(self, "Get kAudioDevicePropertyDeviceName error %s A %08X\n", (char*)&err, mInputDevice);
-        }
-        Server_debug(self, "Coreaudio : Uses input device : \"%s\"\n", name);
-        self->input = mInputDevice;
-        free(name);
-    }    
-    
-    /* Acquire output audio device */    
-    if (self->output != -1)
-        mOutputDevice = devices[self->output];
-        
-    if (mOutputDevice==kAudioDeviceUnknown) {
-        count = sizeof(mOutputDevice);
-        err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &count, (void *) &mOutputDevice);
-        if (err != kAudioHardwareNoError) {
-            Server_error(self, "Get kAudioHardwarePropertyDefaultOutputDevice error %s\n", (char*)&err);
-            return -1;
-        }
-    }
-
-    err = AudioDeviceGetPropertyInfo(mOutputDevice, 0, false, kAudioDevicePropertyDeviceName, &namelen, 0);
-    if (err != kAudioHardwareNoError) {
-        Server_error(self, "Info kAudioDevicePropertyDeviceName error %s A %08X\n", (char*)&err, mOutputDevice);
-    }    
-    name = (char*)malloc(namelen);
-    err = AudioDeviceGetProperty(mOutputDevice, 0, false, kAudioDevicePropertyDeviceName, &namelen, name);
-    if (err != kAudioHardwareNoError) {
-        Server_error(self, "Get kAudioDevicePropertyDeviceName error %s A %08X\n", (char*)&err, mOutputDevice);
-    }
-    Server_debug(self, "Coreaudio : Uses output device : \"%s\"\n", name);
-    self->output = mOutputDevice;
-    free(name);
-    
-    /*************************************************/
-    /* Get in/out buffer frame and buffer frame size */
-    /*************************************************/
-    UInt32 bufferSize;
-    AudioValueRange range;
-    Float64 sampleRate;
-
-    /* Get input device buffer frame size and buffer frame size range */
-    if (self->duplex == 1) {
-        count = sizeof(UInt32);
-        err = AudioDeviceGetProperty(mInputDevice, 0, false, kAudioDevicePropertyBufferFrameSize, &count, &bufferSize);
-        if (err != kAudioHardwareNoError)
-            Server_error(self, "Get kAudioDevicePropertyBufferFrameSize error %s\n", (char*)&err);
-        Server_debug(self, "Coreaudio : Coreaudio input device buffer size = %ld\n", bufferSize);
-    
-        count = sizeof(AudioValueRange);
-        err = AudioDeviceGetProperty(mInputDevice, 0, false, kAudioDevicePropertyBufferSizeRange, &count, &range);
-        if (err != kAudioHardwareNoError)
-            Server_error(self, "Get kAudioDevicePropertyBufferSizeRange error %s\n", (char*)&err);
-        Server_debug(self, "Coreaudio : Coreaudio input device buffer size range = %f -> %f\n", range.mMinimum, range.mMaximum);
-    
-        /* Get input device sampling rate */
-        count = sizeof(Float64);
-        err = AudioDeviceGetProperty(mInputDevice, 0, false, kAudioDevicePropertyNominalSampleRate, &count, &sampleRate);
-        if (err != kAudioHardwareNoError)
-            Server_debug(self, "Get kAudioDevicePropertyNominalSampleRate error %s\n", (char*)&err);
-        Server_debug(self, "Coreaudio : Coreaudio input device sampling rate = %.2f\n", sampleRate);
-    }
-    
-    /* Get output device buffer frame size and buffer frame size range */
-    count = sizeof(UInt32);
-    err = AudioDeviceGetProperty(mOutputDevice, 0, false, kAudioDevicePropertyBufferFrameSize, &count, &bufferSize);
-    if (err != kAudioHardwareNoError)
-        Server_error(self, "Get kAudioDevicePropertyBufferFrameSize error %s\n", (char*)&err);
-    Server_debug(self, "Coreaudio : Coreaudio output device buffer size = %ld\n", bufferSize);
-
-    count = sizeof(AudioValueRange);
-    err = AudioDeviceGetProperty(mOutputDevice, 0, false, kAudioDevicePropertyBufferSizeRange, &count, &range);
-    if (err != kAudioHardwareNoError)
-        Server_error(self, "Get kAudioDevicePropertyBufferSizeRange error %s\n", (char*)&err);
-    Server_debug(self, "Coreaudio : Coreaudio output device buffer size range = %.2f -> %.2f\n", range.mMinimum, range.mMaximum);
-    
-    /* Get output device sampling rate */
-    count = sizeof(Float64);
-    err = AudioDeviceGetProperty(mOutputDevice, 0, false, kAudioDevicePropertyNominalSampleRate, &count, &sampleRate);
-    if (err != kAudioHardwareNoError)
-        Server_debug(self, "Get kAudioDevicePropertyNominalSampleRate error %s\n", (char*)&err);
-    Server_debug(self, "Coreaudio : Coreaudio output device sampling rate = %.2f\n", sampleRate);
-
-    
-    /****************************************/
-    /********* Set audio properties *********/
-    /****************************************/
-    /* set/get the buffersize for the devices */
-    count = sizeof(UInt32);
-    err = AudioDeviceSetProperty(mOutputDevice, &now, 0, false, kAudioDevicePropertyBufferFrameSize, count, &self->bufferSize);
-    if (err != kAudioHardwareNoError) {
-        Server_error(self, "set kAudioDevicePropertyBufferFrameSize error %4.4s\n", (char*)&err);
-        self->bufferSize = bufferSize;
-        err = AudioDeviceSetProperty(mOutputDevice, &now, 0, false, kAudioDevicePropertyBufferFrameSize, count, &self->bufferSize);
-        if (err != kAudioHardwareNoError)
-            Server_error(self, "set kAudioDevicePropertyBufferFrameSize error %4.4s\n", (char*)&err);
-        else
-            Server_debug(self, "pyo buffer size set to output device buffer size : %i\n", self->bufferSize);
-    } 
-    else
-        Server_debug(self, "Coreaudio : Changed output device buffer size successfully: %i\n", self->bufferSize);
-
-    if (self->duplex == 1) {
-        err = AudioDeviceSetProperty(mInputDevice, &now, 0, false, kAudioDevicePropertyBufferFrameSize, count, &self->bufferSize);
-        if (err != kAudioHardwareNoError) {
-            Server_error(self, "set kAudioDevicePropertyBufferFrameSize error %4.4s\n", (char*)&err);
-        }    
-    }    
-
-    /* set/get the sampling rate for the devices */
-    count = sizeof(double);
-    double pyoSamplingRate = self->samplingRate;
-    err = AudioDeviceSetProperty(mOutputDevice, &now, 0, false, kAudioDevicePropertyNominalSampleRate, count, &pyoSamplingRate);
-    if (err != kAudioHardwareNoError) {
-        Server_error(self, "set kAudioDevicePropertyNominalSampleRate error %s\n", (char*)&err);
-        self->samplingRate = (double)sampleRate;        
-        err = AudioDeviceSetProperty(mOutputDevice, &now, 0, false, kAudioDevicePropertyNominalSampleRate, count, &sampleRate);
-        if (err != kAudioHardwareNoError)
-            Server_error(self, "set kAudioDevicePropertyNominalSampleRate error %s\n", (char*)&err);
-        else    
-            Server_debug(self, "pyo sampling rate set to output device sampling rate : %i\n", self->samplingRate);
-    }
-    else
-        Server_debug(self, "Coreaudio : Changed output device sampling rate successfully: %.2f\n", self->samplingRate);
-    
-    if (self->duplex ==1) {
-        pyoSamplingRate = self->samplingRate;
-        err = AudioDeviceSetProperty(mInputDevice, &now, 0, false, kAudioDevicePropertyNominalSampleRate, count, &pyoSamplingRate);
-        if (err != kAudioHardwareNoError) {
-            Server_error(self, "set kAudioDevicePropertyNominalSampleRate error %s\n", (char*)&err);
-        }
-    }    
-
-
-    /****************************************/
-    /* Input and output stream descriptions */
-    /****************************************/
-    AudioStreamBasicDescription outputStreamDescription;
-    AudioStreamBasicDescription inputStreamDescription;
-
-    // Get input device stream configuration
-    if (self->duplex == 1) {
-        count = sizeof(AudioStreamBasicDescription);
-        err = AudioDeviceGetProperty(mInputDevice, 0, true, kAudioDevicePropertyStreamFormat, &count, &inputStreamDescription);
-        if (err != kAudioHardwareNoError)
-            Server_debug(self, "Get kAudioDevicePropertyStreamFormat error %s\n", (char*)&err);
-    
-        /*
-        inputStreamDescription.mSampleRate = (Float64)self->samplingRate;
-    
-        err = AudioDeviceSetProperty(mInputDevice, &now, 0, false, kAudioDevicePropertyStreamFormat, count, &inputStreamDescription);
-        if (err != kAudioHardwareNoError)
-            Server_debug(self, "-- Set kAudioDevicePropertyStreamFormat error %s\n", (char*)&err);
-    
-        // Print new input stream description
-        err = AudioDeviceGetProperty(mInputDevice, 0, true, kAudioDevicePropertyStreamFormat, &count, &inputStreamDescription);
-        if (err != kAudioHardwareNoError)
-            Server_debug(self, "Get kAudioDevicePropertyNominalSampleRate error %s\n", (char*)&err);
-        */
-        Server_debug(self, "Coreaudio : Coreaudio driver input stream sampling rate = %.2f\n", inputStreamDescription.mSampleRate);
-        Server_debug(self, "Coreaudio : Coreaudio driver input stream bytes per frame = %i\n", inputStreamDescription.mBytesPerFrame);
-        Server_debug(self, "Coreaudio : Coreaudio driver input stream number of channels = %i\n", inputStreamDescription.mChannelsPerFrame);
-    }
-    
-    /* Get output device stream configuration */
-    count = sizeof(AudioStreamBasicDescription);
-	err = AudioDeviceGetProperty(mOutputDevice, 0, false, kAudioDevicePropertyStreamFormat, &count, &outputStreamDescription);
-    if (err != kAudioHardwareNoError)
-        Server_debug(self, "Get kAudioDevicePropertyStreamFormat error %s\n", (char*)&err);
-
-    /*
-    outputStreamDescription.mSampleRate = (Float64)self->samplingRate;
-    
-	err = AudioDeviceSetProperty(mOutputDevice, &now, 0, false, kAudioDevicePropertyStreamFormat, count, &outputStreamDescription);
-    if (err != kAudioHardwareNoError)
-        Server_debug(self, "Set kAudioDevicePropertyStreamFormat error %s\n", (char*)&err);
-    
-    // Print new output stream description
-	err = AudioDeviceGetProperty(mOutputDevice, 0, false, kAudioDevicePropertyStreamFormat, &count, &outputStreamDescription);
-    if (err != kAudioHardwareNoError)
-        Server_debug(self, "Get kAudioDevicePropertyStreamFormat error %s\n", (char*)&err);
-    */
-    Server_debug(self, "Coreaudio : Coreaudio driver output stream sampling rate = %.2f\n", outputStreamDescription.mSampleRate);
-    Server_debug(self, "Coreaudio : Coreaudio driver output stream bytes per frame = %i\n", outputStreamDescription.mBytesPerFrame);
-    Server_debug(self, "Coreaudio : Coreaudio driver output stream number of channels = %i\n", outputStreamDescription.mChannelsPerFrame);
-
-
-    /**************************************************/
-    /********* Set input and output callbacks *********/
-    /**************************************************/
-    if (self->duplex == 1) {
-        err = AudioDeviceAddIOProc(self->input, coreaudio_input_callback, (void *) self);	// setup our device with an IO proc
-        if (err != kAudioHardwareNoError) {
-            Server_error(self, "Input AudioDeviceAddIOProc failed %d\n", (int)err);
-            return -1;
-        }        
-        err = AudioDeviceGetPropertyInfo(self->input, 0, true, kAudioDevicePropertyIOProcStreamUsage, &propertySize, &writable);
-        AudioHardwareIOProcStreamUsage *input_su = (AudioHardwareIOProcStreamUsage*)malloc(propertySize);
-        input_su->mIOProc = (void*)coreaudio_input_callback;
-        err = AudioDeviceGetProperty(self->input, 0, true, kAudioDevicePropertyIOProcStreamUsage, &propertySize, input_su);
-        for (i=0; i<inputStreamDescription.mChannelsPerFrame; ++i) {
-            input_su->mStreamIsOn[i] = 1;
-        }
-        err = AudioDeviceSetProperty(self->input, &now, 0, true, kAudioDevicePropertyIOProcStreamUsage, propertySize, input_su);
-    }
-    
-    err = AudioDeviceAddIOProc(self->output, coreaudio_output_callback, (void *) self);	// setup our device with an IO proc
-    if (err != kAudioHardwareNoError) {
-        Server_error(self, "Output AudioDeviceAddIOProc failed %d\n", (int)err);
-        return -1;
-    }
-    err = AudioDeviceGetPropertyInfo(self->output, 0, false, kAudioDevicePropertyIOProcStreamUsage, &propertySize, &writable);
-    AudioHardwareIOProcStreamUsage *output_su = (AudioHardwareIOProcStreamUsage*)malloc(propertySize);
-    output_su->mIOProc = (void*)coreaudio_output_callback;
-    err = AudioDeviceGetProperty(self->output, 0, false, kAudioDevicePropertyIOProcStreamUsage, &propertySize, output_su);
-    for (i=0; i<outputStreamDescription.mChannelsPerFrame; ++i) {
-        output_su->mStreamIsOn[i] = 1;
-    }
-    err = AudioDeviceSetProperty(self->output, &now, 0, false, kAudioDevicePropertyIOProcStreamUsage, propertySize, output_su);
-    
-    return 0;
-}
-
-int 
-Server_coreaudio_deinit(Server *self)
-{
-    OSStatus err = kAudioHardwareNoError;
-
-    if (self->duplex == 1) {
-        err = AudioDeviceRemoveIOProc(self->input, coreaudio_input_callback);
-        if (err != kAudioHardwareNoError) {
-            Server_error(self, "Input AudioDeviceRemoveIOProc failed %d\n", (int)err);
-            return -1;
-        }    
-    }
-    
-    err = AudioDeviceRemoveIOProc(self->output, coreaudio_output_callback);
-    if (err != kAudioHardwareNoError) {
-        Server_error(self, "Output AudioDeviceRemoveIOProc failed %d\n", (int)err);
-        return -1;
-    }
-    
-    return 0;
-}
-
-int 
-Server_coreaudio_start(Server *self)
-{
-    OSStatus err = kAudioHardwareNoError;
-
-    if (self->duplex == 1) {
-        err = AudioDeviceStart(self->input, coreaudio_input_callback);
-        if (err != kAudioHardwareNoError) {
-            Server_error(self, "Input AudioDeviceStart failed %d\n", (int)err);
-            return -1;
-        }        
-    }
-    
-    err = AudioDeviceStart(self->output, coreaudio_output_callback);
-    if (err != kAudioHardwareNoError) {
-        Server_error(self, "Output AudioDeviceStart failed %d\n", (int)err);
-        return -1;
-    }
-    return 0;
-} 
-
-int
-Server_coreaudio_stop(Server *self)
-{
-    self->timeStep = (int)(0.1 * self->samplingRate);
-    self->amp = 0.;
-    self->server_stopped = 1;
-    return 0;
-}
-
-#endif
-
-int
-Server_offline_init(Server *self)
-{
-    return 0;
-}
-
-int
-Server_offline_deinit(Server *self)
-{
-    return 0;
-}
-
-void 
+void
 *Server_offline_thread(void *arg)
 {
     int numBlocks;
     Server *self;
     self = (Server *)arg;
-    
+
+    PyGILState_STATE s = PyGILState_Ensure();
     if (self->recdur < 0) {
         Server_error(self,"Duration must be specified for Offline Server (see Server.recordOptions).");
     }
@@ -1128,13 +205,15 @@ void
         Server_debug(self,"Number of blocks: %i\n", numBlocks);
         Server_start_rec_internal(self, self->recpath);
         while (numBlocks-- > 0 && self->server_stopped == 0) {
-            offline_process_block((Server *) self); 
+            offline_process_block((Server *) self);
         }
         self->server_started = 0;
         self->record = 0;
         sf_close(self->recfile);
-        Server_message(self,"Offline Server rendering finished.\n");         
+        Server_message(self,"Offline Server rendering finished.\n");
     }
+    PyGILState_Release(s);
+
     return NULL;
 }
 
@@ -1150,7 +229,7 @@ int
 Server_offline_start(Server *self)
 {
     int numBlocks;
-    
+
     if (self->recdur < 0) {
         Server_error(self,"Duration must be specified for Offline Server (see Server.recordOptions).");
         return -1;
@@ -1160,12 +239,13 @@ Server_offline_start(Server *self)
     Server_debug(self,"Number of blocks: %i\n", numBlocks);
     Server_start_rec_internal(self, self->recpath);
     while (numBlocks-- > 0 && self->server_stopped == 0) {
-        offline_process_block((Server *) self); 
+        offline_process_block((Server *) self);
     }
     self->server_started = 0;
+    self->server_stopped = 1;
     self->record = 0;
     sf_close(self->recfile);
-    Server_message(self,"Offline Server rendering finished.\n"); 
+    Server_message(self,"Offline Server rendering finished.\n");
     return 0;
 }
 
@@ -1176,28 +256,21 @@ Server_offline_stop(Server *self)
     return 0;
 }
 
-/******* Embedded Server *******/
-int
-Server_embedded_init(Server *self)
-{
-    return 0;
-}
+/** Embedded server. **/
+/**********************/
 
-int
-Server_embedded_deinit(Server *self)
-{
-    return 0;
-}
+int Server_embedded_init(Server *self) { return 0; };
+int Server_embedded_deinit(Server *self) { return 0; };
 
 /* interleaved embedded callback */
 int
 Server_embedded_i_start(Server *self)
 {
     Server_process_buffers(self);
+    self->midi_count = 0;
     return 0;
 }
 
-// To be easier to call without depending on the Server structure
 int
 Server_embedded_i_startIdx(int idx)
 {
@@ -1210,20 +283,20 @@ int
 Server_embedded_ni_start(Server *self)
 {
     int i, j;
+    float out[self->bufferSize * self->nchnls];
+
     Server_process_buffers(self);
-    float *out = (float *)calloc(self->bufferSize * self->nchnls, sizeof(float));
+
     for (i=0; i<(self->bufferSize*self->nchnls); i++){
         out[i] = self->output_buffer[i];
     }
 
-    /* Non-Interleaved */
     for (i=0; i<self->bufferSize; i++) {
-        for (j=0; j<=self->nchnls; j++) {
-            /* This could probably be more efficient (ob) */
-            self->output_buffer[i+(self->bufferSize*(j+1))-self->bufferSize] = out[(i*self->nchnls)+j];
+        for (j=0; j<self->nchnls; j++) {
+            self->output_buffer[(j*self->bufferSize)+i] = out[(i*self->nchnls)+j];
         }
     }
-    
+    self->midi_count = 0;
     return 0;
 }
 
@@ -1234,13 +307,14 @@ Server_embedded_ni_startIdx(int idx)
     return 0;
 }
 
-void 
+void
 *Server_embedded_thread(void *arg)
 {
     Server *self;
     self = (Server *)arg;
-    
+
     Server_process_buffers(self);
+    self->midi_count = 0;
 
     return NULL;
 }
@@ -1253,8 +327,6 @@ Server_embedded_nb_start(Server *self)
     return 0;
 }
 
-/* this stop function is not very useful since the processing is stopped at the end 
-of every processing callback, but function put to not break pyo */
 int
 Server_embedded_stop(Server *self)
 {
@@ -1263,22 +335,34 @@ Server_embedded_stop(Server *self)
     return 0;
 }
 
-/***************************************************/
-/*  Main Processing functions                      */
+/** Main Processing functions. **/
+/********************************/
 
-static inline void
+void
 Server_process_buffers(Server *server)
 {
-    float *out = server->output_buffer;    
+    //clock_t begin = clock();
+
+    float *out = server->output_buffer;
     MYFLT buffer[server->nchnls][server->bufferSize];
-    int i, j, chnl;
-    int nchnls = server->nchnls;
+    int i, j, chnl, nchnls = server->nchnls;
     MYFLT amp = server->amp;
     Stream *stream_tmp;
     MYFLT *data;
 
     memset(&buffer, 0, sizeof(buffer));
+
+    /* This is the biggest bottle-neck of the callback. Don't know
+       how (or if possible) to improve GIL acquire/release.
+    */
     PyGILState_STATE s = PyGILState_Ensure();
+
+    if (server->elapsedSamples == 0)
+        server->midi_time_offset = pm_get_current_time();
+
+    if (server->CALLBACK != NULL)
+        PyObject_Call((PyObject *)server->CALLBACK, PyTuple_New(0), NULL);
+
     for (i=0; i<server->stream_count; i++) {
         stream_tmp = (Stream *)PyList_GET_ITEM(server->streams, i);
         if (Stream_getStreamActive(stream_tmp) == 1) {
@@ -1292,25 +376,27 @@ Server_process_buffers(Server *server)
             }
             if (Stream_getDuration(stream_tmp) != 0) {
                 Stream_IncrementDurationCount(stream_tmp);
-            }    
+            }
         }
         else if (Stream_getBufferCountWait(stream_tmp) != 0)
             Stream_IncrementBufferCount(stream_tmp);
     }
-    if (server->withGUI == 1 && nchnls <= 8) {
+    if (server->withGUI == 1 && nchnls <= 16) {
         Server_process_gui(server);
     }
     if (server->withTIME == 1) {
         Server_process_time(server);
     }
     server->elapsedSamples += server->bufferSize;
+
     PyGILState_Release(s);
+
     if (amp != server->lastAmp) {
         server->timeCount = 0;
         server->stepVal = (amp - server->currentAmp) / server->timeStep;
         server->lastAmp = amp;
     }
-    
+
     for (i=0; i < server->bufferSize; i++){
         if (server->timeCount < server->timeStep) {
             server->currentAmp += server->stepVal;
@@ -1320,12 +406,17 @@ Server_process_buffers(Server *server)
             out[(i*server->nchnls)+j] = (float)buffer[j][i] * server->currentAmp;
         }
     }
+
+    /* Writing to disk is not real time safe. */
     if (server->record == 1)
         sf_write_float(server->recfile, out, server->bufferSize * server->nchnls);
 
+    //clock_t end = clock();
+    //double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
+    //printf("%f\n", time_spent);
 }
 
-static void
+void
 Server_process_gui(Server *server)
 {
     float rms[server->nchnls];
@@ -1340,17 +431,17 @@ Server_process_gui(Server *server)
             if (outAmp > rms[j])
                 rms[j] = outAmp;
         }
-    }    
+    }
     if (server->gcount <= server->numPass) {
-        for (j=0; j<server->nchnls; j++) {            
+        for (j=0; j<server->nchnls; j++) {
             server->lastRms[j] = (rms[j] + server->lastRms[j]) * 0.5;
-        }    
+        }
         server->gcount++;
     }
     else {
-        for (j=0; j<server->nchnls; j++) {            
+        for (j=0; j<server->nchnls; j++) {
             server->lastRms[j] = (rms[j] + server->lastRms[j]) * 0.5;
-        }  
+        }
         switch (server->nchnls) {
             case 1:
                 PyObject_CallMethod((PyObject *)server->GUI, "setRms", "f", server->lastRms[0]);
@@ -1376,185 +467,174 @@ Server_process_gui(Server *server)
             case 8:
                 PyObject_CallMethod((PyObject *)server->GUI, "setRms", "ffffffff", server->lastRms[0], server->lastRms[1], server->lastRms[2], server->lastRms[3], server->lastRms[4], server->lastRms[5], server->lastRms[6], server->lastRms[7]);
                 break;
-        }        
+            case 9:
+                PyObject_CallMethod((PyObject *)server->GUI, "setRms", "fffffffff", server->lastRms[0], server->lastRms[1], server->lastRms[2], server->lastRms[3], server->lastRms[4], server->lastRms[5], server->lastRms[6], server->lastRms[7], server->lastRms[8]);
+                break;
+            case 10:
+                PyObject_CallMethod((PyObject *)server->GUI, "setRms", "ffffffffff", server->lastRms[0], server->lastRms[1], server->lastRms[2], server->lastRms[3], server->lastRms[4], server->lastRms[5], server->lastRms[6], server->lastRms[7], server->lastRms[8], server->lastRms[9]);
+                break;
+            case 11:
+                PyObject_CallMethod((PyObject *)server->GUI, "setRms", "fffffffffff", server->lastRms[0], server->lastRms[1], server->lastRms[2], server->lastRms[3], server->lastRms[4], server->lastRms[5], server->lastRms[6], server->lastRms[7], server->lastRms[8], server->lastRms[9], server->lastRms[10]);
+                break;
+            case 12:
+                PyObject_CallMethod((PyObject *)server->GUI, "setRms", "ffffffffffff", server->lastRms[0], server->lastRms[1], server->lastRms[2], server->lastRms[3], server->lastRms[4], server->lastRms[5], server->lastRms[6], server->lastRms[7], server->lastRms[8], server->lastRms[9], server->lastRms[10], server->lastRms[11]);
+                break;
+            case 13:
+                PyObject_CallMethod((PyObject *)server->GUI, "setRms", "fffffffffffff", server->lastRms[0], server->lastRms[1], server->lastRms[2], server->lastRms[3], server->lastRms[4], server->lastRms[5], server->lastRms[6], server->lastRms[7], server->lastRms[8], server->lastRms[9], server->lastRms[10], server->lastRms[11], server->lastRms[12]);
+                break;
+            case 14:
+                PyObject_CallMethod((PyObject *)server->GUI, "setRms", "ffffffffffffff", server->lastRms[0], server->lastRms[1], server->lastRms[2], server->lastRms[3], server->lastRms[4], server->lastRms[5], server->lastRms[6], server->lastRms[7], server->lastRms[8], server->lastRms[9], server->lastRms[10], server->lastRms[11], server->lastRms[12], server->lastRms[13]);
+                break;
+            case 15:
+                PyObject_CallMethod((PyObject *)server->GUI, "setRms", "fffffffffffffff", server->lastRms[0], server->lastRms[1], server->lastRms[2], server->lastRms[3], server->lastRms[4], server->lastRms[5], server->lastRms[6], server->lastRms[7], server->lastRms[8], server->lastRms[9], server->lastRms[10], server->lastRms[11], server->lastRms[12], server->lastRms[13], server->lastRms[14]);
+                break;
+            case 16:
+                PyObject_CallMethod((PyObject *)server->GUI, "setRms", "ffffffffffffffff", server->lastRms[0], server->lastRms[1], server->lastRms[2], server->lastRms[3], server->lastRms[4], server->lastRms[5], server->lastRms[6], server->lastRms[7], server->lastRms[8], server->lastRms[9], server->lastRms[10], server->lastRms[11], server->lastRms[12], server->lastRms[13], server->lastRms[14], server->lastRms[15]);
+                break;
+        }
         server->gcount = 0;
     }
 }
 
-static void
+void
 Server_process_time(Server *server)
 {
     int hours, minutes, seconds, milliseconds;
     float sr = server->samplingRate;
     double sampsToSecs;
-    
+
     if (server->tcount <= server->timePass) {
         server->tcount++;
     }
-    else {
-        sampsToSecs = (double)(server->elapsedSamples / sr);
-        seconds = (int)sampsToSecs;
-        milliseconds = (int)((sampsToSecs - seconds) * 1000);
-        minutes = seconds / 60;
-        hours = minutes / 60;
-        minutes = minutes % 60;
-        seconds = seconds % 60;
-        PyObject_CallMethod((PyObject *)server->TIME, "setTime", "iiii", hours, minutes, seconds, milliseconds);   
-        server->tcount = 0;
-    }
-}
-
-/***************************************************/
-
-/* Global function called by any new audio object to 
- get a pointer to the server */
-PyObject *
-PyServer_get_server()
-{
-    return (PyObject *)my_server[serverID];
-}
-
-static 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_INCREF(Py_None);
-        return Py_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->audio_be_type) {
-        case PyoPortaudio:
-            ret = Server_pa_deinit(self);
-            break;     
-        case PyoCoreaudio:
-#ifdef USE_COREAUDIO       
-            ret = Server_coreaudio_deinit(self);
-#endif      
-            break;          
-        case PyoJack:    
-#ifdef USE_JACK    
-            ret = Server_jack_deinit(self);
-#endif 
-            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");
+    else {
+        sampsToSecs = (double)(server->elapsedSamples / sr);
+        seconds = (int)sampsToSecs;
+        milliseconds = (int)((sampsToSecs - seconds) * 1000);
+        minutes = seconds / 60;
+        hours = minutes / 60;
+        minutes = minutes % 60;
+        seconds = seconds % 60;
+        PyObject_CallMethod((PyObject *)server->TIME, "setTime", "iiii", hours, minutes, seconds, milliseconds);
+        server->tcount = 0;
     }
-
-    Py_INCREF(Py_None);
-    return Py_None;
 }
 
 static int
 Server_traverse(Server *self, visitproc visit, void *arg)
 {
+    Py_VISIT(self->GUI);
+    Py_VISIT(self->TIME);
+    if (self->CALLBACK != NULL)
+        Py_VISIT(self->CALLBACK);
     Py_VISIT(self->streams);
+    Py_VISIT(self->jackAutoConnectInputPorts);
+    Py_VISIT(self->jackAutoConnectOutputPorts);
     return 0;
 }
 
-static int 
+static int
 Server_clear(Server *self)
-{    
+{
+    Py_CLEAR(self->GUI);
+    Py_CLEAR(self->TIME);
+    if (self->CALLBACK != NULL)
+        Py_CLEAR(self->CALLBACK);
     Py_CLEAR(self->streams);
+    Py_CLEAR(self->jackAutoConnectInputPorts);
+    Py_CLEAR(self->jackAutoConnectOutputPorts);
     return 0;
 }
 
 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);
     free(self->serverName);
+    if (self->withGUI == 1)
+        free(self->lastRms);
     my_server[self->thisServerID] = NULL;
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
 Server_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
-    /* Unused variables to allow the safety check of the embeded audio backend. */
+    /* Unused variables to allow the safety check of the embedded audio backend. */
     double samplingRate = 44100.0;
     int  nchnls = 2;
+    int  ichnls = 2;
     int  bufferSize = 256;
     int  duplex = 0;
     char *audioType = "portaudio";
     char *serverName = "pyo";
-        
-    static char *kwlist[] = {"sr", "nchnls", "buffersize", "duplex", "audio", "jackname", NULL};
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|diiiss", kwlist, 
-            &samplingRate, &nchnls, &bufferSize, &duplex, &audioType, &serverName))
-        Py_RETURN_FALSE;
-        
-    if (strcmp(audioType, "embedded") != 0)
-    {
-        if (PyServer_get_server() != NULL) {
-            Server_warning((Server *) PyServer_get_server(), "Warning: A Server is already created!\n"
-                "If you put this Server in a new variable, please delete it!\n");
-            return PyServer_get_server();
-        }
+
+    static char *kwlist[] = {"sr", "nchnls", "buffersize", "duplex", "audio", "jackname", "ichnls", NULL};
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|diiissi", kwlist,
+            &samplingRate, &nchnls, &bufferSize, &duplex, &audioType, &serverName, &ichnls)) {
+        Py_INCREF(Py_False);
+        return Py_False;
     }
 
     /* find the first free serverID */
     for(serverID = 0; serverID < MAX_NBR_SERVER; serverID++){
-        if(my_server[serverID] == NULL){
+        if (my_server[serverID] == NULL){
             break;
         }
     }
     if(serverID == MAX_NBR_SERVER){
-        return PyString_FromString("You are already using the maximum number of server allowed!");
+        PyErr_SetString(PyExc_RuntimeError, "You are already using the maximum number of server allowed!\n");
+        Py_RETURN_NONE;
     }
 
     Server *self;
     self = (Server *)type->tp_alloc(type, 0);
     self->server_booted = 0;
     self->audio_be_data = NULL;
+    self->midi_be_data = NULL;
     self->serverName = (char *) calloc(32, sizeof(char));
     self->jackautoin = 1;
     self->jackautoout = 1;
+    self->jackAutoConnectInputPorts = PyList_New(0);
+    self->jackAutoConnectOutputPorts = PyList_New(0);
+    self->isJackTransportSlave = 0;
+    self->jack_transport_state = 0;
     self->samplingRate = 44100.0;
     self->nchnls = 2;
+    self->ichnls = 2;
     self->record = 0;
     self->bufferSize = 256;
+    self->currentResampling = 1;
+    self->lastResampling = 1;
     self->duplex = 0;
     self->input = -1;
     self->output = -1;
     self->input_offset = 0;
     self->output_offset = 0;
+    self->midiin_count = 0;
+    self->midiout_count = 0;
     self->midi_input = -1;
     self->midi_output = -1;
+    self->midiActive = 1;
+    self->allowMMMapper = 0; // Disable Microsoft MIDI Mapper by default.
+    self->midi_time_offset = 0;
     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;
     self->recdur = -1;
     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;
     self->thisServerID = serverID;
     Py_XDECREF(my_server[serverID]);
     my_server[serverID] = (Server *)self;
@@ -1564,15 +644,16 @@ Server_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 static int
 Server_init(Server *self, PyObject *args, PyObject *kwds)
 {
-    static char *kwlist[] = {"sr", "nchnls", "buffersize", "duplex", "audio", "jackname", NULL};
-    
+    static char *kwlist[] = {"sr", "nchnls", "buffersize", "duplex", "audio", "jackname", "ichnls", NULL};
+
     char *audioType = "portaudio";
+    char *midiType = "portmidi";
     char *serverName = "pyo";
 
-    //Server_debug(self, "Server_init. Compiled " TIMESTAMP "\n");  // Only for debugging purposes
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|diiiss", kwlist, 
-            &self->samplingRate, &self->nchnls, &self->bufferSize, &self->duplex, &audioType, &serverName))
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|diiissi", kwlist,
+            &self->samplingRate, &self->nchnls, &self->bufferSize, &self->duplex, &audioType, &serverName, &self->ichnls))
         return -1;
+
     if (strcmp(audioType, "jack") == 0) {
         self->audio_be_type = PyoJack;
     }
@@ -1581,13 +662,13 @@ Server_init(Server *self, PyObject *args, PyObject *kwds)
     }
     else if (strcmp(audioType, "coreaudio") == 0) {
         self->audio_be_type = PyoCoreaudio;
-    }    
+    }
     else if (strcmp(audioType, "offline") == 0) {
         self->audio_be_type = PyoOffline;
-    } 
+    }
     else if (strcmp(audioType, "offline_nb") == 0) {
         self->audio_be_type = PyoOfflineNB;
-    } 
+    }
     else if (strcmp(audioType, "embedded") == 0) {
         self->audio_be_type = PyoEmbedded;
     }
@@ -1595,6 +676,15 @@ Server_init(Server *self, PyObject *args, PyObject *kwds)
         Server_warning(self, "Unknown audio type. Using Portaudio\n");
         self->audio_be_type = PyoPortaudio;
     }
+
+    if (strcmp(midiType, "portmidi") == 0 || strcmp(midiType, "pm") == 0 ) {
+        self->midi_be_type = PyoPortmidi;
+    }
+    else {
+        Server_warning(self, "Unknown midi type. Using Portmidi\n");
+        self->midi_be_type = PyoPortmidi;
+    }
+
     strncpy(self->serverName, serverName, 32);
     if (strlen(serverName) > 31) {
         self->serverName[31] = '\0';
@@ -1603,16 +693,18 @@ Server_init(Server *self, PyObject *args, PyObject *kwds)
     return 0;
 }
 
+/** Server's setters. **/
+/***********************/
+
 static PyObject *
 Server_setDefaultRecPath(Server *self, PyObject *args, PyObject *kwds)
 {
     static char *kwlist[] = {"path", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &self->recpath))
         return PyInt_FromLong(-1);
 
-    Py_INCREF(Py_None);
-    return Py_None;
+    Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -1620,15 +712,13 @@ Server_setInputOffset(Server *self, PyObject *arg)
 {
     if (self->server_booted) {
         Server_warning(self, "Can't change input offset for booted server.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        Py_RETURN_NONE;
     }
-	if (arg != NULL) {
+    if (arg != NULL) {
         if (PyInt_Check(arg))
             self->input_offset = PyInt_AsLong(arg);
     }
-    Py_INCREF(Py_None);
-    return Py_None;
+    Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -1636,71 +726,72 @@ Server_setOutputOffset(Server *self, PyObject *arg)
 {
     if (self->server_booted) {
         Server_warning(self, "Can't change output offset for booted server.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        Py_RETURN_NONE;
     }
-	if (arg != NULL) {
+    if (arg != NULL) {
         if (PyInt_Check(arg))
             self->output_offset = PyInt_AsLong(arg);
     }
-    Py_INCREF(Py_None);
-    return Py_None;
+    Py_RETURN_NONE;
 }
 
 static PyObject *
 Server_setInputDevice(Server *self, PyObject *arg)
 {
-	if (arg != NULL) {
+    if (arg != NULL) {
         if (PyInt_Check(arg))
             self->input = PyInt_AsLong(arg);
     }
-    Py_INCREF(Py_None);
-    return Py_None;
+    Py_RETURN_NONE;
 }
 
 static PyObject *
 Server_setInOutDevice(Server *self, PyObject *arg)
 {
-	if (arg != NULL) {
-        if (PyInt_Check(arg))
+    if (arg != NULL) {
+        if (PyInt_Check(arg)) {
             self->input = PyInt_AsLong(arg);
             self->output = PyInt_AsLong(arg);
+        }
     }
-    Py_INCREF(Py_None);
-    return Py_None;
+    Py_RETURN_NONE;
 }
 
 static PyObject *
 Server_setOutputDevice(Server *self, PyObject *arg)
 {
-	if (arg != NULL) {
+    if (arg != NULL) {
         if (PyInt_Check(arg))
             self->output = PyInt_AsLong(arg);
     }
-    Py_INCREF(Py_None);
-    return Py_None;
+    Py_RETURN_NONE;
 }
 
 static PyObject *
 Server_setMidiInputDevice(Server *self, PyObject *arg)
 {
-	if (arg != NULL) {
+    if (arg != NULL) {
         if (PyInt_Check(arg))
             self->midi_input = PyInt_AsLong(arg);
     }
-    Py_INCREF(Py_None);
-    return Py_None;
+    Py_RETURN_NONE;
 }
 
 static PyObject *
 Server_setMidiOutputDevice(Server *self, PyObject *arg)
 {
-	if (arg != NULL) {
+    if (arg != NULL) {
         if (PyInt_Check(arg))
             self->midi_output = PyInt_AsLong(arg);
     }
-    Py_INCREF(Py_None);
-    return Py_None;
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+Server_deactivateMidi(Server *self)
+{
+    self->midiActive = 0;
+    Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -1708,17 +799,15 @@ Server_setSamplingRate(Server *self, PyObject *arg)
 {
     if (self->server_booted) {
         Server_warning(self, "Can't change sampling rate for booted server.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        Py_RETURN_NONE;
     }
     if (arg != NULL && PyNumber_Check(arg)) {
-        self->samplingRate = PyFloat_AsDouble(PyNumber_Float(arg));
+        self->samplingRate = PyFloat_AsDouble(arg);
     }
     else {
         Server_error(self, "Sampling rate must be a number.\n");
     }
-    Py_INCREF(Py_None);
-    return Py_None;
+    Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -1726,8 +815,7 @@ Server_setNchnls(Server *self, PyObject *arg)
 {
     if (self->server_booted) {
         Server_warning(self, "Can't change number of channels for booted server.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        Py_RETURN_NONE;
     }
     if (arg != NULL && PyInt_Check(arg)) {
         self->nchnls = PyInt_AsLong(arg);
@@ -1735,8 +823,23 @@ Server_setNchnls(Server *self, PyObject *arg)
     else {
         Server_error(self, "Number of channels must be an integer.\n");
     }
-    Py_INCREF(Py_None);
-    return Py_None;
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+Server_setIchnls(Server *self, PyObject *arg)
+{
+    if (self->server_booted) {
+        Server_warning(self, "Can't change number of input channels for booted server.\n");
+        Py_RETURN_NONE;
+    }
+    if (arg != NULL && PyInt_Check(arg)) {
+        self->ichnls = PyInt_AsLong(arg);
+    }
+    else {
+        Server_error(self, "Number of input channels must be an integer.\n");
+    }
+    Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -1744,8 +847,7 @@ Server_setBufferSize(Server *self, PyObject *arg)
 {
     if (self->server_booted) {
         Server_warning(self, "Can't change buffer size for booted server.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        Py_RETURN_NONE;
     }
     if (arg != NULL && PyInt_Check(arg)) {
         self->bufferSize = PyInt_AsLong(arg);
@@ -1753,8 +855,25 @@ Server_setBufferSize(Server *self, PyObject *arg)
     else {
         Server_error(self, "Buffer size must be an integer.\n");
     }
-    Py_INCREF(Py_None);
-    return Py_None;
+    Py_RETURN_NONE;
+}
+
+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 *
@@ -1762,75 +881,146 @@ Server_setDuplex(Server *self, PyObject *arg)
 {
     if (self->server_booted) {
         Server_warning(self,"Can't change duplex mode for booted server.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        Py_RETURN_NONE;
     }
     if (arg != NULL) {
         if (PyInt_Check(arg))
             self->duplex = PyInt_AsLong(arg);
     }
-    Py_INCREF(Py_None);
-    return Py_None;
+    Py_RETURN_NONE;
 }
 
 static PyObject *
 Server_setJackAuto(Server *self, PyObject *args)
 {
     int in=1, out=1;
-    
+
     if (! PyArg_ParseTuple(args, "ii", &in, &out)) {
-        Py_INCREF(Py_None);
-        return Py_None;
+        Py_RETURN_NONE;
     }
 
     self->jackautoin = in;
     self->jackautoout = out;
 
-    Py_INCREF(Py_None);
-    return Py_None;
+    Py_RETURN_NONE;
 }
 
 static PyObject *
-Server_setGlobalSeed(Server *self, PyObject *arg)
+Server_setJackAutoConnectInputPorts(Server *self, PyObject *arg)
 {
-    unsigned int tmp;
-    
+    PyObject *tmp;
+
     if (arg != NULL) {
-        if (PyInt_Check(arg)) {
-            tmp = PyInt_AsLong(arg);
-            if (tmp < 0)
-                self->globalSeed = 0;
-            else
-                self->globalSeed = tmp;
+        if (PyList_Check(arg)) {
+            tmp = arg;
+            Py_XDECREF(self->jackAutoConnectInputPorts);
+            Py_INCREF(tmp);
+            self->jackAutoConnectInputPorts = tmp;
         }
-        else
-            self->globalSeed = 0;
     }
-    else
-        self->globalSeed = 0;
-    
-    Py_INCREF(Py_None);
-    return Py_None;
+
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+Server_setJackAutoConnectOutputPorts(Server *self, PyObject *arg)
+{
+    PyObject *tmp;
+
+    if (arg != NULL) {
+        if (PyList_Check(arg)) {
+            tmp = arg;
+            Py_XDECREF(self->jackAutoConnectOutputPorts);
+            Py_INCREF(tmp);
+            self->jackAutoConnectOutputPorts = tmp;
+        }
+    }
+
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+Server_setJackInputPortNames(Server *self, PyObject *arg)
+{
+    PyObject *tmp;
+
+    if (arg != NULL) {
+        if (PyList_Check(arg) || PY_STRING_CHECK(arg)) {
+            tmp = arg;
+            Py_XDECREF(self->jackInputPortNames);
+            Py_INCREF(tmp);
+            self->jackInputPortNames = tmp;
+
+            jack_input_port_set_names(self);
+        }
+    }
+
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+Server_setJackOutputPortNames(Server *self, PyObject *arg)
+{
+    PyObject *tmp;
+
+    if (arg != NULL) {
+        if (PyList_Check(arg) || PY_STRING_CHECK(arg)) {
+            tmp = arg;
+            Py_XDECREF(self->jackOutputPortNames);
+            Py_INCREF(tmp);
+            self->jackOutputPortNames = tmp;
+
+            jack_output_port_set_names(self);
+        }
+    }
+
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+Server_setIsJackTransportSlave(Server *self, PyObject *arg)
+{
+    if (self->server_booted) {
+        Server_warning(self,"Can't change isJackTransportSlave mode for booted server.\n");
+        Py_RETURN_NONE;
+    }
+    if (arg != NULL) {
+        if (PyInt_Check(arg))
+            self->isJackTransportSlave = PyInt_AsLong(arg);
+    }
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+Server_setGlobalSeed(Server *self, PyObject *arg)
+{
+    self->globalSeed = 0;
+
+    if (arg != NULL && PyLong_Check(arg)) {
+        self->globalSeed = (int)PyInt_AsLong(arg);
+        self->globalSeed = self->globalSeed > 0 ? self->globalSeed : 0;
+    }
+
+    Py_RETURN_NONE;
 }
 
 int
 Server_generateSeed(Server *self, int oid)
 {
-    int curseed, seed, count, mult;
-    long ltime;
+    unsigned int curseed, count, mult, ltime;
 
     count = ++rnd_objs_count[oid];
     mult = rnd_objs_mult[oid];
 
     if (self->globalSeed > 0) {
-        curseed = self->globalSeed + ((count * mult) % 32768);
+        curseed = (self->globalSeed + count * mult) % PYO_RAND_MAX;
     }
     else {
-        ltime = time(NULL);
-        seed = (unsigned) (ltime / 2) % 32768;
-        curseed = seed + ((count * mult) % 32768);
+        ltime = (unsigned int)time(NULL);
+        curseed = (ltime * ltime + count * mult) % PYO_RAND_MAX;
     }
-    srand(curseed);
+
+    PYO_RAND_SEED = curseed;
 
     return 0;
 }
@@ -1840,15 +1030,14 @@ Server_setAmp(Server *self, PyObject *arg)
 {
     if (arg != NULL) {
         int check = PyNumber_Check(arg);
-        
+
         if (check) {
-            self->amp = PyFloat_AsDouble(PyNumber_Float(arg));
+            self->amp = PyFloat_AsDouble(arg);
             if (self->amp != 0.0)
                 self->resetAmp = self->amp;
         }
     }
-    Py_INCREF(Py_None);
-    return Py_None;
+    Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -1856,13 +1045,9 @@ Server_setAmpCallable(Server *self, PyObject *arg)
 {
     int i;
     PyObject *tmp;
-    
-    if (arg == NULL) {
-        Server_error(self,"The amplitude callable attribute must be a method.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
-    }
-    
+
+    ASSERT_ARG_NOT_NULL
+
     tmp = arg;
     Py_XDECREF(self->GUI);
     Py_INCREF(tmp);
@@ -1872,18 +1057,17 @@ Server_setAmpCallable(Server *self, PyObject *arg)
     for (i=0; i<self->nchnls; i++) {
         self->lastRms[i] = 0.0;
     }
-    
+
     for (i=1; i<100; i++) {
         if ((self->bufferSize * i / self->samplingRate) > 0.045) {
             self->numPass = i;
             break;
         }
-    } 
+    }
     self->gcount = 0;
     self->withGUI = 1;
-    
-    Py_INCREF(Py_None);
-    return Py_None;
+
+    Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -1891,13 +1075,9 @@ Server_setTimeCallable(Server *self, PyObject *arg)
 {
     int i;
     PyObject *tmp;
-    
-    if (arg == NULL) {
-        Server_error(self,"The time callable attribute must be a method.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
-    }
-    
+
+    ASSERT_ARG_NOT_NULL
+
     tmp = arg;
     Py_XDECREF(self->TIME);
     Py_INCREF(tmp);
@@ -1908,12 +1088,26 @@ Server_setTimeCallable(Server *self, PyObject *arg)
             self->timePass = i;
             break;
         }
-    } 
+    }
     self->tcount = 0;
     self->withTIME = 1;
-    
-    Py_INCREF(Py_None);
-    return Py_None;
+
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+Server_setCallback(Server *self, PyObject *arg)
+{
+    PyObject *tmp;
+
+    ASSERT_ARG_NOT_NULL
+
+    tmp = arg;
+    Py_XDECREF(self->CALLBACK);
+    Py_INCREF(tmp);
+    self->CALLBACK = tmp;
+
+    Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -1921,14 +1115,13 @@ Server_setVerbosity(Server *self, PyObject *arg)
 {
     if (arg != NULL) {
         int check = PyInt_Check(arg);
-        
+
         if (check) {
             self->verbosity = PyInt_AsLong(arg);
         }
     }
-    
-    Py_INCREF(Py_None);
-    return Py_None;
+
+    Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -1936,247 +1129,129 @@ Server_setStartOffset(Server *self, PyObject *arg)
 {
     if (arg != NULL) {
         int check = PyNumber_Check(arg);
-        
+
         if (check) {
-            self->startoffset = PyFloat_AsDouble(PyNumber_Float(arg));
+            self->startoffset = PyFloat_AsDouble(arg);
         }
     }
-    
-    Py_INCREF(Py_None);
-    return Py_None;
+
+    Py_RETURN_NONE;
 }
 
-int
-Server_pm_init(Server *self)
+static PyObject *
+Server_allowMicrosoftMidiDevices(Server *self)
 {
-   /* Initializing MIDI */    
-    PmError pmerr;
-
-    pmerr = Pm_Initialize();
-    if (pmerr) {
-        Server_warning(self, "Portmidi warning: could not initialize Portmidi: %s\n", Pm_GetErrorText(pmerr));
-        self->withPortMidi = 0;
-        self->withPortMidiOut = 0;
-        return -1;
-    }    
-    else {
-        Server_debug(self, "Portmidi initialized.\n");
-        self->withPortMidi = 1;
-        self->withPortMidiOut = 1;
-    }    
-
-    if (self->withPortMidi == 1) {
-        int num_devices = Pm_CountDevices();
-        if (num_devices > 0) {
-            if (self->midi_input == -1 || self->midi_input >= num_devices)
-                self->midi_input = Pm_GetDefaultInputDeviceID();
-            Server_debug(self, "Midi input device : %d.\n", self->midi_input);
-            const PmDeviceInfo *info = Pm_GetDeviceInfo(self->midi_input);
-            if (info != NULL) {
-                if (info->input) {
-                    pmerr = Pm_OpenInput(&self->in, self->midi_input, NULL, 100, NULL, NULL);
-                    if (pmerr) {
-                        Server_warning(self, 
-                                 "Portmidi warning: could not open midi input %d (%s): %s\n",
-                                 0, info->name, Pm_GetErrorText(pmerr));
-                        self->withPortMidi = 0;
-                    }    
-                    else
-                        Server_debug(self, "Midi input (%s) opened.\n", info->name);
-                }
-                else {
-                    Server_warning(self, "Portmidi warning: something wrong with midi input device!\n");
-                    self->withPortMidi = 0;
-                }
-            }
-            else {
-                    Server_warning(self, "Portmidi warning: no input device!\n");
-                    self->withPortMidi = 0;
-            }
-            
-            if (self->midi_output == -1 || self->midi_output >= num_devices)
-                self->midi_output = Pm_GetDefaultOutputDeviceID();
-            Server_debug(self, "Midi output device : %d.\n", self->midi_output);
-            const PmDeviceInfo *outinfo = Pm_GetDeviceInfo(self->midi_output);
-            if (outinfo != NULL) {
-                if (outinfo->output) {
-                    Pt_Start(1, 0, 0); /* start a timer with millisecond accuracy */
-                    pmerr = Pm_OpenOutput(&self->out, self->midi_output, NULL, 0, NULL, NULL, 1);
-                    if (pmerr) {
-                        Server_warning(self, 
-                                 "Portmidi warning: could not open midi output %d (%s): %s\n",
-                                 0, outinfo->name, Pm_GetErrorText(pmerr));
-                        self->withPortMidiOut = 0;
-                    }    
-                    else
-                        Server_debug(self, "Midi output (%s) opened.\n", outinfo->name);
-                }
-                else {
-                    Server_warning(self, "Portmidi warning: something wrong with midi output device!\n");
-                    self->withPortMidiOut = 0;
-                }
-            }
-            else {
-                    Server_warning(self, "Portmidi warning: no output device!\n");
-                    self->withPortMidi = 0;
-            }
-            
-            if (self->withPortMidi == 0 && self->withPortMidiOut == 0) {
-                Pm_Terminate();
-                Server_warning(self, "Portmidi closed.\n");
-            }
-        }    
-        else {
-            Server_warning(self, "Portmidi warning: no midi device found!\nPortmidi closed.\n");
-            self->withPortMidi = 0;
-            self->withPortMidiOut = 0;
-            Pm_Terminate();
-        }    
-    }
-    if (self->withPortMidi == 1) {
-        self->midi_count = 0;
-        Pm_SetFilter(self->in, PM_FILT_ACTIVE | PM_FILT_CLOCK);
-    } 
-    return 0;
+    self->allowMMMapper = 1;
+    Py_RETURN_NONE;
 }
 
+/*******************************************/
+/** Server shutdown / boot / start / stop **/
+/*******************************************/
 
-static PyObject *
-Server_boot(Server *self, PyObject *arg)
+PyObject *
+Server_shutdown(Server *self)
 {
-    int audioerr = 0;
-    int i;
-    if (self->server_booted == 1) {
-        Server_error(self, "Server already booted!\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+    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);
     }
-    self->server_started = 0;
-    self->stream_count = 0;
-    self->elapsedSamples = 0;
 
-    int needNewBuffer = 0;
-    if (arg != NULL && PyBool_Check(arg)) {
-        needNewBuffer = PyObject_IsTrue(arg);
+    for (i=0; i<num_rnd_objs; i++) {
+        rnd_objs_count[i] = 0;
     }
-    else {
-        Server_error(self, "The argument to set for a new buffer must be a boolean.\n");
+
+    switch (self->midi_be_type) {
+        case PyoPortmidi:
+            if (self->withPortMidi == 1 || self->withPortMidiOut == 1)
+                ret = Server_pm_deinit(self);
+            break;
+        default:
+            break;
     }
 
-    self->streams = PyList_New(0);
     switch (self->audio_be_type) {
         case PyoPortaudio:
-            audioerr = Server_pa_init(self);
-            break;
-        case PyoJack:
-#ifdef USE_JACK
-            audioerr = Server_jack_init(self);
-            if (audioerr < 0) {
-                Server_jack_deinit(self);
-            }
-#else
-            audioerr = -1;
-            Server_error(self, "Pyo built without Jack support\n");
-#endif
+            ret = Server_pa_deinit(self);
             break;
         case PyoCoreaudio:
-#ifdef USE_COREAUDIO
-            audioerr = Server_coreaudio_init(self);
-            if (audioerr < 0) {
-                Server_coreaudio_deinit(self);
-            }
-#else
-            audioerr = -1;
-            Server_error(self, "Pyo built without Coreaudio support\n");
-#endif
+            ret = Server_coreaudio_deinit(self);
+            break;
+        case PyoJack:
+            ret = Server_jack_deinit(self);
             break;
         case PyoOffline:
-            audioerr = Server_offline_init(self);
-            if (audioerr < 0) {
-                Server_offline_deinit(self);
-            }
+            ret = Server_offline_deinit(self);
             break;
         case PyoOfflineNB:
-            audioerr = Server_offline_init(self);
-            if (audioerr < 0) {
-                Server_offline_deinit(self);
-            }
+            ret = Server_offline_deinit(self);
             break;
         case PyoEmbedded:
-            audioerr = Server_embedded_init(self);
-            if (audioerr < 0) {
-                Server_embedded_deinit(self);
-            }
+            ret = Server_embedded_deinit(self);
             break;
     }
-    if (needNewBuffer == 1){
-        /* Must allocate buffer after initializing the audio backend in case parameters change there */
-        if (self->input_buffer) {
-            free(self->input_buffer);
-        }
-        self->input_buffer = (MYFLT *)calloc(self->bufferSize * self->nchnls, sizeof(MYFLT));
-        if (self->output_buffer) {
-            free(self->output_buffer);
-        }
-        self->output_buffer = (float *)calloc(self->bufferSize * self->nchnls, sizeof(float));
-    }
-    for (i=0; i<self->bufferSize*self->nchnls; i++) {
-        self->input_buffer[i] = 0.0;
-        self->output_buffer[i] = 0.0;
-    }
-    if (audioerr == 0) {
-        self->server_booted = 1;
-    }
-    else {
-        self->server_booted = 0;
-        Server_error(self, "\nServer not booted.\n");
-    }    
-    
-    Py_INCREF(Py_None);
-    return Py_None;
+    self->server_booted = 0;
+    if (ret < 0) {
+        Server_error(self, "Error closing audio backend.\n");
+    }
+
+    Py_RETURN_NONE;
 }
 
-/* Like the Server_boot() but without reinitializing the buffers */
-static PyObject *
-Server_flush(Server *self)
+PyObject *
+Server_boot(Server *self, PyObject *arg)
 {
-    int audioerr = 0;
-    int i;
+    int i, audioerr = 0, midierr = 0;
     if (self->server_booted == 1) {
         Server_error(self, "Server already booted!\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        Py_RETURN_NONE;
     }
     self->server_started = 0;
     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);
+    }
+    else {
+        Server_error(self, "The argument to set for a new buffer must be a boolean.\n");
+    }
+
     self->streams = PyList_New(0);
     switch (self->audio_be_type) {
         case PyoPortaudio:
             audioerr = Server_pa_init(self);
+            if (audioerr < 0) {
+                Server_pa_deinit(self);
+                if (audioerr == -10)
+                    Server_error(self, "Pyo built without Portaudio support\n");
+            }
             break;
         case PyoJack:
-#ifdef USE_JACK
             audioerr = Server_jack_init(self);
             if (audioerr < 0) {
                 Server_jack_deinit(self);
+                if (audioerr == -10)
+                    Server_error(self, "Pyo built without Jack support\n");
             }
-#else
-            audioerr = -1;
-            Server_error(self, "Pyo built without Jack support\n");
-#endif
             break;
         case PyoCoreaudio:
-#ifdef USE_COREAUDIO
             audioerr = Server_coreaudio_init(self);
             if (audioerr < 0) {
                 Server_coreaudio_deinit(self);
+                if (audioerr == -10)
+                    Server_error(self, "Pyo built without Coreaudio support\n");
             }
-#else
-            audioerr = -1;
-            Server_error(self, "Pyo built without Coreaudio support\n");
-#endif
             break;
         case PyoOffline:
             audioerr = Server_offline_init(self);
@@ -2197,87 +1272,96 @@ Server_flush(Server *self)
             }
             break;
     }
-
-    for (i=0; i<self->bufferSize*self->nchnls; i++) {
+    if (needNewBuffer == 1){
+        /* Must allocate buffer after initializing the audio backend in case parameters change there */
+        if (self->input_buffer) {
+            free(self->input_buffer);
+        }
+        self->input_buffer = (MYFLT *)calloc(self->bufferSize * self->ichnls, sizeof(MYFLT));
+        if (self->output_buffer) {
+            free(self->output_buffer);
+        }
+        self->output_buffer = (float *)calloc(self->bufferSize * self->nchnls, sizeof(float));
+    }
+    for (i=0; i<self->bufferSize*self->ichnls; i++) {
         self->input_buffer[i] = 0.0;
+    }
+    for (i=0; i<self->bufferSize*self->nchnls; i++) {
         self->output_buffer[i] = 0.0;
     }
-    
     if (audioerr == 0) {
         self->server_booted = 1;
     }
     else {
         self->server_booted = 0;
         Server_error(self, "\nServer not booted.\n");
-    }    
-    
-    Py_INCREF(Py_None);
-    return Py_None;
+    }
+
+    if (self->audio_be_type != PyoOffline && self->audio_be_type != PyoOfflineNB && self->audio_be_type != PyoEmbedded) {
+        switch (self->midi_be_type) {
+            case PyoPortmidi:
+                midierr = Server_pm_init(self);
+                if (midierr < 0) {
+                    Server_pm_deinit(self);
+                    if (midierr == -10)
+                        Server_error(self, "Pyo built without Portmidi support\n");
+                }
+                break;
+        }
+    }
+
+    Py_RETURN_NONE;
 }
 
-static PyObject *
+PyObject *
 Server_start(Server *self)
 {
-    int err = -1, midierr = 0;
+    int err = -1;
     if (self->server_started == 1) {
         Server_warning(self, "Server already started!\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        Py_RETURN_NONE;
     }
 
     if (self->server_booted == 0) {
         Server_warning(self, "The Server must be booted!\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        Py_RETURN_NONE;
     }
-    
-    Server_debug(self, "Server_start: number of streams %d\n", self->stream_count);
 
-    /* Ensure Python is set up for threading */
-    PyEval_InitThreads();
+    Server_debug(self, "Server_start: number of streams %d\n", self->stream_count);
 
     self->server_stopped = 0;
     self->server_started = 1;
-    self->timeStep = (int)(0.01 * self->samplingRate);
-
-    if (self->audio_be_type != PyoOffline && self->audio_be_type != PyoOfflineNB) {
-        midierr = Server_pm_init(self);
-        Server_debug(self, "PortMidi initialization return code : %d.\n", midierr);
-    }
+    self->timeStep = (int)(0.005 * self->samplingRate);
 
     if (self->startoffset > 0.0) {
         Server_message(self,"Rendering %.2f seconds offline...\n", self->startoffset);
         int numBlocks = ceil(self->startoffset * self->samplingRate/self->bufferSize);
         self->lastAmp = 1.0; self->amp = 0.0;
         while (numBlocks-- > 0) {
-            offline_process_block((Server *) self); 
+            offline_process_block((Server *) self);
         }
         Server_message(self,"Offline rendering completed. Start realtime processing.\n");
         self->startoffset = 0.0;
-    }    
+    }
 
     self->amp = self->resetAmp;
 
     switch (self->audio_be_type) {
         case PyoPortaudio:
             err = Server_pa_start(self);
-            break;          
+            break;
         case PyoCoreaudio:
-#ifdef USE_COREAUDIO  
             err = Server_coreaudio_start(self);
-#endif     
-            break;           
-        case PyoJack:  
-#ifdef USE_JACK      
+            break;
+        case PyoJack:
             err = Server_jack_start(self);
-#endif    
             break;
         case PyoOffline:
             err = Server_offline_start(self);
-            break;           
+            break;
         case PyoOfflineNB:
             err = Server_offline_nb_start(self);
-            break;           
+            break;
         case PyoEmbedded:
             err = Server_embedded_nb_start(self);
             break;
@@ -2286,95 +1370,79 @@ Server_start(Server *self)
         Server_error(self, "Error starting server.\n");
     }
 
-    Py_INCREF(Py_None);
-    return Py_None;
+    if (self->withGUI && PyObject_HasAttrString((PyObject *)self->GUI, "setStartButtonState"))
+        PyObject_CallMethod((PyObject *)self->GUI, "setStartButtonState", "i", 1);
+
+    Py_RETURN_NONE;
 }
 
-static PyObject *
+PyObject *
 Server_stop(Server *self)
 {
-    int err = -1;
+    int err = 0;
     if (self->server_started == 0) {
         Server_warning(self, "The Server must be started!\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        Py_RETURN_NONE;
     }
     switch (self->audio_be_type) {
         case PyoPortaudio:
-            err = Server_pa_stop(self);
-            break;          
+            err = Server_pa_stop(self); break;
         case PyoCoreaudio:
-#ifdef USE_COREAUDIO  
-            err = Server_coreaudio_stop(self);
-#endif            
-            break;        
+            err = Server_coreaudio_stop(self); break;
         case PyoJack:
-#ifdef USE_JACK    
-            err = Server_jack_stop(self);
-#endif            
-            break;
+            err = Server_jack_stop(self); break;
         case PyoOffline:
-            err = Server_offline_stop(self);
-            break;    
+            err = Server_offline_stop(self); break;
         case PyoOfflineNB:
-            err = Server_offline_stop(self);
-            break;    
+            err = Server_offline_stop(self); break;
         case PyoEmbedded:
-            err = Server_embedded_stop(self);
-            break;
+            err = Server_embedded_stop(self); break;
     }
 
-    if (err < 0) {
+    if (err != 0) {
         Server_error(self, "Error stopping server.\n");
     }
     else {
         self->server_stopped = 1;
-        if (self->withPortMidi == 1) {
-            Pm_Close(self->in);
-        }
-        if (self->withPortMidiOut == 1) {
-            Pm_Close(self->out);
-        }
-        if (self->withPortMidi == 1 || self->withPortMidiOut == 1) {
-            Pm_Terminate();
-        }
-        self->withPortMidi = 0;
-        self->withPortMidiOut = 0;
+        self->server_started = 0;
     }
-    Py_INCREF(Py_None);
-    return Py_None;
+
+    if (self->withGUI && PyObject_HasAttrString((PyObject *)self->GUI, "setStartButtonState"))
+        PyObject_CallMethod((PyObject *)self->GUI, "setStartButtonState", "i", 0);
+
+    Py_RETURN_NONE;
 }
 
 static PyObject *
 Server_recordOptions(Server *self, PyObject *args, PyObject *kwds)
-{    
-    static char *kwlist[] = {"dur", "filename", "fileformat", "sampletype", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "d|sii", kwlist, &self->recdur, &self->recpath, &self->recformat, &self->rectype)) {
+{
+    Py_ssize_t psize;
+    static char *kwlist[] = {"dur", "filename", "fileformat", "sampletype", "quality", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "d|s#iid", kwlist, &self->recdur, &self->recpath, &psize, &self->recformat, &self->rectype, &self->recquality)) {
         return PyInt_FromLong(-1);
     }
-    
-    Py_INCREF(Py_None);
-    return Py_None;
+
+    Py_RETURN_NONE;
 }
 
 static PyObject *
 Server_start_rec(Server *self, PyObject *args, PyObject *kwds)
-{    
+{
+    Py_ssize_t psize;
     char *filename=NULL;
-    
+
     static char *kwlist[] = {"filename", NULL};
 
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|s", kwlist, &filename)) {
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|s#", kwlist, &filename, &psize)) {
         return PyInt_FromLong(-1);
     }
     Server_start_rec_internal(self, filename);
-    
-    Py_INCREF(Py_None);
-    return Py_None;
+
+    Py_RETURN_NONE;
 }
 
-static int 
+int
 Server_start_rec_internal(Server *self, char *filename)
 {
     /* Prepare sfinfo */
@@ -2440,7 +1508,7 @@ Server_start_rec_internal(Server *self, char *filename)
     /* Open the output file. */
     if (filename == NULL) {
         Server_debug(self, "recpath : %s\n", self->recpath);
-        if (! (self->recfile = sf_open(self->recpath, SFM_WRITE, &self->recinfo))) {   
+        if (! (self->recfile = sf_open(self->recpath, SFM_WRITE, &self->recinfo))) {
             Server_error(self, "Not able to open output file %s.\n", self->recpath);
             Server_debug(self, "%s\n", sf_strerror(self->recfile));
             return -1;
@@ -2448,13 +1516,18 @@ Server_start_rec_internal(Server *self, char *filename)
     }
     else {
         Server_debug(self, "filename : %s\n", filename);
-        if (! (self->recfile = sf_open(filename, SFM_WRITE, &self->recinfo))) {   
+        if (! (self->recfile = sf_open(filename, SFM_WRITE, &self->recinfo))) {
             Server_error(self, "Not able to open output file %s.\n", filename);
             Server_debug(self, "%s\n", sf_strerror(self->recfile));
             return -1;
         }
     }
-    
+
+    /* Sets the encoding quality for FLAC and OGG compressed formats. */
+    if (self->recformat == 5 || self->recformat == 7) {
+        sf_command(self->recfile, SFC_SET_VBR_ENCODING_QUALITY, &self->recquality, sizeof(double));
+    }
+
     self->record = 1;
     return 0;
 }
@@ -2464,19 +1537,18 @@ Server_stop_rec(Server *self, PyObject *args)
 {
     self->record = 0;
     sf_close(self->recfile);
-    
-    Py_INCREF(Py_None);
-    return Py_None;
+
+    Py_RETURN_NONE;
 }
 
 static PyObject *
 Server_addStream(Server *self, PyObject *args)
 {
     PyObject *tmp;
-    
+
     if (! PyArg_ParseTuple(args, "O", &tmp))
-        return PyInt_FromLong(-1); 
-        
+        return PyInt_FromLong(-1);
+
     if (tmp == NULL) {
         Server_error(self, "Server_addStream needs a pyo object as argument.\n");
         return PyInt_FromLong(-1);
@@ -2485,9 +1557,8 @@ Server_addStream(Server *self, PyObject *args)
     PyList_Append(self->streams, tmp);
 
     self->stream_count++;
-    
-    Py_INCREF(Py_None);
-    return Py_None;
+
+    Py_RETURN_NONE;
 }
 
 PyObject *
@@ -2495,20 +1566,25 @@ Server_removeStream(Server *self, int id)
 {
     int i, sid;
     Stream *stream_tmp;
-    
-    for (i=0; i<self->stream_count; i++) {
-        stream_tmp = (Stream *)PyList_GET_ITEM(self->streams, i);
-        sid = Stream_getStreamId(stream_tmp);
-        if (sid == id) {
-            Server_debug(self, "Removed stream id %d\n", id);
-            PySequence_DelItem(self->streams, i);
-            self->stream_count--;
-            break;
+    PyGILState_STATE s = PyGILState_Ensure();
+    //if (PyObject_HasAttrString((PyObject *)self, "streams")) {
+    if (PySequence_Size(self->streams) != -1) {
+        for (i=0; i<self->stream_count; i++) {
+            stream_tmp = (Stream *)PyList_GetItem(self->streams, i);
+            if (stream_tmp != NULL) {
+                sid = Stream_getStreamId(stream_tmp);
+                if (sid == id) {
+                    Server_debug(self, "Removed stream id %d\n", id);
+                    PySequence_DelItem(self->streams, i);
+                    self->stream_count--;
+                    break;
+                }
+            }
         }
     }
+    PyGILState_Release(s);
 
-    Py_INCREF(Py_None);
-    return Py_None;    
+    Py_RETURN_NONE;
 }
 
 PyObject *
@@ -2518,11 +1594,11 @@ Server_changeStreamPosition(Server *self, PyObject *args)
     Stream *ref_stream_tmp, *cur_stream_tmp, *stream_tmp;
 
     if (! PyArg_ParseTuple(args, "OO", &ref_stream_tmp, &cur_stream_tmp))
-        return PyInt_FromLong(-1); 
+        return PyInt_FromLong(-1);
 
     rsid = Stream_getStreamId(ref_stream_tmp);
     csid = Stream_getStreamId(cur_stream_tmp);
-    
+
     for (i=0; i<self->stream_count; i++) {
         stream_tmp = (Stream *)PyList_GET_ITEM(self->streams, i);
         sid = Stream_getStreamId(stream_tmp);
@@ -2545,30 +1621,165 @@ Server_changeStreamPosition(Server *self, PyObject *args)
     PyList_Insert(self->streams, i, (PyObject *)cur_stream_tmp);
     self->stream_count++;
 
-    Py_INCREF(Py_None);
-    return Py_None;    
+    Py_RETURN_NONE;
+}
+
+void pyoGetMidiEvents(Server *self) {
+    switch (self->midi_be_type) {
+        case PyoPortmidi:
+            portmidiGetEvents(self);
+            break;
+        default:
+            break;
+    }
 }
 
 PyObject *
-Server_sendMidiNote(Server *self, PyObject *args)
+Server_noteout(Server *self, PyObject *args)
 {
-    int pit, vel, chan, curtime;
-    PmEvent buffer[1];
-    PmTimestamp timestamp;
+    int pit, vel, chan;
+    PyoMidiTimestamp timestamp;
 
-    if (! PyArg_ParseTuple(args, "iiii", &pit, &vel, &chan, &timestamp))
-        return PyInt_FromLong(-1); 
+    if (! PyArg_ParseTuple(args, "iiil", &pit, &vel, &chan, &timestamp))
+        return PyInt_FromLong(-1);
 
-    curtime = Pt_Time();
-    buffer[0].timestamp = curtime + timestamp;
-    if (chan == 0)
-        buffer[0].message = Pm_Message(0x90, pit, vel);
-    else
-        buffer[0].message = Pm_Message(0x90 | (chan - 1), pit, vel);
-    Pm_Write(self->out, buffer, 1);
+    if (self->withPortMidiOut) {
+        switch (self->midi_be_type) {
+            case PyoPortmidi:
+                pm_noteout(self, pit, vel, chan, timestamp);
+                break;
+            default:
+                break;
+        }
+    }
+    Py_RETURN_NONE;
+}
+
+PyObject *
+Server_afterout(Server *self, PyObject *args)
+{
+    int pit, vel, chan;
+    PyoMidiTimestamp timestamp;
+
+    if (! PyArg_ParseTuple(args, "iiil", &pit, &vel, &chan, &timestamp))
+        return PyInt_FromLong(-1);
+
+    if (self->withPortMidiOut) {
+        switch (self->midi_be_type) {
+            case PyoPortmidi:
+                pm_afterout(self, pit, vel, chan, timestamp);
+                break;
+            default:
+                break;
+        }
+    }
+    Py_RETURN_NONE;
+}
+
+PyObject *
+Server_ctlout(Server *self, PyObject *args)
+{
+    int ctlnum, value, chan;
+    PyoMidiTimestamp timestamp;
+
+    if (! PyArg_ParseTuple(args, "iiil", &ctlnum, &value, &chan, &timestamp))
+        return PyInt_FromLong(-1);
+
+    if (self->withPortMidiOut) {
+        switch (self->midi_be_type) {
+            case PyoPortmidi:
+                pm_ctlout(self, ctlnum, value, chan, timestamp);
+                break;
+            default:
+                break;
+        }
+    }
+    Py_RETURN_NONE;
+}
+
+PyObject *
+Server_programout(Server *self, PyObject *args)
+{
+    int value, chan;
+    PyoMidiTimestamp timestamp;
+
+    if (! PyArg_ParseTuple(args, "iil", &value, &chan, &timestamp))
+        return PyInt_FromLong(-1);
+
+    if (self->withPortMidiOut) {
+        switch (self->midi_be_type) {
+            case PyoPortmidi:
+                pm_programout(self, value, chan, timestamp);
+                break;
+            default:
+                break;
+        }
+    }
+    Py_RETURN_NONE;
+}
+
+PyObject *
+Server_pressout(Server *self, PyObject *args)
+{
+    int value, chan;
+    PyoMidiTimestamp timestamp;
+
+    if (! PyArg_ParseTuple(args, "iil", &value, &chan, &timestamp))
+        return PyInt_FromLong(-1);
+
+    if (self->withPortMidiOut) {
+        switch (self->midi_be_type) {
+            case PyoPortmidi:
+                pm_pressout(self, value, chan, timestamp);
+                break;
+            default:
+                break;
+        }
+    }
+    Py_RETURN_NONE;
+}
+
+PyObject *
+Server_bendout(Server *self, PyObject *args)
+{
+    int value, chan;
+    PyoMidiTimestamp timestamp;
+
+    if (! PyArg_ParseTuple(args, "iil", &value, &chan, &timestamp))
+        return PyInt_FromLong(-1);
+
+    if (self->withPortMidiOut) {
+        switch (self->midi_be_type) {
+            case PyoPortmidi:
+                pm_bendout(self, value, chan, timestamp);
+                break;
+            default:
+                break;
+        }
+    }
+    Py_RETURN_NONE;
+}
+
+PyObject *
+Server_sysexout(Server *self, PyObject *args)
+{
+    unsigned char *msg;
+    int size;
+    PyoMidiTimestamp timestamp;
+
+    if (! PyArg_ParseTuple(args, "s#l", &msg, &size, &timestamp))
+        return PyInt_FromLong(-1);
 
-    Py_INCREF(Py_None);
-    return Py_None;    
+    if (self->withPortMidiOut) {
+        switch (self->midi_be_type) {
+            case PyoPortmidi:
+                pm_sysexout(self, msg, timestamp);
+                break;
+            default:
+                break;
+        }
+    }
+    Py_RETURN_NONE;
 }
 
 MYFLT *
@@ -2576,9 +1787,9 @@ Server_getInputBuffer(Server *self) {
     return (MYFLT *)self->input_buffer;
 }
 
-PmEvent *
+PyoMidiEvent *
 Server_getMidiEventBuffer(Server *self) {
-    return (PmEvent *)self->midiEvents;
+    return (PyoMidiEvent *)self->midiEvents;
 }
 
 int
@@ -2586,10 +1797,47 @@ Server_getMidiEventCount(Server *self) {
     return self->midi_count;
 }
 
+long
+Server_getMidiTimeOffset(Server *self) {
+    return self->midi_time_offset;
+}
+
+unsigned long Server_getElapsedTime(Server *self) {
+    return self->elapsedSamples;
+}
+
+static PyObject *
+Server_addMidiEvent(Server *self, PyObject *args)
+{
+    int status, data1, data2;
+    PyoMidiEvent buffer;
+    
+    if (! PyArg_ParseTuple(args, "iii", &status, &data1, &data2))
+        return PyInt_FromLong(-1);
+
+    buffer.timestamp = 0;
+    buffer.message = PyoMidi_Message(status, data1, data2);
+    self->midiEvents[self->midi_count++] = buffer;
+    Py_RETURN_NONE;
+}
+
+int
+Server_getCurrentResamplingFactor(Server *self) {
+    return self->currentResampling;
+}
+
+int
+Server_getLastResamplingFactor(Server *self) {
+    return self->lastResampling;
+}
+
 static PyObject *
 Server_getSamplingRate(Server *self)
 {
-    return PyFloat_FromDouble(self->samplingRate);
+    if (self->currentResampling < 0)
+        return PyFloat_FromDouble(self->samplingRate / -self->currentResampling);
+    else
+        return PyFloat_FromDouble(self->samplingRate * self->currentResampling);
 }
 
 static PyObject *
@@ -2599,6 +1847,12 @@ Server_getNchnls(Server *self)
 }
 
 static PyObject *
+Server_getIchnls(Server *self)
+{
+    return PyInt_FromLong(self->ichnls);
+}
+
+static PyObject *
 Server_getGlobalSeed(Server *self)
 {
     return PyInt_FromLong(self->globalSeed);
@@ -2607,7 +1861,40 @@ Server_getGlobalSeed(Server *self)
 static PyObject *
 Server_getBufferSize(Server *self)
 {
-    return PyInt_FromLong(self->bufferSize);
+    if (self->currentResampling < 0)
+        return PyInt_FromLong(self->bufferSize / -self->currentResampling);
+    else
+        return PyInt_FromLong(self->bufferSize * self->currentResampling);
+}
+
+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)) {
+        self->lastResampling = self->currentResampling;
+        self->currentResampling = PyInt_AsLong(arg);
+    }
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+Server_endResamplingBlock(Server *self)
+{
+    self->lastResampling = self->currentResampling;
+    self->currentResampling = 1;
+    Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -2639,8 +1926,7 @@ static PyObject *
 Server_setServer(Server *self)
 {
     serverID = self->thisServerID;
-    /* Should return a more conventional signal, like True or False */
-    return PyString_FromString("Server set");
+    return PyInt_FromLong(serverID);
 }
 
 
@@ -2649,7 +1935,7 @@ Server_getInputAddr(Server *self)
 {
     char address[32];
     sprintf(address, "%p", &self->input_buffer[0]);
-    return PyString_FromString(address);
+    return PyUnicode_FromString(address);
 }
 
 
@@ -2658,7 +1944,7 @@ Server_getOutputAddr(Server *self)
 {
     char address[32];
     sprintf(address, "%p", &self->output_buffer[0]);
-    return PyString_FromString(address);
+    return PyUnicode_FromString(address);
 }
 
 static PyObject *
@@ -2672,7 +1958,7 @@ Server_getServerAddr(Server *self)
 {
     char address[32];
     sprintf(address, "%p", &my_server[self->thisServerID]);
-    return PyString_FromString(address);
+    return PyUnicode_FromString(address);
 }
 
 void
@@ -2687,7 +1973,7 @@ Server_getThisServerFunc(Server *self)
 {
     char address[32];
     sprintf(address, "%p", &Server_getThisServer);
-    return PyString_FromString(address);
+    return PyUnicode_FromString(address);
 }
 */
 
@@ -2696,7 +1982,50 @@ Server_getEmbedICallbackAddr(Server *self)
 {
     char address[32];
     sprintf(address, "%p", &Server_embedded_i_startIdx);
-    return PyString_FromString(address);
+    return PyUnicode_FromString(address);
+}
+
+static PyObject *
+Server_getCurrentTime(Server *self)
+{
+    int hours, minutes, seconds, milliseconds;
+    float sr = self->samplingRate;
+    double sampsToSecs;
+    char curtime[20];
+
+    sampsToSecs = (double)(self->elapsedSamples / sr);
+    seconds = (int)sampsToSecs;
+    milliseconds = (int)((sampsToSecs - seconds) * 1000);
+    minutes = seconds / 60;
+    hours = minutes / 60;
+    minutes = minutes % 60;
+    seconds = seconds % 60;
+    sprintf(curtime, "%02d : %02d : %02d : %03d", hours, minutes, seconds, milliseconds);
+    return PyUnicode_FromString(curtime);
+}
+
+static PyObject *
+Server_getCurrentAmp(Server *self)
+{
+    PyObject *amplist;
+    float rms[self->nchnls];
+    float *out = self->output_buffer;
+    float outAmp;
+    int i,j;
+    for (j=0; j<self->nchnls; j++) {
+        rms[j] = 0.0;
+        for (i=0; i<self->bufferSize; i++) {
+            outAmp = out[(i*self->nchnls)+j];
+            outAmp *= outAmp;
+            if (outAmp > rms[j])
+                rms[j] = outAmp;
+        }
+    }
+    amplist = PyTuple_New(self->nchnls);
+    for (i=0; i<self->nchnls; i++) {
+        PyTuple_SET_ITEM(amplist, i, PyFloat_FromDouble(rms[i]));
+    }
+    return amplist;
 }
 
 static PyMethodDef Server_methods[] = {
@@ -2707,19 +2036,32 @@ static PyMethodDef Server_methods[] = {
     {"setInOutDevice", (PyCFunction)Server_setInOutDevice, METH_O, "Sets both audio input and output device."},
     {"setMidiInputDevice", (PyCFunction)Server_setMidiInputDevice, METH_O, "Sets MIDI input device."},
     {"setMidiOutputDevice", (PyCFunction)Server_setMidiOutputDevice, METH_O, "Sets MIDI output device."},
+    {"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."},
-    {"setNchnls", (PyCFunction)Server_setNchnls, METH_O, "Sets the server's number of channels."},
+    {"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."},
+    {"setIchnls", (PyCFunction)Server_setIchnls, METH_O, "Sets the server's number of input channels."},
     {"setDuplex", (PyCFunction)Server_setDuplex, METH_O, "Sets the server's duplex mode (0 = only out, 1 = in/out)."},
     {"setJackAuto", (PyCFunction)Server_setJackAuto, METH_VARARGS, "Tells the server to auto-connect Jack ports (0 = disable, 1 = enable)."},
+    {"setJackAutoConnectInputPorts", (PyCFunction)Server_setJackAutoConnectInputPorts, METH_O, "Sets a list of ports to auto-connect inputs when using Jack."},
+    {"setJackAutoConnectOutputPorts", (PyCFunction)Server_setJackAutoConnectOutputPorts, METH_O, "Sets a list of ports to auto-connect outputs when using Jack."},
+    {"setJackInputPortNames", (PyCFunction)Server_setJackInputPortNames, METH_O, "Sets the short name of input ports for jack server."},
+    {"setJackOutputPortNames", (PyCFunction)Server_setJackOutputPortNames, METH_O, "Sets the short name of output ports for jack server."},
+    {"setIsJackTransportSlave", (PyCFunction)Server_setIsJackTransportSlave, METH_O, "Sets if the server's start/stop is slave of jack transport."},
     {"setGlobalSeed", (PyCFunction)Server_setGlobalSeed, METH_O, "Sets the server's global seed for random objects."},
     {"setAmp", (PyCFunction)Server_setAmp, METH_O, "Sets the overall amplitude."},
     {"setAmpCallable", (PyCFunction)Server_setAmpCallable, METH_O, "Sets the Server's GUI callable object."},
     {"setTimeCallable", (PyCFunction)Server_setTimeCallable, METH_O, "Sets the Server's TIME callable object."},
+    {"setCallback", (PyCFunction)Server_setCallback, METH_O, "Sets the Server's CALLBACK callable object."},
     {"setVerbosity", (PyCFunction)Server_setVerbosity, METH_O, "Sets the verbosity."},
+    {"allowMicrosoftMidiDevices", (PyCFunction)Server_allowMicrosoftMidiDevices, METH_NOARGS, "Allow Microsoft Midi Mapper or GS Wavetable Synth devices."},
     {"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."},
@@ -2731,23 +2073,34 @@ static PyMethodDef Server_methods[] = {
                                                                 This is for internal use and must never be called by the user."},
     {"changeStreamPosition", (PyCFunction)Server_changeStreamPosition, METH_VARARGS, "Puts an audio stream before another in the stack. \
                                                                 This is for internal use and must never be called by the user."},
-    {"sendMidiNote", (PyCFunction)Server_sendMidiNote, METH_VARARGS, "Send a Midi note to Portmidi output stream."},
+    {"noteout", (PyCFunction)Server_noteout, METH_VARARGS, "Send a Midi note event to Portmidi output stream."},
+    {"afterout", (PyCFunction)Server_afterout, METH_VARARGS, "Send an aftertouch event to Portmidi output stream."},
+    {"ctlout", (PyCFunction)Server_ctlout, METH_VARARGS, "Send a control change event to Portmidi output stream."},
+    {"programout", (PyCFunction)Server_programout, METH_VARARGS, "Send a program change event to Portmidi output stream."},
+    {"pressout", (PyCFunction)Server_pressout, METH_VARARGS, "Send a channel pressure event to Portmidi output stream."},
+    {"bendout", (PyCFunction)Server_bendout, METH_VARARGS, "Send a pitch bend event to Portmidi output stream."},
+    {"sysexout", (PyCFunction)Server_sysexout, METH_VARARGS, "Send a system exclusive message to midi output stream."},
+    {"addMidiEvent", (PyCFunction)Server_addMidiEvent, METH_VARARGS, "Add a midi event manually (without using portmidi callback)."},
     {"getStreams", (PyCFunction)Server_getStreams, METH_NOARGS, "Returns the list of streams added to the server."},
     {"getSamplingRate", (PyCFunction)Server_getSamplingRate, METH_NOARGS, "Returns the server's sampling rate."},
-    {"getNchnls", (PyCFunction)Server_getNchnls, METH_NOARGS, "Returns the server's current number of channels."},
+    {"getNchnls", (PyCFunction)Server_getNchnls, METH_NOARGS, "Returns the server's current number of output channels."},
+    {"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."},
     {"_setDefaultRecPath", (PyCFunction)Server_setDefaultRecPath, METH_VARARGS|METH_KEYWORDS, "Sets the default recording path."},
     {"setServer", (PyCFunction)Server_setServer, METH_NOARGS, "Sets this server as the one to use for new objects when using the embedded device"},
-    {"flush", (PyCFunction)Server_flush, METH_NOARGS, "Flush the server objects"},
     {"getInputAddr", (PyCFunction)Server_getInputAddr, METH_NOARGS, "Get the embedded device input buffer memory address"},
     {"getOutputAddr", (PyCFunction)Server_getOutputAddr, METH_NOARGS, "Get the embedded device output buffer memory address"},
     {"getServerID", (PyCFunction)Server_getServerID, METH_NOARGS, "Get the embedded device server memory address"},
     {"getServerAddr", (PyCFunction)Server_getServerAddr, METH_NOARGS, "Get the embedded device server memory address"},
     {"getEmbedICallbackAddr", (PyCFunction)Server_getEmbedICallbackAddr, METH_NOARGS, "Get the embedded device interleaved callback method memory address"},
+    {"getCurrentTime", (PyCFunction)Server_getCurrentTime, METH_NOARGS, "Get the current time as a formatted string."},
+    {"getCurrentAmp", (PyCFunction)Server_getCurrentAmp, METH_NOARGS, "Get the current global amplitudes as a list of floats."},
     {NULL}  /* Sentinel */
 };
 
@@ -2757,8 +2110,7 @@ static PyMemberDef Server_members[] = {
 };
 
 PyTypeObject ServerType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Server",         /*tp_name*/
     sizeof(Server),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -2766,7 +2118,7 @@ PyTypeObject ServerType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     0,                         /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -2781,10 +2133,10 @@ PyTypeObject ServerType = {
     "Pyo Server object. Handles communication with Portaudio and processing callback loop.",           /* tp_doc */
     (traverseproc)Server_traverse,   /* tp_traverse */
     (inquiry)Server_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 */
     Server_methods,             /* tp_methods */
     Server_members,             /* tp_members */
     0,                      /* tp_getset */
diff --git a/src/engine/streammodule.c b/src/engine/streammodule.c
index e67b6bc..9e800be 100644
--- a/src/engine/streammodule.c
+++ b/src/engine/streammodule.c
@@ -1,21 +1,21 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
@@ -28,8 +28,8 @@
 
 int stream_id = 1;
 
-int 
-Stream_getNewStreamId() 
+int
+Stream_getNewStreamId()
 {
     return stream_id++;
 }
@@ -37,14 +37,14 @@ Stream_getNewStreamId()
 static int
 Stream_traverse(Stream *self, visitproc visit, void *arg)
 {
-    Py_VISIT(self->streamobject);    
+    Py_VISIT(self->streamobject);
     return 0;
 }
 
-static int 
+static int
 Stream_clear(Stream *self)
 {
-    Py_CLEAR(self->streamobject);    
+    Py_CLEAR(self->streamobject);
     return 0;
 }
 
@@ -53,7 +53,7 @@ Stream_dealloc(Stream* self)
 {
     self->data = NULL;
     Stream_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 int
@@ -96,13 +96,13 @@ MYFLT *
 Stream_getData(Stream *self)
 {
     return (MYFLT *)self->data;
-}    
+}
 
 void
 Stream_setData(Stream *self, MYFLT *data)
 {
     self->data = data;
-}    
+}
 
 void Stream_setFunctionPtr(Stream *self, void *ptr)
 {
@@ -112,9 +112,9 @@ void Stream_setFunctionPtr(Stream *self, void *ptr)
 void Stream_callFunction(Stream *self)
 {
     (*self->funcptr)(self->streamobject);
-}    
+}
 
-void Stream_IncrementBufferCount(Stream *self) 
+void Stream_IncrementBufferCount(Stream *self)
 {
     self->bufferCount++;
     if (self->bufferCount >= self->bufferCountWait) {
@@ -123,7 +123,7 @@ void Stream_IncrementBufferCount(Stream *self)
     }
 }
 
-void Stream_IncrementDurationCount(Stream *self) 
+void Stream_IncrementDurationCount(Stream *self)
 {
     self->bufferCount++;
     if (self->bufferCount >= self->duration) {
@@ -152,19 +152,27 @@ Stream_getStreamObject(Stream *self)
 PyObject *
 Stream_isPlaying(Stream *self)
 {
-    if (self->active || self->todac)
-        Py_RETURN_TRUE;
-    else 
-        Py_RETURN_FALSE;
+    if (self->active || self->todac) {
+        Py_INCREF(Py_True);
+        return Py_True;
+    }
+    else {
+        Py_INCREF(Py_False);
+        return Py_False;
+    }
 }
 
 PyObject *
 Stream_isOutputting(Stream *self)
 {
-    if (self->todac)
-        Py_RETURN_TRUE;
-    else 
-        Py_RETURN_FALSE;
+    if (self->todac) {
+        Py_INCREF(Py_True);
+        return Py_True;
+    }
+    else {
+        Py_INCREF(Py_False);
+        return Py_False;
+    }
 }
 
 static PyMethodDef Stream_methods[] = {
@@ -177,8 +185,7 @@ static PyMethodDef Stream_methods[] = {
 };
 
 PyTypeObject StreamType = {
-    PyObject_HEAD_INIT(NULL)
-    0, /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "pyo.Stream", /*tp_name*/
     sizeof(Stream), /*tp_basicsize*/
     0, /*tp_itemsize*/
@@ -186,7 +193,7 @@ PyTypeObject StreamType = {
     0, /*tp_print*/
     0, /*tp_getattr*/
     0, /*tp_setattr*/
-    0, /*tp_compare*/
+    0, /*tp_as_async (tp_compare in Python 2)*/
     0, /*tp_repr*/
     0, /*tp_as_number*/
     0, /*tp_as_sequence*/
@@ -247,24 +254,23 @@ static void
 TriggerStream_dealloc(TriggerStream* self)
 {
     self->data = NULL;
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 MYFLT *
 TriggerStream_getData(TriggerStream *self)
 {
     return (MYFLT *)self->data;
-}    
+}
 
 void
 TriggerStream_setData(TriggerStream *self, MYFLT *data)
 {
     self->data = data;
-}    
+}
 
 PyTypeObject TriggerStreamType = {
-    PyObject_HEAD_INIT(NULL)
-    0, /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "pyo.TriggerStream", /*tp_name*/
     sizeof(TriggerStream), /*tp_basicsize*/
     0, /*tp_itemsize*/
@@ -272,7 +278,7 @@ PyTypeObject TriggerStreamType = {
     0, /*tp_print*/
     0, /*tp_getattr*/
     0, /*tp_setattr*/
-    0, /*tp_compare*/
+    0, /*tp_as_async (tp_compare in Python 2)*/
     0, /*tp_repr*/
     0, /*tp_as_number*/
     0, /*tp_as_sequence*/
@@ -304,4 +310,4 @@ PyTypeObject TriggerStreamType = {
     0, /* tp_init */
     0, /* tp_alloc */
     0, /* tp_new */
-};
+};
\ No newline at end of file
diff --git a/src/engine/wind.c b/src/engine/wind.c
index 8fc1f94..f0ba09d 100644
--- a/src/engine/wind.c
+++ b/src/engine/wind.c
@@ -1,21 +1,21 @@
-/*************************************************************************
- * Copyright 2011 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *                                                                        *
  * Envelope window generator :                                            *
  *      0 : Rectangular (no window)                                       *
@@ -35,8 +35,8 @@
 void gen_window(MYFLT *window, int size, int wintype) {
     int i;
     MYFLT arg;
-   
-    switch (wintype) { 
+
+    switch (wintype) {
         case 0:
             /* Rectangular */
             for (i=0; i<size; i++) {
@@ -122,4 +122,3 @@ void gen_window(MYFLT *window, int size, int wintype) {
     }
     return;
 }
-
diff --git a/src/objects/analysismodule.c b/src/objects/analysismodule.c
index b4ef933..461e2b1 100644
--- a/src/objects/analysismodule.c
+++ b/src/objects/analysismodule.c
@@ -1,23 +1,24 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
@@ -25,6 +26,8 @@
 #include "servermodule.h"
 #include "dummymodule.h"
 #include "interpolation.h"
+#include "fft.h"
+#include "wind.h"
 
 /************/
 /* Follower */
@@ -35,7 +38,7 @@ typedef struct {
     Stream *input_stream;
     PyObject *freq;
     Stream *freq_stream;
-    int modebuffer[3]; // need at least 2 slots for mul & add 
+    int modebuffer[3]; // need at least 2 slots for mul & add
     MYFLT follow;
     MYFLT last_freq;
     MYFLT factor;
@@ -50,10 +53,12 @@ Follower_filters_i(Follower *self) {
     freq = PyFloat_AS_DOUBLE(self->freq);
 
     if (freq != self->last_freq) {
-        self->factor = MYEXP(-1.0 / (self->sr / freq));
+        if (freq < 0)
+            freq = 0.0;
+        self->factor = MYEXP(-TWOPI * freq / self->sr);
         self->last_freq = freq;
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         absin = in[i];
         if (absin < 0.0)
@@ -66,20 +71,22 @@ static void
 Follower_filters_a(Follower *self) {
     MYFLT freq, absin;
     int i;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         freq = fr[i];
         if (freq != self->last_freq) {
-            self->factor = MYEXP(-1.0 / (self->sr / freq));
+            if (freq < 0)
+                freq = 0.0;
+            self->factor = MYEXP(-TWOPI * freq / self->sr);
             self->last_freq = freq;
         }
         absin = in[i];
         if (absin < 0.0)
             absin = -absin;
-        self->follow = self->data[i] = absin + self->factor * (self->follow - absin);        
+        self->follow = self->data[i] = absin + self->factor * (self->follow - absin);
     }
 }
 
@@ -99,50 +106,50 @@ Follower_setProcMode(Follower *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2];
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Follower_filters_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Follower_filters_a;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Follower_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Follower_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Follower_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Follower_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Follower_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Follower_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Follower_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Follower_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Follower_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Follower_compute_next_data_frame(Follower *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -152,19 +159,19 @@ Follower_traverse(Follower *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
     return 0;
 }
 
-static int 
+static int
 Follower_clear(Follower *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
     return 0;
 }
 
@@ -173,7 +180,7 @@ Follower_dealloc(Follower* self)
 {
     pyo_DEALLOC
     Follower_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -183,7 +190,7 @@ Follower_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *multmp=NULL, *addtmp=NULL;
     Follower *self;
     self = (Follower *)type->tp_alloc(type, 0);
-    
+
     self->freq = PyFloat_FromDouble(20);
     self->follow = 0.0;
     self->last_freq = -1.0;
@@ -191,32 +198,32 @@ Follower_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Follower_compute_next_data_frame);
     self->mode_func_ptr = Follower_setProcMode;
 
     static char *kwlist[] = {"input", "freq", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &freqtmp, &multmp, &addtmp))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     INIT_INPUT_STREAM
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    
+
     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;
@@ -224,10 +231,10 @@ Follower_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Follower_getServer(Follower* self) { GET_SERVER };
 static PyObject * Follower_getStream(Follower* self) { GET_STREAM };
-static PyObject * Follower_setMul(Follower *self, PyObject *arg) { SET_MUL };	
-static PyObject * Follower_setAdd(Follower *self, PyObject *arg) { SET_ADD };	
-static PyObject * Follower_setSub(Follower *self, PyObject *arg) { SET_SUB };	
-static PyObject * Follower_setDiv(Follower *self, PyObject *arg) { SET_DIV };	
+static PyObject * Follower_setMul(Follower *self, PyObject *arg) { SET_MUL };
+static PyObject * Follower_setAdd(Follower *self, PyObject *arg) { SET_ADD };
+static PyObject * Follower_setSub(Follower *self, PyObject *arg) { SET_SUB };
+static PyObject * Follower_setDiv(Follower *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Follower_play(Follower *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Follower_stop(Follower *self) { STOP };
@@ -245,14 +252,11 @@ static PyObject *
 Follower_setFreq(Follower *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -268,9 +272,9 @@ Follower_setFreq(Follower *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -302,7 +306,7 @@ static PyNumberMethods Follower_as_number = {
 (binaryfunc)Follower_add,                         /*nb_add*/
 (binaryfunc)Follower_sub,                         /*nb_subtract*/
 (binaryfunc)Follower_multiply,                    /*nb_multiply*/
-(binaryfunc)Follower_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -316,16 +320,16 @@ static PyNumberMethods Follower_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)Follower_inplace_add,                 /*inplace_add*/
 (binaryfunc)Follower_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)Follower_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)Follower_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -334,15 +338,14 @@ static PyNumberMethods Follower_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)Follower_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)Follower_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject FollowerType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Follower_base",                                   /*tp_name*/
 sizeof(Follower),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -350,7 +353,7 @@ sizeof(Follower),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &Follower_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -393,7 +396,7 @@ typedef struct {
     Stream *risetime_stream;
     PyObject *falltime;
     Stream *falltime_stream;
-    int modebuffer[4]; // need at least 2 slots for mul & add 
+    int modebuffer[4]; // need at least 2 slots for mul & add
     MYFLT follow;
     MYFLT last_risetime;
     MYFLT last_falltime;
@@ -405,25 +408,25 @@ static void
 Follower2_filters_ii(Follower2 *self) {
     MYFLT absin, risetime, falltime;
     int i;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     risetime = PyFloat_AS_DOUBLE(self->risetime);
     if (risetime <= 0.0)
-        risetime = 0.001;
+        risetime = 0.000001;
     falltime = PyFloat_AS_DOUBLE(self->falltime);
     if (falltime <= 0.0)
-        falltime = 0.001;
-    
+        falltime = 0.000001;
+
     if (risetime != self->last_risetime) {
-        self->risefactor = MYEXP(-1.0 / (self->sr * risetime));
+        self->risefactor = MYEXP(-TWOPI * (1.0 / risetime) / self->sr);
         self->last_risetime = risetime;
     }
 
     if (falltime != self->last_falltime) {
-        self->fallfactor = MYEXP(-1.0 / (self->sr * falltime));
+        self->fallfactor = MYEXP(-TWOPI * (1.0 / falltime) / self->sr);
         self->last_falltime = falltime;
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         absin = in[i];
         if (absin < 0.0)
@@ -439,24 +442,24 @@ static void
 Follower2_filters_ai(Follower2 *self) {
     MYFLT absin, risetime, falltime;
     int i;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *rise = Stream_getData((Stream *)self->risetime_stream);
     falltime = PyFloat_AS_DOUBLE(self->falltime);
     if (falltime <= 0.0)
-        falltime = 0.001;
+        falltime = 0.000001;
 
     if (falltime != self->last_falltime) {
-        self->fallfactor = MYEXP(-1.0 / (self->sr * falltime));
+        self->fallfactor = MYEXP(-TWOPI * (1.0 / falltime) / self->sr);
         self->last_falltime = falltime;
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         risetime = rise[i];
         if (risetime <= 0.0)
-            risetime = 0.001;
+            risetime = 0.000001;
         if (risetime != self->last_risetime) {
-            self->risefactor = MYEXP(-1.0 / (self->sr * risetime));
+            self->risefactor = MYEXP(-TWOPI * (1.0 / risetime) / self->sr);
             self->last_risetime = risetime;
         }
         absin = in[i];
@@ -473,26 +476,26 @@ static void
 Follower2_filters_ia(Follower2 *self) {
     MYFLT absin, risetime, falltime;
     int i;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     risetime = PyFloat_AS_DOUBLE(self->risetime);
     if (risetime <= 0.0)
-        risetime = 0.001;
+        risetime = 0.000001;
     MYFLT *fall = Stream_getData((Stream *)self->falltime_stream);
-    
+
     if (risetime != self->last_risetime) {
-        self->risefactor = MYEXP(-1.0 / (self->sr * risetime));
+        self->risefactor = MYEXP(-TWOPI * (1.0 / risetime) / self->sr);
         self->last_risetime = risetime;
     }
 
     for (i=0; i<self->bufsize; i++) {
         falltime = fall[i];
         if (falltime <= 0.0)
-            falltime = 0.001;
+            falltime = 0.000001;
         if (falltime != self->last_falltime) {
-            self->fallfactor = MYEXP(-1.0 / (self->sr * falltime));
+            self->fallfactor = MYEXP(-TWOPI * (1.0 / falltime) / self->sr);
             self->last_falltime = falltime;
-        }        
+        }
         absin = in[i];
         if (absin < 0.0)
             absin = -absin;
@@ -507,7 +510,7 @@ static void
 Follower2_filters_aa(Follower2 *self) {
     MYFLT absin, risetime, falltime;
     int i;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *rise = Stream_getData((Stream *)self->risetime_stream);
     MYFLT *fall = Stream_getData((Stream *)self->falltime_stream);
@@ -515,18 +518,18 @@ Follower2_filters_aa(Follower2 *self) {
     for (i=0; i<self->bufsize; i++) {
         risetime = rise[i];
         if (risetime <= 0.0)
-            risetime = 0.001;
+            risetime = 0.000001;
         if (risetime != self->last_risetime) {
-            self->risefactor = MYEXP(-1.0 / (self->sr * risetime));
+            self->risefactor = MYEXP(-TWOPI * (1.0 / risetime) / self->sr);
             self->last_risetime = risetime;
         }
         falltime = fall[i];
         if (falltime <= 0.0)
-            falltime = 0.001;
+            falltime = 0.000001;
         if (falltime != self->last_falltime) {
-            self->fallfactor = MYEXP(-1.0 / (self->sr * falltime));
+            self->fallfactor = MYEXP(-TWOPI * (1.0 / falltime) / self->sr);
             self->last_falltime = falltime;
-        }        
+        }
         absin = in[i];
         if (absin < 0.0)
             absin = -absin;
@@ -553,56 +556,56 @@ Follower2_setProcMode(Follower2 *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Follower2_filters_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Follower2_filters_ai;
             break;
-        case 10:    
+        case 10:
             self->proc_func_ptr = Follower2_filters_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Follower2_filters_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Follower2_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Follower2_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Follower2_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Follower2_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Follower2_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Follower2_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Follower2_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Follower2_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Follower2_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Follower2_compute_next_data_frame(Follower2 *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -612,23 +615,23 @@ Follower2_traverse(Follower2 *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->risetime);    
-    Py_VISIT(self->risetime_stream);    
-    Py_VISIT(self->falltime);    
-    Py_VISIT(self->falltime_stream);    
+    Py_VISIT(self->risetime);
+    Py_VISIT(self->risetime_stream);
+    Py_VISIT(self->falltime);
+    Py_VISIT(self->falltime_stream);
     return 0;
 }
 
-static int 
+static int
 Follower2_clear(Follower2 *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->risetime);    
-    Py_CLEAR(self->risetime_stream);    
-    Py_CLEAR(self->falltime);    
-    Py_CLEAR(self->falltime_stream);    
+    Py_CLEAR(self->risetime);
+    Py_CLEAR(self->risetime_stream);
+    Py_CLEAR(self->falltime);
+    Py_CLEAR(self->falltime_stream);
     return 0;
 }
 
@@ -637,7 +640,7 @@ Follower2_dealloc(Follower2* self)
 {
     pyo_DEALLOC
     Follower2_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -647,7 +650,7 @@ Follower2_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *risetimetmp=NULL, *falltimetmp=NULL, *multmp=NULL, *addtmp=NULL;
     Follower2 *self;
     self = (Follower2 *)type->tp_alloc(type, 0);
-    
+
     self->risetime = PyFloat_FromDouble(0.01);
     self->falltime = PyFloat_FromDouble(0.1);
     self->follow = 0.0;
@@ -658,36 +661,36 @@ Follower2_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Follower2_compute_next_data_frame);
     self->mode_func_ptr = Follower2_setProcMode;
 
     static char *kwlist[] = {"input", "risetime", "falltime", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &risetimetmp, &falltimetmp, &multmp, &addtmp))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     INIT_INPUT_STREAM
-    
+
     if (risetimetmp) {
         PyObject_CallMethod((PyObject *)self, "setRisetime", "O", risetimetmp);
     }
-    
+
     if (falltimetmp) {
         PyObject_CallMethod((PyObject *)self, "setFalltime", "O", falltimetmp);
     }
-    
+
     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;
@@ -695,10 +698,10 @@ Follower2_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Follower2_getServer(Follower2* self) { GET_SERVER };
 static PyObject * Follower2_getStream(Follower2* self) { GET_STREAM };
-static PyObject * Follower2_setMul(Follower2 *self, PyObject *arg) { SET_MUL };	
-static PyObject * Follower2_setAdd(Follower2 *self, PyObject *arg) { SET_ADD };	
-static PyObject * Follower2_setSub(Follower2 *self, PyObject *arg) { SET_SUB };	
-static PyObject * Follower2_setDiv(Follower2 *self, PyObject *arg) { SET_DIV };	
+static PyObject * Follower2_setMul(Follower2 *self, PyObject *arg) { SET_MUL };
+static PyObject * Follower2_setAdd(Follower2 *self, PyObject *arg) { SET_ADD };
+static PyObject * Follower2_setSub(Follower2 *self, PyObject *arg) { SET_SUB };
+static PyObject * Follower2_setDiv(Follower2 *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Follower2_play(Follower2 *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Follower2_stop(Follower2 *self) { STOP };
@@ -716,14 +719,11 @@ static PyObject *
 Follower2_setRisetime(Follower2 *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->risetime);
@@ -739,9 +739,9 @@ Follower2_setRisetime(Follower2 *self, PyObject *arg)
         self->risetime_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -750,14 +750,11 @@ static PyObject *
 Follower2_setFalltime(Follower2 *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->falltime);
@@ -773,9 +770,9 @@ Follower2_setFalltime(Follower2 *self, PyObject *arg)
         self->falltime_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -809,7 +806,7 @@ static PyNumberMethods Follower2_as_number = {
     (binaryfunc)Follower2_add,                         /*nb_add*/
     (binaryfunc)Follower2_sub,                         /*nb_subtract*/
     (binaryfunc)Follower2_multiply,                    /*nb_multiply*/
-    (binaryfunc)Follower2_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -823,16 +820,16 @@ static PyNumberMethods Follower2_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Follower2_inplace_add,                 /*inplace_add*/
     (binaryfunc)Follower2_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Follower2_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Follower2_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -841,15 +838,14 @@ static PyNumberMethods Follower2_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Follower2_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Follower2_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject Follower2Type = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Follower2_base",                                   /*tp_name*/
     sizeof(Follower2),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -857,7 +853,7 @@ PyTypeObject Follower2Type = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &Follower2_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -908,7 +904,7 @@ ZCross_process(ZCross *self) {
     int count = 0;
     MYFLT inval;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = self->lastValue;
         inval = in[i];
@@ -940,44 +936,44 @@ ZCross_setProcMode(ZCross *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = ZCross_process;
- 
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = ZCross_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = ZCross_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = ZCross_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = ZCross_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = ZCross_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = ZCross_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = ZCross_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = ZCross_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = ZCross_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 ZCross_compute_next_data_frame(ZCross *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -990,7 +986,7 @@ ZCross_traverse(ZCross *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 ZCross_clear(ZCross *self)
 {
     pyo_CLEAR
@@ -1004,7 +1000,7 @@ ZCross_dealloc(ZCross* self)
 {
     pyo_DEALLOC
     ZCross_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1014,33 +1010,33 @@ ZCross_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     ZCross *self;
     self = (ZCross *)type->tp_alloc(type, 0);
-    
+
     self->thresh = 0.0;
     self->lastValue = self->lastSample = 0.0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, ZCross_compute_next_data_frame);
     self->mode_func_ptr = ZCross_setProcMode;
 
     static char *kwlist[] = {"input", "thresh", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_FOO, kwlist, &inputtmp, &self->thresh, &multmp, &addtmp))
-        Py_RETURN_NONE; 
+        Py_RETURN_NONE;
 
     INIT_INPUT_STREAM
-    
+
     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;
@@ -1048,10 +1044,10 @@ ZCross_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * ZCross_getServer(ZCross* self) { GET_SERVER };
 static PyObject * ZCross_getStream(ZCross* self) { GET_STREAM };
-static PyObject * ZCross_setMul(ZCross *self, PyObject *arg) { SET_MUL };	
-static PyObject * ZCross_setAdd(ZCross *self, PyObject *arg) { SET_ADD };	
-static PyObject * ZCross_setSub(ZCross *self, PyObject *arg) { SET_SUB };	
-static PyObject * ZCross_setDiv(ZCross *self, PyObject *arg) { SET_DIV };	
+static PyObject * ZCross_setMul(ZCross *self, PyObject *arg) { SET_MUL };
+static PyObject * ZCross_setAdd(ZCross *self, PyObject *arg) { SET_ADD };
+static PyObject * ZCross_setSub(ZCross *self, PyObject *arg) { SET_SUB };
+static PyObject * ZCross_setDiv(ZCross *self, PyObject *arg) { SET_DIV };
 
 static PyObject * ZCross_play(ZCross *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * ZCross_stop(ZCross *self) { STOP };
@@ -1068,17 +1064,14 @@ static PyObject * ZCross_inplace_div(ZCross *self, PyObject *arg) { INPLACE_DIV
 static PyObject *
 ZCross_setThresh(ZCross *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	if (isNumber == 1) {
-		self->thresh = PyFloat_AS_DOUBLE(PyNumber_Float(arg));
+		self->thresh = PyFloat_AsDouble(arg);
 	}
-  
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -1109,7 +1102,7 @@ static PyNumberMethods ZCross_as_number = {
 (binaryfunc)ZCross_add,                         /*nb_add*/
 (binaryfunc)ZCross_sub,                         /*nb_subtract*/
 (binaryfunc)ZCross_multiply,                    /*nb_multiply*/
-(binaryfunc)ZCross_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -1123,16 +1116,16 @@ static PyNumberMethods ZCross_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)ZCross_inplace_add,                 /*inplace_add*/
 (binaryfunc)ZCross_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)ZCross_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)ZCross_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -1141,15 +1134,14 @@ static PyNumberMethods ZCross_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)ZCross_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)ZCross_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject ZCrossType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.ZCross_base",                                   /*tp_name*/
 sizeof(ZCross),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -1157,7 +1149,7 @@ sizeof(ZCross),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &ZCross_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -1245,17 +1237,16 @@ typedef struct {
 static void
 Yin_process(Yin *self) {
     int i, j, period, tau = 0;
-    MYFLT candidate, tmp = 0.0, tmp2 = 0.0, b = 0.0;
+    MYFLT candidate, tmp = 0.0, tmp2 = 0.0;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->cutoff != self->last_cutoff) {
         if (self->cutoff <= 1.0)
             self->cutoff = 1.0;
         else if (self->cutoff >= self->sr*0.5)
-            self->cutoff = self->sr*0.5;        
+            self->cutoff = self->sr*0.5;
         self->last_cutoff = self->cutoff;
-        b = 2.0 - MYCOS(TWOPI * self->cutoff / self->sr);
-        self->c2 = (b - MYSQRT(b * b - 1.0));
+        self->c2 = MYEXP(-TWOPI * self->cutoff / self->sr);
     }
 
     for (i=0; i<self->bufsize; i++) {
@@ -1263,7 +1254,7 @@ Yin_process(Yin *self) {
         self->input_buffer[self->input_count] = self->y1;
         if (self->input_count++ == self->winsize) {
             self->input_count = 0;
- 
+
             self->yin_buffer[0] = 1.0;
             for (tau = 1; tau < self->halfsize; tau++) {
                 self->yin_buffer[tau] = 0.0;
@@ -1283,10 +1274,10 @@ Yin_process(Yin *self) {
             candidate = quadraticInterpolation(self->yin_buffer, min_elem_pos(self->yin_buffer, self->halfsize), self->halfsize);
 
         founded:
-            
+
             candidate = self->sr / candidate;
             if (candidate > self->minfreq && candidate < self->maxfreq)
-                self->pitch = candidate;           
+                self->pitch = candidate;
 
         }
         self->data[i] = self->pitch;
@@ -1308,44 +1299,44 @@ Yin_setProcMode(Yin *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = Yin_process;
- 
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Yin_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Yin_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Yin_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Yin_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Yin_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Yin_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Yin_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Yin_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Yin_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Yin_compute_next_data_frame(Yin *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1358,7 +1349,7 @@ Yin_traverse(Yin *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Yin_clear(Yin *self)
 {
     pyo_CLEAR
@@ -1374,7 +1365,7 @@ Yin_dealloc(Yin* self)
     free(self->input_buffer);
     free(self->yin_buffer);
     Yin_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1384,7 +1375,7 @@ Yin_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     Yin *self;
     self = (Yin *)type->tp_alloc(type, 0);
-    
+
     self->winsize = 1024;
     self->halfsize = 512;
     self->input_count = 0;
@@ -1397,40 +1388,40 @@ Yin_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->y1 = self->c2 = 0.0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Yin_compute_next_data_frame);
     self->mode_func_ptr = Yin_setProcMode;
 
     static char *kwlist[] = {"input", "tolerance", "minfreq", "maxfreq", "cutoff", "winsize", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_FFFFIOO, kwlist, &inputtmp, &self->tolerance, &self->minfreq, &self->maxfreq, &self->cutoff, &self->winsize, &multmp, &addtmp))
-        Py_RETURN_NONE; 
+        Py_RETURN_NONE;
 
     INIT_INPUT_STREAM
-    
+
     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);
 
     if (self->winsize % 2 == 1)
         self->winsize += 1;
 
-    self->input_buffer = (MYFLT *)realloc(self->input_buffer, self->winsize * sizeof(MYFLT)); 
+    self->input_buffer = (MYFLT *)realloc(self->input_buffer, self->winsize * sizeof(MYFLT));
     for (i=0; i<self->winsize; i++)
         self->input_buffer[i] = 0.0;
 
     self->halfsize = self->winsize / 2;
-    self->yin_buffer = (MYFLT *)realloc(self->yin_buffer, self->halfsize * sizeof(MYFLT)); 
+    self->yin_buffer = (MYFLT *)realloc(self->yin_buffer, self->halfsize * sizeof(MYFLT));
     for (i=0; i<self->halfsize; i++)
         self->yin_buffer[i] = 0.0;
-       
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
@@ -1438,10 +1429,10 @@ Yin_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Yin_getServer(Yin* self) { GET_SERVER };
 static PyObject * Yin_getStream(Yin* self) { GET_STREAM };
-static PyObject * Yin_setMul(Yin *self, PyObject *arg) { SET_MUL };	
-static PyObject * Yin_setAdd(Yin *self, PyObject *arg) { SET_ADD };	
-static PyObject * Yin_setSub(Yin *self, PyObject *arg) { SET_SUB };	
-static PyObject * Yin_setDiv(Yin *self, PyObject *arg) { SET_DIV };	
+static PyObject * Yin_setMul(Yin *self, PyObject *arg) { SET_MUL };
+static PyObject * Yin_setAdd(Yin *self, PyObject *arg) { SET_ADD };
+static PyObject * Yin_setSub(Yin *self, PyObject *arg) { SET_SUB };
+static PyObject * Yin_setDiv(Yin *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Yin_play(Yin *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Yin_stop(Yin *self) { STOP };
@@ -1458,68 +1449,56 @@ static PyObject * Yin_inplace_div(Yin *self, PyObject *arg) { INPLACE_DIV };
 static PyObject *
 Yin_setTolerance(Yin *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	if (isNumber == 1) {
-		self->tolerance = PyFloat_AS_DOUBLE(PyNumber_Float(arg));
+		self->tolerance = PyFloat_AsDouble(arg);
 	}
-  
+
 	Py_RETURN_NONE;
 }
 
 static PyObject *
 Yin_setMinfreq(Yin *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	if (isNumber == 1) {
-		self->minfreq = PyFloat_AS_DOUBLE(PyNumber_Float(arg));
+		self->minfreq = PyFloat_AsDouble(arg);
 	}
-  
+
 	Py_RETURN_NONE;
 }
 
 static PyObject *
 Yin_setMaxfreq(Yin *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	if (isNumber == 1) {
-		self->maxfreq = PyFloat_AS_DOUBLE(PyNumber_Float(arg));
+		self->maxfreq = PyFloat_AsDouble(arg);
 	}
-  
+
 	Py_RETURN_NONE;
 }
 
 static PyObject *
 Yin_setCutoff(Yin *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	if (isNumber == 1) {
-		self->cutoff = PyFloat_AS_DOUBLE(PyNumber_Float(arg));
+		self->cutoff = PyFloat_AsDouble(arg);
 	}
-  
+
 	Py_RETURN_NONE;
 }
 
@@ -1552,7 +1531,7 @@ static PyNumberMethods Yin_as_number = {
 (binaryfunc)Yin_add,                         /*nb_add*/
 (binaryfunc)Yin_sub,                         /*nb_subtract*/
 (binaryfunc)Yin_multiply,                    /*nb_multiply*/
-(binaryfunc)Yin_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -1566,16 +1545,16 @@ static PyNumberMethods Yin_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)Yin_inplace_add,                 /*inplace_add*/
 (binaryfunc)Yin_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)Yin_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)Yin_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -1584,15 +1563,14 @@ static PyNumberMethods Yin_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)Yin_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)Yin_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject YinType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Yin_base",                                   /*tp_name*/
 sizeof(Yin),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -1600,7 +1578,7 @@ sizeof(Yin),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &Yin_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -1630,4 +1608,1308 @@ Yin_members,                                 /* tp_members */
 0,                          /* tp_init */
 0,                                              /* tp_alloc */
 Yin_new,                                     /* tp_new */
+};
+
+/********************/
+/* Centroid */
+/********************/
+
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *input;
+    Stream *input_stream;
+    int size;
+    int hsize;
+    int incount;
+    MYFLT centroid;
+    MYFLT *inframe;
+    MYFLT *outframe;
+    MYFLT **twiddle;
+    MYFLT *input_buffer;
+    MYFLT *window;
+    int modebuffer[2];
+} Centroid;
+
+static void
+Centroid_alloc_memories(Centroid *self) {
+    int i, n8;
+    self->hsize = self->size / 2;
+    n8 = self->size >> 3;
+    self->inframe = (MYFLT *)realloc(self->inframe, self->size * sizeof(MYFLT));
+    self->outframe = (MYFLT *)realloc(self->outframe, self->size * sizeof(MYFLT));
+    self->input_buffer = (MYFLT *)realloc(self->input_buffer, self->size * sizeof(MYFLT));
+    for (i=0; i<self->size; i++)
+        self->inframe[i] = self->outframe[i] = self->input_buffer[i] = 0.0;
+    self->twiddle = (MYFLT **)realloc(self->twiddle, 4 * sizeof(MYFLT *));
+    for(i=0; i<4; i++)
+        self->twiddle[i] = (MYFLT *)malloc(n8 * sizeof(MYFLT));
+    fft_compute_split_twiddle(self->twiddle, self->size);
+    self->window = (MYFLT *)realloc(self->window, self->size * sizeof(MYFLT));
+    gen_window(self->window, self->size, 2);
+}
+
+static void
+Centroid_process_i(Centroid *self) {
+    int i;
+    MYFLT re, im, tmp, sum1, sum2;
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+
+    for (i=0; i<self->bufsize; i++) {
+        self->input_buffer[self->incount] = in[i];
+        self->data[i] = self->centroid;
+
+        self->incount++;
+        if (self->incount == self->size) {
+            self->incount = self->hsize;
+
+            for (i=0; i<self->size; i++) {
+                self->inframe[i] = self->input_buffer[i] * self->window[i];
+            }
+            realfft_split(self->inframe, self->outframe, self->size, self->twiddle);
+            sum1 = sum2 = 0.0;
+            for (i=1; i<self->hsize; i++) {
+                re = self->outframe[i];
+                im = self->outframe[self->size - i];
+                tmp = MYSQRT(re*re + im*im);
+                sum1 += tmp * i;
+                sum2 += tmp;
+            }
+            if (sum2 < 0.000000001)
+                tmp = 0.0;
+            else
+                tmp = sum1 / sum2;
+            self->centroid += tmp * self->sr / self->size;
+            self->centroid *= 0.5;
+            for (i=0; i<self->hsize; i++) {
+                self->input_buffer[i] = self->input_buffer[i + self->hsize];
+            }
+        }
+    }
+}
+
+static void Centroid_postprocessing_ii(Centroid *self) { POST_PROCESSING_II };
+static void Centroid_postprocessing_ai(Centroid *self) { POST_PROCESSING_AI };
+static void Centroid_postprocessing_ia(Centroid *self) { POST_PROCESSING_IA };
+static void Centroid_postprocessing_aa(Centroid *self) { POST_PROCESSING_AA };
+static void Centroid_postprocessing_ireva(Centroid *self) { POST_PROCESSING_IREVA };
+static void Centroid_postprocessing_areva(Centroid *self) { POST_PROCESSING_AREVA };
+static void Centroid_postprocessing_revai(Centroid *self) { POST_PROCESSING_REVAI };
+static void Centroid_postprocessing_revaa(Centroid *self) { POST_PROCESSING_REVAA };
+static void Centroid_postprocessing_revareva(Centroid *self) { POST_PROCESSING_REVAREVA };
+
+static void
+Centroid_setProcMode(Centroid *self)
+{
+    int muladdmode;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+    self->proc_func_ptr = Centroid_process_i;
+
+    switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = Centroid_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = Centroid_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = Centroid_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = Centroid_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = Centroid_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = Centroid_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = Centroid_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = Centroid_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = Centroid_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+Centroid_compute_next_data_frame(Centroid *self)
+{
+    (*self->proc_func_ptr)(self);
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+Centroid_traverse(Centroid *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->input);
+    Py_VISIT(self->input_stream);
+    return 0;
+}
+
+static int
+Centroid_clear(Centroid *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->input);
+    Py_CLEAR(self->input_stream);
+    return 0;
+}
+
+static void
+Centroid_dealloc(Centroid* self)
+{
+    int i;
+    pyo_DEALLOC
+    free(self->inframe);
+    free(self->outframe);
+    free(self->input_buffer);
+    for(i=0; i<4; i++) {
+        free(self->twiddle[i]);
+    }
+    free(self->twiddle);
+    free(self->window);
+    Centroid_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+Centroid_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i, k;
+    PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
+    Centroid *self;
+    self = (Centroid *)type->tp_alloc(type, 0);
+
+    self->centroid = 0;
+    self->size = 1024;
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, Centroid_compute_next_data_frame);
+    self->mode_func_ptr = Centroid_setProcMode;
+
+    static char *kwlist[] = {"input", "size", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOO", kwlist, &inputtmp, &self->size, &multmp, &addtmp))
+        Py_RETURN_NONE;
+
+    if (self->size < self->bufsize) {
+        PySys_WriteStdout("Warning : Centroid size less than buffer size!\nCentroid size set to buffersize: %d\n", self->bufsize);
+        self->size = self->bufsize;
+    }
+
+    k = 1;
+    while (k < self->size)
+        k <<= 1;
+    self->size = k;
+
+    INIT_INPUT_STREAM
+
+    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);
+
+    Centroid_alloc_memories(self);
+
+    self->incount = self->hsize;
+
+    (*self->mode_func_ptr)(self);
+
+    return (PyObject *)self;
+}
+
+static PyObject * Centroid_getServer(Centroid* self) { GET_SERVER };
+static PyObject * Centroid_getStream(Centroid* self) { GET_STREAM };
+static PyObject * Centroid_setMul(Centroid *self, PyObject *arg) { SET_MUL };
+static PyObject * Centroid_setAdd(Centroid *self, PyObject *arg) { SET_ADD };
+static PyObject * Centroid_setSub(Centroid *self, PyObject *arg) { SET_SUB };
+static PyObject * Centroid_setDiv(Centroid *self, PyObject *arg) { SET_DIV };
+
+static PyObject * Centroid_play(Centroid *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * Centroid_stop(Centroid *self) { STOP };
+
+static PyObject * Centroid_multiply(Centroid *self, PyObject *arg) { MULTIPLY };
+static PyObject * Centroid_inplace_multiply(Centroid *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * Centroid_add(Centroid *self, PyObject *arg) { ADD };
+static PyObject * Centroid_inplace_add(Centroid *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * Centroid_sub(Centroid *self, PyObject *arg) { SUB };
+static PyObject * Centroid_inplace_sub(Centroid *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * Centroid_div(Centroid *self, PyObject *arg) { DIV };
+static PyObject * Centroid_inplace_div(Centroid *self, PyObject *arg) { INPLACE_DIV };
+
+
+static PyMemberDef Centroid_members[] = {
+{"server", T_OBJECT_EX, offsetof(Centroid, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(Centroid, stream), 0, "Stream object."},
+{"mul", T_OBJECT_EX, offsetof(Centroid, mul), 0, "Mul factor."},
+{"add", T_OBJECT_EX, offsetof(Centroid, add), 0, "Add factor."},
+{"input", T_OBJECT_EX, offsetof(Centroid, input), 0, "Input sound object."},
+{NULL}  /* Sentinel */
+};
+
+static PyMethodDef Centroid_methods[] = {
+{"getServer", (PyCFunction)Centroid_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)Centroid_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)Centroid_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"stop", (PyCFunction)Centroid_stop, METH_NOARGS, "Stops computing."},
+{"setMul", (PyCFunction)Centroid_setMul, METH_O, "Sets Centroid mul factor."},
+{"setAdd", (PyCFunction)Centroid_setAdd, METH_O, "Sets Centroid add factor."},
+{"setSub", (PyCFunction)Centroid_setSub, METH_O, "Sets Centroid add factor."},
+{"setDiv", (PyCFunction)Centroid_setDiv, METH_O, "Sets Centroid mul factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyNumberMethods Centroid_as_number = {
+    (binaryfunc)Centroid_add,                      /*nb_add*/
+    (binaryfunc)Centroid_sub,                 /*nb_subtract*/
+    (binaryfunc)Centroid_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)Centroid_inplace_add,              /*inplace_add*/
+    (binaryfunc)Centroid_inplace_sub,         /*inplace_subtract*/
+    (binaryfunc)Centroid_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)Centroid_div,                       /*nb_true_divide*/
+    0,     /*nb_inplace_floor_divide*/
+    (binaryfunc)Centroid_inplace_div,                       /*nb_inplace_true_divide*/
+    0,                     /* nb_index */
+};
+
+PyTypeObject CentroidType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.Centroid_base",                                   /*tp_name*/
+sizeof(Centroid),                                 /*tp_basicsize*/
+0,                                              /*tp_itemsize*/
+(destructor)Centroid_dealloc,                     /*tp_dealloc*/
+0,                                              /*tp_print*/
+0,                                              /*tp_getattr*/
+0,                                              /*tp_setattr*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
+0,                                              /*tp_repr*/
+&Centroid_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*/
+"Centroid objects. FFT transform.",           /* tp_doc */
+(traverseproc)Centroid_traverse,                  /* tp_traverse */
+(inquiry)Centroid_clear,                          /* tp_clear */
+0,                                              /* tp_richcompare */
+0,                                              /* tp_weaklistoffset */
+0,                                              /* tp_iter */
+0,                                              /* tp_iternext */
+Centroid_methods,                                 /* tp_methods */
+Centroid_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 */
+Centroid_new,                                     /* tp_new */
+};
+
+/************/
+/* AttackDetector */
+/************/
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *input;
+    Stream *input_stream;
+    MYFLT deltime;
+    MYFLT cutoff;
+    MYFLT maxthresh;
+    MYFLT minthresh;
+    MYFLT reltime;
+    MYFLT folfactor;
+    MYFLT follow;
+    MYFLT followdb;
+    MYFLT *buffer;
+    MYFLT previous;
+    int memsize;
+    int sampdel;
+    int incount;
+    int overminok;
+    int belowminok;
+    long maxtime;
+    long timer;
+    int modebuffer[2]; // need at least 2 slots for mul & add
+} AttackDetector;
+
+static void
+AttackDetector_process(AttackDetector *self) {
+    int i, ind;
+    MYFLT absin;
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+
+    for (i=0; i<self->bufsize; i++) {
+        self->data[i] = 0.0;
+        absin = in[i];
+        // envelope follower
+        if (absin < 0.0)
+            absin = -absin;
+        self->follow = absin + self->folfactor * (self->follow - absin);
+        // follower in dB
+        if (self->follow <= 0.000001)
+            self->followdb = -120.0;
+        else
+            self->followdb = 20.0 * MYLOG10(self->follow);
+        // previous analysis
+        ind = self->incount - self->sampdel;
+        if (ind < 0)
+            ind += self->memsize;
+        self->previous = self->buffer[ind];
+        self->buffer[self->incount] = self->followdb;
+        self->incount++;
+        if (self->incount >= self->memsize)
+            self->incount = 0;
+        // if release time has past
+        if (self->timer >= self->maxtime) {
+            // if rms is over min threshold
+            if (self->overminok) {
+                // if rms is greater than previous + maxthresh
+                if (self->followdb > (self->previous + self->maxthresh)) {
+                    self->data[i] = 1.0;
+                    self->overminok = self->belowminok = 0;
+                    self->timer = 0;
+                }
+            }
+        }
+        if (self->belowminok == 0 && self->followdb < self->minthresh)
+            self->belowminok = 1;
+        else if (self->belowminok == 1 && self->followdb > self->minthresh)
+            self->overminok = 1;
+        self->timer++;
+    }
+}
+
+static void AttackDetector_postprocessing_ii(AttackDetector *self) { POST_PROCESSING_II };
+static void AttackDetector_postprocessing_ai(AttackDetector *self) { POST_PROCESSING_AI };
+static void AttackDetector_postprocessing_ia(AttackDetector *self) { POST_PROCESSING_IA };
+static void AttackDetector_postprocessing_aa(AttackDetector *self) { POST_PROCESSING_AA };
+static void AttackDetector_postprocessing_ireva(AttackDetector *self) { POST_PROCESSING_IREVA };
+static void AttackDetector_postprocessing_areva(AttackDetector *self) { POST_PROCESSING_AREVA };
+static void AttackDetector_postprocessing_revai(AttackDetector *self) { POST_PROCESSING_REVAI };
+static void AttackDetector_postprocessing_revaa(AttackDetector *self) { POST_PROCESSING_REVAA };
+static void AttackDetector_postprocessing_revareva(AttackDetector *self) { POST_PROCESSING_REVAREVA };
+
+static void
+AttackDetector_setProcMode(AttackDetector *self)
+{
+    int muladdmode;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+    self->proc_func_ptr = AttackDetector_process;
+
+	switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = AttackDetector_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = AttackDetector_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = AttackDetector_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = AttackDetector_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = AttackDetector_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = AttackDetector_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = AttackDetector_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = AttackDetector_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = AttackDetector_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+AttackDetector_compute_next_data_frame(AttackDetector *self)
+{
+    (*self->proc_func_ptr)(self);
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+AttackDetector_traverse(AttackDetector *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->input);
+    Py_VISIT(self->input_stream);
+    return 0;
+}
+
+static int
+AttackDetector_clear(AttackDetector *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->input);
+    Py_CLEAR(self->input_stream);
+    return 0;
+}
+
+static void
+AttackDetector_dealloc(AttackDetector* self)
+{
+    pyo_DEALLOC
+    free(self->buffer);
+    AttackDetector_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+AttackDetector_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
+    AttackDetector *self;
+    self = (AttackDetector *)type->tp_alloc(type, 0);
+
+    self->deltime = 0.005;
+    self->cutoff = 10.0;
+    self->maxthresh = 3.0;
+    self->minthresh = -30.0;
+    self->reltime = 0.1;
+    self->follow = 0.0;
+    self->followdb = -120.0;
+    self->previous = 0.0;
+    self->incount = 0;
+    self->overminok = 0;
+    self->belowminok = 0;
+    self->timer = 0;
+	self->modebuffer[0] = 0;
+	self->modebuffer[1] = 0;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, AttackDetector_compute_next_data_frame);
+    self->mode_func_ptr = AttackDetector_setProcMode;
+
+    static char *kwlist[] = {"input", "deltime", "cutoff", "maxthresh", "minthresh", "reltime", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_FFFFFOO, kwlist, &inputtmp, &self->deltime, &self->cutoff, &self->maxthresh, &self->minthresh, &self->reltime, &multmp, &addtmp))
+        Py_RETURN_NONE;
+
+    INIT_INPUT_STREAM
+
+    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->memsize = (int)(0.055 * self->sr + 0.5);
+    self->buffer = (MYFLT *)realloc(self->buffer, (self->memsize+1) * sizeof(MYFLT));
+    for (i=0; i<(self->memsize+1); i++) {
+        self->buffer[i] = 0.0;
+    }
+
+    if (self->deltime < 0.001) self->deltime = 0.001;
+    else if (self->deltime > 0.05) self->deltime = 0.05;
+    self->sampdel = (int)(self->deltime * self->sr);
+
+    if (self->cutoff < 1.0) self->cutoff = 1.0;
+    else if (self->cutoff > 1000.0) self->cutoff = 1000.0;
+    self->folfactor = MYEXP(-TWOPI * self->cutoff / self->sr);
+
+    if (self->cutoff < 1.0) self->cutoff = 1.0;
+    else if (self->cutoff > 1000.0) self->cutoff = 1000.0;
+
+    if (self->maxthresh < 0.0) self->maxthresh = 0.0;
+    else if (self->maxthresh > 18.0) self->maxthresh = 18.0;
+
+    if (self->minthresh < -90.0) self->minthresh = -90.0;
+    else if (self->minthresh > 0.0) self->minthresh = 0.0;
+
+    if (self->reltime < 0.001) self->reltime = 0.001;
+    self->maxtime = (long)(self->reltime * self->sr + 0.5);
+
+    (*self->mode_func_ptr)(self);
+
+    return (PyObject *)self;
+}
+
+static PyObject * AttackDetector_getServer(AttackDetector* self) { GET_SERVER };
+static PyObject * AttackDetector_getStream(AttackDetector* self) { GET_STREAM };
+static PyObject * AttackDetector_setMul(AttackDetector *self, PyObject *arg) { SET_MUL };
+static PyObject * AttackDetector_setAdd(AttackDetector *self, PyObject *arg) { SET_ADD };
+static PyObject * AttackDetector_setSub(AttackDetector *self, PyObject *arg) { SET_SUB };
+static PyObject * AttackDetector_setDiv(AttackDetector *self, PyObject *arg) { SET_DIV };
+
+static PyObject * AttackDetector_play(AttackDetector *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * AttackDetector_stop(AttackDetector *self) { STOP };
+
+static PyObject * AttackDetector_multiply(AttackDetector *self, PyObject *arg) { MULTIPLY };
+static PyObject * AttackDetector_inplace_multiply(AttackDetector *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * AttackDetector_add(AttackDetector *self, PyObject *arg) { ADD };
+static PyObject * AttackDetector_inplace_add(AttackDetector *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * AttackDetector_sub(AttackDetector *self, PyObject *arg) { SUB };
+static PyObject * AttackDetector_inplace_sub(AttackDetector *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * AttackDetector_div(AttackDetector *self, PyObject *arg) { DIV };
+static PyObject * AttackDetector_inplace_div(AttackDetector *self, PyObject *arg) { INPLACE_DIV };
+
+static PyObject *
+AttackDetector_setDeltime(AttackDetector *self, PyObject *arg)
+{
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	if (isNumber == 1) {
+		self->deltime = PyFloat_AsDouble(arg);
+        if (self->deltime < 0.001) self->deltime = 0.001;
+        else if (self->deltime > 0.05) self->deltime = 0.05;
+        self->sampdel = (int)(self->deltime * self->sr);
+	}
+
+	Py_RETURN_NONE;
+}
+
+static PyObject *
+AttackDetector_setCutoff(AttackDetector *self, PyObject *arg)
+{
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	if (isNumber == 1) {
+		self->cutoff = PyFloat_AsDouble(arg);
+        if (self->cutoff < 1.0) self->cutoff = 1.0;
+        else if (self->cutoff > 1000.0) self->cutoff = 1000.0;
+        self->folfactor = MYEXP(-TWOPI * self->cutoff / self->sr);
+	}
+
+	Py_RETURN_NONE;
+}
+
+static PyObject *
+AttackDetector_setMaxthresh(AttackDetector *self, PyObject *arg)
+{
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	if (isNumber == 1) {
+		self->maxthresh = PyFloat_AsDouble(arg);
+        if (self->maxthresh < 0.0) self->maxthresh = 0.0;
+        else if (self->maxthresh > 18.0) self->maxthresh = 18.0;
+	}
+
+	Py_RETURN_NONE;
+}
+
+static PyObject *
+AttackDetector_setMinthresh(AttackDetector *self, PyObject *arg)
+{
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	if (isNumber == 1) {
+		self->minthresh = PyFloat_AsDouble(arg);
+        if (self->minthresh < -90.0) self->minthresh = -90.0;
+        else if (self->minthresh > 0.0) self->minthresh = 0.0;
+	}
+
+	Py_RETURN_NONE;
+}
+
+static PyObject *
+AttackDetector_setReltime(AttackDetector *self, PyObject *arg)
+{
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	if (isNumber == 1) {
+		self->reltime = PyFloat_AsDouble(arg);
+        if (self->reltime < 0.001) self->reltime = 0.001;
+        self->maxtime = (long)(self->reltime * self->sr + 0.5);
+	}
+
+	Py_RETURN_NONE;
+}
+
+static PyObject *
+AttackDetector_readyToDetect(AttackDetector *self)
+{
+    self->overminok = 1;
+    self->timer = self->maxtime;
+	Py_RETURN_NONE;
+}
+
+static PyMemberDef AttackDetector_members[] = {
+{"server", T_OBJECT_EX, offsetof(AttackDetector, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(AttackDetector, stream), 0, "Stream object."},
+{"input", T_OBJECT_EX, offsetof(AttackDetector, input), 0, "Input sound object."},
+{"mul", T_OBJECT_EX, offsetof(AttackDetector, mul), 0, "Mul factor."},
+{"add", T_OBJECT_EX, offsetof(AttackDetector, add), 0, "Add factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyMethodDef AttackDetector_methods[] = {
+{"getServer", (PyCFunction)AttackDetector_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)AttackDetector_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)AttackDetector_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"stop", (PyCFunction)AttackDetector_stop, METH_NOARGS, "Stops computing."},
+{"setDeltime", (PyCFunction)AttackDetector_setDeltime, METH_O, "Sets the delay time between current and previous analysis."},
+{"setCutoff", (PyCFunction)AttackDetector_setCutoff, METH_O, "Sets the frequency of the internal lowpass filter."},
+{"setMaxthresh", (PyCFunction)AttackDetector_setMaxthresh, METH_O, "Sets the higher threshold."},
+{"setMinthresh", (PyCFunction)AttackDetector_setMinthresh, METH_O, "Sets the lower threshold."},
+{"setReltime", (PyCFunction)AttackDetector_setReltime, METH_O, "Sets the release time (min time between two detected attacks)."},
+{"readyToDetect", (PyCFunction)AttackDetector_readyToDetect, METH_NOARGS, "Initializes thresholds."},
+{"setMul", (PyCFunction)AttackDetector_setMul, METH_O, "Sets oscillator mul factor."},
+{"setAdd", (PyCFunction)AttackDetector_setAdd, METH_O, "Sets oscillator add factor."},
+{"setSub", (PyCFunction)AttackDetector_setSub, METH_O, "Sets inverse add factor."},
+{"setDiv", (PyCFunction)AttackDetector_setDiv, METH_O, "Sets inverse mul factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyNumberMethods AttackDetector_as_number = {
+(binaryfunc)AttackDetector_add,                         /*nb_add*/
+(binaryfunc)AttackDetector_sub,                         /*nb_subtract*/
+(binaryfunc)AttackDetector_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)AttackDetector_inplace_add,                 /*inplace_add*/
+(binaryfunc)AttackDetector_inplace_sub,                 /*inplace_subtract*/
+(binaryfunc)AttackDetector_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)AttackDetector_div,                       /*nb_true_divide*/
+0,                                              /*nb_inplace_floor_divide*/
+(binaryfunc)AttackDetector_inplace_div,                       /*nb_inplace_true_divide*/
+0,                                              /* nb_index */
+};
+
+PyTypeObject AttackDetectorType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.AttackDetector_base",                                   /*tp_name*/
+sizeof(AttackDetector),                                 /*tp_basicsize*/
+0,                                              /*tp_itemsize*/
+(destructor)AttackDetector_dealloc,                     /*tp_dealloc*/
+0,                                              /*tp_print*/
+0,                                              /*tp_getattr*/
+0,                                              /*tp_setattr*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
+0,                                              /*tp_repr*/
+&AttackDetector_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*/
+"AttackDetector objects. Audio signal peak detection.",           /* tp_doc */
+(traverseproc)AttackDetector_traverse,                  /* tp_traverse */
+(inquiry)AttackDetector_clear,                          /* tp_clear */
+0,                                              /* tp_richcompare */
+0,                                              /* tp_weaklistoffset */
+0,                                              /* tp_iter */
+0,                                              /* tp_iternext */
+AttackDetector_methods,                                 /* tp_methods */
+AttackDetector_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 */
+AttackDetector_new,                                     /* tp_new */
+};
+
+/**********************************/
+/********* Scope ******************/
+/**********************************/
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *input;
+    Stream *input_stream;
+    int size;
+    int width;
+    int height;
+    int pointer;
+    MYFLT gain;
+    MYFLT *buffer;
+} Scope;
+
+static void
+Scope_generate(Scope *self) {
+    int i;
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+    for (i=0; i<self->bufsize; i++) {
+        if (self->pointer >= self->size)
+            self->pointer = 0;
+        self->buffer[self->pointer] = in[i];
+        self->pointer++;
+    }
+}
+
+static PyObject *
+Scope_display(Scope *self) {
+    int i, ipos;
+    MYFLT pos, step, mag, h2;
+    PyObject *points, *tuple;
+
+    step = self->size / (MYFLT)(self->width);
+    h2 = self->height * 0.5;
+
+    points = PyList_New(self->width);
+
+    for (i=0; i<self->width; i++) {
+        pos = i * step;
+        ipos = (int)pos;
+        tuple = PyTuple_New(2);
+        mag = ((self->buffer[ipos] + (self->buffer[ipos+1] - self->buffer[ipos]) * (pos - ipos)) * self->gain * h2 + h2);
+        PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(i));
+        PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->height - (int)mag));
+        PyList_SET_ITEM(points, i, tuple);
+    }
+    return points;
+}
+
+static void
+Scope_compute_next_data_frame(Scope *self)
+{
+    Scope_generate(self);
+}
+
+static int
+Scope_traverse(Scope *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->input);
+    Py_VISIT(self->input_stream);
+    return 0;
+}
+
+static int
+Scope_clear(Scope *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->input);
+    Py_CLEAR(self->input_stream);
+    return 0;
+}
+
+static void
+Scope_dealloc(Scope* self)
+{
+    pyo_DEALLOC
+    free(self->buffer);
+    Scope_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+Scope_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i, maxsize;
+    MYFLT length = 0.05;
+    PyObject *inputtmp, *input_streamtmp;
+    Scope *self;
+    self = (Scope *)type->tp_alloc(type, 0);
+
+    self->gain = 1.0;
+    self->width = 500;
+    self->height = 400;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, Scope_compute_next_data_frame);
+
+    static char *kwlist[] = {"input", "length", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_F, kwlist, &inputtmp, &length))
+        Py_RETURN_NONE;
+
+    INIT_INPUT_STREAM
+
+    maxsize = (int)(self->sr * 0.25);
+    self->buffer = (MYFLT *)realloc(self->buffer, maxsize * sizeof(MYFLT));
+    self->size = (int)(length * self->sr);
+    if (self->size > maxsize)
+        self->size = maxsize;
+    self->pointer = 0;
+
+    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
+
+    return (PyObject *)self;
+}
+
+static PyObject * Scope_getServer(Scope* self) { GET_SERVER };
+static PyObject * Scope_getStream(Scope* self) { GET_STREAM };
+
+static PyObject * Scope_play(Scope *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * Scope_stop(Scope *self) { STOP };
+
+static PyObject *
+Scope_setLength(Scope *self, PyObject *arg)
+{
+    MYFLT length;
+    int maxsize = (int)(self->sr * 0.25);
+
+    if (PyNumber_Check(arg)) {
+        length = PyFloat_AsDouble(arg);
+        self->size = (int)(length * self->sr);
+        if (self->size > maxsize)
+            self->size = maxsize;
+        self->pointer = 0;
+    }
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+Scope_setGain(Scope *self, PyObject *arg)
+{
+    if (PyNumber_Check(arg)) {
+        self->gain = PyFloat_AsDouble(arg);
+    }
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+Scope_setWidth(Scope *self, PyObject *arg)
+{
+    if (PyInt_Check(arg)) {
+        self->width = PyInt_AsLong(arg);
+    }
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+Scope_setHeight(Scope *self, PyObject *arg)
+{
+    if (PyInt_Check(arg)) {
+        self->height = PyInt_AsLong(arg);
+    }
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyMemberDef Scope_members[] = {
+{"server", T_OBJECT_EX, offsetof(Scope, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(Scope, stream), 0, "Stream object."},
+{"input", T_OBJECT_EX, offsetof(Scope, input), 0, "Input sound object."},
+{NULL}  /* Sentinel */
+};
+
+static PyMethodDef Scope_methods[] = {
+{"getServer", (PyCFunction)Scope_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)Scope_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)Scope_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"stop", (PyCFunction)Scope_stop, METH_NOARGS, "Stops computing."},
+{"display", (PyCFunction)Scope_display, METH_NOARGS, "Computes the samples to draw."},
+{"setLength", (PyCFunction)Scope_setLength, METH_O, "Sets function's argument."},
+{"setGain", (PyCFunction)Scope_setGain, METH_O, "Sets gain compensation."},
+{"setWidth", (PyCFunction)Scope_setWidth, METH_O, "Sets the width of the display."},
+{"setHeight", (PyCFunction)Scope_setHeight, METH_O, "Sets the height of the display."},
+{NULL}  /* Sentinel */
+};
+
+PyTypeObject ScopeType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.Scope_base",                                   /*tp_name*/
+sizeof(Scope),                                 /*tp_basicsize*/
+0,                                              /*tp_itemsize*/
+(destructor)Scope_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*/
+"Scope objects. Show the waveform of an input signal.",           /* tp_doc */
+(traverseproc)Scope_traverse,                  /* tp_traverse */
+(inquiry)Scope_clear,                          /* tp_clear */
+0,                                              /* tp_richcompare */
+0,                                              /* tp_weaklistoffset */
+0,                                              /* tp_iter */
+0,                                              /* tp_iternext */
+Scope_methods,                                 /* tp_methods */
+Scope_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 */
+Scope_new,                                     /* tp_new */
+};
+
+/************/
+/* PeakAmp */
+/************/
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *input;
+    Stream *input_stream;
+    int modebuffer[2]; // need at least 2 slots for mul & add
+    MYFLT follow;
+} PeakAmp;
+
+static void
+PeakAmp_filters_i(PeakAmp *self) {
+    MYFLT absin, peak;
+    int i;
+
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+
+    peak = 0.0;
+    for (i=0; i<self->bufsize; i++) {
+        absin = in[i];
+        if (absin < 0.0)
+            absin = -absin;
+        if (absin > peak)
+            peak = absin;
+        self->data[i] = self->follow;
+    }
+    self->follow = peak;
+}
+
+static void PeakAmp_postprocessing_ii(PeakAmp *self) { POST_PROCESSING_II };
+static void PeakAmp_postprocessing_ai(PeakAmp *self) { POST_PROCESSING_AI };
+static void PeakAmp_postprocessing_ia(PeakAmp *self) { POST_PROCESSING_IA };
+static void PeakAmp_postprocessing_aa(PeakAmp *self) { POST_PROCESSING_AA };
+static void PeakAmp_postprocessing_ireva(PeakAmp *self) { POST_PROCESSING_IREVA };
+static void PeakAmp_postprocessing_areva(PeakAmp *self) { POST_PROCESSING_AREVA };
+static void PeakAmp_postprocessing_revai(PeakAmp *self) { POST_PROCESSING_REVAI };
+static void PeakAmp_postprocessing_revaa(PeakAmp *self) { POST_PROCESSING_REVAA };
+static void PeakAmp_postprocessing_revareva(PeakAmp *self) { POST_PROCESSING_REVAREVA };
+
+static void
+PeakAmp_setProcMode(PeakAmp *self)
+{
+    int muladdmode;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+    self->proc_func_ptr = PeakAmp_filters_i;
+	switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = PeakAmp_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = PeakAmp_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = PeakAmp_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = PeakAmp_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = PeakAmp_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = PeakAmp_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = PeakAmp_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = PeakAmp_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = PeakAmp_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+PeakAmp_compute_next_data_frame(PeakAmp *self)
+{
+    (*self->proc_func_ptr)(self);
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+PeakAmp_traverse(PeakAmp *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->input);
+    Py_VISIT(self->input_stream);
+    return 0;
+}
+
+static int
+PeakAmp_clear(PeakAmp *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->input);
+    Py_CLEAR(self->input_stream);
+    return 0;
+}
+
+static void
+PeakAmp_dealloc(PeakAmp* self)
+{
+    pyo_DEALLOC
+    PeakAmp_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+PeakAmp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
+    PeakAmp *self;
+    self = (PeakAmp *)type->tp_alloc(type, 0);
+
+    self->follow = 0.0;
+	self->modebuffer[0] = 0;
+	self->modebuffer[1] = 0;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, PeakAmp_compute_next_data_frame);
+    self->mode_func_ptr = PeakAmp_setProcMode;
+
+    static char *kwlist[] = {"input", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp))
+        Py_RETURN_NONE;
+
+    INIT_INPUT_STREAM
+
+    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 * PeakAmp_getServer(PeakAmp* self) { GET_SERVER };
+static PyObject * PeakAmp_getStream(PeakAmp* self) { GET_STREAM };
+static PyObject * PeakAmp_setMul(PeakAmp *self, PyObject *arg) { SET_MUL };
+static PyObject * PeakAmp_setAdd(PeakAmp *self, PyObject *arg) { SET_ADD };
+static PyObject * PeakAmp_setSub(PeakAmp *self, PyObject *arg) { SET_SUB };
+static PyObject * PeakAmp_setDiv(PeakAmp *self, PyObject *arg) { SET_DIV };
+
+static PyObject * PeakAmp_play(PeakAmp *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * PeakAmp_stop(PeakAmp *self) { STOP };
+
+static PyObject * PeakAmp_multiply(PeakAmp *self, PyObject *arg) { MULTIPLY };
+static PyObject * PeakAmp_inplace_multiply(PeakAmp *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * PeakAmp_add(PeakAmp *self, PyObject *arg) { ADD };
+static PyObject * PeakAmp_inplace_add(PeakAmp *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * PeakAmp_sub(PeakAmp *self, PyObject *arg) { SUB };
+static PyObject * PeakAmp_inplace_sub(PeakAmp *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * PeakAmp_div(PeakAmp *self, PyObject *arg) { DIV };
+static PyObject * PeakAmp_inplace_div(PeakAmp *self, PyObject *arg) { INPLACE_DIV };
+
+static PyObject *
+PeakAmp_getValue(PeakAmp *self)
+{
+    return PyFloat_FromDouble(self->follow);
+}
+
+static PyMemberDef PeakAmp_members[] = {
+{"server", T_OBJECT_EX, offsetof(PeakAmp, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(PeakAmp, stream), 0, "Stream object."},
+{"input", T_OBJECT_EX, offsetof(PeakAmp, input), 0, "Input sound object."},
+{"mul", T_OBJECT_EX, offsetof(PeakAmp, mul), 0, "Mul factor."},
+{"add", T_OBJECT_EX, offsetof(PeakAmp, add), 0, "Add factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyMethodDef PeakAmp_methods[] = {
+{"getServer", (PyCFunction)PeakAmp_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)PeakAmp_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)PeakAmp_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"stop", (PyCFunction)PeakAmp_stop, METH_NOARGS, "Stops computing."},
+{"getValue", (PyCFunction)PeakAmp_getValue, METH_NOARGS, "Returns the current peaking value."},
+{"setMul", (PyCFunction)PeakAmp_setMul, METH_O, "Sets oscillator mul factor."},
+{"setAdd", (PyCFunction)PeakAmp_setAdd, METH_O, "Sets oscillator add factor."},
+{"setSub", (PyCFunction)PeakAmp_setSub, METH_O, "Sets inverse add factor."},
+{"setDiv", (PyCFunction)PeakAmp_setDiv, METH_O, "Sets inverse mul factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyNumberMethods PeakAmp_as_number = {
+(binaryfunc)PeakAmp_add,                         /*nb_add*/
+(binaryfunc)PeakAmp_sub,                         /*nb_subtract*/
+(binaryfunc)PeakAmp_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)PeakAmp_inplace_add,                 /*inplace_add*/
+(binaryfunc)PeakAmp_inplace_sub,                 /*inplace_subtract*/
+(binaryfunc)PeakAmp_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)PeakAmp_div,                       /*nb_true_divide*/
+0,                                              /*nb_inplace_floor_divide*/
+(binaryfunc)PeakAmp_inplace_div,                       /*nb_inplace_true_divide*/
+0,                                              /* nb_index */
+};
+
+PyTypeObject PeakAmpType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.PeakAmp_base",                                   /*tp_name*/
+sizeof(PeakAmp),                                 /*tp_basicsize*/
+0,                                              /*tp_itemsize*/
+(destructor)PeakAmp_dealloc,                     /*tp_dealloc*/
+0,                                              /*tp_print*/
+0,                                              /*tp_getattr*/
+0,                                              /*tp_setattr*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
+0,                                              /*tp_repr*/
+&PeakAmp_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*/
+"PeakAmp objects. Envelope follower.",           /* tp_doc */
+(traverseproc)PeakAmp_traverse,                  /* tp_traverse */
+(inquiry)PeakAmp_clear,                          /* tp_clear */
+0,                                              /* tp_richcompare */
+0,                                              /* tp_weaklistoffset */
+0,                                              /* tp_iter */
+0,                                              /* tp_iternext */
+PeakAmp_methods,                                 /* tp_methods */
+PeakAmp_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 */
+PeakAmp_new,                                     /* tp_new */
 };
\ No newline at end of file
diff --git a/src/objects/arithmeticmodule.c b/src/objects/arithmeticmodule.c
index 1c06284..b22ba3b 100644
--- a/src/objects/arithmeticmodule.c
+++ b/src/objects/arithmeticmodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
@@ -40,7 +41,7 @@ static void
 M_Sin_process(M_Sin *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = MYSIN(in[i]);
     }
@@ -61,44 +62,44 @@ M_Sin_setProcMode(M_Sin *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = M_Sin_process;
- 
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = M_Sin_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = M_Sin_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = M_Sin_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = M_Sin_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = M_Sin_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = M_Sin_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = M_Sin_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = M_Sin_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = M_Sin_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 M_Sin_compute_next_data_frame(M_Sin *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -111,7 +112,7 @@ M_Sin_traverse(M_Sin *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 M_Sin_clear(M_Sin *self)
 {
     pyo_CLEAR
@@ -125,7 +126,7 @@ M_Sin_dealloc(M_Sin* self)
 {
     pyo_DEALLOC
     M_Sin_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -138,28 +139,28 @@ M_Sin_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, M_Sin_compute_next_data_frame);
     self->mode_func_ptr = M_Sin_setProcMode;
 
     static char *kwlist[] = {"input", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
 
     INIT_INPUT_STREAM
-    
+
     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;
@@ -167,10 +168,10 @@ M_Sin_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * M_Sin_getServer(M_Sin* self) { GET_SERVER };
 static PyObject * M_Sin_getStream(M_Sin* self) { GET_STREAM };
-static PyObject * M_Sin_setMul(M_Sin *self, PyObject *arg) { SET_MUL };	
-static PyObject * M_Sin_setAdd(M_Sin *self, PyObject *arg) { SET_ADD };	
-static PyObject * M_Sin_setSub(M_Sin *self, PyObject *arg) { SET_SUB };	
-static PyObject * M_Sin_setDiv(M_Sin *self, PyObject *arg) { SET_DIV };	
+static PyObject * M_Sin_setMul(M_Sin *self, PyObject *arg) { SET_MUL };
+static PyObject * M_Sin_setAdd(M_Sin *self, PyObject *arg) { SET_ADD };
+static PyObject * M_Sin_setSub(M_Sin *self, PyObject *arg) { SET_SUB };
+static PyObject * M_Sin_setDiv(M_Sin *self, PyObject *arg) { SET_DIV };
 
 static PyObject * M_Sin_play(M_Sin *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * M_Sin_out(M_Sin *self, PyObject *args, PyObject *kwds) { OUT };
@@ -211,7 +212,7 @@ static PyNumberMethods M_Sin_as_number = {
 (binaryfunc)M_Sin_add,                         /*nb_add*/
 (binaryfunc)M_Sin_sub,                         /*nb_subtract*/
 (binaryfunc)M_Sin_multiply,                    /*nb_multiply*/
-(binaryfunc)M_Sin_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -225,16 +226,16 @@ static PyNumberMethods M_Sin_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)M_Sin_inplace_add,                 /*inplace_add*/
 (binaryfunc)M_Sin_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)M_Sin_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)M_Sin_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -243,15 +244,14 @@ static PyNumberMethods M_Sin_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)M_Sin_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)M_Sin_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject M_SinType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.M_Sin_base",                                   /*tp_name*/
 sizeof(M_Sin),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -259,7 +259,7 @@ sizeof(M_Sin),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &M_Sin_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -305,7 +305,7 @@ static void
 M_Cos_process(M_Cos *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = MYCOS(in[i]);
     }
@@ -326,44 +326,44 @@ M_Cos_setProcMode(M_Cos *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = M_Cos_process;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = M_Cos_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = M_Cos_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = M_Cos_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = M_Cos_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = M_Cos_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = M_Cos_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = M_Cos_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = M_Cos_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = M_Cos_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 M_Cos_compute_next_data_frame(M_Cos *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -376,7 +376,7 @@ M_Cos_traverse(M_Cos *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 M_Cos_clear(M_Cos *self)
 {
     pyo_CLEAR
@@ -390,7 +390,7 @@ M_Cos_dealloc(M_Cos* self)
 {
     pyo_DEALLOC
     M_Cos_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -400,31 +400,31 @@ M_Cos_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     M_Cos *self;
     self = (M_Cos *)type->tp_alloc(type, 0);
-    
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, M_Cos_compute_next_data_frame);
     self->mode_func_ptr = M_Cos_setProcMode;
 
     static char *kwlist[] = {"input", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     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;
@@ -432,10 +432,10 @@ M_Cos_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * M_Cos_getServer(M_Cos* self) { GET_SERVER };
 static PyObject * M_Cos_getStream(M_Cos* self) { GET_STREAM };
-static PyObject * M_Cos_setMul(M_Cos *self, PyObject *arg) { SET_MUL };	
-static PyObject * M_Cos_setAdd(M_Cos *self, PyObject *arg) { SET_ADD };	
-static PyObject * M_Cos_setSub(M_Cos *self, PyObject *arg) { SET_SUB };	
-static PyObject * M_Cos_setDiv(M_Cos *self, PyObject *arg) { SET_DIV };	
+static PyObject * M_Cos_setMul(M_Cos *self, PyObject *arg) { SET_MUL };
+static PyObject * M_Cos_setAdd(M_Cos *self, PyObject *arg) { SET_ADD };
+static PyObject * M_Cos_setSub(M_Cos *self, PyObject *arg) { SET_SUB };
+static PyObject * M_Cos_setDiv(M_Cos *self, PyObject *arg) { SET_DIV };
 
 static PyObject * M_Cos_play(M_Cos *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * M_Cos_out(M_Cos *self, PyObject *args, PyObject *kwds) { OUT };
@@ -476,7 +476,7 @@ static PyNumberMethods M_Cos_as_number = {
     (binaryfunc)M_Cos_add,                         /*nb_add*/
     (binaryfunc)M_Cos_sub,                         /*nb_subtract*/
     (binaryfunc)M_Cos_multiply,                    /*nb_multiply*/
-    (binaryfunc)M_Cos_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -490,16 +490,16 @@ static PyNumberMethods M_Cos_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)M_Cos_inplace_add,                 /*inplace_add*/
     (binaryfunc)M_Cos_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)M_Cos_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)M_Cos_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -508,15 +508,14 @@ static PyNumberMethods M_Cos_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)M_Cos_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)M_Cos_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject M_CosType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.M_Cos_base",                                   /*tp_name*/
     sizeof(M_Cos),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -524,7 +523,7 @@ PyTypeObject M_CosType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &M_Cos_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -570,7 +569,7 @@ static void
 M_Tan_process(M_Tan *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = MYTAN(in[i]);
     }
@@ -591,44 +590,44 @@ M_Tan_setProcMode(M_Tan *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = M_Tan_process;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = M_Tan_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = M_Tan_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = M_Tan_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = M_Tan_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = M_Tan_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = M_Tan_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = M_Tan_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = M_Tan_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = M_Tan_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 M_Tan_compute_next_data_frame(M_Tan *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -641,7 +640,7 @@ M_Tan_traverse(M_Tan *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 M_Tan_clear(M_Tan *self)
 {
     pyo_CLEAR
@@ -655,7 +654,7 @@ M_Tan_dealloc(M_Tan* self)
 {
     pyo_DEALLOC
     M_Tan_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -665,31 +664,31 @@ M_Tan_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     M_Tan *self;
     self = (M_Tan *)type->tp_alloc(type, 0);
-    
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, M_Tan_compute_next_data_frame);
     self->mode_func_ptr = M_Tan_setProcMode;
 
     static char *kwlist[] = {"input", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     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;
@@ -697,10 +696,10 @@ M_Tan_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * M_Tan_getServer(M_Tan* self) { GET_SERVER };
 static PyObject * M_Tan_getStream(M_Tan* self) { GET_STREAM };
-static PyObject * M_Tan_setMul(M_Tan *self, PyObject *arg) { SET_MUL };	
-static PyObject * M_Tan_setAdd(M_Tan *self, PyObject *arg) { SET_ADD };	
-static PyObject * M_Tan_setSub(M_Tan *self, PyObject *arg) { SET_SUB };	
-static PyObject * M_Tan_setDiv(M_Tan *self, PyObject *arg) { SET_DIV };	
+static PyObject * M_Tan_setMul(M_Tan *self, PyObject *arg) { SET_MUL };
+static PyObject * M_Tan_setAdd(M_Tan *self, PyObject *arg) { SET_ADD };
+static PyObject * M_Tan_setSub(M_Tan *self, PyObject *arg) { SET_SUB };
+static PyObject * M_Tan_setDiv(M_Tan *self, PyObject *arg) { SET_DIV };
 
 static PyObject * M_Tan_play(M_Tan *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * M_Tan_out(M_Tan *self, PyObject *args, PyObject *kwds) { OUT };
@@ -741,7 +740,7 @@ static PyNumberMethods M_Tan_as_number = {
     (binaryfunc)M_Tan_add,                         /*nb_add*/
     (binaryfunc)M_Tan_sub,                         /*nb_subtract*/
     (binaryfunc)M_Tan_multiply,                    /*nb_multiply*/
-    (binaryfunc)M_Tan_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -755,16 +754,16 @@ static PyNumberMethods M_Tan_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)M_Tan_inplace_add,                 /*inplace_add*/
     (binaryfunc)M_Tan_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)M_Tan_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)M_Tan_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -773,15 +772,14 @@ static PyNumberMethods M_Tan_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)M_Tan_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)M_Tan_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject M_TanType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.M_Tan_base",                                   /*tp_name*/
     sizeof(M_Tan),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -789,7 +787,7 @@ PyTypeObject M_TanType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &M_Tan_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -836,12 +834,12 @@ M_Abs_process(M_Abs *self) {
     int i;
     MYFLT inval;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inval = in[i];
         if (inval < 0.0)
             self->data[i] = -inval;
-        else 
+        else
             self->data[i] = inval;
     }
 }
@@ -861,44 +859,44 @@ M_Abs_setProcMode(M_Abs *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = M_Abs_process;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = M_Abs_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = M_Abs_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = M_Abs_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = M_Abs_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = M_Abs_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = M_Abs_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = M_Abs_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = M_Abs_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = M_Abs_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 M_Abs_compute_next_data_frame(M_Abs *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -911,7 +909,7 @@ M_Abs_traverse(M_Abs *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 M_Abs_clear(M_Abs *self)
 {
     pyo_CLEAR
@@ -925,7 +923,7 @@ M_Abs_dealloc(M_Abs* self)
 {
     pyo_DEALLOC
     M_Abs_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -935,31 +933,31 @@ M_Abs_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     M_Abs *self;
     self = (M_Abs *)type->tp_alloc(type, 0);
-    
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, M_Abs_compute_next_data_frame);
     self->mode_func_ptr = M_Abs_setProcMode;
 
     static char *kwlist[] = {"input", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     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;
@@ -967,10 +965,10 @@ M_Abs_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * M_Abs_getServer(M_Abs* self) { GET_SERVER };
 static PyObject * M_Abs_getStream(M_Abs* self) { GET_STREAM };
-static PyObject * M_Abs_setMul(M_Abs *self, PyObject *arg) { SET_MUL };	
-static PyObject * M_Abs_setAdd(M_Abs *self, PyObject *arg) { SET_ADD };	
-static PyObject * M_Abs_setSub(M_Abs *self, PyObject *arg) { SET_SUB };	
-static PyObject * M_Abs_setDiv(M_Abs *self, PyObject *arg) { SET_DIV };	
+static PyObject * M_Abs_setMul(M_Abs *self, PyObject *arg) { SET_MUL };
+static PyObject * M_Abs_setAdd(M_Abs *self, PyObject *arg) { SET_ADD };
+static PyObject * M_Abs_setSub(M_Abs *self, PyObject *arg) { SET_SUB };
+static PyObject * M_Abs_setDiv(M_Abs *self, PyObject *arg) { SET_DIV };
 
 static PyObject * M_Abs_play(M_Abs *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * M_Abs_out(M_Abs *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1011,7 +1009,7 @@ static PyNumberMethods M_Abs_as_number = {
     (binaryfunc)M_Abs_add,                         /*nb_add*/
     (binaryfunc)M_Abs_sub,                         /*nb_subtract*/
     (binaryfunc)M_Abs_multiply,                    /*nb_multiply*/
-    (binaryfunc)M_Abs_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -1025,16 +1023,16 @@ static PyNumberMethods M_Abs_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)M_Abs_inplace_add,                 /*inplace_add*/
     (binaryfunc)M_Abs_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)M_Abs_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)M_Abs_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -1043,15 +1041,14 @@ static PyNumberMethods M_Abs_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)M_Abs_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)M_Abs_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject M_AbsType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.M_Abs_base",                                   /*tp_name*/
     sizeof(M_Abs),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -1059,7 +1056,7 @@ PyTypeObject M_AbsType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &M_Abs_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -1106,12 +1103,12 @@ M_Sqrt_process(M_Sqrt *self) {
     int i;
     MYFLT inval;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inval = in[i];
         if (inval < 0.0)
             self->data[i] = 0.0;
-        else 
+        else
             self->data[i] = MYSQRT(inval);
     }
 }
@@ -1131,44 +1128,44 @@ M_Sqrt_setProcMode(M_Sqrt *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = M_Sqrt_process;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = M_Sqrt_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = M_Sqrt_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = M_Sqrt_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = M_Sqrt_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = M_Sqrt_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = M_Sqrt_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = M_Sqrt_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = M_Sqrt_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = M_Sqrt_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 M_Sqrt_compute_next_data_frame(M_Sqrt *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1181,7 +1178,7 @@ M_Sqrt_traverse(M_Sqrt *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 M_Sqrt_clear(M_Sqrt *self)
 {
     pyo_CLEAR
@@ -1195,7 +1192,7 @@ M_Sqrt_dealloc(M_Sqrt* self)
 {
     pyo_DEALLOC
     M_Sqrt_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1205,31 +1202,31 @@ M_Sqrt_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     M_Sqrt *self;
     self = (M_Sqrt *)type->tp_alloc(type, 0);
-    
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, M_Sqrt_compute_next_data_frame);
     self->mode_func_ptr = M_Sqrt_setProcMode;
 
     static char *kwlist[] = {"input", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     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;
@@ -1237,10 +1234,10 @@ M_Sqrt_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * M_Sqrt_getServer(M_Sqrt* self) { GET_SERVER };
 static PyObject * M_Sqrt_getStream(M_Sqrt* self) { GET_STREAM };
-static PyObject * M_Sqrt_setMul(M_Sqrt *self, PyObject *arg) { SET_MUL };	
-static PyObject * M_Sqrt_setAdd(M_Sqrt *self, PyObject *arg) { SET_ADD };	
-static PyObject * M_Sqrt_setSub(M_Sqrt *self, PyObject *arg) { SET_SUB };	
-static PyObject * M_Sqrt_setDiv(M_Sqrt *self, PyObject *arg) { SET_DIV };	
+static PyObject * M_Sqrt_setMul(M_Sqrt *self, PyObject *arg) { SET_MUL };
+static PyObject * M_Sqrt_setAdd(M_Sqrt *self, PyObject *arg) { SET_ADD };
+static PyObject * M_Sqrt_setSub(M_Sqrt *self, PyObject *arg) { SET_SUB };
+static PyObject * M_Sqrt_setDiv(M_Sqrt *self, PyObject *arg) { SET_DIV };
 
 static PyObject * M_Sqrt_play(M_Sqrt *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * M_Sqrt_out(M_Sqrt *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1281,7 +1278,7 @@ static PyNumberMethods M_Sqrt_as_number = {
     (binaryfunc)M_Sqrt_add,                         /*nb_add*/
     (binaryfunc)M_Sqrt_sub,                         /*nb_subtract*/
     (binaryfunc)M_Sqrt_multiply,                    /*nb_multiply*/
-    (binaryfunc)M_Sqrt_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -1295,16 +1292,16 @@ static PyNumberMethods M_Sqrt_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)M_Sqrt_inplace_add,                 /*inplace_add*/
     (binaryfunc)M_Sqrt_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)M_Sqrt_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)M_Sqrt_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -1313,15 +1310,14 @@ static PyNumberMethods M_Sqrt_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)M_Sqrt_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)M_Sqrt_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject M_SqrtType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.M_Sqrt_base",                                   /*tp_name*/
     sizeof(M_Sqrt),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -1329,7 +1325,7 @@ PyTypeObject M_SqrtType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &M_Sqrt_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -1376,12 +1372,12 @@ M_Log_process(M_Log *self) {
     int i;
     MYFLT inval;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inval = in[i];
         if (inval <= 0.0)
             self->data[i] = 0.0;
-        else 
+        else
             self->data[i] = MYLOG(inval);
     }
 }
@@ -1401,44 +1397,44 @@ M_Log_setProcMode(M_Log *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = M_Log_process;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = M_Log_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = M_Log_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = M_Log_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = M_Log_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = M_Log_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = M_Log_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = M_Log_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = M_Log_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = M_Log_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 M_Log_compute_next_data_frame(M_Log *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1451,7 +1447,7 @@ M_Log_traverse(M_Log *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 M_Log_clear(M_Log *self)
 {
     pyo_CLEAR
@@ -1465,7 +1461,7 @@ M_Log_dealloc(M_Log* self)
 {
     pyo_DEALLOC
     M_Log_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1475,31 +1471,31 @@ M_Log_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     M_Log *self;
     self = (M_Log *)type->tp_alloc(type, 0);
-    
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, M_Log_compute_next_data_frame);
     self->mode_func_ptr = M_Log_setProcMode;
 
     static char *kwlist[] = {"input", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     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;
@@ -1507,10 +1503,10 @@ M_Log_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * M_Log_getServer(M_Log* self) { GET_SERVER };
 static PyObject * M_Log_getStream(M_Log* self) { GET_STREAM };
-static PyObject * M_Log_setMul(M_Log *self, PyObject *arg) { SET_MUL };	
-static PyObject * M_Log_setAdd(M_Log *self, PyObject *arg) { SET_ADD };	
-static PyObject * M_Log_setSub(M_Log *self, PyObject *arg) { SET_SUB };	
-static PyObject * M_Log_setDiv(M_Log *self, PyObject *arg) { SET_DIV };	
+static PyObject * M_Log_setMul(M_Log *self, PyObject *arg) { SET_MUL };
+static PyObject * M_Log_setAdd(M_Log *self, PyObject *arg) { SET_ADD };
+static PyObject * M_Log_setSub(M_Log *self, PyObject *arg) { SET_SUB };
+static PyObject * M_Log_setDiv(M_Log *self, PyObject *arg) { SET_DIV };
 
 static PyObject * M_Log_play(M_Log *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * M_Log_out(M_Log *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1551,7 +1547,7 @@ static PyNumberMethods M_Log_as_number = {
     (binaryfunc)M_Log_add,                         /*nb_add*/
     (binaryfunc)M_Log_sub,                         /*nb_subtract*/
     (binaryfunc)M_Log_multiply,                    /*nb_multiply*/
-    (binaryfunc)M_Log_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -1565,16 +1561,16 @@ static PyNumberMethods M_Log_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)M_Log_inplace_add,                 /*inplace_add*/
     (binaryfunc)M_Log_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)M_Log_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)M_Log_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -1583,15 +1579,14 @@ static PyNumberMethods M_Log_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)M_Log_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)M_Log_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject M_LogType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.M_Log_base",                                   /*tp_name*/
     sizeof(M_Log),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -1599,7 +1594,7 @@ PyTypeObject M_LogType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &M_Log_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -1646,12 +1641,12 @@ M_Log10_process(M_Log10 *self) {
     int i;
     MYFLT inval;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inval = in[i];
         if (inval <= 0.0)
             self->data[i] = 0.0;
-        else 
+        else
             self->data[i] = MYLOG10(inval);
     }
 }
@@ -1671,44 +1666,44 @@ M_Log10_setProcMode(M_Log10 *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = M_Log10_process;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = M_Log10_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = M_Log10_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = M_Log10_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = M_Log10_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = M_Log10_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = M_Log10_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = M_Log10_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = M_Log10_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = M_Log10_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 M_Log10_compute_next_data_frame(M_Log10 *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1721,7 +1716,7 @@ M_Log10_traverse(M_Log10 *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 M_Log10_clear(M_Log10 *self)
 {
     pyo_CLEAR
@@ -1735,7 +1730,7 @@ M_Log10_dealloc(M_Log10* self)
 {
     pyo_DEALLOC
     M_Log10_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1745,31 +1740,31 @@ M_Log10_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     M_Log10 *self;
     self = (M_Log10 *)type->tp_alloc(type, 0);
-    
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, M_Log10_compute_next_data_frame);
     self->mode_func_ptr = M_Log10_setProcMode;
 
     static char *kwlist[] = {"input", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     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;
@@ -1777,10 +1772,10 @@ M_Log10_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * M_Log10_getServer(M_Log10* self) { GET_SERVER };
 static PyObject * M_Log10_getStream(M_Log10* self) { GET_STREAM };
-static PyObject * M_Log10_setMul(M_Log10 *self, PyObject *arg) { SET_MUL };	
-static PyObject * M_Log10_setAdd(M_Log10 *self, PyObject *arg) { SET_ADD };	
-static PyObject * M_Log10_setSub(M_Log10 *self, PyObject *arg) { SET_SUB };	
-static PyObject * M_Log10_setDiv(M_Log10 *self, PyObject *arg) { SET_DIV };	
+static PyObject * M_Log10_setMul(M_Log10 *self, PyObject *arg) { SET_MUL };
+static PyObject * M_Log10_setAdd(M_Log10 *self, PyObject *arg) { SET_ADD };
+static PyObject * M_Log10_setSub(M_Log10 *self, PyObject *arg) { SET_SUB };
+static PyObject * M_Log10_setDiv(M_Log10 *self, PyObject *arg) { SET_DIV };
 
 static PyObject * M_Log10_play(M_Log10 *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * M_Log10_out(M_Log10 *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1821,7 +1816,7 @@ static PyNumberMethods M_Log10_as_number = {
     (binaryfunc)M_Log10_add,                         /*nb_add*/
     (binaryfunc)M_Log10_sub,                         /*nb_subtract*/
     (binaryfunc)M_Log10_multiply,                    /*nb_multiply*/
-    (binaryfunc)M_Log10_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -1835,16 +1830,16 @@ static PyNumberMethods M_Log10_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)M_Log10_inplace_add,                 /*inplace_add*/
     (binaryfunc)M_Log10_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)M_Log10_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)M_Log10_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -1853,15 +1848,14 @@ static PyNumberMethods M_Log10_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)M_Log10_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)M_Log10_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject M_Log10Type = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.M_Log10_base",                                   /*tp_name*/
     sizeof(M_Log10),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -1869,7 +1863,7 @@ PyTypeObject M_Log10Type = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &M_Log10_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -1916,12 +1910,12 @@ M_Log2_process(M_Log2 *self) {
     int i;
     MYFLT inval;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inval = in[i];
         if (inval <= 0.0)
             self->data[i] = 0.0;
-        else 
+        else
             self->data[i] = MYLOG2(inval);
     }
 }
@@ -1941,44 +1935,44 @@ M_Log2_setProcMode(M_Log2 *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = M_Log2_process;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = M_Log2_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = M_Log2_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = M_Log2_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = M_Log2_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = M_Log2_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = M_Log2_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = M_Log2_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = M_Log2_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = M_Log2_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 M_Log2_compute_next_data_frame(M_Log2 *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1991,7 +1985,7 @@ M_Log2_traverse(M_Log2 *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 M_Log2_clear(M_Log2 *self)
 {
     pyo_CLEAR
@@ -2005,7 +1999,7 @@ M_Log2_dealloc(M_Log2* self)
 {
     pyo_DEALLOC
     M_Log2_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2015,31 +2009,31 @@ M_Log2_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     M_Log2 *self;
     self = (M_Log2 *)type->tp_alloc(type, 0);
-    
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, M_Log2_compute_next_data_frame);
     self->mode_func_ptr = M_Log2_setProcMode;
 
     static char *kwlist[] = {"input", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     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;
@@ -2047,10 +2041,10 @@ M_Log2_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * M_Log2_getServer(M_Log2* self) { GET_SERVER };
 static PyObject * M_Log2_getStream(M_Log2* self) { GET_STREAM };
-static PyObject * M_Log2_setMul(M_Log2 *self, PyObject *arg) { SET_MUL };	
-static PyObject * M_Log2_setAdd(M_Log2 *self, PyObject *arg) { SET_ADD };	
-static PyObject * M_Log2_setSub(M_Log2 *self, PyObject *arg) { SET_SUB };	
-static PyObject * M_Log2_setDiv(M_Log2 *self, PyObject *arg) { SET_DIV };	
+static PyObject * M_Log2_setMul(M_Log2 *self, PyObject *arg) { SET_MUL };
+static PyObject * M_Log2_setAdd(M_Log2 *self, PyObject *arg) { SET_ADD };
+static PyObject * M_Log2_setSub(M_Log2 *self, PyObject *arg) { SET_SUB };
+static PyObject * M_Log2_setDiv(M_Log2 *self, PyObject *arg) { SET_DIV };
 
 static PyObject * M_Log2_play(M_Log2 *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * M_Log2_out(M_Log2 *self, PyObject *args, PyObject *kwds) { OUT };
@@ -2091,7 +2085,7 @@ static PyNumberMethods M_Log2_as_number = {
     (binaryfunc)M_Log2_add,                         /*nb_add*/
     (binaryfunc)M_Log2_sub,                         /*nb_subtract*/
     (binaryfunc)M_Log2_multiply,                    /*nb_multiply*/
-    (binaryfunc)M_Log2_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -2105,16 +2099,16 @@ static PyNumberMethods M_Log2_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)M_Log2_inplace_add,                 /*inplace_add*/
     (binaryfunc)M_Log2_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)M_Log2_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)M_Log2_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -2123,15 +2117,14 @@ static PyNumberMethods M_Log2_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)M_Log2_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)M_Log2_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject M_Log2Type = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.M_Log2_base",                                   /*tp_name*/
     sizeof(M_Log2),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -2139,7 +2132,7 @@ PyTypeObject M_Log2Type = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &M_Log2_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -2186,10 +2179,10 @@ typedef struct {
 static void
 M_Pow_readframes_ii(M_Pow *self) {
     int i;
-    
+
     MYFLT base = PyFloat_AS_DOUBLE(self->base);
     MYFLT exp = PyFloat_AS_DOUBLE(self->exponent);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = MYPOW(base, exp);
     }
@@ -2198,10 +2191,10 @@ M_Pow_readframes_ii(M_Pow *self) {
 static void
 M_Pow_readframes_ai(M_Pow *self) {
     int i;
-    
+
     MYFLT *base = Stream_getData((Stream *)self->base_stream);
     MYFLT exp = PyFloat_AS_DOUBLE(self->exponent);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = MYPOW(base[i], exp);
     }
@@ -2210,10 +2203,10 @@ M_Pow_readframes_ai(M_Pow *self) {
 static void
 M_Pow_readframes_ia(M_Pow *self) {
     int i;
-    
+
     MYFLT base = PyFloat_AS_DOUBLE(self->base);
     MYFLT *exp = Stream_getData((Stream *)self->exponent_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = MYPOW(base, exp[i]);
     }
@@ -2222,10 +2215,10 @@ M_Pow_readframes_ia(M_Pow *self) {
 static void
 M_Pow_readframes_aa(M_Pow *self) {
     int i;
-    
+
     MYFLT *base = Stream_getData((Stream *)self->base_stream);
     MYFLT *exp = Stream_getData((Stream *)self->exponent_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = MYPOW(base[i], exp[i]);
     }
@@ -2247,56 +2240,56 @@ M_Pow_setProcMode(M_Pow *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:        
+        case 0:
             self->proc_func_ptr = M_Pow_readframes_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = M_Pow_readframes_ai;
             break;
-        case 10:        
+        case 10:
             self->proc_func_ptr = M_Pow_readframes_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = M_Pow_readframes_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = M_Pow_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = M_Pow_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = M_Pow_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = M_Pow_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = M_Pow_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = M_Pow_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = M_Pow_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = M_Pow_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = M_Pow_postprocessing_revareva;
             break;
-    } 
+    }
 }
 
 static void
 M_Pow_compute_next_data_frame(M_Pow *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -2304,21 +2297,21 @@ static int
 M_Pow_traverse(M_Pow *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->exponent);    
-    Py_VISIT(self->exponent_stream);    
-    Py_VISIT(self->base);    
-    Py_VISIT(self->base_stream);    
+    Py_VISIT(self->exponent);
+    Py_VISIT(self->exponent_stream);
+    Py_VISIT(self->base);
+    Py_VISIT(self->base_stream);
     return 0;
 }
 
-static int 
+static int
 M_Pow_clear(M_Pow *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->exponent);    
-    Py_CLEAR(self->exponent_stream);    
-    Py_CLEAR(self->base);    
-    Py_CLEAR(self->base_stream);    
+    Py_CLEAR(self->exponent);
+    Py_CLEAR(self->exponent_stream);
+    Py_CLEAR(self->base);
+    Py_CLEAR(self->base_stream);
     return 0;
 }
 
@@ -2327,7 +2320,7 @@ M_Pow_dealloc(M_Pow* self)
 {
     pyo_DEALLOC
     M_Pow_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2337,41 +2330,41 @@ M_Pow_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *basetmp=NULL, *exponenttmp=NULL, *multmp=NULL, *addtmp=NULL;
     M_Pow *self;
     self = (M_Pow *)type->tp_alloc(type, 0);
-    
+
     self->base = PyFloat_FromDouble(10);
     self->exponent = PyFloat_FromDouble(1);
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, M_Pow_compute_next_data_frame);
     self->mode_func_ptr = M_Pow_setProcMode;
-    
+
     static char *kwlist[] = {"base", "exponent", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &basetmp, &exponenttmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     if (basetmp) {
         PyObject_CallMethod((PyObject *)self, "setBase", "O", basetmp);
     }
-    
+
     if (exponenttmp) {
         PyObject_CallMethod((PyObject *)self, "setExponent", "O", exponenttmp);
     }
-    
+
     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;
@@ -2379,10 +2372,10 @@ M_Pow_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * M_Pow_getServer(M_Pow* self) { GET_SERVER };
 static PyObject * M_Pow_getStream(M_Pow* self) { GET_STREAM };
-static PyObject * M_Pow_setMul(M_Pow *self, PyObject *arg) { SET_MUL };	
-static PyObject * M_Pow_setAdd(M_Pow *self, PyObject *arg) { SET_ADD };	
-static PyObject * M_Pow_setSub(M_Pow *self, PyObject *arg) { SET_SUB };	
-static PyObject * M_Pow_setDiv(M_Pow *self, PyObject *arg) { SET_DIV };	
+static PyObject * M_Pow_setMul(M_Pow *self, PyObject *arg) { SET_MUL };
+static PyObject * M_Pow_setAdd(M_Pow *self, PyObject *arg) { SET_ADD };
+static PyObject * M_Pow_setSub(M_Pow *self, PyObject *arg) { SET_SUB };
+static PyObject * M_Pow_setDiv(M_Pow *self, PyObject *arg) { SET_DIV };
 
 static PyObject * M_Pow_play(M_Pow *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * M_Pow_out(M_Pow *self, PyObject *args, PyObject *kwds) { OUT };
@@ -2401,14 +2394,11 @@ static PyObject *
 M_Pow_setBase(M_Pow *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->base);
@@ -2424,25 +2414,22 @@ M_Pow_setBase(M_Pow *self, PyObject *arg)
         self->base_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 M_Pow_setExponent(M_Pow *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->exponent);
@@ -2458,12 +2445,12 @@ M_Pow_setExponent(M_Pow *self, PyObject *arg)
         self->exponent_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef M_Pow_members[] = {
     {"server", T_OBJECT_EX, offsetof(M_Pow, server), 0, "Pyo server."},
@@ -2494,7 +2481,7 @@ static PyNumberMethods M_Pow_as_number = {
     (binaryfunc)M_Pow_add,                      /*nb_add*/
     (binaryfunc)M_Pow_sub,                 /*nb_subtract*/
     (binaryfunc)M_Pow_multiply,                 /*nb_multiply*/
-    (binaryfunc)M_Pow_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -2508,16 +2495,16 @@ static PyNumberMethods M_Pow_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)M_Pow_inplace_add,              /*inplace_add*/
     (binaryfunc)M_Pow_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)M_Pow_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)M_Pow_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -2526,15 +2513,14 @@ static PyNumberMethods M_Pow_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)M_Pow_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)M_Pow_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject M_PowType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.M_Pow_base",         /*tp_name*/
     sizeof(M_Pow),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -2542,7 +2528,7 @@ PyTypeObject M_PowType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &M_Pow_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -2589,10 +2575,10 @@ typedef struct {
 static void
 M_Atan2_readframes_ii(M_Atan2 *self) {
     int i;
-    
+
     MYFLT b = PyFloat_AS_DOUBLE(self->b);
     MYFLT a = PyFloat_AS_DOUBLE(self->a);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = MYATAN2(b, a);
     }
@@ -2601,10 +2587,10 @@ M_Atan2_readframes_ii(M_Atan2 *self) {
 static void
 M_Atan2_readframes_ai(M_Atan2 *self) {
     int i;
-    
+
     MYFLT *b = Stream_getData((Stream *)self->b_stream);
     MYFLT a = PyFloat_AS_DOUBLE(self->a);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = MYATAN2(b[i], a);
     }
@@ -2613,10 +2599,10 @@ M_Atan2_readframes_ai(M_Atan2 *self) {
 static void
 M_Atan2_readframes_ia(M_Atan2 *self) {
     int i;
-    
+
     MYFLT b = PyFloat_AS_DOUBLE(self->b);
     MYFLT *a = Stream_getData((Stream *)self->a_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = MYATAN2(b, a[i]);
     }
@@ -2625,10 +2611,10 @@ M_Atan2_readframes_ia(M_Atan2 *self) {
 static void
 M_Atan2_readframes_aa(M_Atan2 *self) {
     int i;
-    
+
     MYFLT *b = Stream_getData((Stream *)self->b_stream);
     MYFLT *a = Stream_getData((Stream *)self->a_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = MYATAN2(b[i], a[i]);
     }
@@ -2650,56 +2636,56 @@ M_Atan2_setProcMode(M_Atan2 *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:        
+        case 0:
             self->proc_func_ptr = M_Atan2_readframes_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = M_Atan2_readframes_ai;
             break;
-        case 10:        
+        case 10:
             self->proc_func_ptr = M_Atan2_readframes_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = M_Atan2_readframes_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = M_Atan2_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = M_Atan2_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = M_Atan2_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = M_Atan2_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = M_Atan2_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = M_Atan2_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = M_Atan2_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = M_Atan2_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = M_Atan2_postprocessing_revareva;
             break;
-    } 
+    }
 }
 
 static void
 M_Atan2_compute_next_data_frame(M_Atan2 *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -2707,21 +2693,21 @@ static int
 M_Atan2_traverse(M_Atan2 *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->b);    
-    Py_VISIT(self->b_stream);    
-    Py_VISIT(self->a);    
-    Py_VISIT(self->a_stream);    
+    Py_VISIT(self->b);
+    Py_VISIT(self->b_stream);
+    Py_VISIT(self->a);
+    Py_VISIT(self->a_stream);
     return 0;
 }
 
-static int 
+static int
 M_Atan2_clear(M_Atan2 *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->b);    
-    Py_CLEAR(self->b_stream);    
-    Py_CLEAR(self->a);    
-    Py_CLEAR(self->a_stream);    
+    Py_CLEAR(self->b);
+    Py_CLEAR(self->b_stream);
+    Py_CLEAR(self->a);
+    Py_CLEAR(self->a_stream);
     return 0;
 }
 
@@ -2730,7 +2716,7 @@ M_Atan2_dealloc(M_Atan2* self)
 {
     pyo_DEALLOC
     M_Atan2_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2740,52 +2726,52 @@ M_Atan2_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *btmp=NULL, *atmp=NULL, *multmp=NULL, *addtmp=NULL;
     M_Atan2 *self;
     self = (M_Atan2 *)type->tp_alloc(type, 0);
-    
+
     self->a = PyFloat_FromDouble(1);
     self->b = PyFloat_FromDouble(1);
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, M_Atan2_compute_next_data_frame);
     self->mode_func_ptr = M_Atan2_setProcMode;
 
     static char *kwlist[] = {"b", "a", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &btmp, &atmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     if (btmp) {
         PyObject_CallMethod((PyObject *)self, "setB", "O", btmp);
     }
-    
+
     if (atmp) {
         PyObject_CallMethod((PyObject *)self, "setA", "O", atmp);
     }
-    
+
     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 * M_Atan2_getServer(M_Atan2* self) { GET_SERVER };
 static PyObject * M_Atan2_getStream(M_Atan2* self) { GET_STREAM };
-static PyObject * M_Atan2_setMul(M_Atan2 *self, PyObject *arg) { SET_MUL };	
-static PyObject * M_Atan2_setAdd(M_Atan2 *self, PyObject *arg) { SET_ADD };	
-static PyObject * M_Atan2_setSub(M_Atan2 *self, PyObject *arg) { SET_SUB };	
-static PyObject * M_Atan2_setDiv(M_Atan2 *self, PyObject *arg) { SET_DIV };	
+static PyObject * M_Atan2_setMul(M_Atan2 *self, PyObject *arg) { SET_MUL };
+static PyObject * M_Atan2_setAdd(M_Atan2 *self, PyObject *arg) { SET_ADD };
+static PyObject * M_Atan2_setSub(M_Atan2 *self, PyObject *arg) { SET_SUB };
+static PyObject * M_Atan2_setDiv(M_Atan2 *self, PyObject *arg) { SET_DIV };
 
 static PyObject * M_Atan2_play(M_Atan2 *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * M_Atan2_out(M_Atan2 *self, PyObject *args, PyObject *kwds) { OUT };
@@ -2804,14 +2790,11 @@ static PyObject *
 M_Atan2_setB(M_Atan2 *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->b);
@@ -2827,25 +2810,22 @@ M_Atan2_setB(M_Atan2 *self, PyObject *arg)
         self->b_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 M_Atan2_setA(M_Atan2 *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->a);
@@ -2861,12 +2841,12 @@ M_Atan2_setA(M_Atan2 *self, PyObject *arg)
         self->a_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef M_Atan2_members[] = {
     {"server", T_OBJECT_EX, offsetof(M_Atan2, server), 0, "Pyo server."},
@@ -2897,7 +2877,7 @@ static PyNumberMethods M_Atan2_as_number = {
     (binaryfunc)M_Atan2_add,                      /*nb_add*/
     (binaryfunc)M_Atan2_sub,                 /*nb_subtract*/
     (binaryfunc)M_Atan2_multiply,                 /*nb_multiply*/
-    (binaryfunc)M_Atan2_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -2911,16 +2891,16 @@ static PyNumberMethods M_Atan2_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)M_Atan2_inplace_add,              /*inplace_add*/
     (binaryfunc)M_Atan2_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)M_Atan2_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)M_Atan2_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -2929,15 +2909,14 @@ static PyNumberMethods M_Atan2_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)M_Atan2_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)M_Atan2_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject M_Atan2Type = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.M_Atan2_base",         /*tp_name*/
     sizeof(M_Atan2),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -2945,7 +2924,7 @@ PyTypeObject M_Atan2Type = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &M_Atan2_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -2991,7 +2970,7 @@ static void
 M_Floor_process(M_Floor *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = MYFLOOR(in[i]);
     }
@@ -3012,44 +2991,44 @@ M_Floor_setProcMode(M_Floor *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = M_Floor_process;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = M_Floor_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = M_Floor_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = M_Floor_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = M_Floor_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = M_Floor_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = M_Floor_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = M_Floor_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = M_Floor_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = M_Floor_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 M_Floor_compute_next_data_frame(M_Floor *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -3062,7 +3041,7 @@ M_Floor_traverse(M_Floor *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 M_Floor_clear(M_Floor *self)
 {
     pyo_CLEAR
@@ -3076,7 +3055,7 @@ M_Floor_dealloc(M_Floor* self)
 {
     pyo_DEALLOC
     M_Floor_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -3086,31 +3065,31 @@ M_Floor_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     M_Floor *self;
     self = (M_Floor *)type->tp_alloc(type, 0);
-    
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, M_Floor_compute_next_data_frame);
     self->mode_func_ptr = M_Floor_setProcMode;
 
     static char *kwlist[] = {"input", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     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;
@@ -3118,10 +3097,10 @@ M_Floor_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * M_Floor_getServer(M_Floor* self) { GET_SERVER };
 static PyObject * M_Floor_getStream(M_Floor* self) { GET_STREAM };
-static PyObject * M_Floor_setMul(M_Floor *self, PyObject *arg) { SET_MUL };	
-static PyObject * M_Floor_setAdd(M_Floor *self, PyObject *arg) { SET_ADD };	
-static PyObject * M_Floor_setSub(M_Floor *self, PyObject *arg) { SET_SUB };	
-static PyObject * M_Floor_setDiv(M_Floor *self, PyObject *arg) { SET_DIV };	
+static PyObject * M_Floor_setMul(M_Floor *self, PyObject *arg) { SET_MUL };
+static PyObject * M_Floor_setAdd(M_Floor *self, PyObject *arg) { SET_ADD };
+static PyObject * M_Floor_setSub(M_Floor *self, PyObject *arg) { SET_SUB };
+static PyObject * M_Floor_setDiv(M_Floor *self, PyObject *arg) { SET_DIV };
 
 static PyObject * M_Floor_play(M_Floor *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * M_Floor_out(M_Floor *self, PyObject *args, PyObject *kwds) { OUT };
@@ -3162,7 +3141,7 @@ static PyNumberMethods M_Floor_as_number = {
     (binaryfunc)M_Floor_add,                         /*nb_add*/
     (binaryfunc)M_Floor_sub,                         /*nb_subtract*/
     (binaryfunc)M_Floor_multiply,                    /*nb_multiply*/
-    (binaryfunc)M_Floor_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -3176,16 +3155,16 @@ static PyNumberMethods M_Floor_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)M_Floor_inplace_add,                 /*inplace_add*/
     (binaryfunc)M_Floor_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)M_Floor_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)M_Floor_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -3194,15 +3173,14 @@ static PyNumberMethods M_Floor_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)M_Floor_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)M_Floor_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject M_FloorType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.M_Floor_base",                                   /*tp_name*/
     sizeof(M_Floor),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -3210,7 +3188,7 @@ PyTypeObject M_FloorType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &M_Floor_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -3256,7 +3234,7 @@ static void
 M_Ceil_process(M_Ceil *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = MYCEIL(in[i]);
     }
@@ -3277,44 +3255,44 @@ M_Ceil_setProcMode(M_Ceil *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = M_Ceil_process;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = M_Ceil_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = M_Ceil_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = M_Ceil_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = M_Ceil_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = M_Ceil_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = M_Ceil_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = M_Ceil_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = M_Ceil_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = M_Ceil_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 M_Ceil_compute_next_data_frame(M_Ceil *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -3327,7 +3305,7 @@ M_Ceil_traverse(M_Ceil *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 M_Ceil_clear(M_Ceil *self)
 {
     pyo_CLEAR
@@ -3341,7 +3319,7 @@ M_Ceil_dealloc(M_Ceil* self)
 {
     pyo_DEALLOC
     M_Ceil_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -3351,31 +3329,31 @@ M_Ceil_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     M_Ceil *self;
     self = (M_Ceil *)type->tp_alloc(type, 0);
-    
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, M_Ceil_compute_next_data_frame);
     self->mode_func_ptr = M_Ceil_setProcMode;
 
     static char *kwlist[] = {"input", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     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;
@@ -3383,10 +3361,10 @@ M_Ceil_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * M_Ceil_getServer(M_Ceil* self) { GET_SERVER };
 static PyObject * M_Ceil_getStream(M_Ceil* self) { GET_STREAM };
-static PyObject * M_Ceil_setMul(M_Ceil *self, PyObject *arg) { SET_MUL };	
-static PyObject * M_Ceil_setAdd(M_Ceil *self, PyObject *arg) { SET_ADD };	
-static PyObject * M_Ceil_setSub(M_Ceil *self, PyObject *arg) { SET_SUB };	
-static PyObject * M_Ceil_setDiv(M_Ceil *self, PyObject *arg) { SET_DIV };	
+static PyObject * M_Ceil_setMul(M_Ceil *self, PyObject *arg) { SET_MUL };
+static PyObject * M_Ceil_setAdd(M_Ceil *self, PyObject *arg) { SET_ADD };
+static PyObject * M_Ceil_setSub(M_Ceil *self, PyObject *arg) { SET_SUB };
+static PyObject * M_Ceil_setDiv(M_Ceil *self, PyObject *arg) { SET_DIV };
 
 static PyObject * M_Ceil_play(M_Ceil *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * M_Ceil_out(M_Ceil *self, PyObject *args, PyObject *kwds) { OUT };
@@ -3427,7 +3405,7 @@ static PyNumberMethods M_Ceil_as_number = {
     (binaryfunc)M_Ceil_add,                         /*nb_add*/
     (binaryfunc)M_Ceil_sub,                         /*nb_subtract*/
     (binaryfunc)M_Ceil_multiply,                    /*nb_multiply*/
-    (binaryfunc)M_Ceil_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -3441,16 +3419,16 @@ static PyNumberMethods M_Ceil_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)M_Ceil_inplace_add,                 /*inplace_add*/
     (binaryfunc)M_Ceil_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)M_Ceil_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)M_Ceil_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -3459,15 +3437,14 @@ static PyNumberMethods M_Ceil_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)M_Ceil_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)M_Ceil_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject M_CeilType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.M_Ceil_base",                                   /*tp_name*/
     sizeof(M_Ceil),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -3475,7 +3452,7 @@ PyTypeObject M_CeilType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &M_Ceil_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -3521,7 +3498,7 @@ static void
 M_Round_process(M_Round *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = MYROUND(in[i]);
     }
@@ -3542,44 +3519,44 @@ M_Round_setProcMode(M_Round *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = M_Round_process;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = M_Round_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = M_Round_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = M_Round_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = M_Round_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = M_Round_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = M_Round_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = M_Round_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = M_Round_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = M_Round_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 M_Round_compute_next_data_frame(M_Round *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -3592,7 +3569,7 @@ M_Round_traverse(M_Round *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 M_Round_clear(M_Round *self)
 {
     pyo_CLEAR
@@ -3606,7 +3583,7 @@ M_Round_dealloc(M_Round* self)
 {
     pyo_DEALLOC
     M_Round_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -3616,31 +3593,31 @@ M_Round_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     M_Round *self;
     self = (M_Round *)type->tp_alloc(type, 0);
-    
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, M_Round_compute_next_data_frame);
     self->mode_func_ptr = M_Round_setProcMode;
 
     static char *kwlist[] = {"input", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     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;
@@ -3648,10 +3625,10 @@ M_Round_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * M_Round_getServer(M_Round* self) { GET_SERVER };
 static PyObject * M_Round_getStream(M_Round* self) { GET_STREAM };
-static PyObject * M_Round_setMul(M_Round *self, PyObject *arg) { SET_MUL };	
-static PyObject * M_Round_setAdd(M_Round *self, PyObject *arg) { SET_ADD };	
-static PyObject * M_Round_setSub(M_Round *self, PyObject *arg) { SET_SUB };	
-static PyObject * M_Round_setDiv(M_Round *self, PyObject *arg) { SET_DIV };	
+static PyObject * M_Round_setMul(M_Round *self, PyObject *arg) { SET_MUL };
+static PyObject * M_Round_setAdd(M_Round *self, PyObject *arg) { SET_ADD };
+static PyObject * M_Round_setSub(M_Round *self, PyObject *arg) { SET_SUB };
+static PyObject * M_Round_setDiv(M_Round *self, PyObject *arg) { SET_DIV };
 
 static PyObject * M_Round_play(M_Round *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * M_Round_out(M_Round *self, PyObject *args, PyObject *kwds) { OUT };
@@ -3692,7 +3669,7 @@ static PyNumberMethods M_Round_as_number = {
     (binaryfunc)M_Round_add,                         /*nb_add*/
     (binaryfunc)M_Round_sub,                         /*nb_subtract*/
     (binaryfunc)M_Round_multiply,                    /*nb_multiply*/
-    (binaryfunc)M_Round_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -3706,16 +3683,16 @@ static PyNumberMethods M_Round_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)M_Round_inplace_add,                 /*inplace_add*/
     (binaryfunc)M_Round_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)M_Round_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)M_Round_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -3724,15 +3701,14 @@ static PyNumberMethods M_Round_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)M_Round_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)M_Round_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject M_RoundType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.M_Round_base",                                   /*tp_name*/
     sizeof(M_Round),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -3740,7 +3716,7 @@ PyTypeObject M_RoundType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &M_Round_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -3771,3 +3747,531 @@ PyTypeObject M_RoundType = {
     0,                                              /* tp_alloc */
     M_Round_new,                                     /* tp_new */
 };
+
+/************/
+/* M_Tanh */
+/************/
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *input;
+    Stream *input_stream;
+    int modebuffer[2]; // need at least 2 slots for mul & add
+} M_Tanh;
+
+static void
+M_Tanh_process(M_Tanh *self) {
+    int i;
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+
+    for (i=0; i<self->bufsize; i++) {
+        self->data[i] = MYTANH(in[i]);
+    }
+}
+
+static void M_Tanh_postprocessing_ii(M_Tanh *self) { POST_PROCESSING_II };
+static void M_Tanh_postprocessing_ai(M_Tanh *self) { POST_PROCESSING_AI };
+static void M_Tanh_postprocessing_ia(M_Tanh *self) { POST_PROCESSING_IA };
+static void M_Tanh_postprocessing_aa(M_Tanh *self) { POST_PROCESSING_AA };
+static void M_Tanh_postprocessing_ireva(M_Tanh *self) { POST_PROCESSING_IREVA };
+static void M_Tanh_postprocessing_areva(M_Tanh *self) { POST_PROCESSING_AREVA };
+static void M_Tanh_postprocessing_revai(M_Tanh *self) { POST_PROCESSING_REVAI };
+static void M_Tanh_postprocessing_revaa(M_Tanh *self) { POST_PROCESSING_REVAA };
+static void M_Tanh_postprocessing_revareva(M_Tanh *self) { POST_PROCESSING_REVAREVA };
+
+static void
+M_Tanh_setProcMode(M_Tanh *self)
+{
+    int muladdmode;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+    self->proc_func_ptr = M_Tanh_process;
+
+	switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = M_Tanh_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = M_Tanh_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = M_Tanh_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = M_Tanh_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = M_Tanh_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = M_Tanh_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = M_Tanh_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = M_Tanh_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = M_Tanh_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+M_Tanh_compute_next_data_frame(M_Tanh *self)
+{
+    (*self->proc_func_ptr)(self);
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+M_Tanh_traverse(M_Tanh *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->input);
+    Py_VISIT(self->input_stream);
+    return 0;
+}
+
+static int
+M_Tanh_clear(M_Tanh *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->input);
+    Py_CLEAR(self->input_stream);
+    return 0;
+}
+
+static void
+M_Tanh_dealloc(M_Tanh* self)
+{
+    pyo_DEALLOC
+    M_Tanh_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+M_Tanh_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
+    M_Tanh *self;
+    self = (M_Tanh *)type->tp_alloc(type, 0);
+
+	self->modebuffer[0] = 0;
+	self->modebuffer[1] = 0;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, M_Tanh_compute_next_data_frame);
+    self->mode_func_ptr = M_Tanh_setProcMode;
+
+    static char *kwlist[] = {"input", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp))
+        Py_RETURN_NONE;
+
+    INIT_INPUT_STREAM
+
+    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 * M_Tanh_getServer(M_Tanh* self) { GET_SERVER };
+static PyObject * M_Tanh_getStream(M_Tanh* self) { GET_STREAM };
+static PyObject * M_Tanh_setMul(M_Tanh *self, PyObject *arg) { SET_MUL };
+static PyObject * M_Tanh_setAdd(M_Tanh *self, PyObject *arg) { SET_ADD };
+static PyObject * M_Tanh_setSub(M_Tanh *self, PyObject *arg) { SET_SUB };
+static PyObject * M_Tanh_setDiv(M_Tanh *self, PyObject *arg) { SET_DIV };
+
+static PyObject * M_Tanh_play(M_Tanh *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * M_Tanh_out(M_Tanh *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * M_Tanh_stop(M_Tanh *self) { STOP };
+
+static PyObject * M_Tanh_multiply(M_Tanh *self, PyObject *arg) { MULTIPLY };
+static PyObject * M_Tanh_inplace_multiply(M_Tanh *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * M_Tanh_add(M_Tanh *self, PyObject *arg) { ADD };
+static PyObject * M_Tanh_inplace_add(M_Tanh *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * M_Tanh_sub(M_Tanh *self, PyObject *arg) { SUB };
+static PyObject * M_Tanh_inplace_sub(M_Tanh *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * M_Tanh_div(M_Tanh *self, PyObject *arg) { DIV };
+static PyObject * M_Tanh_inplace_div(M_Tanh *self, PyObject *arg) { INPLACE_DIV };
+
+static PyMemberDef M_Tanh_members[] = {
+{"server", T_OBJECT_EX, offsetof(M_Tanh, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(M_Tanh, stream), 0, "Stream object."},
+{"input", T_OBJECT_EX, offsetof(M_Tanh, input), 0, "Input sound object."},
+{"mul", T_OBJECT_EX, offsetof(M_Tanh, mul), 0, "Mul factor."},
+{"add", T_OBJECT_EX, offsetof(M_Tanh, add), 0, "Add factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyMethodDef M_Tanh_methods[] = {
+{"getServer", (PyCFunction)M_Tanh_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)M_Tanh_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)M_Tanh_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"stop", (PyCFunction)M_Tanh_stop, METH_NOARGS, "Stops computing."},
+{"out", (PyCFunction)M_Tanh_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+{"setMul", (PyCFunction)M_Tanh_setMul, METH_O, "Sets oscillator mul factor."},
+{"setAdd", (PyCFunction)M_Tanh_setAdd, METH_O, "Sets oscillator add factor."},
+{"setSub", (PyCFunction)M_Tanh_setSub, METH_O, "Sets inverse add factor."},
+{"setDiv", (PyCFunction)M_Tanh_setDiv, METH_O, "Sets inverse mul factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyNumberMethods M_Tanh_as_number = {
+(binaryfunc)M_Tanh_add,                         /*nb_add*/
+(binaryfunc)M_Tanh_sub,                         /*nb_subtract*/
+(binaryfunc)M_Tanh_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)M_Tanh_inplace_add,                 /*inplace_add*/
+(binaryfunc)M_Tanh_inplace_sub,                 /*inplace_subtract*/
+(binaryfunc)M_Tanh_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)M_Tanh_div,                       /*nb_true_divide*/
+0,                                              /*nb_inplace_floor_divide*/
+(binaryfunc)M_Tanh_inplace_div,                       /*nb_inplace_true_divide*/
+0,                                              /* nb_index */
+};
+
+PyTypeObject M_TanhType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.M_Tanh_base",                                   /*tp_name*/
+sizeof(M_Tanh),                                 /*tp_basicsize*/
+0,                                              /*tp_itemsize*/
+(destructor)M_Tanh_dealloc,                     /*tp_dealloc*/
+0,                                              /*tp_print*/
+0,                                              /*tp_getattr*/
+0,                                              /*tp_setattr*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
+0,                                              /*tp_repr*/
+&M_Tanh_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*/
+"M_Tanh objects. Performs tanh function on audio samples.",           /* tp_doc */
+(traverseproc)M_Tanh_traverse,                  /* tp_traverse */
+(inquiry)M_Tanh_clear,                          /* tp_clear */
+0,                                              /* tp_richcompare */
+0,                                              /* tp_weaklistoffset */
+0,                                              /* tp_iter */
+0,                                              /* tp_iternext */
+M_Tanh_methods,                                 /* tp_methods */
+M_Tanh_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 */
+M_Tanh_new,                                     /* tp_new */
+};
+
+/************/
+/* M_Exp */
+/************/
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *input;
+    Stream *input_stream;
+    int modebuffer[2]; // need at least 2 slots for mul & add
+} M_Exp;
+
+static void
+M_Exp_process(M_Exp *self) {
+    int i;
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+
+    for (i=0; i<self->bufsize; i++) {
+        self->data[i] = MYEXP(in[i]);
+    }
+}
+
+static void M_Exp_postprocessing_ii(M_Exp *self) { POST_PROCESSING_II };
+static void M_Exp_postprocessing_ai(M_Exp *self) { POST_PROCESSING_AI };
+static void M_Exp_postprocessing_ia(M_Exp *self) { POST_PROCESSING_IA };
+static void M_Exp_postprocessing_aa(M_Exp *self) { POST_PROCESSING_AA };
+static void M_Exp_postprocessing_ireva(M_Exp *self) { POST_PROCESSING_IREVA };
+static void M_Exp_postprocessing_areva(M_Exp *self) { POST_PROCESSING_AREVA };
+static void M_Exp_postprocessing_revai(M_Exp *self) { POST_PROCESSING_REVAI };
+static void M_Exp_postprocessing_revaa(M_Exp *self) { POST_PROCESSING_REVAA };
+static void M_Exp_postprocessing_revareva(M_Exp *self) { POST_PROCESSING_REVAREVA };
+
+static void
+M_Exp_setProcMode(M_Exp *self)
+{
+    int muladdmode;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+    self->proc_func_ptr = M_Exp_process;
+
+	switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = M_Exp_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = M_Exp_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = M_Exp_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = M_Exp_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = M_Exp_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = M_Exp_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = M_Exp_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = M_Exp_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = M_Exp_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+M_Exp_compute_next_data_frame(M_Exp *self)
+{
+    (*self->proc_func_ptr)(self);
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+M_Exp_traverse(M_Exp *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->input);
+    Py_VISIT(self->input_stream);
+    return 0;
+}
+
+static int
+M_Exp_clear(M_Exp *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->input);
+    Py_CLEAR(self->input_stream);
+    return 0;
+}
+
+static void
+M_Exp_dealloc(M_Exp* self)
+{
+    pyo_DEALLOC
+    M_Exp_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+M_Exp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
+    M_Exp *self;
+    self = (M_Exp *)type->tp_alloc(type, 0);
+
+	self->modebuffer[0] = 0;
+	self->modebuffer[1] = 0;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, M_Exp_compute_next_data_frame);
+    self->mode_func_ptr = M_Exp_setProcMode;
+
+    static char *kwlist[] = {"input", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp))
+        Py_RETURN_NONE;
+
+    INIT_INPUT_STREAM
+
+    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 * M_Exp_getServer(M_Exp* self) { GET_SERVER };
+static PyObject * M_Exp_getStream(M_Exp* self) { GET_STREAM };
+static PyObject * M_Exp_setMul(M_Exp *self, PyObject *arg) { SET_MUL };
+static PyObject * M_Exp_setAdd(M_Exp *self, PyObject *arg) { SET_ADD };
+static PyObject * M_Exp_setSub(M_Exp *self, PyObject *arg) { SET_SUB };
+static PyObject * M_Exp_setDiv(M_Exp *self, PyObject *arg) { SET_DIV };
+
+static PyObject * M_Exp_play(M_Exp *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * M_Exp_out(M_Exp *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * M_Exp_stop(M_Exp *self) { STOP };
+
+static PyObject * M_Exp_multiply(M_Exp *self, PyObject *arg) { MULTIPLY };
+static PyObject * M_Exp_inplace_multiply(M_Exp *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * M_Exp_add(M_Exp *self, PyObject *arg) { ADD };
+static PyObject * M_Exp_inplace_add(M_Exp *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * M_Exp_sub(M_Exp *self, PyObject *arg) { SUB };
+static PyObject * M_Exp_inplace_sub(M_Exp *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * M_Exp_div(M_Exp *self, PyObject *arg) { DIV };
+static PyObject * M_Exp_inplace_div(M_Exp *self, PyObject *arg) { INPLACE_DIV };
+
+static PyMemberDef M_Exp_members[] = {
+{"server", T_OBJECT_EX, offsetof(M_Exp, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(M_Exp, stream), 0, "Stream object."},
+{"input", T_OBJECT_EX, offsetof(M_Exp, input), 0, "Input sound object."},
+{"mul", T_OBJECT_EX, offsetof(M_Exp, mul), 0, "Mul factor."},
+{"add", T_OBJECT_EX, offsetof(M_Exp, add), 0, "Add factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyMethodDef M_Exp_methods[] = {
+{"getServer", (PyCFunction)M_Exp_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)M_Exp_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)M_Exp_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"stop", (PyCFunction)M_Exp_stop, METH_NOARGS, "Stops computing."},
+{"out", (PyCFunction)M_Exp_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+{"setMul", (PyCFunction)M_Exp_setMul, METH_O, "Sets oscillator mul factor."},
+{"setAdd", (PyCFunction)M_Exp_setAdd, METH_O, "Sets oscillator add factor."},
+{"setSub", (PyCFunction)M_Exp_setSub, METH_O, "Sets inverse add factor."},
+{"setDiv", (PyCFunction)M_Exp_setDiv, METH_O, "Sets inverse mul factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyNumberMethods M_Exp_as_number = {
+(binaryfunc)M_Exp_add,                         /*nb_add*/
+(binaryfunc)M_Exp_sub,                         /*nb_subtract*/
+(binaryfunc)M_Exp_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)M_Exp_inplace_add,                 /*inplace_add*/
+(binaryfunc)M_Exp_inplace_sub,                 /*inplace_subtract*/
+(binaryfunc)M_Exp_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)M_Exp_div,                       /*nb_true_divide*/
+0,                                              /*nb_inplace_floor_divide*/
+(binaryfunc)M_Exp_inplace_div,                       /*nb_inplace_true_divide*/
+0,                                              /* nb_index */
+};
+
+PyTypeObject M_ExpType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.M_Exp_base",                                   /*tp_name*/
+sizeof(M_Exp),                                 /*tp_basicsize*/
+0,                                              /*tp_itemsize*/
+(destructor)M_Exp_dealloc,                     /*tp_dealloc*/
+0,                                              /*tp_print*/
+0,                                              /*tp_getattr*/
+0,                                              /*tp_setattr*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
+0,                                              /*tp_repr*/
+&M_Exp_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*/
+"M_Exp objects. Performs exp function on audio samples.",           /* tp_doc */
+(traverseproc)M_Exp_traverse,                  /* tp_traverse */
+(inquiry)M_Exp_clear,                          /* tp_clear */
+0,                                              /* tp_richcompare */
+0,                                              /* tp_weaklistoffset */
+0,                                              /* tp_iter */
+0,                                              /* tp_iternext */
+M_Exp_methods,                                 /* tp_methods */
+M_Exp_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 */
+M_Exp_new,                                     /* tp_new */
+};
diff --git a/src/objects/bandsplitmodule.c b/src/objects/bandsplitmodule.c
index a48e717..b5bfebe 100644
--- a/src/objects/bandsplitmodule.c
+++ b/src/objects/bandsplitmodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
@@ -54,29 +55,28 @@ typedef struct {
     int modebuffer[1];
 } BandSplitter;
 
-
 static void
 BandSplitter_compute_variables(BandSplitter *self, MYFLT q)
-{    
+{
     int i;
     MYFLT freq;
     for (i=0; i<self->bands; i++) {
         freq = self->band_freqs[i];
-        if (freq <= 1) 
+        if (freq <= 1)
             freq = 1;
         else if (freq >= self->halfSr)
             freq = self->halfSr;
-    
+
         MYFLT w0 = self->TwoPiOnSr * freq;
         MYFLT c = MYCOS(w0);
         MYFLT alpha = MYSIN(w0) / (2 * q);
-    
+
         self->b0[i] = alpha;
         self->b2[i] = -alpha;
-        self->a0[i] = 1 + alpha;
+        self->a0[i] = 1.0 / (1 + alpha);
         self->a1[i] = -2 * c;
         self->a2[i] = 1 - alpha;
-    }    
+    }
 }
 
 static void
@@ -84,7 +84,7 @@ BandSplitter_setFrequencies(BandSplitter *self)
 {
     int i;
     MYFLT frac = 1. / self->bands;
-    for (i=0; i<self->bands; i++) {        
+    for (i=0; i<self->bands; i++) {
         self->band_freqs[i] = MYPOW(MYPOW(self->max_freq/self->min_freq, frac), i) * self->min_freq;
     }
 }
@@ -94,23 +94,22 @@ BandSplitter_filters_i(BandSplitter *self) {
     MYFLT val;
     int j, i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->init == 1) {
         for (j=0; j<self->bands; j++) {
             self->x1[j] = self->x2[j] = self->y1[j] = self->y2[j] = in[0];
-        }    
+        }
         self->init = 0;
     }
-    
+
     for (j=0; j<self->bands; j++) {
-        for (i=0; i<self->bufsize; i++) {        
-            val = ( (self->b0[j] * in[i]) + (self->b2[j] * self->x2[j]) - (self->a1[j] * self->y1[j]) - (self->a2[j] * self->y2[j]) ) / self->a0[j];
+        for (i=0; i<self->bufsize; i++) {
+            val = ( (self->b0[j] * in[i]) + (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] = val;
+            self->buffer_streams[i + j * self->bufsize] = self->y1[j] = val;
             self->x2[j] = self->x1[j];
             self->x1[j] = in[i];
-            self->buffer_streams[i + j * self->bufsize] = val;
-        }    
+        }
     }
 }
 
@@ -119,11 +118,11 @@ BandSplitter_filters_a(BandSplitter *self) {
     MYFLT val;
     int j, i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->init == 1) {
         for (j=0; j<self->bands; j++) {
             self->x1[j] = self->x2[j] = self->y1[j] = self->y2[j] = in[0];
-        }    
+        }
         self->init = 0;
     }
 
@@ -132,13 +131,12 @@ BandSplitter_filters_a(BandSplitter *self) {
     for (i=0; i<self->bufsize; i++) {
         BandSplitter_compute_variables((BandSplitter *)self, q[i]);
         for (j=0; j<self->bands; j++) {
-            val = ( (self->b0[j] * in[i]) + (self->b2[j] * self->x2[j]) - (self->a1[j] * self->y1[j]) - (self->a2[j] * self->y2[j]) ) / self->a0[j];
+            val = ( (self->b0[j] * in[i]) + (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] = val;
+            self->buffer_streams[i + j * self->bufsize] = self->y1[j] = val;
             self->x2[j] = self->x1[j];
             self->x1[j] = in[i];
-            self->buffer_streams[i + j * self->bufsize] = val;
-        }    
+        }
     }
 }
 
@@ -146,28 +144,28 @@ MYFLT *
 BandSplitter_getSamplesBuffer(BandSplitter *self)
 {
     return (MYFLT *)self->buffer_streams;
-}    
+}
 
 static void
 BandSplitter_setProcMode(BandSplitter *self)
 {
     int procmode;
     procmode = self->modebuffer[0];
-    
+
 	switch (procmode) {
-        case 0:        
+        case 0:
             self->proc_func_ptr = BandSplitter_filters_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = BandSplitter_filters_a;
             break;
-    }    
+    }
 }
 
 static void
 BandSplitter_compute_next_data_frame(BandSplitter *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -181,7 +179,7 @@ BandSplitter_traverse(BandSplitter *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 BandSplitter_clear(BandSplitter *self)
 {
     pyo_CLEAR
@@ -208,7 +206,7 @@ BandSplitter_dealloc(BandSplitter* self)
     free(self->a2);
     free(self->buffer_streams);
     BandSplitter_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -223,23 +221,23 @@ BandSplitter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->bands = 4;
     self->q = PyFloat_FromDouble(1.);
     self->init = 1;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, BandSplitter_compute_next_data_frame);
     self->mode_func_ptr = BandSplitter_setProcMode;
-    
-    self->halfSr = self->sr / 2.;
+
+    self->halfSr = self->sr / 2.01;
     self->TwoPiOnSr = TWOPI / self->sr;
 
     static char *kwlist[] = {"input", "bands", "min", "max", "q", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_IFFO, kwlist, &inputtmp, &self->bands, &self->min_freq, &self->max_freq, &qtmp))
         Py_RETURN_NONE;
 
     INIT_INPUT_STREAM
- 
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     self->band_freqs = (MYFLT *)realloc(self->band_freqs, self->bands * sizeof(MYFLT));
     self->x1 = (MYFLT *)realloc(self->x1, self->bands * sizeof(MYFLT));
     self->x2 = (MYFLT *)realloc(self->x2, self->bands * sizeof(MYFLT));
@@ -270,14 +268,11 @@ static PyObject *
 BandSplitter_setQ(BandSplitter *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->q);
@@ -299,7 +294,7 @@ BandSplitter_setQ(BandSplitter *self, PyObject *arg)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject * BandSplitter_getServer(BandSplitter* self) { GET_SERVER };
 static PyObject * BandSplitter_getStream(BandSplitter* self) { GET_STREAM };
@@ -325,8 +320,7 @@ static PyMethodDef BandSplitter_methods[] = {
 };
 
 PyTypeObject BandSplitterType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.BandSplitter_base",                                   /*tp_name*/
 sizeof(BandSplitter),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -334,7 +328,7 @@ sizeof(BandSplitter),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 0,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -373,7 +367,7 @@ typedef struct {
     pyo_audio_HEAD
     BandSplitter *mainSplitter;
     int modebuffer[2];
-    int chnl; 
+    int chnl;
 } BandSplit;
 
 static void BandSplit_postprocessing_ii(BandSplit *self) { POST_PROCESSING_II };
@@ -391,33 +385,33 @@ BandSplit_setProcMode(BandSplit *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = BandSplit_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = BandSplit_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = BandSplit_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = BandSplit_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = BandSplit_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = BandSplit_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = BandSplit_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = BandSplit_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = BandSplit_postprocessing_revareva;
             break;
     }
@@ -432,7 +426,7 @@ BandSplit_compute_next_data_frame(BandSplit *self)
     tmp = BandSplitter_getSamplesBuffer((BandSplitter *)self->mainSplitter);
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = tmp[i + offset];
-    }    
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -444,11 +438,11 @@ BandSplit_traverse(BandSplit *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 BandSplit_clear(BandSplit *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->mainSplitter);    
+    Py_CLEAR(self->mainSplitter);
     return 0;
 }
 
@@ -457,7 +451,7 @@ BandSplit_dealloc(BandSplit* self)
 {
     pyo_DEALLOC
     BandSplit_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -467,45 +461,45 @@ BandSplit_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL;
     BandSplit *self;
     self = (BandSplit *)type->tp_alloc(type, 0);
-    
+
     self->chnl = 0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, BandSplit_compute_next_data_frame);
     self->mode_func_ptr = BandSplit_setProcMode;
 
     static char *kwlist[] = {"mainSplitter", "chnl", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOO", kwlist, &maintmp, &self->chnl, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     Py_XDECREF(self->mainSplitter);
     Py_INCREF(maintmp);
     self->mainSplitter = (BandSplitter *)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 * BandSplit_getServer(BandSplit* self) { GET_SERVER };
 static PyObject * BandSplit_getStream(BandSplit* self) { GET_STREAM };
-static PyObject * BandSplit_setMul(BandSplit *self, PyObject *arg) { SET_MUL };	
-static PyObject * BandSplit_setAdd(BandSplit *self, PyObject *arg) { SET_ADD };	
-static PyObject * BandSplit_setSub(BandSplit *self, PyObject *arg) { SET_SUB };	
-static PyObject * BandSplit_setDiv(BandSplit *self, PyObject *arg) { SET_DIV };	
+static PyObject * BandSplit_setMul(BandSplit *self, PyObject *arg) { SET_MUL };
+static PyObject * BandSplit_setAdd(BandSplit *self, PyObject *arg) { SET_ADD };
+static PyObject * BandSplit_setSub(BandSplit *self, PyObject *arg) { SET_SUB };
+static PyObject * BandSplit_setDiv(BandSplit *self, PyObject *arg) { SET_DIV };
 
 static PyObject * BandSplit_play(BandSplit *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * BandSplit_out(BandSplit *self, PyObject *args, PyObject *kwds) { OUT };
@@ -545,7 +539,7 @@ static PyNumberMethods BandSplit_as_number = {
 (binaryfunc)BandSplit_add,                      /*nb_add*/
 (binaryfunc)BandSplit_sub,                 /*nb_subtract*/
 (binaryfunc)BandSplit_multiply,                 /*nb_multiply*/
-(binaryfunc)BandSplit_div,                   /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -559,16 +553,16 @@ static PyNumberMethods BandSplit_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
 (binaryfunc)BandSplit_inplace_add,              /*inplace_add*/
 (binaryfunc)BandSplit_inplace_sub,         /*inplace_subtract*/
 (binaryfunc)BandSplit_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)BandSplit_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -577,15 +571,14 @@ static PyNumberMethods BandSplit_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)BandSplit_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)BandSplit_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
 PyTypeObject BandSplitType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.BandSplit_base",         /*tp_name*/
 sizeof(BandSplit),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -593,7 +586,7 @@ sizeof(BandSplit),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &BandSplit_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -668,7 +661,7 @@ typedef struct {
 
 static void
 FourBandMain_compute_variables(FourBandMain *self, double freq, int band)
-{    
+{
     double wc = TWOPI * freq;
     double wc2 = wc * wc;
     double wc3 = wc2 * wc;
@@ -683,31 +676,31 @@ FourBandMain_compute_variables(FourBandMain *self, double freq, int band)
     double a_tmp = 4.0 * wc2 * k2 + 2.0 * sq_tmp1 + k4 + 2.0 * sq_tmp2 + wc4;
     double wc4_a_tmp = wc4 / a_tmp;
     double k4_a_tmp = k4 / a_tmp;
-    
+
     /* common */
     self->b1[band] = (4.0 * (wc4 + sq_tmp1 - k4 - sq_tmp2)) / a_tmp;
     self->b2[band] = (6.0 * wc4 - 8.0 * wc2 * k2 + 6.0 * k4) / a_tmp;
     self->b3[band] = (4.0 * (wc4 - sq_tmp1 + sq_tmp2 - k4)) / a_tmp;
     self->b4[band] = (k4 - 2.0 * sq_tmp1 + wc4 - 2.0 * sq_tmp2 + 4.0 * wc2 * k2) / a_tmp;
-    
+
     /* lowpass */
     self->la0[band] = wc4_a_tmp;
     self->la1[band] = 4.0 * wc4_a_tmp;
     self->la2[band] = 6.0 * wc4_a_tmp;
-    
+
     /* highpass */
     self->ha0[band] = k4_a_tmp;
     self->ha1[band] = -4.0 * k4_a_tmp;
-    self->ha2[band] = 6.0 * k4_a_tmp;    
+    self->ha2[band] = 6.0 * k4_a_tmp;
 }
 
 static void
 FourBandMain_filters(FourBandMain *self) {
     double val, inval, tmp, f1, f2, f3;
     int i, j, j1, ind, ind1;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->modebuffer[0] == 0)
         f1 = PyFloat_AS_DOUBLE(self->freq1);
     else
@@ -720,7 +713,7 @@ FourBandMain_filters(FourBandMain *self) {
         f3 = PyFloat_AS_DOUBLE(self->freq3);
     else
         f3 = (double)Stream_getData((Stream *)self->freq3_stream)[0];
-    
+
     if (f1 != self->last_freq1) {
         self->last_freq1 = f1;
         FourBandMain_compute_variables(self, f1, 0);
@@ -735,12 +728,12 @@ FourBandMain_filters(FourBandMain *self) {
         self->last_freq3 = f3;
         FourBandMain_compute_variables(self, f3, 2);
     }
-    
-    
-    for (i=0; i<self->bufsize; i++) {   
+
+
+    for (i=0; i<self->bufsize; i++) {
         inval = (double)in[i];
         /* First band */
-        val = self->la0[0] * inval + self->la1[0] * self->x1[0] + self->la2[0] * self->x2[0] + self->la1[0] * self->x3[0] + self->la0[0] * self->x4[0] - 
+        val = self->la0[0] * inval + self->la1[0] * self->x1[0] + self->la2[0] * self->x2[0] + self->la1[0] * self->x3[0] + self->la0[0] * self->x4[0] -
               self->b1[0] * self->y1[0] - self->b2[0] * self->y2[0] - self->b3[0] * self->y3[0] - self->b4[0] * self->y4[0];
         self->y4[0] = self->y3[0];
         self->y3[0] = self->y2[0];
@@ -751,13 +744,13 @@ FourBandMain_filters(FourBandMain *self) {
         self->x2[0] = self->x1[0];
         self->x1[0] = inval;
         self->buffer_streams[i] = (MYFLT)val;
-        
+
         /* Second and third bands */
         for (j=0; j<2; j++) {
             j1 = j + 1;
             ind = j * 2 + 1;
             ind1 = ind + 1;
-            tmp = self->ha0[j] * inval + self->ha1[j] * self->x1[ind] + self->ha2[j] * self->x2[ind] + self->ha1[j] * self->x3[ind] + self->ha0[j] * self->x4[ind] - 
+            tmp = self->ha0[j] * inval + self->ha1[j] * self->x1[ind] + self->ha2[j] * self->x2[ind] + self->ha1[j] * self->x3[ind] + self->ha0[j] * self->x4[ind] -
                   self->b1[j] * self->y1[ind] - self->b2[j] * self->y2[ind] - self->b3[j] * self->y3[ind] - self->b4[j] * self->y4[ind];
             self->y4[ind] = self->y3[ind];
             self->y3[ind] = self->y2[ind];
@@ -767,8 +760,8 @@ FourBandMain_filters(FourBandMain *self) {
             self->x3[ind] = self->x2[ind];
             self->x2[ind] = self->x1[ind];
             self->x1[ind] = inval;
-            
-            val = self->la0[j1] * tmp + self->la1[j1] * self->x1[ind1] + self->la2[j1] * self->x2[ind1] + self->la1[j1] * self->x3[ind1] + self->la0[j1] * self->x4[ind1] - 
+
+            val = self->la0[j1] * tmp + self->la1[j1] * self->x1[ind1] + self->la2[j1] * self->x2[ind1] + self->la1[j1] * self->x3[ind1] + self->la0[j1] * self->x4[ind1] -
                   self->b1[j1] * self->y1[ind1] - self->b2[j1] * self->y2[ind1] - self->b3[j1] * self->y3[ind1] - self->b4[j1] * self->y4[ind1];
             self->y4[ind1] = self->y3[ind1];
             self->y3[ind1] = self->y2[ind1];
@@ -778,11 +771,11 @@ FourBandMain_filters(FourBandMain *self) {
             self->x3[ind1] = self->x2[ind1];
             self->x2[ind1] = self->x1[ind1];
             self->x1[ind1] = tmp;
-            
-            self->buffer_streams[i + j1 * self->bufsize] = (MYFLT)val;            
+
+            self->buffer_streams[i + j1 * self->bufsize] = (MYFLT)val;
         }
 
-        val = self->ha0[2] * inval + self->ha1[2] * self->x1[5] + self->ha2[2] * self->x2[5] + self->ha1[2] * self->x3[5] + self->ha0[2] * self->x4[5] - 
+        val = self->ha0[2] * inval + self->ha1[2] * self->x1[5] + self->ha2[2] * self->x2[5] + self->ha1[2] * self->x3[5] + self->ha0[2] * self->x4[5] -
               self->b1[2] * self->y1[5] - self->b2[2] * self->y2[5] - self->b3[2] * self->y3[5] - self->b4[2] * self->y4[5];
         self->y4[5] = self->y3[5];
         self->y3[5] = self->y2[5];
@@ -793,14 +786,14 @@ FourBandMain_filters(FourBandMain *self) {
         self->x2[5] = self->x1[5];
         self->x1[5] = inval;
         self->buffer_streams[i + 3 * self->bufsize] = (MYFLT)val;
-    }    
+    }
 }
 
 MYFLT *
 FourBandMain_getSamplesBuffer(FourBandMain *self)
 {
     return (MYFLT *)self->buffer_streams;
-}    
+}
 
 static void
 FourBandMain_setProcMode(FourBandMain *self)
@@ -811,7 +804,7 @@ FourBandMain_setProcMode(FourBandMain *self)
 static void
 FourBandMain_compute_next_data_frame(FourBandMain *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -829,7 +822,7 @@ FourBandMain_traverse(FourBandMain *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 FourBandMain_clear(FourBandMain *self)
 {
     pyo_CLEAR
@@ -850,7 +843,7 @@ FourBandMain_dealloc(FourBandMain* self)
     pyo_DEALLOC
     free(self->buffer_streams);
     FourBandMain_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -860,12 +853,12 @@ FourBandMain_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *freq1tmp=NULL, *freq2tmp=NULL, *freq3tmp=NULL;
     FourBandMain *self;
     self = (FourBandMain *)type->tp_alloc(type, 0);
-    
+
     self->freq1 = PyFloat_FromDouble(150);
     self->freq2 = PyFloat_FromDouble(500);
     self->freq3 = PyFloat_FromDouble(2000);
     self->last_freq1 = self->last_freq2 = self->last_freq3 = -1.0;
-    
+
     self->modebuffer[0] = 0;
     self->modebuffer[1] = 0;
     self->modebuffer[2] = 0;
@@ -875,14 +868,14 @@ FourBandMain_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = FourBandMain_setProcMode;
 
     static char *kwlist[] = {"input", "freq1", "freq2", "freq3", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &freq1tmp, &freq2tmp, &freq3tmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     for (i=0; i<6; i++) {
         self->x1[i] = self->x2[i] = self->x3[i] = self->x4[i] = self->y1[i] = self->y2[i] = self->y3[i] = self->y4[i] = 0.0;
     }
@@ -892,7 +885,7 @@ FourBandMain_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     for (i=0; i<(4 * self->bufsize); i++) {
         self->buffer_streams[i] = 0.0;
     }
-    
+
     if (freq1tmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq1", "O", freq1tmp);
     }
@@ -904,9 +897,9 @@ FourBandMain_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (freq3tmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq3", "O", freq3tmp);
     }
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
@@ -914,14 +907,11 @@ static PyObject *
 FourBandMain_setFreq1(FourBandMain *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq1);
@@ -940,20 +930,17 @@ FourBandMain_setFreq1(FourBandMain *self, PyObject *arg)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 FourBandMain_setFreq2(FourBandMain *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq2);
@@ -972,20 +959,17 @@ FourBandMain_setFreq2(FourBandMain *self, PyObject *arg)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 FourBandMain_setFreq3(FourBandMain *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq3);
@@ -1004,7 +988,7 @@ FourBandMain_setFreq3(FourBandMain *self, PyObject *arg)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject * FourBandMain_getServer(FourBandMain* self) { GET_SERVER };
 static PyObject * FourBandMain_getStream(FourBandMain* self) { GET_STREAM };
@@ -1034,8 +1018,7 @@ static PyMethodDef FourBandMain_methods[] = {
 };
 
 PyTypeObject FourBandMainType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.FourBandMain_base",                                   /*tp_name*/
     sizeof(FourBandMain),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -1043,7 +1026,7 @@ PyTypeObject FourBandMainType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     0,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -1082,7 +1065,7 @@ typedef struct {
     pyo_audio_HEAD
     FourBandMain *mainSplitter;
     int modebuffer[2];
-    int chnl; 
+    int chnl;
 } FourBand;
 
 static void FourBand_postprocessing_ii(FourBand *self) { POST_PROCESSING_II };
@@ -1100,33 +1083,33 @@ FourBand_setProcMode(FourBand *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = FourBand_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = FourBand_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = FourBand_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = FourBand_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = FourBand_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = FourBand_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = FourBand_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = FourBand_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = FourBand_postprocessing_revareva;
             break;
     }
@@ -1141,7 +1124,7 @@ FourBand_compute_next_data_frame(FourBand *self)
     tmp = FourBandMain_getSamplesBuffer((FourBandMain *)self->mainSplitter);
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = tmp[i + offset];
-    }    
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1153,11 +1136,11 @@ FourBand_traverse(FourBand *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 FourBand_clear(FourBand *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->mainSplitter);    
+    Py_CLEAR(self->mainSplitter);
     return 0;
 }
 
@@ -1166,7 +1149,7 @@ FourBand_dealloc(FourBand* self)
 {
     pyo_DEALLOC
     FourBand_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1176,45 +1159,45 @@ FourBand_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL;
     FourBand *self;
     self = (FourBand *)type->tp_alloc(type, 0);
-    
+
     self->chnl = 0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, FourBand_compute_next_data_frame);
     self->mode_func_ptr = FourBand_setProcMode;
 
     static char *kwlist[] = {"mainSplitter", "chnl", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOO", kwlist, &maintmp, &self->chnl, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     Py_XDECREF(self->mainSplitter);
     Py_INCREF(maintmp);
     self->mainSplitter = (FourBandMain *)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 * FourBand_getServer(FourBand* self) { GET_SERVER };
 static PyObject * FourBand_getStream(FourBand* self) { GET_STREAM };
-static PyObject * FourBand_setMul(FourBand *self, PyObject *arg) { SET_MUL };	
-static PyObject * FourBand_setAdd(FourBand *self, PyObject *arg) { SET_ADD };	
-static PyObject * FourBand_setSub(FourBand *self, PyObject *arg) { SET_SUB };	
-static PyObject * FourBand_setDiv(FourBand *self, PyObject *arg) { SET_DIV };	
+static PyObject * FourBand_setMul(FourBand *self, PyObject *arg) { SET_MUL };
+static PyObject * FourBand_setAdd(FourBand *self, PyObject *arg) { SET_ADD };
+static PyObject * FourBand_setSub(FourBand *self, PyObject *arg) { SET_SUB };
+static PyObject * FourBand_setDiv(FourBand *self, PyObject *arg) { SET_DIV };
 
 static PyObject * FourBand_play(FourBand *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * FourBand_out(FourBand *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1254,7 +1237,7 @@ static PyNumberMethods FourBand_as_number = {
     (binaryfunc)FourBand_add,                      /*nb_add*/
     (binaryfunc)FourBand_sub,                 /*nb_subtract*/
     (binaryfunc)FourBand_multiply,                 /*nb_multiply*/
-    (binaryfunc)FourBand_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -1268,16 +1251,16 @@ static PyNumberMethods FourBand_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)FourBand_inplace_add,              /*inplace_add*/
     (binaryfunc)FourBand_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)FourBand_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)FourBand_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -1286,15 +1269,14 @@ static PyNumberMethods FourBand_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)FourBand_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)FourBand_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject FourBandType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.FourBand_base",         /*tp_name*/
     sizeof(FourBand),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -1302,7 +1284,7 @@ PyTypeObject FourBandType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &FourBand_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -1332,4 +1314,4 @@ PyTypeObject FourBandType = {
     0,      /* tp_init */
     0,                         /* tp_alloc */
     FourBand_new,                 /* tp_new */
-};
+};
\ No newline at end of file
diff --git a/src/objects/chorusmodule.c b/src/objects/chorusmodule.c
index c6de4f6..498548b 100644
--- a/src/objects/chorusmodule.c
+++ b/src/objects/chorusmodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include "pyomodule.h"
 #include "streammodule.h"
@@ -66,7 +67,7 @@ static void
 Chorus_process_ii(Chorus *self) {
     MYFLT lfo, pos, val, fpart, inval;
     int i, j, ipart;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT dpth = PyFloat_AS_DOUBLE(self->depth);
     MYFLT feed = PyFloat_AS_DOUBLE(self->feedback);
@@ -74,16 +75,16 @@ Chorus_process_ii(Chorus *self) {
     if (dpth < 0)
         dpth = 0;
     else if (dpth > 5)
-        dpth = 5;        
-    
+        dpth = 5;
+
     if (feed < 0)
         feed = 0;
     else if (feed > 1)
         feed = 1;
- 
+
     for (i=0; i<self->bufsize; i++) {
         inval = in[i];
-        
+
         self->total_signal = 0.0;
         for (j=0; j<8; j++) {
             if (self->pointerPos[j] < 0.0)
@@ -94,7 +95,7 @@ Chorus_process_ii(Chorus *self) {
             fpart = self->pointerPos[j] - ipart;
             lfo = self->delay_devs[j] * dpth * (LFO_ARRAY[ipart] * (1.0 - fpart) + LFO_ARRAY[ipart+1] * fpart) + self->delays[j];
             self->pointerPos[j] += self->inc[j];
-            
+
             pos = self->in_count[j] - lfo;
             if (pos < 0)
                 pos += self->size[j];
@@ -102,23 +103,23 @@ Chorus_process_ii(Chorus *self) {
             fpart = pos - ipart;
             val = (self->buffer[j][ipart] * (1.0 - fpart) + self->buffer[j][ipart+1] * fpart);
             self->total_signal += val;
-            
+
             self->buffer[j][self->in_count[j]] = inval + val * feed;
             if (self->in_count[j] == 0)
                 self->buffer[j][self->size[j]] = self->buffer[j][self->in_count[j]];
             self->in_count[j]++;
             if (self->in_count[j] >= self->size[j])
                 self->in_count[j] = 0;
-        } 
+        }
         self->data[i] = self->total_signal * 0.25;
-    }    
+    }
 }
 
 static void
 Chorus_process_ai(Chorus *self) {
     MYFLT lfo, pos, val, fpart, inval, dpth;
     int i, j, ipart;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *depth = Stream_getData((Stream *)self->depth_stream);
     MYFLT feed = PyFloat_AS_DOUBLE(self->feedback);
@@ -129,7 +130,7 @@ Chorus_process_ai(Chorus *self) {
         if (dpth < 0)
             dpth = 0;
         else if (dpth > 5)
-            dpth = 5;        
+            dpth = 5;
 
         self->total_signal = 0.0;
         for (j=0; j<8; j++) {
@@ -141,7 +142,7 @@ Chorus_process_ai(Chorus *self) {
             fpart = self->pointerPos[j] - ipart;
             lfo = self->delay_devs[j] * dpth * (LFO_ARRAY[ipart] * (1.0 - fpart) + LFO_ARRAY[ipart+1] * fpart) + self->delays[j];
             self->pointerPos[j] += self->inc[j];
-            
+
             pos = self->in_count[j] - lfo;
             if (pos < 0)
                 pos += self->size[j];
@@ -149,35 +150,35 @@ Chorus_process_ai(Chorus *self) {
             fpart = pos - ipart;
             val = (self->buffer[j][ipart] * (1.0 - fpart) + self->buffer[j][ipart+1] * fpart);
             self->total_signal += val;
-            
+
             self->buffer[j][self->in_count[j]] = inval + val * feed;
             if (self->in_count[j] == 0)
                 self->buffer[j][self->size[j]] = self->buffer[j][self->in_count[j]];
             self->in_count[j]++;
             if (self->in_count[j] >= self->size[j])
                 self->in_count[j] = 0;
-        } 
+        }
         self->data[i] = self->total_signal * 0.25;
-    }    
+    }
 }
 
 static void
 Chorus_process_ia(Chorus *self) {
     MYFLT lfo, pos, val, fpart, inval, feed;
     int i, j, ipart;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT dpth = PyFloat_AS_DOUBLE(self->depth);
     MYFLT *feedback = Stream_getData((Stream *)self->feedback_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inval = in[i];
         feed = feedback[i];
         if (feed < 0)
             feed = 0;
         else if (feed > 1)
-            feed = 1;        
-        
+            feed = 1;
+
         self->total_signal = 0.0;
         for (j=0; j<8; j++) {
             if (self->pointerPos[j] < 0.0)
@@ -188,7 +189,7 @@ Chorus_process_ia(Chorus *self) {
             fpart = self->pointerPos[j] - ipart;
             lfo = self->delay_devs[j] * dpth * (LFO_ARRAY[ipart] * (1.0 - fpart) + LFO_ARRAY[ipart+1] * fpart) + self->delays[j];
             self->pointerPos[j] += self->inc[j];
-            
+
             pos = self->in_count[j] - lfo;
             if (pos < 0)
                 pos += self->size[j];
@@ -196,27 +197,27 @@ Chorus_process_ia(Chorus *self) {
             fpart = pos - ipart;
             val = (self->buffer[j][ipart] * (1.0 - fpart) + self->buffer[j][ipart+1] * fpart);
             self->total_signal += val;
-            
+
             self->buffer[j][self->in_count[j]] = inval + val * feed;
             if (self->in_count[j] == 0)
                 self->buffer[j][self->size[j]] = self->buffer[j][self->in_count[j]];
             self->in_count[j]++;
             if (self->in_count[j] >= self->size[j])
                 self->in_count[j] = 0;
-        } 
+        }
         self->data[i] = self->total_signal * 0.25;
-    }    
+    }
 }
 
 static void
 Chorus_process_aa(Chorus *self) {
     MYFLT lfo, pos, val, fpart, inval, dpth, feed;
     int i, j, ipart;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *depth = Stream_getData((Stream *)self->depth_stream);
     MYFLT *feedback = Stream_getData((Stream *)self->feedback_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inval = in[i];
         dpth = depth[i];
@@ -224,12 +225,12 @@ Chorus_process_aa(Chorus *self) {
         if (dpth < 0)
             dpth = 0;
         else if (dpth > 5)
-            dpth = 5;        
+            dpth = 5;
         if (feed < 0)
             feed = 0;
         else if (feed > 1)
-            feed = 1;        
-        
+            feed = 1;
+
         self->total_signal = 0.0;
         for (j=0; j<8; j++) {
             if (self->pointerPos[j] < 0.0)
@@ -240,7 +241,7 @@ Chorus_process_aa(Chorus *self) {
             fpart = self->pointerPos[j] - ipart;
             lfo = self->delay_devs[j] * dpth * (LFO_ARRAY[ipart] * (1.0 - fpart) + LFO_ARRAY[ipart+1] * fpart) + self->delays[j];
             self->pointerPos[j] += self->inc[j];
-            
+
             pos = self->in_count[j] - lfo;
             if (pos < 0)
                 pos += self->size[j];
@@ -248,31 +249,31 @@ Chorus_process_aa(Chorus *self) {
             fpart = pos - ipart;
             val = (self->buffer[j][ipart] * (1.0 - fpart) + self->buffer[j][ipart+1] * fpart);
             self->total_signal += val;
-            
+
             self->buffer[j][self->in_count[j]] = inval + val * feed;
             if (self->in_count[j] == 0)
                 self->buffer[j][self->size[j]] = self->buffer[j][self->in_count[j]];
             self->in_count[j]++;
             if (self->in_count[j] >= self->size[j])
                 self->in_count[j] = 0;
-        } 
+        }
         self->data[i] = self->total_signal * 0.25;
-    }    
+    }
 }
 
 static void
 Chorus_mix_i(Chorus *self) {
     int i;
     MYFLT val;
-    
+
     MYFLT mix = PyFloat_AS_DOUBLE(self->mix);
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (mix < 0.0)
         mix = 0.0;
     else if (mix > 1.0)
         mix = 1.0;
-    
+
     for (i=0; i<self->bufsize; i++) {
         val = in[i] * (1.0 - mix) + self->data[i] * mix;
         self->data[i] = val;
@@ -283,17 +284,17 @@ static void
 Chorus_mix_a(Chorus *self) {
     int i;
     MYFLT mix, val;
-    
+
     MYFLT *mi = Stream_getData((Stream *)self->mix_stream);
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         mix = mi[i];
         if (mix < 0.0)
             mix = 0.0;
         else if (mix > 1.0)
             mix = 1.0;
-        
+
         val = in[i] * (1.0 - mix) + self->data[i] * mix;
         self->data[i] = val;
     }
@@ -316,66 +317,66 @@ Chorus_setProcMode(Chorus *self)
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
     mixmode = self->modebuffer[4];
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Chorus_process_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Chorus_process_ai;
             break;
-        case 10:    
+        case 10:
             self->proc_func_ptr = Chorus_process_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Chorus_process_aa;
             break;
-    } 
+    }
     switch (mixmode) {
-        case 0:    
+        case 0:
             self->mix_func_ptr = Chorus_mix_i;
             break;
-        case 1:    
+        case 1:
             self->mix_func_ptr = Chorus_mix_a;
             break;
-    }        
-            
+    }
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Chorus_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Chorus_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Chorus_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Chorus_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Chorus_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Chorus_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Chorus_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Chorus_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Chorus_postprocessing_revareva;
             break;
-    } 
+    }
 }
 
 static void
 Chorus_compute_next_data_frame(Chorus *self)
 {
-    (*self->proc_func_ptr)(self); 
-    (*self->mix_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
+    (*self->mix_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -384,28 +385,28 @@ Chorus_traverse(Chorus *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->input);
-    Py_VISIT(self->input_stream);    
-    Py_VISIT(self->feedback);    
-    Py_VISIT(self->feedback_stream);    
-    Py_VISIT(self->depth);    
-    Py_VISIT(self->depth_stream);    
-    Py_VISIT(self->mix);    
-    Py_VISIT(self->mix_stream);    
+    Py_VISIT(self->input_stream);
+    Py_VISIT(self->feedback);
+    Py_VISIT(self->feedback_stream);
+    Py_VISIT(self->depth);
+    Py_VISIT(self->depth_stream);
+    Py_VISIT(self->mix);
+    Py_VISIT(self->mix_stream);
     return 0;
 }
 
-static int 
+static int
 Chorus_clear(Chorus *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
-    Py_CLEAR(self->input_stream);    
-    Py_CLEAR(self->feedback);    
-    Py_CLEAR(self->feedback_stream);    
-    Py_CLEAR(self->depth);    
-    Py_CLEAR(self->depth_stream);    
-    Py_CLEAR(self->mix);    
-    Py_CLEAR(self->mix_stream);    
+    Py_CLEAR(self->input_stream);
+    Py_CLEAR(self->feedback);
+    Py_CLEAR(self->feedback_stream);
+    Py_CLEAR(self->depth);
+    Py_CLEAR(self->depth_stream);
+    Py_CLEAR(self->mix);
+    Py_CLEAR(self->mix_stream);
     return 0;
 }
 
@@ -416,9 +417,9 @@ Chorus_dealloc(Chorus* self)
     pyo_DEALLOC
     for (i=0; i<8; i++) {
         free(self->buffer[i]);
-    }    
+    }
     Chorus_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -430,7 +431,7 @@ Chorus_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *depthtmp=NULL, *feedbacktmp=NULL, *mixtmp=NULL, *multmp=NULL, *addtmp=NULL;
     Chorus *self;
     self = (Chorus *)type->tp_alloc(type, 0);
-    
+
     self->feedback = PyFloat_FromDouble(0.5);
     self->depth = PyFloat_FromDouble(1.0);
     self->mix = PyFloat_FromDouble(0.5);
@@ -441,13 +442,13 @@ Chorus_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
 	self->modebuffer[4] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Chorus_compute_next_data_frame);
     self->mode_func_ptr = Chorus_setProcMode;
- 
+
     srfac = self->sr / 44100.0;
-   
+
     for (i=0; i<8; i++) {
         self->in_count[i] = 0;
         self->delays[i] = chorusParams[i][0] * srfac;
@@ -456,16 +457,16 @@ Chorus_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     }
 
     static char *kwlist[] = {"input", "depth", "feedback", "mix", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOOO", kwlist, &inputtmp, &depthtmp, &feedbacktmp, &mixtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
 
     if (depthtmp) {
         PyObject_CallMethod((PyObject *)self, "setDepth", "O", depthtmp);
     }
-    
+
     if (feedbacktmp) {
         PyObject_CallMethod((PyObject *)self, "setFeedback", "O", feedbacktmp);
     }
@@ -473,15 +474,15 @@ Chorus_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (mixtmp) {
         PyObject_CallMethod((PyObject *)self, "setMix", "O", mixtmp);
     }
-    
+
     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);
 
     for (i=0; i<8; i++) {
@@ -489,20 +490,20 @@ Chorus_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         self->buffer[i] = (MYFLT *)realloc(self->buffer[i], (self->size[i]+1) * sizeof(MYFLT));
         for (j=0; j<(self->size[i]+1); j++) {
             self->buffer[i][j] = 0.;
-        }    
-    }    
-    
+        }
+    }
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * Chorus_getServer(Chorus* self) { GET_SERVER };
 static PyObject * Chorus_getStream(Chorus* self) { GET_STREAM };
-static PyObject * Chorus_setMul(Chorus *self, PyObject *arg) { SET_MUL };	
-static PyObject * Chorus_setAdd(Chorus *self, PyObject *arg) { SET_ADD };	
-static PyObject * Chorus_setSub(Chorus *self, PyObject *arg) { SET_SUB };	
-static PyObject * Chorus_setDiv(Chorus *self, PyObject *arg) { SET_DIV };	
+static PyObject * Chorus_setMul(Chorus *self, PyObject *arg) { SET_MUL };
+static PyObject * Chorus_setAdd(Chorus *self, PyObject *arg) { SET_ADD };
+static PyObject * Chorus_setSub(Chorus *self, PyObject *arg) { SET_SUB };
+static PyObject * Chorus_setDiv(Chorus *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Chorus_play(Chorus *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Chorus_out(Chorus *self, PyObject *args, PyObject *kwds) { OUT };
@@ -518,17 +519,26 @@ static PyObject * Chorus_div(Chorus *self, PyObject *arg) { DIV };
 static PyObject * Chorus_inplace_div(Chorus *self, PyObject *arg) { INPLACE_DIV };
 
 static PyObject *
+Chorus_reset(Chorus *self)
+{
+    int i, j;
+    for (i=0; i<8; i++) {
+        for (j=0; j<(self->size[i]+1); j++) {
+            self->buffer[i][j] = 0.;
+        }
+    }
+	Py_RETURN_NONE;
+}
+
+static PyObject *
 Chorus_setDepth(Chorus *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-    
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->depth);
@@ -544,9 +554,9 @@ Chorus_setDepth(Chorus *self, PyObject *arg)
         self->depth_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -555,14 +565,11 @@ static PyObject *
 Chorus_setFeedback(Chorus *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-    
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->feedback);
@@ -578,25 +585,22 @@ Chorus_setFeedback(Chorus *self, PyObject *arg)
         self->feedback_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Chorus_setMix(Chorus *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-    
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->mix);
@@ -612,12 +616,12 @@ Chorus_setMix(Chorus *self, PyObject *arg)
         self->mix_stream = (Stream *)streamtmp;
 		self->modebuffer[4] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Chorus_members[] = {
 {"server", T_OBJECT_EX, offsetof(Chorus, server), 0, "Pyo server."},
@@ -637,6 +641,7 @@ static PyMethodDef Chorus_methods[] = {
 {"play", (PyCFunction)Chorus_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
 {"out", (PyCFunction)Chorus_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
 {"stop", (PyCFunction)Chorus_stop, METH_NOARGS, "Stops computing."},
+{"reset", (PyCFunction)Chorus_reset, METH_NOARGS, "Reset the delay line."},
 {"setFeedback", (PyCFunction)Chorus_setFeedback, METH_O, "Sets feedback value between 0 -> 1."},
 {"setDepth", (PyCFunction)Chorus_setDepth, METH_O, "Sets chorus depth."},
 {"setMix", (PyCFunction)Chorus_setMix, METH_O, "Sets balance between dry and wet signals."},
@@ -651,7 +656,7 @@ static PyNumberMethods Chorus_as_number = {
 (binaryfunc)Chorus_add,                      /*nb_add*/
 (binaryfunc)Chorus_sub,                 /*nb_subtract*/
 (binaryfunc)Chorus_multiply,                 /*nb_multiply*/
-(binaryfunc)Chorus_div,                   /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -665,16 +670,16 @@ static PyNumberMethods Chorus_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
 (binaryfunc)Chorus_inplace_add,              /*inplace_add*/
 (binaryfunc)Chorus_inplace_sub,         /*inplace_subtract*/
 (binaryfunc)Chorus_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)Chorus_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -683,15 +688,14 @@ static PyNumberMethods Chorus_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)Chorus_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)Chorus_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
 PyTypeObject ChorusType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Chorus_base",         /*tp_name*/
 sizeof(Chorus),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -699,7 +703,7 @@ sizeof(Chorus),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &Chorus_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -729,4 +733,4 @@ Chorus_members,             /* tp_members */
 0,      /* tp_init */
 0,                         /* tp_alloc */
 Chorus_new,                 /* tp_new */
-};
+};
\ No newline at end of file
diff --git a/src/objects/compressmodule.c b/src/objects/compressmodule.c
index 30233ac..fe5ec25 100644
--- a/src/objects/compressmodule.c
+++ b/src/objects/compressmodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
@@ -39,20 +40,20 @@ typedef struct {
     Stream *falltime_stream;
     Stream *thresh_stream;
     Stream *ratio_stream;
-    int modebuffer[6]; // need at least 2 slots for mul & add 
+    int modebuffer[6]; // need at least 2 slots for mul & add
     int outputAmp;
     MYFLT follow;
     MYFLT knee;
     long lh_delay;
     long lh_size;
-    long lh_in_count;    
+    long lh_in_count;
     MYFLT *lh_buffer;
 } Compress;
 
 static MYFLT
 C_clip(MYFLT x)
 {
-    if (x <= 0.0)
+    if (x < 0.00000001)
         return 0.00000001;
     else if (x > 1.0)
         return 1.0;
@@ -67,9 +68,9 @@ Compress_compress_soft(Compress *self) {
     MYFLT risetime, falltime, thresh, ratio;
     int i;
     long ind;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->modebuffer[2] == 0)
         risetime = PyFloat_AS_DOUBLE(self->risetime);
     else
@@ -91,7 +92,7 @@ Compress_compress_soft(Compress *self) {
     else
         ratio = Stream_getData((Stream *)self->ratio_stream)[0];
 
-    ratio = 1.0 / ratio;    
+    ratio = 1.0 / ratio;
     risetime = MYEXP(-1.0 / (self->sr * risetime));
     falltime = MYEXP(-1.0 / (self->sr * falltime));
     knee = self->knee * 0.999 + 0.001; /* 0 = hard knee, 1 = soft knee */
@@ -104,25 +105,25 @@ Compress_compress_soft(Compress *self) {
 
     for (i=0; i<self->bufsize; i++) {
         /* Envelope follower */
-        absin = in[i];  
+        absin = in[i];
         if (absin < 0.0)
             absin = -absin;
         if (self->follow < absin)
             self->follow = absin + risetime * (self->follow - absin);
         else
             self->follow = absin + falltime * (self->follow - absin);
-        
+
         /* Look ahead */
         ind = self->lh_in_count - self->lh_delay;
         if (ind < 0)
             ind += self->lh_size;
         samp = self->lh_buffer[ind];
-        
+
         self->lh_buffer[self->lh_in_count] = in[i];
         self->lh_in_count++;
         if (self->lh_in_count >= self->lh_size)
             self->lh_in_count = 0;
-        
+
         /* Compress signal */
         outa = 1.0;
         if (self->follow > ampthresh) { /* Above threshold */
@@ -137,7 +138,7 @@ Compress_compress_soft(Compress *self) {
             indb = 20.0 * MYLOG10(C_clip(self->follow));
             diff = indb - thresh;
             outdb = diff - diff * kneeratio;
-            outa = MYPOW(10.0, -outdb * 0.05);            
+            outa = MYPOW(10.0, -outdb * 0.05);
         }
         if (self->outputAmp == 0)
             self->data[i] = samp * C_clip(outa);
@@ -161,42 +162,42 @@ Compress_setProcMode(Compress *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Compress_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Compress_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Compress_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Compress_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Compress_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Compress_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Compress_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Compress_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Compress_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 Compress_compute_next_data_frame(Compress *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -206,31 +207,31 @@ Compress_traverse(Compress *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->risetime);    
-    Py_VISIT(self->risetime_stream);    
-    Py_VISIT(self->falltime);    
-    Py_VISIT(self->falltime_stream);    
-    Py_VISIT(self->thresh);    
-    Py_VISIT(self->thresh_stream);    
-    Py_VISIT(self->ratio);    
-    Py_VISIT(self->ratio_stream);    
+    Py_VISIT(self->risetime);
+    Py_VISIT(self->risetime_stream);
+    Py_VISIT(self->falltime);
+    Py_VISIT(self->falltime_stream);
+    Py_VISIT(self->thresh);
+    Py_VISIT(self->thresh_stream);
+    Py_VISIT(self->ratio);
+    Py_VISIT(self->ratio_stream);
     return 0;
 }
 
-static int 
+static int
 Compress_clear(Compress *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->risetime);    
-    Py_CLEAR(self->risetime_stream);    
-    Py_CLEAR(self->falltime);    
-    Py_CLEAR(self->falltime_stream);    
-    Py_CLEAR(self->thresh);    
-    Py_CLEAR(self->thresh_stream);    
-    Py_CLEAR(self->ratio);    
-    Py_CLEAR(self->ratio_stream);    
+    Py_CLEAR(self->risetime);
+    Py_CLEAR(self->risetime_stream);
+    Py_CLEAR(self->falltime);
+    Py_CLEAR(self->falltime_stream);
+    Py_CLEAR(self->thresh);
+    Py_CLEAR(self->thresh_stream);
+    Py_CLEAR(self->ratio);
+    Py_CLEAR(self->ratio_stream);
     return 0;
 }
 
@@ -240,7 +241,7 @@ Compress_dealloc(Compress* self)
     pyo_DEALLOC
     free(self->lh_buffer);
     Compress_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -251,7 +252,7 @@ Compress_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *looktmp=NULL, *kneetmp=NULL;
     Compress *self;
     self = (Compress *)type->tp_alloc(type, 0);
-    
+
     self->thresh = PyFloat_FromDouble(-20.0);
     self->ratio = PyFloat_FromDouble(2.0);
     self->risetime = PyFloat_FromDouble(0.01);
@@ -274,49 +275,49 @@ Compress_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = Compress_setProcMode;
 
     static char *kwlist[] = {"input", "thresh", "ratio", "risetime", "falltime", "lookahead", "knee", "outputAmp", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOOOOiOO", kwlist, &inputtmp, &threshtmp, &ratiotmp, &risetimetmp, &falltimetmp, &looktmp, &kneetmp, &self->outputAmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (threshtmp) {
         PyObject_CallMethod((PyObject *)self, "setThresh", "O", threshtmp);
     }
-   
+
     if (ratiotmp) {
         PyObject_CallMethod((PyObject *)self, "setRatio", "O", ratiotmp);
     }
-   
+
     if (risetimetmp) {
         PyObject_CallMethod((PyObject *)self, "setRiseTime", "O", risetimetmp);
     }
-    
+
     if (falltimetmp) {
         PyObject_CallMethod((PyObject *)self, "setFallTime", "O", falltimetmp);
     }
-    
+
     if (multmp) {
         PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
     }
-    
+
     if (addtmp) {
         PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
     }
 
     PyObject_CallMethod((PyObject *)self, "setLookAhead", "O", looktmp);
     PyObject_CallMethod((PyObject *)self, "setKnee", "O", kneetmp);
-    
+
     self->lh_size = (long)(0.025 * self->sr + 0.5);
     self->lh_buffer = (MYFLT *)realloc(self->lh_buffer, (self->lh_size+1) * sizeof(MYFLT));
     for (i=0; i<(self->lh_size+1); i++) {
         self->lh_buffer[i] = 0.;
-    }    
+    }
 
     self->proc_func_ptr = Compress_compress_soft;
 
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
@@ -324,10 +325,10 @@ Compress_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Compress_getServer(Compress* self) { GET_SERVER };
 static PyObject * Compress_getStream(Compress* self) { GET_STREAM };
-static PyObject * Compress_setMul(Compress *self, PyObject *arg) { SET_MUL };	
-static PyObject * Compress_setAdd(Compress *self, PyObject *arg) { SET_ADD };	
-static PyObject * Compress_setSub(Compress *self, PyObject *arg) { SET_SUB };	
-static PyObject * Compress_setDiv(Compress *self, PyObject *arg) { SET_DIV };	
+static PyObject * Compress_setMul(Compress *self, PyObject *arg) { SET_MUL };
+static PyObject * Compress_setAdd(Compress *self, PyObject *arg) { SET_ADD };
+static PyObject * Compress_setSub(Compress *self, PyObject *arg) { SET_SUB };
+static PyObject * Compress_setDiv(Compress *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Compress_play(Compress *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Compress_out(Compress *self, PyObject *args, PyObject *kwds) { OUT };
@@ -346,14 +347,11 @@ static PyObject *
 Compress_setThresh(Compress *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->thresh);
@@ -369,23 +367,20 @@ Compress_setThresh(Compress *self, PyObject *arg)
         self->thresh_stream = (Stream *)streamtmp;
 		self->modebuffer[4] = 1;
 	}
-        
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Compress_setRatio(Compress *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->ratio);
@@ -404,20 +399,17 @@ Compress_setRatio(Compress *self, PyObject *arg)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Compress_setRiseTime(Compress *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->risetime);
@@ -436,20 +428,17 @@ Compress_setRiseTime(Compress *self, PyObject *arg)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Compress_setFallTime(Compress *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->falltime);
@@ -468,51 +457,45 @@ Compress_setFallTime(Compress *self, PyObject *arg)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Compress_setLookAhead(Compress *self, PyObject *arg)
 {
     MYFLT tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
+
+    ASSERT_ARG_NOT_NULL
 
 	if (PyNumber_Check(arg)) {
-		tmp = PyFloat_AsDouble(PyNumber_Float(arg));
+		tmp = PyFloat_AsDouble(arg);
         if (tmp <= 25.0)
             self->lh_delay = (long)(tmp * 0.001 * self->sr);
         else
-            printf("lookahead must be less than 25.0 ms.\n");
+            PySys_WriteStdout("Compress: lookahead argument must be less than 25.0 ms.\n");
 	}
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Compress_setKnee(Compress *self, PyObject *arg)
 {
     MYFLT tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	if (PyNumber_Check(arg)) {
-		tmp = PyFloat_AsDouble(PyNumber_Float(arg));
+		tmp = PyFloat_AsDouble(arg);
         if (tmp >= 0.0 && tmp <= 1.0)
             self->knee = tmp;
         else
-            printf("knee must be in range 0 (hard) -> 1 (soft).\n");
+            PySys_WriteStdout("Compress: knee argument must be in range 0 (hard) -> 1 (soft).\n");
 	}
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Compress_members[] = {
 {"server", T_OBJECT_EX, offsetof(Compress, server), 0, "Pyo server."},
@@ -550,7 +533,7 @@ static PyNumberMethods Compress_as_number = {
 (binaryfunc)Compress_add,                         /*nb_add*/
 (binaryfunc)Compress_sub,                         /*nb_subtract*/
 (binaryfunc)Compress_multiply,                    /*nb_multiply*/
-(binaryfunc)Compress_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -564,16 +547,16 @@ static PyNumberMethods Compress_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)Compress_inplace_add,                 /*inplace_add*/
 (binaryfunc)Compress_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)Compress_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)Compress_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -582,15 +565,14 @@ static PyNumberMethods Compress_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)Compress_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)Compress_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject CompressType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Compress_base",                                   /*tp_name*/
 sizeof(Compress),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -598,7 +580,7 @@ sizeof(Compress),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &Compress_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -644,7 +626,7 @@ typedef struct {
     Stream *risetime_stream;
     PyObject *falltime;
     Stream *falltime_stream;
-    int modebuffer[5]; // need at least 2 slots for mul & add 
+    int modebuffer[5]; // need at least 2 slots for mul & add
     int outputAmp;
     MYFLT lpfollow;
     MYFLT lpfactor;
@@ -655,7 +637,7 @@ typedef struct {
     MYFLT fallfactor;
     long lh_delay;
     long lh_size;
-    long lh_in_count;    
+    long lh_in_count;
     MYFLT *lh_buffer;
 } Gate;
 
@@ -663,9 +645,9 @@ static void
 Gate_filters_iii(Gate *self) {
     MYFLT samp, absin, thresh, ampthresh, risetime, falltime;
     int i, ind;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     thresh = PyFloat_AS_DOUBLE(self->thresh);
     risetime = PyFloat_AS_DOUBLE(self->risetime);
     if (risetime <= 0.0)
@@ -673,23 +655,23 @@ Gate_filters_iii(Gate *self) {
     falltime = PyFloat_AS_DOUBLE(self->falltime);
     if (falltime <= 0.0)
         falltime = GATE_MIN_RAMP_TIME;
-    
+
     if (risetime != self->last_risetime) {
         self->risefactor = MYEXP(-1.0 / (self->sr * risetime));
         self->last_risetime = risetime;
     }
-    
+
     if (falltime != self->last_falltime) {
         self->fallfactor = MYEXP(-1.0 / (self->sr * falltime));
         self->last_falltime = falltime;
     }
-    
+
     ampthresh = MYPOW(10.0, thresh * 0.05);
     for (i=0; i<self->bufsize; i++) {
         /* Follower */
         absin = in[i] * in[i];
         self->lpfollow = absin + self->lpfactor * (self->lpfollow - absin);
-        
+
         /* Gate slope */
         if (self->lpfollow >= ampthresh)
             self->gate = 1.0 + self->risefactor * (self->gate - 1.0);
@@ -701,12 +683,12 @@ Gate_filters_iii(Gate *self) {
         if (ind < 0)
             ind += self->lh_size;
         samp = self->lh_buffer[ind];
-        
+
         self->lh_buffer[self->lh_in_count] = in[i];
         self->lh_in_count++;
         if (self->lh_in_count >= self->lh_size)
             self->lh_in_count = 0;
-        
+
         /* Gate the signal */
         if (self->outputAmp == 0)
             self->data[i] = samp * self->gate;
@@ -719,8 +701,8 @@ static void
 Gate_filters_aii(Gate *self) {
     MYFLT samp, absin, thresh, ampthresh, risetime, falltime;
     int i, ind;
-    
-    MYFLT *in = Stream_getData((Stream *)self->input_stream);    
+
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *tr = Stream_getData((Stream *)self->thresh_stream);
 
     risetime = PyFloat_AS_DOUBLE(self->risetime);
@@ -729,41 +711,41 @@ Gate_filters_aii(Gate *self) {
     falltime = PyFloat_AS_DOUBLE(self->falltime);
     if (falltime <= 0.0)
         falltime = GATE_MIN_RAMP_TIME;
-    
+
     if (risetime != self->last_risetime) {
         self->risefactor = MYEXP(-1.0 / (self->sr * risetime));
         self->last_risetime = risetime;
     }
-    
+
     if (falltime != self->last_falltime) {
         self->fallfactor = MYEXP(-1.0 / (self->sr * falltime));
         self->last_falltime = falltime;
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         thresh = tr[i];
         ampthresh = MYPOW(10.0, thresh * 0.05);
         /* Follower */
         absin = in[i] * in[i];
         self->lpfollow = absin + self->lpfactor * (self->lpfollow - absin);
-        
+
         /* Gate slope */
         if (self->lpfollow >= ampthresh)
             self->gate = 1.0 + self->risefactor * (self->gate - 1.0);
         else
             self->gate = self->fallfactor * self->gate;
-        
+
         /* Look ahead */
         ind = self->lh_in_count - self->lh_delay;
         if (ind < 0)
             ind += self->lh_size;
         samp = self->lh_buffer[ind];
-        
+
         self->lh_buffer[self->lh_in_count] = in[i];
         self->lh_in_count++;
         if (self->lh_in_count >= self->lh_size)
             self->lh_in_count = 0;
-        
+
         /* Gate the signal */
         if (self->outputAmp == 0)
             self->data[i] = samp * self->gate;
@@ -776,7 +758,7 @@ static void
 Gate_filters_iai(Gate *self) {
     MYFLT samp, absin, thresh, ampthresh, risetime, falltime;
     int i, ind;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
     thresh = PyFloat_AS_DOUBLE(self->thresh);
@@ -790,7 +772,7 @@ Gate_filters_iai(Gate *self) {
         self->fallfactor = MYEXP(-1.0 / (self->sr * falltime));
         self->last_falltime = falltime;
     }
-    
+
     ampthresh = MYPOW(10.0, thresh * 0.05);
     for (i=0; i<self->bufsize; i++) {
         risetime = rise[i];
@@ -800,28 +782,28 @@ Gate_filters_iai(Gate *self) {
             self->risefactor = MYEXP(-1.0 / (self->sr * risetime));
             self->last_risetime = risetime;
         }
-        
+
         /* Follower */
         absin = in[i] * in[i];
         self->lpfollow = absin + self->lpfactor * (self->lpfollow - absin);
-        
+
         /* Gate slope */
         if (self->lpfollow >= ampthresh)
             self->gate = 1.0 + self->risefactor * (self->gate - 1.0);
         else
             self->gate = self->fallfactor * self->gate;
-        
+
         /* Look ahead */
         ind = self->lh_in_count - self->lh_delay;
         if (ind < 0)
             ind += self->lh_size;
         samp = self->lh_buffer[ind];
-        
+
         self->lh_buffer[self->lh_in_count] = in[i];
         self->lh_in_count++;
         if (self->lh_in_count >= self->lh_size)
             self->lh_in_count = 0;
-        
+
         /* Gate the signal */
         if (self->outputAmp == 0)
             self->data[i] = samp * self->gate;
@@ -834,21 +816,21 @@ static void
 Gate_filters_aai(Gate *self) {
     MYFLT samp, absin, thresh, ampthresh, risetime, falltime;
     int i, ind;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     MYFLT *tr = Stream_getData((Stream *)self->thresh_stream);
     MYFLT *rise = Stream_getData((Stream *)self->risetime_stream);
-    
+
     falltime = PyFloat_AS_DOUBLE(self->falltime);
     if (falltime <= 0.0)
         falltime = GATE_MIN_RAMP_TIME;
-    
+
     if (falltime != self->last_falltime) {
         self->fallfactor = MYEXP(-1.0 / (self->sr * falltime));
         self->last_falltime = falltime;
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         thresh = tr[i];
         ampthresh = MYPOW(10.0, thresh * 0.05);
@@ -859,28 +841,28 @@ Gate_filters_aai(Gate *self) {
             self->risefactor = MYEXP(-1.0 / (self->sr * risetime));
             self->last_risetime = risetime;
         }
-        
+
         /* Follower */
         absin = in[i] * in[i];
         self->lpfollow = absin + self->lpfactor * (self->lpfollow - absin);
-        
+
         /* Gate slope */
         if (self->lpfollow >= ampthresh)
             self->gate = 1.0 + self->risefactor * (self->gate - 1.0);
         else
             self->gate = self->fallfactor * self->gate;
-        
+
         /* Look ahead */
         ind = self->lh_in_count - self->lh_delay;
         if (ind < 0)
             ind += self->lh_size;
         samp = self->lh_buffer[ind];
-        
+
         self->lh_buffer[self->lh_in_count] = in[i];
         self->lh_in_count++;
         if (self->lh_in_count >= self->lh_size)
             self->lh_in_count = 0;
-        
+
         /* Gate the signal */
         if (self->outputAmp == 0)
             self->data[i] = samp * self->gate;
@@ -893,15 +875,15 @@ static void
 Gate_filters_iia(Gate *self) {
     MYFLT samp, absin, thresh, ampthresh, risetime, falltime;
     int i, ind;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     thresh = PyFloat_AS_DOUBLE(self->thresh);
     risetime = PyFloat_AS_DOUBLE(self->risetime);
     if (risetime <= 0.0)
         risetime = GATE_MIN_RAMP_TIME;
     MYFLT *fall = Stream_getData((Stream *)self->falltime_stream);
-    
+
     if (risetime != self->last_risetime) {
         self->risefactor = MYEXP(-1.0 / (self->sr * risetime));
         self->last_risetime = risetime;
@@ -916,28 +898,28 @@ Gate_filters_iia(Gate *self) {
             self->fallfactor = MYEXP(-1.0 / (self->sr * falltime));
             self->last_falltime = falltime;
         }
-        
+
         /* Follower */
         absin = in[i] * in[i];
         self->lpfollow = absin + self->lpfactor * (self->lpfollow - absin);
-        
+
         /* Gate slope */
         if (self->lpfollow >= ampthresh)
             self->gate = 1.0 + self->risefactor * (self->gate - 1.0);
         else
             self->gate = self->fallfactor * self->gate;
-        
+
         /* Look ahead */
         ind = self->lh_in_count - self->lh_delay;
         if (ind < 0)
             ind += self->lh_size;
         samp = self->lh_buffer[ind];
-        
+
         self->lh_buffer[self->lh_in_count] = in[i];
         self->lh_in_count++;
         if (self->lh_in_count >= self->lh_size)
             self->lh_in_count = 0;
-        
+
         /* Gate the signal */
         if (self->outputAmp == 0)
             self->data[i] = samp * self->gate;
@@ -950,20 +932,20 @@ static void
 Gate_filters_aia(Gate *self) {
     MYFLT samp, absin, thresh, ampthresh, risetime, falltime;
     int i, ind;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     MYFLT *tr = Stream_getData((Stream *)self->thresh_stream);
     risetime = PyFloat_AS_DOUBLE(self->risetime);
     if (risetime <= 0.0)
         risetime = GATE_MIN_RAMP_TIME;
     MYFLT *fall = Stream_getData((Stream *)self->falltime_stream);
-    
+
     if (risetime != self->last_risetime) {
         self->risefactor = MYEXP(-1.0 / (self->sr * risetime));
         self->last_risetime = risetime;
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         thresh = tr[i];
         ampthresh = MYPOW(10.0, thresh * 0.05);
@@ -974,28 +956,28 @@ Gate_filters_aia(Gate *self) {
             self->fallfactor = MYEXP(-1.0 / (self->sr * falltime));
             self->last_falltime = falltime;
         }
-        
+
         /* Follower */
         absin = in[i] * in[i];
         self->lpfollow = absin + self->lpfactor * (self->lpfollow - absin);
-        
+
         /* Gate slope */
         if (self->lpfollow >= ampthresh)
             self->gate = 1.0 + self->risefactor * (self->gate - 1.0);
         else
             self->gate = self->fallfactor * self->gate;
-        
+
         /* Look ahead */
         ind = self->lh_in_count - self->lh_delay;
         if (ind < 0)
             ind += self->lh_size;
         samp = self->lh_buffer[ind];
-        
+
         self->lh_buffer[self->lh_in_count] = in[i];
         self->lh_in_count++;
         if (self->lh_in_count >= self->lh_size)
             self->lh_in_count = 0;
-        
+
         /* Gate the signal */
         if (self->outputAmp == 0)
             self->data[i] = samp * self->gate;
@@ -1008,9 +990,9 @@ static void
 Gate_filters_iaa(Gate *self) {
     MYFLT samp, absin, thresh, ampthresh, risetime, falltime;
     int i, ind;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     thresh = PyFloat_AS_DOUBLE(self->thresh);
     MYFLT *rise = Stream_getData((Stream *)self->risetime_stream);
     MYFLT *fall = Stream_getData((Stream *)self->falltime_stream);
@@ -1031,28 +1013,28 @@ Gate_filters_iaa(Gate *self) {
             self->fallfactor = MYEXP(-1.0 / (self->sr * falltime));
             self->last_falltime = falltime;
         }
-        
+
         /* Follower */
         absin = in[i] * in[i];
         self->lpfollow = absin + self->lpfactor * (self->lpfollow - absin);
-        
+
         /* Gate slope */
         if (self->lpfollow >= ampthresh)
             self->gate = 1.0 + self->risefactor * (self->gate - 1.0);
         else
             self->gate = self->fallfactor * self->gate;
-        
+
         /* Look ahead */
         ind = self->lh_in_count - self->lh_delay;
         if (ind < 0)
             ind += self->lh_size;
         samp = self->lh_buffer[ind];
-        
+
         self->lh_buffer[self->lh_in_count] = in[i];
         self->lh_in_count++;
         if (self->lh_in_count >= self->lh_size)
             self->lh_in_count = 0;
-        
+
         /* Gate the signal */
         if (self->outputAmp == 0)
             self->data[i] = samp * self->gate;
@@ -1065,13 +1047,13 @@ static void
 Gate_filters_aaa(Gate *self) {
     MYFLT samp, absin, thresh, ampthresh, risetime, falltime;
     int i, ind;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     MYFLT *tr = Stream_getData((Stream *)self->thresh_stream);
     MYFLT *rise = Stream_getData((Stream *)self->risetime_stream);
     MYFLT *fall = Stream_getData((Stream *)self->falltime_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         thresh = tr[i];
         ampthresh = MYPOW(10.0, thresh * 0.05);
@@ -1089,28 +1071,28 @@ Gate_filters_aaa(Gate *self) {
             self->fallfactor = MYEXP(-1.0 / (self->sr * falltime));
             self->last_falltime = falltime;
         }
-        
+
         /* Follower */
         absin = in[i] * in[i];
         self->lpfollow = absin + self->lpfactor * (self->lpfollow - absin);
-        
+
         /* Gate slope */
         if (self->lpfollow >= ampthresh)
             self->gate = 1.0 + self->risefactor * (self->gate - 1.0);
         else
             self->gate = self->fallfactor * self->gate;
-        
+
         /* Look ahead */
         ind = self->lh_in_count - self->lh_delay;
         if (ind < 0)
             ind += self->lh_size;
         samp = self->lh_buffer[ind];
-        
+
         self->lh_buffer[self->lh_in_count] = in[i];
         self->lh_in_count++;
         if (self->lh_in_count >= self->lh_size)
             self->lh_in_count = 0;
-        
+
         /* Gate the signal */
         if (self->outputAmp == 0)
             self->data[i] = samp * self->gate;
@@ -1135,68 +1117,68 @@ Gate_setProcMode(Gate *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Gate_filters_iii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Gate_filters_aii;
             break;
-        case 10:    
+        case 10:
             self->proc_func_ptr = Gate_filters_iai;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Gate_filters_aai;
             break;
-        case 100:    
+        case 100:
             self->proc_func_ptr = Gate_filters_iia;
             break;
-        case 101:    
+        case 101:
             self->proc_func_ptr = Gate_filters_aia;
             break;
-        case 110:    
+        case 110:
             self->proc_func_ptr = Gate_filters_iaa;
             break;
-        case 111:    
+        case 111:
             self->proc_func_ptr = Gate_filters_aaa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Gate_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Gate_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Gate_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Gate_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Gate_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Gate_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Gate_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Gate_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Gate_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Gate_compute_next_data_frame(Gate *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1206,27 +1188,27 @@ Gate_traverse(Gate *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->thresh);    
-    Py_VISIT(self->thresh_stream);    
-    Py_VISIT(self->risetime);    
-    Py_VISIT(self->risetime_stream);    
-    Py_VISIT(self->falltime);    
-    Py_VISIT(self->falltime_stream);    
+    Py_VISIT(self->thresh);
+    Py_VISIT(self->thresh_stream);
+    Py_VISIT(self->risetime);
+    Py_VISIT(self->risetime_stream);
+    Py_VISIT(self->falltime);
+    Py_VISIT(self->falltime_stream);
     return 0;
 }
 
-static int 
+static int
 Gate_clear(Gate *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->thresh);    
-    Py_CLEAR(self->thresh_stream);    
-    Py_CLEAR(self->risetime);    
-    Py_CLEAR(self->risetime_stream);    
-    Py_CLEAR(self->falltime);    
-    Py_CLEAR(self->falltime_stream);    
+    Py_CLEAR(self->thresh);
+    Py_CLEAR(self->thresh_stream);
+    Py_CLEAR(self->risetime);
+    Py_CLEAR(self->risetime_stream);
+    Py_CLEAR(self->falltime);
+    Py_CLEAR(self->falltime_stream);
     return 0;
 }
 
@@ -1236,7 +1218,7 @@ Gate_dealloc(Gate* self)
     pyo_DEALLOC
     free(self->lh_buffer);
     Gate_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1247,7 +1229,7 @@ Gate_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *looktmp=NULL;
     Gate *self;
     self = (Gate *)type->tp_alloc(type, 0);
-    
+
     self->thresh = PyFloat_FromDouble(-70.0);
     self->risetime = PyFloat_FromDouble(0.01);
     self->falltime = PyFloat_FromDouble(0.05);
@@ -1263,51 +1245,51 @@ Gate_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->lh_delay = 0;
     self->lh_in_count = 0;
     self->outputAmp = 0;
-    
+
     INIT_OBJECT_COMMON
-    
+
     self->lpfactor = MYEXP(-1.0 / (self->sr / 20.0));
 
     Stream_setFunctionPtr(self->stream, Gate_compute_next_data_frame);
     self->mode_func_ptr = Gate_setProcMode;
 
     static char *kwlist[] = {"input", "thresh", "risetime", "falltime", "lookahead", "outputAmp", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOOiOO", kwlist, &inputtmp, &threshtmp, &risetimetmp, &falltimetmp, &looktmp, &self->outputAmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
 
     if (threshtmp) {
         PyObject_CallMethod((PyObject *)self, "setThresh", "O", threshtmp);
     }
-    
+
     if (risetimetmp) {
         PyObject_CallMethod((PyObject *)self, "setRiseTime", "O", risetimetmp);
     }
-    
+
     if (falltimetmp) {
         PyObject_CallMethod((PyObject *)self, "setFallTime", "O", falltimetmp);
     }
-    
+
     if (multmp) {
         PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
     }
-    
+
     if (addtmp) {
         PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
     }
 
     PyObject_CallMethod((PyObject *)self, "setLookAhead", "O", looktmp);
-    
+
     self->lh_size = (long)(0.025 * self->sr + 0.5);
     self->lh_buffer = (MYFLT *)realloc(self->lh_buffer, (self->lh_size+1) * sizeof(MYFLT));
     for (i=0; i<(self->lh_size+1); i++) {
         self->lh_buffer[i] = 0.;
-    }    
-    
+    }
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
@@ -1315,10 +1297,10 @@ Gate_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Gate_getServer(Gate* self) { GET_SERVER };
 static PyObject * Gate_getStream(Gate* self) { GET_STREAM };
-static PyObject * Gate_setMul(Gate *self, PyObject *arg) { SET_MUL };	
-static PyObject * Gate_setAdd(Gate *self, PyObject *arg) { SET_ADD };	
-static PyObject * Gate_setSub(Gate *self, PyObject *arg) { SET_SUB };	
-static PyObject * Gate_setDiv(Gate *self, PyObject *arg) { SET_DIV };	
+static PyObject * Gate_setMul(Gate *self, PyObject *arg) { SET_MUL };
+static PyObject * Gate_setAdd(Gate *self, PyObject *arg) { SET_ADD };
+static PyObject * Gate_setSub(Gate *self, PyObject *arg) { SET_SUB };
+static PyObject * Gate_setDiv(Gate *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Gate_play(Gate *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Gate_out(Gate *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1337,14 +1319,11 @@ static PyObject *
 Gate_setThresh(Gate *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->thresh);
@@ -1360,9 +1339,9 @@ Gate_setThresh(Gate *self, PyObject *arg)
         self->thresh_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -1371,14 +1350,11 @@ static PyObject *
 Gate_setRiseTime(Gate *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->risetime);
@@ -1394,9 +1370,9 @@ Gate_setRiseTime(Gate *self, PyObject *arg)
         self->risetime_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -1405,14 +1381,11 @@ static PyObject *
 Gate_setFallTime(Gate *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->falltime);
@@ -1428,9 +1401,9 @@ Gate_setFallTime(Gate *self, PyObject *arg)
         self->falltime_stream = (Stream *)streamtmp;
 		self->modebuffer[4] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -1439,23 +1412,20 @@ static PyObject *
 Gate_setLookAhead(Gate *self, PyObject *arg)
 {
     MYFLT tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	if (PyNumber_Check(arg)) {
-		tmp = PyFloat_AsDouble(PyNumber_Float(arg));
+		tmp = PyFloat_AsDouble(arg);
         if (tmp <= 25.0)
             self->lh_delay = (long)(tmp * 0.001 * self->sr);
         else
-            printf("lookahead must be less than 25.0 ms.\n");
+            PySys_WriteStdout("Gate: lookahead argument must be less than 25.0 ms.\n");
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Gate_members[] = {
     {"server", T_OBJECT_EX, offsetof(Gate, server), 0, "Pyo server."},
@@ -1490,7 +1460,7 @@ static PyNumberMethods Gate_as_number = {
     (binaryfunc)Gate_add,                         /*nb_add*/
     (binaryfunc)Gate_sub,                         /*nb_subtract*/
     (binaryfunc)Gate_multiply,                    /*nb_multiply*/
-    (binaryfunc)Gate_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -1504,16 +1474,16 @@ static PyNumberMethods Gate_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Gate_inplace_add,                 /*inplace_add*/
     (binaryfunc)Gate_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Gate_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Gate_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -1522,15 +1492,14 @@ static PyNumberMethods Gate_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Gate_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Gate_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject GateType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Gate_base",                                   /*tp_name*/
     sizeof(Gate),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -1538,7 +1507,7 @@ PyTypeObject GateType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &Gate_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -1581,7 +1550,7 @@ typedef struct {
     Stream *input2_stream;
     PyObject *freq;
     Stream *freq_stream;
-    int modebuffer[3]; // need at least 2 slots for mul & add 
+    int modebuffer[3]; // need at least 2 slots for mul & add
     MYFLT follow1;
     MYFLT follow2;
     MYFLT last_freq;
@@ -1595,13 +1564,13 @@ Balance_filters_i(Balance *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *in2 = Stream_getData((Stream *)self->input2_stream);
     freq = PyFloat_AS_DOUBLE(self->freq);
-    
+
     if (freq < 0.1)
         freq = 0.1;
-    
+
     if (freq != self->last_freq) {
         self->factor = MYEXP(-1.0 / (self->sr / freq));
-        self->last_freq = freq;    
+        self->last_freq = freq;
     }
 
     for (i=0; i<self->bufsize; i++) {
@@ -1614,7 +1583,7 @@ Balance_filters_i(Balance *self) {
         absin = in2[i];
         if (absin < 0.0)
             absin = -absin;
-        self->follow2 = absin + self->factor * (self->follow2 - absin);        
+        self->follow2 = absin + self->factor * (self->follow2 - absin);
         self->data[i] = in[i] * (self->follow2 / self->follow1);
     }
 }
@@ -1626,15 +1595,15 @@ Balance_filters_a(Balance *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *in2 = Stream_getData((Stream *)self->input2_stream);
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-        
+
     for (i=0; i<self->bufsize; i++) {
         freq = fr[i];
         if (freq < 0.1)
             freq = 0.1;
-        
+
         if (freq != self->last_freq) {
             self->factor = MYEXP(-1.0 / (self->sr / freq));
-            self->last_freq = freq;    
+            self->last_freq = freq;
         }
         absin = in[i];
         if (absin < 0.0)
@@ -1645,7 +1614,7 @@ Balance_filters_a(Balance *self) {
         absin = in2[i];
         if (absin < 0.0)
             absin = -absin;
-        self->follow2 = absin + self->factor * (self->follow2 - absin);        
+        self->follow2 = absin + self->factor * (self->follow2 - absin);
         self->data[i] = in[i] * (self->follow2 / self->follow1);
     }
 }
@@ -1666,50 +1635,50 @@ Balance_setProcMode(Balance *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2];
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Balance_filters_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Balance_filters_a;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Balance_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Balance_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Balance_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Balance_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Balance_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Balance_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Balance_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Balance_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Balance_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Balance_compute_next_data_frame(Balance *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1721,12 +1690,12 @@ Balance_traverse(Balance *self, visitproc visit, void *arg)
     Py_VISIT(self->input_stream);
     Py_VISIT(self->input2);
     Py_VISIT(self->input2_stream);
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
     return 0;
 }
 
-static int 
+static int
 Balance_clear(Balance *self)
 {
     pyo_CLEAR
@@ -1734,8 +1703,8 @@ Balance_clear(Balance *self)
     Py_CLEAR(self->input_stream);
     Py_CLEAR(self->input2);
     Py_CLEAR(self->input2_stream);
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
     return 0;
 }
 
@@ -1744,7 +1713,7 @@ Balance_dealloc(Balance* self)
 {
     pyo_DEALLOC
     Balance_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1754,7 +1723,7 @@ Balance_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *input2tmp, *input2_streamtmp, *freqtmp=NULL, *multmp=NULL, *addtmp=NULL;
     Balance *self;
     self = (Balance *)type->tp_alloc(type, 0);
-    
+
     self->freq = PyFloat_FromDouble(10);
     self->follow1 = self->follow2 = 0.0;
     self->last_freq = -1.0;
@@ -1762,50 +1731,50 @@ Balance_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Balance_compute_next_data_frame);
     self->mode_func_ptr = Balance_setProcMode;
-    
+
     static char *kwlist[] = {"input", "input2", "freq", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOO", kwlist, &inputtmp, &input2tmp, &freqtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     Py_XDECREF(self->input2);
     self->input2 = input2tmp;
     input2_streamtmp = PyObject_CallMethod((PyObject *)self->input2, "_getStream", NULL);
     Py_INCREF(input2_streamtmp);
     Py_XDECREF(self->input2_stream);
     self->input2_stream = (Stream *)input2_streamtmp;
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    
+
     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 * Balance_getServer(Balance* self) { GET_SERVER };
 static PyObject * Balance_getStream(Balance* self) { GET_STREAM };
-static PyObject * Balance_setMul(Balance *self, PyObject *arg) { SET_MUL };	
-static PyObject * Balance_setAdd(Balance *self, PyObject *arg) { SET_ADD };	
-static PyObject * Balance_setSub(Balance *self, PyObject *arg) { SET_SUB };	
-static PyObject * Balance_setDiv(Balance *self, PyObject *arg) { SET_DIV };	
+static PyObject * Balance_setMul(Balance *self, PyObject *arg) { SET_MUL };
+static PyObject * Balance_setAdd(Balance *self, PyObject *arg) { SET_ADD };
+static PyObject * Balance_setSub(Balance *self, PyObject *arg) { SET_SUB };
+static PyObject * Balance_setDiv(Balance *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Balance_play(Balance *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Balance_out(Balance *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1824,14 +1793,11 @@ static PyObject *
 Balance_setFreq(Balance *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -1847,9 +1813,9 @@ Balance_setFreq(Balance *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -1883,7 +1849,7 @@ static PyNumberMethods Balance_as_number = {
     (binaryfunc)Balance_add,                         /*nb_add*/
     (binaryfunc)Balance_sub,                         /*nb_subtract*/
     (binaryfunc)Balance_multiply,                    /*nb_multiply*/
-    (binaryfunc)Balance_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -1897,16 +1863,16 @@ static PyNumberMethods Balance_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Balance_inplace_add,                 /*inplace_add*/
     (binaryfunc)Balance_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Balance_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Balance_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -1915,15 +1881,14 @@ static PyNumberMethods Balance_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Balance_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Balance_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject BalanceType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Balance_base",                                   /*tp_name*/
     sizeof(Balance),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -1931,7 +1896,7 @@ PyTypeObject BalanceType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &Balance_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -1962,4 +1927,3 @@ PyTypeObject BalanceType = {
     0,                                              /* tp_alloc */
     Balance_new,                                     /* tp_new */
 };
-
diff --git a/src/objects/convolvemodule.c b/src/objects/convolvemodule.c
index 63b3fc3..841c277 100644
--- a/src/objects/convolvemodule.c
+++ b/src/objects/convolvemodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include "pyomodule.h"
 #include "streammodule.h"
@@ -36,7 +37,7 @@ typedef struct {
     PyObject *table;
     PyObject *input;
     Stream *input_stream;
-    int modebuffer[2]; // need at least 2 slots for mul & add 
+    int modebuffer[2]; // need at least 2 slots for mul & add
     MYFLT *input_tmp;
     int size;
     int count;
@@ -57,7 +58,7 @@ Convolve_filters(Convolve *self) {
                 tmp_count += self->size;
             self->data[i] += self->input_tmp[tmp_count--] * impulse[j];
         }
-        
+
         self->count++;
         if (self->count == self->size)
             self->count = 0;
@@ -80,44 +81,44 @@ Convolve_setProcMode(Convolve *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = Convolve_filters;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Convolve_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Convolve_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Convolve_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Convolve_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Convolve_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Convolve_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Convolve_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Convolve_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Convolve_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Convolve_compute_next_data_frame(Convolve *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -131,7 +132,7 @@ Convolve_traverse(Convolve *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Convolve_clear(Convolve *self)
 {
     pyo_CLEAR
@@ -147,7 +148,7 @@ Convolve_dealloc(Convolve* self)
     pyo_DEALLOC
     free(self->input_tmp);
     Convolve_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -157,42 +158,39 @@ Convolve_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *tabletmp, *multmp=NULL, *addtmp=NULL;
     Convolve *self;
     self = (Convolve *)type->tp_alloc(type, 0);
-    
+
     self->count = 0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Convolve_compute_next_data_frame);
     self->mode_func_ptr = Convolve_setProcMode;
 
     static char *kwlist[] = {"input", "table", "size", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OOi|OO", kwlist, &inputtmp, &tabletmp, &self->size, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
 
     if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
-        PySys_WriteStderr("TypeError: \"table\" argument of Convolve must be a PyoTableObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"table\" argument of Convolve 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);
 
     self->input_tmp = (MYFLT *)realloc(self->input_tmp, self->size * sizeof(MYFLT));
@@ -205,10 +203,10 @@ Convolve_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Convolve_getServer(Convolve* self) { GET_SERVER };
 static PyObject * Convolve_getStream(Convolve* self) { GET_STREAM };
-static PyObject * Convolve_setMul(Convolve *self, PyObject *arg) { SET_MUL };	
-static PyObject * Convolve_setAdd(Convolve *self, PyObject *arg) { SET_ADD };	
-static PyObject * Convolve_setSub(Convolve *self, PyObject *arg) { SET_SUB };	
-static PyObject * Convolve_setDiv(Convolve *self, PyObject *arg) { SET_DIV };	
+static PyObject * Convolve_setMul(Convolve *self, PyObject *arg) { SET_MUL };
+static PyObject * Convolve_setAdd(Convolve *self, PyObject *arg) { SET_ADD };
+static PyObject * Convolve_setSub(Convolve *self, PyObject *arg) { SET_SUB };
+static PyObject * Convolve_setDiv(Convolve *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Convolve_play(Convolve *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Convolve_out(Convolve *self, PyObject *args, PyObject *kwds) { OUT };
@@ -234,19 +232,16 @@ static PyObject *
 Convolve_setTable(Convolve *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    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 PyMemberDef Convolve_members[] = {
 {"server", T_OBJECT_EX, offsetof(Convolve, server), 0, "Pyo server."},
@@ -276,7 +271,7 @@ static PyNumberMethods Convolve_as_number = {
 (binaryfunc)Convolve_add,                         /*nb_add*/
 (binaryfunc)Convolve_sub,                         /*nb_subtract*/
 (binaryfunc)Convolve_multiply,                    /*nb_multiply*/
-(binaryfunc)Convolve_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -290,16 +285,16 @@ static PyNumberMethods Convolve_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)Convolve_inplace_add,                 /*inplace_add*/
 (binaryfunc)Convolve_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)Convolve_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)Convolve_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -308,15 +303,14 @@ static PyNumberMethods Convolve_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)Convolve_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)Convolve_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject ConvolveType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Convolve_base",                                   /*tp_name*/
 sizeof(Convolve),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -324,7 +318,7 @@ sizeof(Convolve),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &Convolve_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -367,7 +361,7 @@ typedef struct {
     Stream *freq_stream;
     PyObject *bandwidth;
     Stream *bandwidth_stream;
-    int modebuffer[4]; // need at least 2 slots for mul & add 
+    int modebuffer[4]; // need at least 2 slots for mul & add
     MYFLT *impulse;
     MYFLT *impulse_tmp;
     MYFLT *input_tmp;
@@ -380,14 +374,14 @@ typedef struct {
     MYFLT last_bandwidth;
 } IRWinSinc;
 
-static void 
+static void
 IRWinSinc_alloc_memory(IRWinSinc *self) {
     int i;
     if ((self->order % 2) != 0)
         self->order += 1;
-    
+
     self->size = self->order + 1;
-    
+
     self->input_tmp = (MYFLT *)realloc(self->input_tmp, self->size * sizeof(MYFLT));
     self->impulse = (MYFLT *)realloc(self->impulse, self->size * sizeof(MYFLT));
     self->impulse_tmp = (MYFLT *)realloc(self->impulse_tmp, self->size * sizeof(MYFLT));
@@ -400,12 +394,12 @@ static void
 IRWinSinc_create_impulse(IRWinSinc *self, MYFLT freq, MYFLT bandwidth) {
     int i, half, ipart;
     MYFLT val, fpart, sum, invSum, env, envPointer, envPointerScaling, sincScaling, w;
-    
+
     half = self->order / 2;
     sum = 0.0;
     envPointerScaling = 1.0 / self->size * 512.0;
     sincScaling = self->order / 2.0;
-    
+
     if (freq < 1)
         freq = 1.0;
     else if (freq > (self->sr*0.5))
@@ -415,12 +409,12 @@ IRWinSinc_create_impulse(IRWinSinc *self, MYFLT freq, MYFLT bandwidth) {
         bandwidth = 1.0;
     else if (bandwidth > (self->sr*0.5))
         bandwidth = self->sr*0.5;
-    
+
     if (self->filtertype <= 1)
         w = TWOPI * freq / self->sr;
     else
         w = TWOPI * (freq - bandwidth / 2.0) / self->sr;
-    
+
     /* LOWPASS */
     for (i=0; i<half; i++) {
         envPointer = i * envPointerScaling;
@@ -441,7 +435,7 @@ IRWinSinc_create_impulse(IRWinSinc *self, MYFLT freq, MYFLT bandwidth) {
     for (i=half+1; i<self->size; i++) {
         self->impulse[i] = self->impulse[self->order-i];
     }
-    
+
     /* HIGHPASS */
     if (self->filtertype == 1) {
         for (i=0; i<self->size; i++) {
@@ -449,7 +443,7 @@ IRWinSinc_create_impulse(IRWinSinc *self, MYFLT freq, MYFLT bandwidth) {
         }
         self->impulse[half] = self->impulse[half] + 1.0;
     }
-    
+
     /* BANDREJECT */
     if (self->filtertype >= 2) {
         sum = 0.0;
@@ -485,7 +479,7 @@ IRWinSinc_create_impulse(IRWinSinc *self, MYFLT freq, MYFLT bandwidth) {
             for (i=0; i<self->size; i++) {
                 self->impulse[i] = -self->impulse[i];
             }
-            self->impulse[half] = self->impulse[half] + 1.0;            
+            self->impulse[half] = self->impulse[half] + 1.0;
         }
     }
 }
@@ -494,9 +488,9 @@ static void
 IRWinSinc_filters(IRWinSinc *self) {
     int i,j,tmp_count;
     MYFLT freq, bw;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->modebuffer[2] == 0)
         freq = PyFloat_AS_DOUBLE(self->freq);
     else {
@@ -509,14 +503,14 @@ IRWinSinc_filters(IRWinSinc *self) {
         MYFLT *band = Stream_getData((Stream *)self->bandwidth_stream);
         bw = band[0];
     }
-    
+
     if (freq != self->last_freq || bw != self->last_bandwidth || self->changed == 1) {
         IRWinSinc_create_impulse(self, freq, bw);
         self->last_freq = freq;
         self->last_bandwidth = bw;
         self->changed = 0;
     }
-        
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = 0.0;
         tmp_count = self->count;
@@ -525,7 +519,7 @@ IRWinSinc_filters(IRWinSinc *self) {
                 tmp_count += self->size;
             self->data[i] += self->input_tmp[tmp_count--] * self->impulse[j];
         }
-        
+
         self->count++;
         if (self->count == self->size)
             self->count = 0;
@@ -548,44 +542,44 @@ IRWinSinc_setProcMode(IRWinSinc *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = IRWinSinc_filters;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = IRWinSinc_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = IRWinSinc_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = IRWinSinc_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = IRWinSinc_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = IRWinSinc_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = IRWinSinc_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = IRWinSinc_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = IRWinSinc_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = IRWinSinc_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 IRWinSinc_compute_next_data_frame(IRWinSinc *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -595,23 +589,23 @@ IRWinSinc_traverse(IRWinSinc *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
-    Py_VISIT(self->bandwidth);    
-    Py_VISIT(self->bandwidth_stream);    
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->bandwidth);
+    Py_VISIT(self->bandwidth_stream);
     return 0;
 }
 
-static int 
+static int
 IRWinSinc_clear(IRWinSinc *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
-    Py_CLEAR(self->bandwidth);    
-    Py_CLEAR(self->bandwidth_stream);    
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->bandwidth);
+    Py_CLEAR(self->bandwidth_stream);
     return 0;
 }
 
@@ -623,7 +617,7 @@ IRWinSinc_dealloc(IRWinSinc* self)
     free(self->impulse);
     free(self->impulse_tmp);
     IRWinSinc_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -633,7 +627,7 @@ IRWinSinc_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *bandwidthtmp=NULL, *multmp=NULL, *addtmp=NULL;
     IRWinSinc *self;
     self = (IRWinSinc *)type->tp_alloc(type, 0);
-    
+
     self->last_freq = -1.0;
     self->last_bandwidth = -1.0;
     self->freq = PyFloat_FromDouble(1000.0);
@@ -646,16 +640,16 @@ IRWinSinc_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, IRWinSinc_compute_next_data_frame);
     self->mode_func_ptr = IRWinSinc_setProcMode;
 
     static char *kwlist[] = {"input", "freq", "bw", "type", "order", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOiiOO", kwlist, &inputtmp, &freqtmp, &bandwidthtmp, &self->filtertype, &self->order, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
 
     if (freqtmp) {
@@ -665,19 +659,19 @@ IRWinSinc_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (bandwidthtmp) {
         PyObject_CallMethod((PyObject *)self, "setBandwidth", "O", bandwidthtmp);
     }
-    
+
     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);
-    
+
     IRWinSinc_alloc_memory(self);
-    
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
@@ -685,10 +679,10 @@ IRWinSinc_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * IRWinSinc_getServer(IRWinSinc* self) { GET_SERVER };
 static PyObject * IRWinSinc_getStream(IRWinSinc* self) { GET_STREAM };
-static PyObject * IRWinSinc_setMul(IRWinSinc *self, PyObject *arg) { SET_MUL };	
-static PyObject * IRWinSinc_setAdd(IRWinSinc *self, PyObject *arg) { SET_ADD };	
-static PyObject * IRWinSinc_setSub(IRWinSinc *self, PyObject *arg) { SET_SUB };	
-static PyObject * IRWinSinc_setDiv(IRWinSinc *self, PyObject *arg) { SET_DIV };	
+static PyObject * IRWinSinc_setMul(IRWinSinc *self, PyObject *arg) { SET_MUL };
+static PyObject * IRWinSinc_setAdd(IRWinSinc *self, PyObject *arg) { SET_ADD };
+static PyObject * IRWinSinc_setSub(IRWinSinc *self, PyObject *arg) { SET_SUB };
+static PyObject * IRWinSinc_setDiv(IRWinSinc *self, PyObject *arg) { SET_DIV };
 
 static PyObject * IRWinSinc_play(IRWinSinc *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * IRWinSinc_out(IRWinSinc *self, PyObject *args, PyObject *kwds) { OUT };
@@ -707,14 +701,11 @@ static PyObject *
 IRWinSinc_setFreq(IRWinSinc *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -733,20 +724,17 @@ IRWinSinc_setFreq(IRWinSinc *self, PyObject *arg)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 IRWinSinc_setBandwidth(IRWinSinc *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->bandwidth);
@@ -765,19 +753,15 @@ IRWinSinc_setBandwidth(IRWinSinc *self, PyObject *arg)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 IRWinSinc_setType(IRWinSinc *self, PyObject *arg)
 {
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	
+    ASSERT_ARG_NOT_NULL
+
 	int isInt = PyInt_Check(arg);
-    
+
 	if (isInt == 1) {
 		self->filtertype = PyInt_AsLong(arg);
         self->changed = 1;
@@ -785,7 +769,7 @@ IRWinSinc_setType(IRWinSinc *self, PyObject *arg)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef IRWinSinc_members[] = {
     {"server", T_OBJECT_EX, offsetof(IRWinSinc, server), 0, "Pyo server."},
@@ -818,7 +802,7 @@ static PyNumberMethods IRWinSinc_as_number = {
     (binaryfunc)IRWinSinc_add,                         /*nb_add*/
     (binaryfunc)IRWinSinc_sub,                         /*nb_subtract*/
     (binaryfunc)IRWinSinc_multiply,                    /*nb_multiply*/
-    (binaryfunc)IRWinSinc_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -832,16 +816,16 @@ static PyNumberMethods IRWinSinc_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)IRWinSinc_inplace_add,                 /*inplace_add*/
     (binaryfunc)IRWinSinc_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)IRWinSinc_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)IRWinSinc_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -850,15 +834,14 @@ static PyNumberMethods IRWinSinc_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)IRWinSinc_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)IRWinSinc_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject IRWinSincType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.IRWinSinc_base",                                   /*tp_name*/
     sizeof(IRWinSinc),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -866,7 +849,7 @@ PyTypeObject IRWinSincType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &IRWinSinc_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -905,7 +888,7 @@ typedef struct {
     pyo_audio_HEAD
     PyObject *input;
     Stream *input_stream;
-    int modebuffer[2]; // need at least 2 slots for mul & add 
+    int modebuffer[2]; // need at least 2 slots for mul & add
     MYFLT *impulse;
     MYFLT *input_tmp;
     int count;
@@ -913,15 +896,15 @@ typedef struct {
     int size;
 } IRAverage;
 
-static void 
+static void
 IRAverage_alloc_memory(IRAverage *self) {
     int i;
     MYFLT val, sum;
     if ((self->order % 2) != 0)
         self->order += 1;
-    
+
     self->size = self->order + 1;
-    
+
     self->input_tmp = (MYFLT *)realloc(self->input_tmp, self->size * sizeof(MYFLT));
     self->impulse = (MYFLT *)realloc(self->impulse, self->size * sizeof(MYFLT));
 
@@ -940,9 +923,9 @@ IRAverage_alloc_memory(IRAverage *self) {
 static void
 IRAverage_filters(IRAverage *self) {
     int i,j,tmp_count;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-        
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = 0.0;
         tmp_count = self->count;
@@ -951,7 +934,7 @@ IRAverage_filters(IRAverage *self) {
                 tmp_count += self->size;
             self->data[i] += self->input_tmp[tmp_count--] * self->impulse[j];
         }
-        
+
         self->count++;
         if (self->count == self->size)
             self->count = 0;
@@ -974,44 +957,44 @@ IRAverage_setProcMode(IRAverage *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = IRAverage_filters;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = IRAverage_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = IRAverage_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = IRAverage_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = IRAverage_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = IRAverage_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = IRAverage_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = IRAverage_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = IRAverage_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = IRAverage_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 IRAverage_compute_next_data_frame(IRAverage *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1024,7 +1007,7 @@ IRAverage_traverse(IRAverage *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 IRAverage_clear(IRAverage *self)
 {
     pyo_CLEAR
@@ -1040,7 +1023,7 @@ IRAverage_dealloc(IRAverage* self)
     free(self->input_tmp);
     free(self->impulse);
     IRAverage_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1050,35 +1033,35 @@ IRAverage_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     IRAverage *self;
     self = (IRAverage *)type->tp_alloc(type, 0);
-    
+
     self->order = 32;
     self->count = 0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, IRAverage_compute_next_data_frame);
     self->mode_func_ptr = IRAverage_setProcMode;
 
     static char *kwlist[] = {"input", "order", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOO", kwlist, &inputtmp, &self->order, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
 
     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);
-    
+
     IRAverage_alloc_memory(self);
-    
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
@@ -1086,10 +1069,10 @@ IRAverage_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * IRAverage_getServer(IRAverage* self) { GET_SERVER };
 static PyObject * IRAverage_getStream(IRAverage* self) { GET_STREAM };
-static PyObject * IRAverage_setMul(IRAverage *self, PyObject *arg) { SET_MUL };	
-static PyObject * IRAverage_setAdd(IRAverage *self, PyObject *arg) { SET_ADD };	
-static PyObject * IRAverage_setSub(IRAverage *self, PyObject *arg) { SET_SUB };	
-static PyObject * IRAverage_setDiv(IRAverage *self, PyObject *arg) { SET_DIV };	
+static PyObject * IRAverage_setMul(IRAverage *self, PyObject *arg) { SET_MUL };
+static PyObject * IRAverage_setAdd(IRAverage *self, PyObject *arg) { SET_ADD };
+static PyObject * IRAverage_setSub(IRAverage *self, PyObject *arg) { SET_SUB };
+static PyObject * IRAverage_setDiv(IRAverage *self, PyObject *arg) { SET_DIV };
 
 static PyObject * IRAverage_play(IRAverage *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * IRAverage_out(IRAverage *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1130,7 +1113,7 @@ static PyNumberMethods IRAverage_as_number = {
     (binaryfunc)IRAverage_add,                         /*nb_add*/
     (binaryfunc)IRAverage_sub,                         /*nb_subtract*/
     (binaryfunc)IRAverage_multiply,                    /*nb_multiply*/
-    (binaryfunc)IRAverage_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -1144,16 +1127,16 @@ static PyNumberMethods IRAverage_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)IRAverage_inplace_add,                 /*inplace_add*/
     (binaryfunc)IRAverage_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)IRAverage_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)IRAverage_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -1162,15 +1145,14 @@ static PyNumberMethods IRAverage_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)IRAverage_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)IRAverage_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject IRAverageType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.IRAverage_base",                                   /*tp_name*/
     sizeof(IRAverage),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -1178,7 +1160,7 @@ PyTypeObject IRAverageType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &IRAverage_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -1221,7 +1203,7 @@ typedef struct {
     Stream *freq_stream;
     PyObject *bandwidth;
     Stream *bandwidth_stream;
-    int modebuffer[4]; // need at least 2 slots for mul & add 
+    int modebuffer[4]; // need at least 2 slots for mul & add
     MYFLT *impulse;
     MYFLT *input_tmp;
     int count;
@@ -1233,14 +1215,14 @@ typedef struct {
     MYFLT last_bandwidth;
 } IRPulse;
 
-static void 
+static void
 IRPulse_alloc_memory(IRPulse *self) {
     int i;
     if ((self->order % 2) != 0)
         self->order += 1;
-    
+
     self->size = self->order + 1;
-    
+
     self->input_tmp = (MYFLT *)realloc(self->input_tmp, self->size * sizeof(MYFLT));
     self->impulse = (MYFLT *)realloc(self->impulse, self->size * sizeof(MYFLT));
     for (i=0; i<self->size; i++) {
@@ -1252,19 +1234,19 @@ static void
 IRPulse_create_impulse(IRPulse *self, MYFLT freq, MYFLT bandwidth) {
     int i, n, w, bw, dir, gate;
     MYFLT val, sum;
-    
+
     sum = 0.0;
-    
+
     if (freq < 1)
         freq = 1.0;
     else if (freq > (self->sr*0.5))
         freq = self->sr*0.5;
-    
+
     if (bandwidth < 1)
         bandwidth = 1.0;
     else if (bandwidth > (self->sr*0.5))
         bandwidth = self->sr*0.5;
-    
+
     switch (self->filtertype) {
         case 0:
             /* PULSE */
@@ -1299,11 +1281,11 @@ IRPulse_create_impulse(IRPulse *self, MYFLT freq, MYFLT bandwidth) {
                 else {
                     self->impulse[i] = 0.0;
                 }
-                
+
             }
             for (i=0; i<self->size; i++) {
                 self->impulse[i] /= sum;
-            }            
+            }
             break;
         case 2:
             /* PULSEODD */
@@ -1368,9 +1350,9 @@ static void
 IRPulse_filters(IRPulse *self) {
     int i,j,tmp_count;
     MYFLT freq, bw;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->modebuffer[2] == 0)
         freq = PyFloat_AS_DOUBLE(self->freq);
     else {
@@ -1383,14 +1365,14 @@ IRPulse_filters(IRPulse *self) {
         MYFLT *band = Stream_getData((Stream *)self->bandwidth_stream);
         bw = band[0];
     }
-    
+
     if (freq != self->last_freq || bw != self->last_bandwidth || self->changed == 1) {
         IRPulse_create_impulse(self, freq, bw);
         self->last_freq = freq;
         self->last_bandwidth = bw;
         self->changed = 0;
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = 0.0;
         tmp_count = self->count;
@@ -1399,7 +1381,7 @@ IRPulse_filters(IRPulse *self) {
                 tmp_count += self->size;
             self->data[i] += self->input_tmp[tmp_count--] * self->impulse[j];
         }
-        
+
         self->count++;
         if (self->count == self->size)
             self->count = 0;
@@ -1422,44 +1404,44 @@ IRPulse_setProcMode(IRPulse *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = IRPulse_filters;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = IRPulse_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = IRPulse_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = IRPulse_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = IRPulse_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = IRPulse_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = IRPulse_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = IRPulse_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = IRPulse_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = IRPulse_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 IRPulse_compute_next_data_frame(IRPulse *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1469,23 +1451,23 @@ IRPulse_traverse(IRPulse *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
-    Py_VISIT(self->bandwidth);    
-    Py_VISIT(self->bandwidth_stream);    
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->bandwidth);
+    Py_VISIT(self->bandwidth_stream);
     return 0;
 }
 
-static int 
+static int
 IRPulse_clear(IRPulse *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
-    Py_CLEAR(self->bandwidth);    
-    Py_CLEAR(self->bandwidth_stream);    
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->bandwidth);
+    Py_CLEAR(self->bandwidth_stream);
     return 0;
 }
 
@@ -1496,7 +1478,7 @@ IRPulse_dealloc(IRPulse* self)
     free(self->input_tmp);
     free(self->impulse);
     IRPulse_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1506,7 +1488,7 @@ IRPulse_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *bandwidthtmp=NULL, *multmp=NULL, *addtmp=NULL;
     IRPulse *self;
     self = (IRPulse *)type->tp_alloc(type, 0);
-    
+
     self->last_freq = -1.0;
     self->last_bandwidth = -1.0;
     self->freq = PyFloat_FromDouble(500.0);
@@ -1519,38 +1501,38 @@ IRPulse_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, IRPulse_compute_next_data_frame);
     self->mode_func_ptr = IRPulse_setProcMode;
 
     static char *kwlist[] = {"input", "freq", "bw", "type", "order", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOiiOO", kwlist, &inputtmp, &freqtmp, &bandwidthtmp, &self->filtertype, &self->order, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    
+
     if (bandwidthtmp) {
         PyObject_CallMethod((PyObject *)self, "setBandwidth", "O", bandwidthtmp);
     }
-    
+
     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);
-    
+
     IRPulse_alloc_memory(self);
-    
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
@@ -1558,10 +1540,10 @@ IRPulse_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * IRPulse_getServer(IRPulse* self) { GET_SERVER };
 static PyObject * IRPulse_getStream(IRPulse* self) { GET_STREAM };
-static PyObject * IRPulse_setMul(IRPulse *self, PyObject *arg) { SET_MUL };	
-static PyObject * IRPulse_setAdd(IRPulse *self, PyObject *arg) { SET_ADD };	
-static PyObject * IRPulse_setSub(IRPulse *self, PyObject *arg) { SET_SUB };	
-static PyObject * IRPulse_setDiv(IRPulse *self, PyObject *arg) { SET_DIV };	
+static PyObject * IRPulse_setMul(IRPulse *self, PyObject *arg) { SET_MUL };
+static PyObject * IRPulse_setAdd(IRPulse *self, PyObject *arg) { SET_ADD };
+static PyObject * IRPulse_setSub(IRPulse *self, PyObject *arg) { SET_SUB };
+static PyObject * IRPulse_setDiv(IRPulse *self, PyObject *arg) { SET_DIV };
 
 static PyObject * IRPulse_play(IRPulse *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * IRPulse_out(IRPulse *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1580,14 +1562,11 @@ static PyObject *
 IRPulse_setFreq(IRPulse *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -1603,23 +1582,20 @@ IRPulse_setFreq(IRPulse *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 IRPulse_setBandwidth(IRPulse *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->bandwidth);
@@ -1635,30 +1611,27 @@ IRPulse_setBandwidth(IRPulse *self, PyObject *arg)
         self->bandwidth_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 IRPulse_setType(IRPulse *self, PyObject *arg)
 {
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	
+
+    ASSERT_ARG_NOT_NULL
+
 	int isInt = PyInt_Check(arg);
-    
+
 	if (isInt == 1) {
 		self->filtertype = PyInt_AsLong(arg);
         self->changed = 1;
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef IRPulse_members[] = {
     {"server", T_OBJECT_EX, offsetof(IRPulse, server), 0, "Pyo server."},
@@ -1691,7 +1664,7 @@ static PyNumberMethods IRPulse_as_number = {
     (binaryfunc)IRPulse_add,                         /*nb_add*/
     (binaryfunc)IRPulse_sub,                         /*nb_subtract*/
     (binaryfunc)IRPulse_multiply,                    /*nb_multiply*/
-    (binaryfunc)IRPulse_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -1705,16 +1678,16 @@ static PyNumberMethods IRPulse_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)IRPulse_inplace_add,                 /*inplace_add*/
     (binaryfunc)IRPulse_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)IRPulse_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)IRPulse_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -1723,15 +1696,14 @@ static PyNumberMethods IRPulse_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)IRPulse_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)IRPulse_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject IRPulseType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.IRPulse_base",                                   /*tp_name*/
     sizeof(IRPulse),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -1739,7 +1711,7 @@ PyTypeObject IRPulseType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &IRPulse_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -1784,7 +1756,7 @@ typedef struct {
     Stream *ratio_stream;
     PyObject *index;
     Stream *index_stream;
-    int modebuffer[5]; // need at least 2 slots for mul & add 
+    int modebuffer[5]; // need at least 2 slots for mul & add
     MYFLT *impulse;
     MYFLT *input_tmp;
     int count;
@@ -1795,14 +1767,14 @@ typedef struct {
     MYFLT last_index;
 } IRFM;
 
-static void 
+static void
 IRFM_alloc_memory(IRFM *self) {
     int i;
     if ((self->order % 2) != 0)
         self->order += 1;
-    
+
     self->size = self->order + 1;
-    
+
     self->input_tmp = (MYFLT *)realloc(self->input_tmp, self->size * sizeof(MYFLT));
     self->impulse = (MYFLT *)realloc(self->impulse, self->size * sizeof(MYFLT));
     for (i=0; i<self->size; i++) {
@@ -1819,12 +1791,12 @@ IRFM_create_impulse(IRFM *self, MYFLT carrier, MYFLT ratio, MYFLT index) {
         carrier = 1.0;
     else if (carrier > (self->sr*0.5))
         carrier = self->sr*0.5;
-    
+
     if (ratio < 0.0001)
         ratio = 0.0001;
     else if (ratio > (self->sr*0.5))
         ratio = self->sr*0.5;
-    
+
     if (index < 0)
         index = 0.0;
 
@@ -1850,9 +1822,9 @@ static void
 IRFM_filters(IRFM *self) {
     int i,j,tmp_count;
     MYFLT carrier, ratio, index;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->modebuffer[2] == 0)
         carrier = PyFloat_AS_DOUBLE(self->carrier);
     else {
@@ -1871,14 +1843,14 @@ IRFM_filters(IRFM *self) {
         MYFLT *ind = Stream_getData((Stream *)self->index_stream);
         index = ind[0];
     }
-    
+
     if (carrier != self->last_carrier || ratio != self->last_ratio || index != self->last_index) {
         IRFM_create_impulse(self, carrier, ratio, index);
         self->last_carrier = carrier;
         self->last_ratio = ratio;
         self->last_index = index;
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = 0.0;
         tmp_count = self->count;
@@ -1887,7 +1859,7 @@ IRFM_filters(IRFM *self) {
                 tmp_count += self->size;
             self->data[i] += self->input_tmp[tmp_count--] * self->impulse[j];
         }
-        
+
         self->count++;
         if (self->count == self->size)
             self->count = 0;
@@ -1910,44 +1882,44 @@ IRFM_setProcMode(IRFM *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = IRFM_filters;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = IRFM_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = IRFM_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = IRFM_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = IRFM_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = IRFM_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = IRFM_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = IRFM_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = IRFM_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = IRFM_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 IRFM_compute_next_data_frame(IRFM *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1957,27 +1929,27 @@ IRFM_traverse(IRFM *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->carrier);    
-    Py_VISIT(self->carrier_stream);    
-    Py_VISIT(self->ratio);    
-    Py_VISIT(self->ratio_stream);    
-    Py_VISIT(self->index);    
-    Py_VISIT(self->index_stream);    
+    Py_VISIT(self->carrier);
+    Py_VISIT(self->carrier_stream);
+    Py_VISIT(self->ratio);
+    Py_VISIT(self->ratio_stream);
+    Py_VISIT(self->index);
+    Py_VISIT(self->index_stream);
     return 0;
 }
 
-static int 
+static int
 IRFM_clear(IRFM *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->carrier);    
-    Py_CLEAR(self->carrier_stream);    
-    Py_CLEAR(self->ratio);    
-    Py_CLEAR(self->ratio_stream);    
-    Py_CLEAR(self->index);    
-    Py_CLEAR(self->index_stream);    
+    Py_CLEAR(self->carrier);
+    Py_CLEAR(self->carrier_stream);
+    Py_CLEAR(self->ratio);
+    Py_CLEAR(self->ratio_stream);
+    Py_CLEAR(self->index);
+    Py_CLEAR(self->index_stream);
     return 0;
 }
 
@@ -1988,7 +1960,7 @@ IRFM_dealloc(IRFM* self)
     free(self->input_tmp);
     free(self->impulse);
     IRFM_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1998,7 +1970,7 @@ IRFM_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *carriertmp=NULL, *ratiotmp=NULL, *indextmp=NULL, *multmp=NULL, *addtmp=NULL;
     IRFM *self;
     self = (IRFM *)type->tp_alloc(type, 0);
-    
+
     self->last_carrier = -1.0;
     self->last_ratio = -1.0;
     self->last_index = -1.0;
@@ -2012,22 +1984,22 @@ IRFM_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
 	self->modebuffer[4] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, IRFM_compute_next_data_frame);
     self->mode_func_ptr = IRFM_setProcMode;
 
     static char *kwlist[] = {"input", "carrier", "ratio", "index", "order", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOiOO", kwlist, &inputtmp, &carriertmp, &ratiotmp, &indextmp, &self->order, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (carriertmp) {
         PyObject_CallMethod((PyObject *)self, "setCarrier", "O", carriertmp);
     }
-    
+
     if (ratiotmp) {
         PyObject_CallMethod((PyObject *)self, "setRatio", "O", ratiotmp);
     }
@@ -2035,19 +2007,19 @@ IRFM_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (indextmp) {
         PyObject_CallMethod((PyObject *)self, "setIndex", "O", indextmp);
     }
-    
+
     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);
-    
+
     IRFM_alloc_memory(self);
-    
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
@@ -2055,10 +2027,10 @@ IRFM_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * IRFM_getServer(IRFM* self) { GET_SERVER };
 static PyObject * IRFM_getStream(IRFM* self) { GET_STREAM };
-static PyObject * IRFM_setMul(IRFM *self, PyObject *arg) { SET_MUL };	
-static PyObject * IRFM_setAdd(IRFM *self, PyObject *arg) { SET_ADD };	
-static PyObject * IRFM_setSub(IRFM *self, PyObject *arg) { SET_SUB };	
-static PyObject * IRFM_setDiv(IRFM *self, PyObject *arg) { SET_DIV };	
+static PyObject * IRFM_setMul(IRFM *self, PyObject *arg) { SET_MUL };
+static PyObject * IRFM_setAdd(IRFM *self, PyObject *arg) { SET_ADD };
+static PyObject * IRFM_setSub(IRFM *self, PyObject *arg) { SET_SUB };
+static PyObject * IRFM_setDiv(IRFM *self, PyObject *arg) { SET_DIV };
 
 static PyObject * IRFM_play(IRFM *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * IRFM_out(IRFM *self, PyObject *args, PyObject *kwds) { OUT };
@@ -2077,14 +2049,11 @@ static PyObject *
 IRFM_setCarrier(IRFM *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->carrier);
@@ -2100,23 +2069,20 @@ IRFM_setCarrier(IRFM *self, PyObject *arg)
         self->carrier_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 IRFM_setRatio(IRFM *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->ratio);
@@ -2132,23 +2098,20 @@ IRFM_setRatio(IRFM *self, PyObject *arg)
         self->ratio_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 IRFM_setIndex(IRFM *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->index);
@@ -2164,10 +2127,10 @@ IRFM_setIndex(IRFM *self, PyObject *arg)
         self->index_stream = (Stream *)streamtmp;
 		self->modebuffer[4] = 1;
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef IRFM_members[] = {
     {"server", T_OBJECT_EX, offsetof(IRFM, server), 0, "Pyo server."},
@@ -2201,7 +2164,7 @@ static PyNumberMethods IRFM_as_number = {
     (binaryfunc)IRFM_add,                         /*nb_add*/
     (binaryfunc)IRFM_sub,                         /*nb_subtract*/
     (binaryfunc)IRFM_multiply,                    /*nb_multiply*/
-    (binaryfunc)IRFM_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -2215,16 +2178,16 @@ static PyNumberMethods IRFM_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)IRFM_inplace_add,                 /*inplace_add*/
     (binaryfunc)IRFM_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)IRFM_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)IRFM_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -2233,15 +2196,14 @@ static PyNumberMethods IRFM_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)IRFM_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)IRFM_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject IRFMType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.IRFM_base",                                   /*tp_name*/
     sizeof(IRFM),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -2249,7 +2211,7 @@ PyTypeObject IRFMType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &IRFM_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -2279,4 +2241,4 @@ PyTypeObject IRFMType = {
     0,                          /* tp_init */
     0,                                              /* tp_alloc */
     IRFM_new,                                     /* tp_new */
-};
+};
\ No newline at end of file
diff --git a/src/objects/delaymodule.c b/src/objects/delaymodule.c
index f4a0302..528d048 100644
--- a/src/objects/delaymodule.c
+++ b/src/objects/delaymodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
@@ -35,6 +36,7 @@ typedef struct {
     PyObject *feedback;
     Stream *feedback_stream;
     MYFLT maxdelay;
+    MYFLT oneOverSr;
     long size;
     long in_count;
     int modebuffer[4];
@@ -49,9 +51,9 @@ Delay_process_ii(Delay *self) {
 
     MYFLT del = PyFloat_AS_DOUBLE(self->delay);
     MYFLT feed = PyFloat_AS_DOUBLE(self->feedback);
-    
-    if (del < 0.)
-        del = 0.;
+
+    if (del < self->oneOverSr)
+        del = self->oneOverSr;
     else if (del > self->maxdelay)
         del = self->maxdelay;
     MYFLT sampdel = del * self->sr;
@@ -60,9 +62,9 @@ Delay_process_ii(Delay *self) {
         feed = 0;
     else if (feed > 1)
         feed = 1;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         xind = self->in_count - sampdel;
         if (xind < 0)
@@ -71,7 +73,7 @@ Delay_process_ii(Delay *self) {
         frac = xind - ind;
         val = self->buffer[ind] * (1.0 - frac) + self->buffer[ind+1] * frac;
         self->data[i] = val;
-        
+
         self->buffer[self->in_count] = in[i] + (val * feed);
         if (self->in_count == 0)
             self->buffer[self->size] = self->buffer[self->in_count];
@@ -87,20 +89,20 @@ Delay_process_ai(Delay *self) {
     int i;
     long ind;
 
-    MYFLT *delobj = Stream_getData((Stream *)self->delay_stream);    
+    MYFLT *delobj = Stream_getData((Stream *)self->delay_stream);
     MYFLT feed = PyFloat_AS_DOUBLE(self->feedback);
 
     if (feed < 0)
         feed = 0;
     else if (feed > 1)
         feed = 1;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         del = delobj[i];
-        if (del < 0.)
-            del = 0.;
+        if (del < self->oneOverSr)
+            del = self->oneOverSr;
         else if (del > self->maxdelay)
             del = self->maxdelay;
         sampdel = del * self->sr;
@@ -111,7 +113,7 @@ Delay_process_ai(Delay *self) {
         frac = xind - ind;
         val = self->buffer[ind] * (1.0 - frac) + self->buffer[ind+1] * frac;
         self->data[i] = val;
-        
+
         self->buffer[self->in_count] = in[i]  + (val * feed);
         if (self->in_count == 0)
             self->buffer[self->size] = self->buffer[self->in_count];
@@ -126,18 +128,18 @@ Delay_process_ia(Delay *self) {
     MYFLT val, xind, frac, feed;
     int i;
     long ind;
-    
+
     MYFLT del = PyFloat_AS_DOUBLE(self->delay);
-    MYFLT *fdb = Stream_getData((Stream *)self->feedback_stream);    
-    
-    if (del < 0.)
-        del = 0.;
+    MYFLT *fdb = Stream_getData((Stream *)self->feedback_stream);
+
+    if (del < self->oneOverSr)
+        del = self->oneOverSr;
     else if (del > self->maxdelay)
         del = self->maxdelay;
     MYFLT sampdel = del * self->sr;
-       
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         xind = self->in_count - sampdel;
         if (xind < 0)
@@ -152,7 +154,7 @@ Delay_process_ia(Delay *self) {
             feed = 0;
         else if (feed > 1)
             feed = 1;
-        
+
         self->buffer[self->in_count] = in[i] + (val * feed);
         if (self->in_count == 0)
             self->buffer[self->size] = self->buffer[self->in_count];
@@ -167,16 +169,16 @@ Delay_process_aa(Delay *self) {
     MYFLT val, xind, frac, sampdel, feed, del;
     int i;
     long ind;
-    
-    MYFLT *delobj = Stream_getData((Stream *)self->delay_stream);    
-    MYFLT *fdb = Stream_getData((Stream *)self->feedback_stream);    
-  
+
+    MYFLT *delobj = Stream_getData((Stream *)self->delay_stream);
+    MYFLT *fdb = Stream_getData((Stream *)self->feedback_stream);
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         del = delobj[i];
-        if (del < 0.)
-            del = 0.;
+        if (del < self->oneOverSr)
+            del = self->oneOverSr;
         else if (del > self->maxdelay)
             del = self->maxdelay;
         sampdel = del * self->sr;
@@ -187,13 +189,13 @@ Delay_process_aa(Delay *self) {
         frac = xind - ind;
         val = self->buffer[ind] * (1.0 - frac) + self->buffer[ind+1] * frac;
         self->data[i] = val;
-        
+
         feed = fdb[i];
         if (feed < 0)
             feed = 0;
         else if (feed > 1)
             feed = 1;
-        
+
         self->buffer[self->in_count] = in[i] + (val * feed);
         if (self->in_count == 0)
             self->buffer[self->size] = self->buffer[self->in_count];
@@ -221,54 +223,54 @@ Delay_setProcMode(Delay *self)
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Delay_process_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Delay_process_ai;
             break;
-        case 10:    
+        case 10:
             self->proc_func_ptr = Delay_process_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Delay_process_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Delay_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Delay_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Delay_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Delay_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Delay_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Delay_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Delay_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Delay_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Delay_postprocessing_revareva;
             break;
-    } 
+    }
 }
 
 static void
 Delay_compute_next_data_frame(Delay *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -277,24 +279,24 @@ Delay_traverse(Delay *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->input);
-    Py_VISIT(self->input_stream);    
-    Py_VISIT(self->delay);    
-    Py_VISIT(self->delay_stream);    
-    Py_VISIT(self->feedback);    
-    Py_VISIT(self->feedback_stream);    
+    Py_VISIT(self->input_stream);
+    Py_VISIT(self->delay);
+    Py_VISIT(self->delay_stream);
+    Py_VISIT(self->feedback);
+    Py_VISIT(self->feedback_stream);
     return 0;
 }
 
-static int 
+static int
 Delay_clear(Delay *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
-    Py_CLEAR(self->input_stream);    
-    Py_CLEAR(self->delay);    
-    Py_CLEAR(self->delay_stream);    
-    Py_CLEAR(self->feedback);    
-    Py_CLEAR(self->feedback_stream);    
+    Py_CLEAR(self->input_stream);
+    Py_CLEAR(self->delay);
+    Py_CLEAR(self->delay_stream);
+    Py_CLEAR(self->feedback);
+    Py_CLEAR(self->feedback_stream);
     return 0;
 }
 
@@ -304,7 +306,7 @@ Delay_dealloc(Delay* self)
     pyo_DEALLOC
     free(self->buffer);
     Delay_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -325,6 +327,9 @@ Delay_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[3] = 0;
 
     INIT_OBJECT_COMMON
+
+    self->oneOverSr = 1.0 / self->sr;
+
     Stream_setFunctionPtr(self->stream, Delay_compute_next_data_frame);
     self->mode_func_ptr = Delay_setProcMode;
 
@@ -342,7 +347,7 @@ Delay_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (feedbacktmp) {
         PyObject_CallMethod((PyObject *)self, "setFeedback", "O", feedbacktmp);
     }
-    
+
     if (multmp) {
         PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
     }
@@ -350,7 +355,7 @@ Delay_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (addtmp) {
         PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
     }
-            
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     self->size = (long)(self->maxdelay * self->sr + 0.5);
@@ -358,19 +363,19 @@ Delay_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->buffer = (MYFLT *)realloc(self->buffer, (self->size+1) * sizeof(MYFLT));
     for (i=0; i<(self->size+1); i++) {
         self->buffer[i] = 0.;
-    }    
+    }
 
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * Delay_getServer(Delay* self) { GET_SERVER };
 static PyObject * Delay_getStream(Delay* self) { GET_STREAM };
-static PyObject * Delay_setMul(Delay *self, PyObject *arg) { SET_MUL };	
-static PyObject * Delay_setAdd(Delay *self, PyObject *arg) { SET_ADD };	
-static PyObject * Delay_setSub(Delay *self, PyObject *arg) { SET_SUB };	
-static PyObject * Delay_setDiv(Delay *self, PyObject *arg) { SET_DIV };	
+static PyObject * Delay_setMul(Delay *self, PyObject *arg) { SET_MUL };
+static PyObject * Delay_setAdd(Delay *self, PyObject *arg) { SET_ADD };
+static PyObject * Delay_setSub(Delay *self, PyObject *arg) { SET_SUB };
+static PyObject * Delay_setDiv(Delay *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Delay_play(Delay *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Delay_out(Delay *self, PyObject *args, PyObject *kwds) { OUT };
@@ -389,12 +394,9 @@ static PyObject *
 Delay_setDelay(Delay *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
 
 	tmp = arg;
@@ -412,25 +414,22 @@ Delay_setDelay(Delay *self, PyObject *arg)
         self->delay_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Delay_setFeedback(Delay *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-    
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->feedback);
@@ -446,12 +445,12 @@ Delay_setFeedback(Delay *self, PyObject *arg)
         self->feedback_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Delay_reset(Delay *self)
@@ -459,7 +458,7 @@ Delay_reset(Delay *self)
     int i;
     for (i=0; i<(self->size+1); i++) {
         self->buffer[i] = 0.;
-    }    
+    }
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -495,7 +494,7 @@ static PyNumberMethods Delay_as_number = {
     (binaryfunc)Delay_add,                      /*nb_add*/
     (binaryfunc)Delay_sub,                 /*nb_subtract*/
     (binaryfunc)Delay_multiply,                 /*nb_multiply*/
-    (binaryfunc)Delay_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -509,16 +508,16 @@ static PyNumberMethods Delay_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)Delay_inplace_add,              /*inplace_add*/
     (binaryfunc)Delay_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)Delay_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)Delay_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -527,15 +526,14 @@ static PyNumberMethods Delay_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)Delay_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)Delay_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject DelayType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Delay_base",         /*tp_name*/
     sizeof(Delay),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -543,7 +541,7 @@ PyTypeObject DelayType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &Delay_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -590,11 +588,11 @@ typedef struct {
 
 static void
 SDelay_process_i(SDelay *self) {
-    int i; 
+    int i;
     long ind;
-    
+
     MYFLT del = PyFloat_AS_DOUBLE(self->delay);
-    
+
     if (del < 0.)
         del = 0.;
     else if (del > self->maxdelay)
@@ -611,13 +609,13 @@ SDelay_process_i(SDelay *self) {
                 self->in_count = 0;
         }
     }
-    else {    
+    else {
         for (i=0; i<self->bufsize; i++) {
             ind = self->in_count - sampdel;
             if (ind < 0)
-                ind += (self->size-1);
+                ind += self->size;
             self->data[i] = self->buffer[ind];
-        
+
             self->buffer[self->in_count] = in[i];
             self->in_count++;
             if (self->in_count >= self->size)
@@ -629,12 +627,12 @@ SDelay_process_i(SDelay *self) {
 static void
 SDelay_process_a(SDelay *self) {
     MYFLT del;
-    int i; 
+    int i;
     long ind, sampdel;
-    
+
     MYFLT *delobj = Stream_getData((Stream *)self->delay_stream);
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         del = delobj[i];
         if (del < 0.)
@@ -648,7 +646,7 @@ SDelay_process_a(SDelay *self) {
         else {
             ind = self->in_count - sampdel;
             if (ind < 0)
-                ind += (self->size-1);
+                ind += self->size;
             self->data[i] = self->buffer[ind];
         }
         self->buffer[self->in_count++] = in[i];
@@ -673,50 +671,50 @@ SDelay_setProcMode(SDelay *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2];
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = SDelay_process_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = SDelay_process_a;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = SDelay_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = SDelay_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = SDelay_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = SDelay_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = SDelay_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = SDelay_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = SDelay_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = SDelay_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = SDelay_postprocessing_revareva;
             break;
-    } 
+    }
 }
 
 static void
 SDelay_compute_next_data_frame(SDelay *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -725,20 +723,20 @@ SDelay_traverse(SDelay *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->input);
-    Py_VISIT(self->input_stream);    
-    Py_VISIT(self->delay);    
-    Py_VISIT(self->delay_stream);    
+    Py_VISIT(self->input_stream);
+    Py_VISIT(self->delay);
+    Py_VISIT(self->delay_stream);
     return 0;
 }
 
-static int 
+static int
 SDelay_clear(SDelay *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
-    Py_CLEAR(self->input_stream);    
-    Py_CLEAR(self->delay);    
-    Py_CLEAR(self->delay_stream);    
+    Py_CLEAR(self->input_stream);
+    Py_CLEAR(self->delay);
+    Py_CLEAR(self->delay_stream);
     return 0;
 }
 
@@ -748,7 +746,7 @@ SDelay_dealloc(SDelay* self)
     pyo_DEALLOC
     free(self->buffer);
     SDelay_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -758,46 +756,46 @@ SDelay_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *delaytmp=NULL, *multmp=NULL, *addtmp=NULL;
     SDelay *self;
     self = (SDelay *)type->tp_alloc(type, 0);
-    
+
     self->delay = PyFloat_FromDouble(0.25);
     self->maxdelay = 1;
     self->in_count = 0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, SDelay_compute_next_data_frame);
     self->mode_func_ptr = SDelay_setProcMode;
 
     static char *kwlist[] = {"input", "delay", "maxdelay", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_OFOO, kwlist, &inputtmp, &delaytmp, &self->maxdelay, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (delaytmp) {
         PyObject_CallMethod((PyObject *)self, "setDelay", "O", delaytmp);
     }
-    
+
     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->size = (long)(self->maxdelay * self->sr + 0.5);
-    
+
     self->buffer = (MYFLT *)realloc(self->buffer, (self->size+1) * sizeof(MYFLT));
     for (i=0; i<(self->size+1); i++) {
         self->buffer[i] = 0.;
-    }    
-    
+    }
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
@@ -805,10 +803,10 @@ SDelay_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * SDelay_getServer(SDelay* self) { GET_SERVER };
 static PyObject * SDelay_getStream(SDelay* self) { GET_STREAM };
-static PyObject * SDelay_setMul(SDelay *self, PyObject *arg) { SET_MUL };	
-static PyObject * SDelay_setAdd(SDelay *self, PyObject *arg) { SET_ADD };	
-static PyObject * SDelay_setSub(SDelay *self, PyObject *arg) { SET_SUB };	
-static PyObject * SDelay_setDiv(SDelay *self, PyObject *arg) { SET_DIV };	
+static PyObject * SDelay_setMul(SDelay *self, PyObject *arg) { SET_MUL };
+static PyObject * SDelay_setAdd(SDelay *self, PyObject *arg) { SET_ADD };
+static PyObject * SDelay_setSub(SDelay *self, PyObject *arg) { SET_SUB };
+static PyObject * SDelay_setDiv(SDelay *self, PyObject *arg) { SET_DIV };
 
 static PyObject * SDelay_play(SDelay *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * SDelay_out(SDelay *self, PyObject *args, PyObject *kwds) { OUT };
@@ -827,14 +825,11 @@ static PyObject *
 SDelay_setDelay(SDelay *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-    
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->delay);
@@ -850,12 +845,12 @@ SDelay_setDelay(SDelay *self, PyObject *arg)
         self->delay_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 SDelay_reset(SDelay *self)
@@ -863,7 +858,7 @@ SDelay_reset(SDelay *self)
     int i;
     for (i=0; i<(self->size+1); i++) {
         self->buffer[i] = 0.;
-    }    
+    }
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -897,7 +892,7 @@ static PyNumberMethods SDelay_as_number = {
     (binaryfunc)SDelay_add,                      /*nb_add*/
     (binaryfunc)SDelay_sub,                 /*nb_subtract*/
     (binaryfunc)SDelay_multiply,                 /*nb_multiply*/
-    (binaryfunc)SDelay_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -911,16 +906,16 @@ static PyNumberMethods SDelay_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)SDelay_inplace_add,              /*inplace_add*/
     (binaryfunc)SDelay_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)SDelay_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)SDelay_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -929,15 +924,14 @@ static PyNumberMethods SDelay_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)SDelay_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)SDelay_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject SDelayType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.SDelay_base",         /*tp_name*/
     sizeof(SDelay),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -945,7 +939,7 @@ PyTypeObject SDelayType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &SDelay_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -1009,9 +1003,9 @@ static void
 Waveguide_process_ii(Waveguide *self) {
     MYFLT val, x, y, sampdel, frac, feed, tmp;
     int i, ind, isamp;
-    
+
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
-    MYFLT dur = PyFloat_AS_DOUBLE(self->dur); 
+    MYFLT dur = PyFloat_AS_DOUBLE(self->dur);
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
     /* Check boundaries */
@@ -1019,11 +1013,11 @@ Waveguide_process_ii(Waveguide *self) {
         fr = self->minfreq;
     else if (fr >= self->nyquist)
         fr = self->nyquist;
-    
+
     if (dur <= 0)
         dur = 0.1;
-    
-    
+
+
     sampdel = self->lastSampDel;
     feed = self->lastFeed;
     /* lagrange coeffs and feedback coeff */
@@ -1038,25 +1032,25 @@ Waveguide_process_ii(Waveguide *self) {
         self->coeffs[2] = frac*(frac-1)*(frac-3)*(frac-4)/4.0;
         self->coeffs[3] = -frac*(frac-1)*(frac-2)*(frac-4)/6.0;
         self->coeffs[4] = frac*(frac-1)*(frac-2)*(frac-3)/24.0;
-        
+
         self->lastDur = dur;
         feed = MYPOW(100, -1.0/(fr*dur));
         self->lastFeed = feed;
-    } 
+    }
     else if (dur != self->lastDur) {
         self->lastDur = dur;
         feed = MYPOW(100, -1.0/(fr*dur));
         self->lastFeed = feed;
     }
-    
+
     /* pick a new value in th delay line */
-    isamp = (int)sampdel;  
+    isamp = (int)sampdel;
     for (i=0; i<self->bufsize; i++) {
         ind = self->in_count - isamp;
         if (ind < 0)
             ind += self->size;
         val = self->buffer[ind];
-        
+
         /* simple lowpass filtering */
         tmp = val;
         val = (val + self->lpsamp) * 0.5;
@@ -1076,7 +1070,7 @@ Waveguide_process_ii(Waveguide *self) {
         self->yn1 = y;
 
         self->data[i] = y;
-        
+
         /* write current value in the delay line */
         self->buffer[self->in_count] = in[i] + (x * feed);
         if (self->in_count == 0)
@@ -1091,11 +1085,11 @@ static void
 Waveguide_process_ai(Waveguide *self) {
     MYFLT val, x, y, sampdel, frac, feed, freq, tmp;
     int i, ind, isamp;
-    
+
     MYFLT *fr =Stream_getData((Stream *)self->freq_stream);
-    MYFLT dur = PyFloat_AS_DOUBLE(self->dur); 
+    MYFLT dur = PyFloat_AS_DOUBLE(self->dur);
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     /* Check dur boundary */
     if (dur <= 0)
         dur = 0.1;
@@ -1122,7 +1116,7 @@ Waveguide_process_ai(Waveguide *self) {
             self->coeffs[2] = frac*(frac-1)*(frac-3)*(frac-4)/4.0;
             self->coeffs[3] = -frac*(frac-1)*(frac-2)*(frac-4)/6.0;
             self->coeffs[4] = frac*(frac-1)*(frac-2)*(frac-3)/24.0;
-            
+
             self->lastDur = dur;
             feed = MYPOW(100, -1.0/(freq*dur));
             self->lastFeed = feed;
@@ -1134,18 +1128,18 @@ Waveguide_process_ai(Waveguide *self) {
         }
 
         /* pick a new value in th delay line */
-        isamp = (int)sampdel;        
-        
+        isamp = (int)sampdel;
+
         ind = self->in_count - isamp;
         if (ind < 0)
             ind += self->size;
         val = self->buffer[ind];
-        
+
         /* simple lowpass filtering */
         tmp = val;
         val = (val + self->lpsamp) * 0.5;
         self->lpsamp = tmp;
-        
+
         /* lagrange filtering */
         x = (val*self->coeffs[0])+(self->lagrange[0]*self->coeffs[1])+(self->lagrange[1]*self->coeffs[2])+
             (self->lagrange[2]*self->coeffs[3])+(self->lagrange[3]*self->coeffs[4]);
@@ -1158,9 +1152,9 @@ Waveguide_process_ai(Waveguide *self) {
         y = x - self->xn1 + 0.995 * self->yn1;
         self->xn1 = x;
         self->yn1 = y;
-        
+
         self->data[i] = y;
-        
+
         /* write current value in the delay line */
         self->buffer[self->in_count] = in[i] + (x * feed);
         if (self->in_count == 0)
@@ -1176,11 +1170,11 @@ static void
 Waveguide_process_ia(Waveguide *self) {
     MYFLT val, x, y, sampdel, frac, feed, dur, tmp;
     int i, ind, isamp;
-    
+
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
     MYFLT *du = Stream_getData((Stream *)self->dur_stream);
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     /* Check boundaries */
     if (fr < self->minfreq)
         fr = self->minfreq;
@@ -1201,9 +1195,9 @@ Waveguide_process_ia(Waveguide *self) {
         self->coeffs[3] = -frac*(frac-1)*(frac-2)*(frac-4)/6.0;
         self->coeffs[4] = frac*(frac-1)*(frac-2)*(frac-3)/24.0;
     }
-    
+
     /* pick a new value in th delay line */
-    isamp = (int)sampdel;  
+    isamp = (int)sampdel;
     for (i=0; i<self->bufsize; i++) {
         feed = self->lastFeed;
         dur = du[i];
@@ -1218,12 +1212,12 @@ Waveguide_process_ia(Waveguide *self) {
         if (ind < 0)
             ind += self->size;
         val = self->buffer[ind];
-        
+
         /* simple lowpass filtering */
         tmp = val;
         val = (val + self->lpsamp) * 0.5;
         self->lpsamp = tmp;
-        
+
         /* lagrange filtering */
         x = (val*self->coeffs[0])+(self->lagrange[0]*self->coeffs[1])+(self->lagrange[1]*self->coeffs[2])+
             (self->lagrange[2]*self->coeffs[3])+(self->lagrange[3]*self->coeffs[4]);
@@ -1236,9 +1230,9 @@ Waveguide_process_ia(Waveguide *self) {
         y = x - self->xn1 + 0.995 * self->yn1;
         self->xn1 = x;
         self->yn1 = y;
-        
+
         self->data[i] = y;
-        
+
         /* write current value in the delay line */
         self->buffer[self->in_count] = in[i] + (x * feed);
         if (self->in_count == 0)
@@ -1254,11 +1248,11 @@ static void
 Waveguide_process_aa(Waveguide *self) {
     MYFLT val, x, y, sampdel, frac, feed, freq, dur, tmp;
     int i, ind, isamp;
-    
+
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    MYFLT *du = Stream_getData((Stream *)self->dur_stream); 
+    MYFLT *du = Stream_getData((Stream *)self->dur_stream);
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         freq = fr[i];
         dur = du[i];
@@ -1270,7 +1264,7 @@ Waveguide_process_aa(Waveguide *self) {
 
         if (dur <= 0)
             dur = 0.1;
-        
+
         sampdel = self->lastSampDel;
         feed = self->lastFeed;
         /* lagrange coeffs and feedback coeff */
@@ -1285,7 +1279,7 @@ Waveguide_process_aa(Waveguide *self) {
             self->coeffs[2] = frac*(frac-1)*(frac-3)*(frac-4)/4.0;
             self->coeffs[3] = -frac*(frac-1)*(frac-2)*(frac-4)/6.0;
             self->coeffs[4] = frac*(frac-1)*(frac-2)*(frac-3)/24.0;
-            
+
             self->lastDur = dur;
             feed = MYPOW(100, -1.0/(freq*dur));
             self->lastFeed = feed;
@@ -1295,20 +1289,20 @@ Waveguide_process_aa(Waveguide *self) {
             feed = MYPOW(100, -1.0/(freq*dur));
             self->lastFeed = feed;
         }
-        
+
         /* pick a new value in th delay line */
-        isamp = (int)sampdel;        
-        
+        isamp = (int)sampdel;
+
         ind = self->in_count - isamp;
         if (ind < 0)
             ind += self->size;
         val = self->buffer[ind];
-        
+
         /* simple lowpass filtering */
         tmp = val;
         val = (val + self->lpsamp) * 0.5;
         self->lpsamp = tmp;
-        
+
         /* lagrange filtering */
         x = (val*self->coeffs[0])+(self->lagrange[0]*self->coeffs[1])+(self->lagrange[1]*self->coeffs[2])+
             (self->lagrange[2]*self->coeffs[3])+(self->lagrange[3]*self->coeffs[4]);
@@ -1316,14 +1310,14 @@ Waveguide_process_aa(Waveguide *self) {
         self->lagrange[2] = self->lagrange[1];
         self->lagrange[1] = self->lagrange[0];
         self->lagrange[0] = val;
-  
+
         /* DC filtering */
         y = x - self->xn1 + 0.995 * self->yn1;
         self->xn1 = x;
         self->yn1 = y;
-        
+
         self->data[i] = y;
-        
+
         /* write current value in the delay line */
         self->buffer[self->in_count] = in[i] + (x * feed);
         if (self->in_count == 0)
@@ -1350,56 +1344,56 @@ Waveguide_setProcMode(Waveguide *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Waveguide_process_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Waveguide_process_ai;
             break;
-        case 10:    
+        case 10:
             self->proc_func_ptr = Waveguide_process_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Waveguide_process_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Waveguide_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Waveguide_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Waveguide_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Waveguide_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Waveguide_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Waveguide_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Waveguide_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Waveguide_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Waveguide_postprocessing_revareva;
             break;
-    } 
+    }
 }
 
 static void
 Waveguide_compute_next_data_frame(Waveguide *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1408,24 +1402,24 @@ Waveguide_traverse(Waveguide *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->input);
-    Py_VISIT(self->input_stream);    
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
-    Py_VISIT(self->dur);    
-    Py_VISIT(self->dur_stream);    
+    Py_VISIT(self->input_stream);
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->dur);
+    Py_VISIT(self->dur_stream);
     return 0;
 }
 
-static int 
+static int
 Waveguide_clear(Waveguide *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
-    Py_CLEAR(self->input_stream);    
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
-    Py_CLEAR(self->dur);    
-    Py_CLEAR(self->dur_stream);    
+    Py_CLEAR(self->input_stream);
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->dur);
+    Py_CLEAR(self->dur_stream);
     return 0;
 }
 
@@ -1435,7 +1429,7 @@ Waveguide_dealloc(Waveguide* self)
     pyo_DEALLOC
     free(self->buffer);
     Waveguide_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1445,7 +1439,7 @@ Waveguide_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *durtmp=NULL, *multmp=NULL, *addtmp=NULL;
     Waveguide *self;
     self = (Waveguide *)type->tp_alloc(type, 0);
-    
+
     self->freq = PyFloat_FromDouble(100);
     self->dur = PyFloat_FromDouble(0.99);
     self->minfreq = 20;
@@ -1457,64 +1451,64 @@ Waveguide_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->lpsamp = 0.0;
     for(i=0; i<4; i++) {
         self->lagrange[i] = 0.0;
-    }    
+    }
     self->xn1 = 0.0;
     self->yn1 = 0.0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
-    
+
     INIT_OBJECT_COMMON
-    
+
     self->nyquist = (MYFLT)self->sr * 0.45;
 
     Stream_setFunctionPtr(self->stream, Waveguide_compute_next_data_frame);
     self->mode_func_ptr = Waveguide_setProcMode;
 
     static char *kwlist[] = {"input", "freq", "dur", "minfreq", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_OOFOO, kwlist, &inputtmp, &freqtmp, &durtmp, &self->minfreq, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    
+
     if (durtmp) {
         PyObject_CallMethod((PyObject *)self, "setDur", "O", durtmp);
     }
-    
+
     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->size = (long)(1.0 / self->minfreq * self->sr + 0.5);
-    
+
     self->buffer = (MYFLT *)realloc(self->buffer, (self->size+1) * sizeof(MYFLT));
     for (i=0; i<(self->size+1); i++) {
         self->buffer[i] = 0.;
-    }    
-    
+    }
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * Waveguide_getServer(Waveguide* self) { GET_SERVER };
 static PyObject * Waveguide_getStream(Waveguide* self) { GET_STREAM };
-static PyObject * Waveguide_setMul(Waveguide *self, PyObject *arg) { SET_MUL };	
-static PyObject * Waveguide_setAdd(Waveguide *self, PyObject *arg) { SET_ADD };	
-static PyObject * Waveguide_setSub(Waveguide *self, PyObject *arg) { SET_SUB };	
-static PyObject * Waveguide_setDiv(Waveguide *self, PyObject *arg) { SET_DIV };	
+static PyObject * Waveguide_setMul(Waveguide *self, PyObject *arg) { SET_MUL };
+static PyObject * Waveguide_setAdd(Waveguide *self, PyObject *arg) { SET_ADD };
+static PyObject * Waveguide_setSub(Waveguide *self, PyObject *arg) { SET_SUB };
+static PyObject * Waveguide_setDiv(Waveguide *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Waveguide_play(Waveguide *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Waveguide_out(Waveguide *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1530,17 +1524,32 @@ static PyObject * Waveguide_div(Waveguide *self, PyObject *arg) { DIV };
 static PyObject * Waveguide_inplace_div(Waveguide *self, PyObject *arg) { INPLACE_DIV };
 
 static PyObject *
+Waveguide_reset(Waveguide *self)
+{
+    int i;
+
+    for (i=0; i<(self->size+1); i++) {
+        self->buffer[i] = 0.;
+    }
+    for(i=0; i<4; i++) {
+        self->lagrange[i] = 0.0;
+    }
+    self->lpsamp = 0.0;
+    self->xn1 = 0.0;
+    self->yn1 = 0.0;
+
+	Py_RETURN_NONE;
+}
+
+static PyObject *
 Waveguide_setFreq(Waveguide *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-    
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -1556,25 +1565,22 @@ Waveguide_setFreq(Waveguide *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Waveguide_setDur(Waveguide *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-    
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->dur);
@@ -1590,12 +1596,12 @@ Waveguide_setDur(Waveguide *self, PyObject *arg)
         self->dur_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Waveguide_members[] = {
 {"server", T_OBJECT_EX, offsetof(Waveguide, server), 0, "Pyo server."},
@@ -1614,6 +1620,7 @@ static PyMethodDef Waveguide_methods[] = {
 {"play", (PyCFunction)Waveguide_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
 {"out", (PyCFunction)Waveguide_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
 {"stop", (PyCFunction)Waveguide_stop, METH_NOARGS, "Stops computing."},
+{"reset", (PyCFunction)Waveguide_reset, METH_NOARGS, "Reset the delay line."},
 {"setFreq", (PyCFunction)Waveguide_setFreq, METH_O, "Sets freq time in seconds."},
 {"setDur", (PyCFunction)Waveguide_setDur, METH_O, "Sets dur value between 0 -> 1."},
 {"setMul", (PyCFunction)Waveguide_setMul, METH_O, "Sets oscillator mul factor."},
@@ -1627,7 +1634,7 @@ static PyNumberMethods Waveguide_as_number = {
 (binaryfunc)Waveguide_add,                      /*nb_add*/
 (binaryfunc)Waveguide_sub,                 /*nb_subtract*/
 (binaryfunc)Waveguide_multiply,                 /*nb_multiply*/
-(binaryfunc)Waveguide_div,                   /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -1641,16 +1648,16 @@ static PyNumberMethods Waveguide_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
 (binaryfunc)Waveguide_inplace_add,              /*inplace_add*/
 (binaryfunc)Waveguide_inplace_sub,         /*inplace_subtract*/
 (binaryfunc)Waveguide_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)Waveguide_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -1659,15 +1666,14 @@ static PyNumberMethods Waveguide_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)Waveguide_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)Waveguide_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
 PyTypeObject WaveguideType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Waveguide_base",         /*tp_name*/
 sizeof(Waveguide),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -1675,7 +1681,7 @@ sizeof(Waveguide),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &Waveguide_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -1741,12 +1747,12 @@ AllpassWG_process_iii(AllpassWG *self) {
     int i, j;
     long ind;
     MYFLT val, y, xind, sampdel, frac, freqshift, alpsampdel, alpsampdelin, alpdetune;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
-    MYFLT feed = PyFloat_AS_DOUBLE(self->feed); 
+    MYFLT feed = PyFloat_AS_DOUBLE(self->feed);
     MYFLT detune = PyFloat_AS_DOUBLE(self->detune);
-    
+
     /* Check boundaries */
     if (fr < self->minfreq)
         fr = self->minfreq;
@@ -1763,7 +1769,7 @@ AllpassWG_process_iii(AllpassWG *self) {
         detune = 0.05;
     else if (detune > 1.0)
         detune = 1.0;
-    
+
     sampdel = self->sr / (fr * freqshift);
     alpdetune = detune * self->alpsize;
 
@@ -1775,7 +1781,7 @@ AllpassWG_process_iii(AllpassWG *self) {
         ind = (long)xind;
         frac = xind - ind;
         val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac;
-        
+
         /* all-pass filter */
         for (j=0; j<3; j++) {
             xind = self->alp_in_count[j] - (alpdetune * alp_chorus_factor[j]);
@@ -1794,19 +1800,19 @@ AllpassWG_process_iii(AllpassWG *self) {
             if (self->alp_in_count[j] == self->alpsize)
                 self->alp_in_count[j] = 0;
         }
-        
+
         /* DC filtering and output */
         y = val - self->xn1 + 0.995 * self->yn1;
         self->xn1 = val;
         self->data[i] = self->yn1 = y;
-        
+
         /* write current value in the delay line */
         self->buffer[self->in_count] = in[i] + val * feed;
         if (self->in_count == 0)
             self->buffer[self->size] = self->buffer[0];
         self->in_count++;
         if (self->in_count == self->size)
-            self->in_count = 0;        
+            self->in_count = 0;
     }
 }
 
@@ -1815,12 +1821,12 @@ AllpassWG_process_aii(AllpassWG *self) {
     int i, j;
     long ind;
     MYFLT val, y, xind, sampdel, frac, fr, freqshift, alpsampdel, alpsampdelin, alpdetune;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *freq = Stream_getData((Stream *)self->freq_stream);
-    MYFLT feed = PyFloat_AS_DOUBLE(self->feed); 
+    MYFLT feed = PyFloat_AS_DOUBLE(self->feed);
     MYFLT detune = PyFloat_AS_DOUBLE(self->detune);
-    
+
     feed *= 0.4525;
     if (feed > 0.4525)
         feed = 0.4525;
@@ -1832,7 +1838,7 @@ AllpassWG_process_aii(AllpassWG *self) {
         detune = 0.05;
     else if (detune > 1.0)
         detune = 1.0;
-    
+
     alpdetune = detune * self->alpsize;
     for (i=0; i<self->bufsize; i++) {
         fr = freq[i];
@@ -1840,7 +1846,7 @@ AllpassWG_process_aii(AllpassWG *self) {
             fr = self->minfreq;
         else if (fr >= self->nyquist)
             fr = self->nyquist;
-        
+
         /* pick a new value in the delay line */
         sampdel = self->sr / (fr * freqshift);
         xind = self->in_count - sampdel;
@@ -1849,7 +1855,7 @@ AllpassWG_process_aii(AllpassWG *self) {
         ind = (long)xind;
         frac = xind - ind;
         val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac;
-        
+
         /* all-pass filter */
         for (j=0; j<3; j++) {
             xind = self->alp_in_count[j] - (alpdetune * alp_chorus_factor[j]);
@@ -1868,19 +1874,19 @@ AllpassWG_process_aii(AllpassWG *self) {
             if (self->alp_in_count[j] == self->alpsize)
                 self->alp_in_count[j] = 0;
         }
-        
+
         /* DC filtering and output */
         y = val - self->xn1 + 0.995 * self->yn1;
         self->xn1 = val;
         self->data[i] = self->yn1 = y;
-        
+
         /* write current value in the delay line */
         self->buffer[self->in_count] = in[i] + val * feed;
         if (self->in_count == 0)
             self->buffer[self->size] = self->buffer[0];
         self->in_count++;
         if (self->in_count == self->size)
-            self->in_count = 0;        
+            self->in_count = 0;
     }
 }
 
@@ -1889,12 +1895,12 @@ AllpassWG_process_iai(AllpassWG *self) {
     int i, j;
     long ind;
     MYFLT val, y, xind, sampdel, frac, feed, freqshift, alpsampdel, alpsampdelin, alpdetune;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
-    MYFLT *fdb = Stream_getData((Stream *)self->feed_stream); 
+    MYFLT *fdb = Stream_getData((Stream *)self->feed_stream);
     MYFLT detune = PyFloat_AS_DOUBLE(self->detune);
-    
+
     /* Check boundaries */
     if (fr < self->minfreq)
         fr = self->minfreq;
@@ -1906,10 +1912,10 @@ AllpassWG_process_iai(AllpassWG *self) {
         detune = 0.05;
     else if (detune > 1.0)
         detune = 1.0;
-    
+
     sampdel = self->sr / (fr * freqshift);
     alpdetune = detune * self->alpsize;
-    
+
     for (i=0; i<self->bufsize; i++) {
         feed = fdb[i] * 0.4525;
         if (feed > 0.4525)
@@ -1923,7 +1929,7 @@ AllpassWG_process_iai(AllpassWG *self) {
         ind = (long)xind;
         frac = xind - ind;
         val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac;
-        
+
         /* all-pass filter */
         for (j=0; j<3; j++) {
             xind = self->alp_in_count[j] - (alpdetune * alp_chorus_factor[j]);
@@ -1942,19 +1948,19 @@ AllpassWG_process_iai(AllpassWG *self) {
             if (self->alp_in_count[j] == self->alpsize)
                 self->alp_in_count[j] = 0;
         }
-        
+
         /* DC filtering and output */
         y = val - self->xn1 + 0.995 * self->yn1;
         self->xn1 = val;
         self->data[i] = self->yn1 = y;
-        
+
         /* write current value in the delay line */
         self->buffer[self->in_count] = in[i] + val * feed;
         if (self->in_count == 0)
             self->buffer[self->size] = self->buffer[0];
         self->in_count++;
         if (self->in_count == self->size)
-            self->in_count = 0;        
+            self->in_count = 0;
     }
 }
 
@@ -1963,19 +1969,19 @@ AllpassWG_process_aai(AllpassWG *self) {
     int i, j;
     long ind;
     MYFLT val, y, xind, sampdel, frac, fr, feed, freqshift, alpsampdel, alpsampdelin, alpdetune;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *freq = Stream_getData((Stream *)self->freq_stream);
-    MYFLT *fdb = Stream_getData((Stream *)self->feed_stream); 
+    MYFLT *fdb = Stream_getData((Stream *)self->feed_stream);
     MYFLT detune = PyFloat_AS_DOUBLE(self->detune);
-    
+
     freqshift = detune * 0.5 + 1.;
     detune = detune * 0.95 + 0.05;
     if (detune < 0.05)
         detune = 0.05;
     else if (detune > 1.0)
         detune = 1.0;
-    
+
     alpdetune = detune * self->alpsize;
     for (i=0; i<self->bufsize; i++) {
         fr = freq[i];
@@ -1988,7 +1994,7 @@ AllpassWG_process_aai(AllpassWG *self) {
             feed = 0.4525;
         else if (feed < 0)
             feed = 0;
-        
+
         /* pick a new value in the delay line */
         sampdel = self->sr / (fr * freqshift);
         xind = self->in_count - sampdel;
@@ -1997,7 +2003,7 @@ AllpassWG_process_aai(AllpassWG *self) {
         ind = (long)xind;
         frac = xind - ind;
         val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac;
-        
+
         /* all-pass filter */
         for (j=0; j<3; j++) {
             xind = self->alp_in_count[j] - (alpdetune * alp_chorus_factor[j]);
@@ -2016,19 +2022,19 @@ AllpassWG_process_aai(AllpassWG *self) {
             if (self->alp_in_count[j] == self->alpsize)
                 self->alp_in_count[j] = 0;
         }
-        
+
         /* DC filtering and output */
         y = val - self->xn1 + 0.995 * self->yn1;
         self->xn1 = val;
         self->data[i] = self->yn1 = y;
-        
+
         /* write current value in the delay line */
         self->buffer[self->in_count] = in[i] + val * feed;
         if (self->in_count == 0)
             self->buffer[self->size] = self->buffer[0];
         self->in_count++;
         if (self->in_count == self->size)
-            self->in_count = 0;        
+            self->in_count = 0;
     }
 }
 
@@ -2037,12 +2043,12 @@ AllpassWG_process_iia(AllpassWG *self) {
     int i, j;
     long ind;
     MYFLT val, y, xind, sampdel, frac, detune, freqshift, alpsampdel, alpsampdelin, alpdetune;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
-    MYFLT feed = PyFloat_AS_DOUBLE(self->feed); 
+    MYFLT feed = PyFloat_AS_DOUBLE(self->feed);
     MYFLT *det = Stream_getData((Stream *)self->detune_stream);
-    
+
     /* Check boundaries */
     if (fr < self->minfreq)
         fr = self->minfreq;
@@ -2053,7 +2059,7 @@ AllpassWG_process_iia(AllpassWG *self) {
         feed = 0.4525;
     else if (feed < 0)
         feed = 0;
-    
+
     for (i=0; i<self->bufsize; i++) {
         detune = det[i];
         freqshift = detune * 0.5 + 1.;
@@ -2062,7 +2068,7 @@ AllpassWG_process_iia(AllpassWG *self) {
             detune = 0.05;
         else if (detune > 1.0)
             detune = 1.0;
-        
+
         /* pick a new value in the delay line */
         sampdel = self->sr / (fr * freqshift);
         xind = self->in_count - sampdel;
@@ -2071,7 +2077,7 @@ AllpassWG_process_iia(AllpassWG *self) {
         ind = (long)xind;
         frac = xind - ind;
         val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac;
-        
+
         /* all-pass filter */
         alpdetune = detune * self->alpsize;
         for (j=0; j<3; j++) {
@@ -2103,7 +2109,7 @@ AllpassWG_process_iia(AllpassWG *self) {
             self->buffer[self->size] = self->buffer[0];
         self->in_count++;
         if (self->in_count == self->size)
-            self->in_count = 0;        
+            self->in_count = 0;
     }
 }
 
@@ -2112,18 +2118,18 @@ AllpassWG_process_aia(AllpassWG *self) {
     int i, j;
     long ind;
     MYFLT val, y, xind, sampdel, frac, fr, detune, freqshift, alpsampdel, alpsampdelin, alpdetune;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *freq = Stream_getData((Stream *)self->freq_stream);
-    MYFLT feed = PyFloat_AS_DOUBLE(self->feed); 
+    MYFLT feed = PyFloat_AS_DOUBLE(self->feed);
     MYFLT *det = Stream_getData((Stream *)self->detune_stream);
-    
+
     feed *= 0.4525;
     if (feed > 0.4525)
         feed = 0.4525;
     else if (feed < 0)
         feed = 0;
-    
+
     for (i=0; i<self->bufsize; i++) {
         fr = freq[i];
         if (fr < self->minfreq)
@@ -2137,7 +2143,7 @@ AllpassWG_process_aia(AllpassWG *self) {
             detune = 0.05;
         else if (detune > 1.0)
             detune = 1.0;
-        
+
         /* pick a new value in the delay line */
         sampdel = self->sr / (fr * freqshift);
         xind = self->in_count - sampdel;
@@ -2146,7 +2152,7 @@ AllpassWG_process_aia(AllpassWG *self) {
         ind = (long)xind;
         frac = xind - ind;
         val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac;
-        
+
         /* all-pass filter */
         alpdetune = detune * self->alpsize;
         for (j=0; j<3; j++) {
@@ -2166,19 +2172,19 @@ AllpassWG_process_aia(AllpassWG *self) {
             if (self->alp_in_count[j] == self->alpsize)
                 self->alp_in_count[j] = 0;
         }
-        
+
         /* DC filtering and output */
         y = val - self->xn1 + 0.995 * self->yn1;
         self->xn1 = val;
         self->data[i] = self->yn1 = y;
-        
+
         /* write current value in the delay line */
         self->buffer[self->in_count] = in[i] + val * feed;
         if (self->in_count == 0)
             self->buffer[self->size] = self->buffer[0];
         self->in_count++;
         if (self->in_count == self->size)
-            self->in_count = 0;        
+            self->in_count = 0;
     }
 }
 
@@ -2187,18 +2193,18 @@ AllpassWG_process_iaa(AllpassWG *self) {
     int i, j;
     long ind;
     MYFLT val, y, xind, sampdel, frac, feed, detune, freqshift, alpsampdel, alpsampdelin, alpdetune;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
-    MYFLT *fdb = Stream_getData((Stream *)self->feed_stream); 
+    MYFLT *fdb = Stream_getData((Stream *)self->feed_stream);
     MYFLT *det = Stream_getData((Stream *)self->detune_stream);
-    
+
     /* Check boundaries */
     if (fr < self->minfreq)
         fr = self->minfreq;
     else if (fr >= self->nyquist)
         fr = self->nyquist;
-    
+
     for (i=0; i<self->bufsize; i++) {
         feed = fdb[i] * 0.4525;
         if (feed > 0.4525)
@@ -2212,7 +2218,7 @@ AllpassWG_process_iaa(AllpassWG *self) {
             detune = 0.05;
         else if (detune > 1.0)
             detune = 1.0;
-        
+
         /* pick a new value in the delay line */
         sampdel = self->sr / (fr * freqshift);
         xind = self->in_count - sampdel;
@@ -2221,7 +2227,7 @@ AllpassWG_process_iaa(AllpassWG *self) {
         ind = (long)xind;
         frac = xind - ind;
         val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac;
-        
+
         /* all-pass filter */
         alpdetune = detune * self->alpsize;
         for (j=0; j<3; j++) {
@@ -2241,19 +2247,19 @@ AllpassWG_process_iaa(AllpassWG *self) {
             if (self->alp_in_count[j] == self->alpsize)
                 self->alp_in_count[j] = 0;
         }
-        
+
         /* DC filtering and output */
         y = val - self->xn1 + 0.995 * self->yn1;
         self->xn1 = val;
         self->data[i] = self->yn1 = y;
-        
+
         /* write current value in the delay line */
         self->buffer[self->in_count] = in[i] + val * feed;
         if (self->in_count == 0)
             self->buffer[self->size] = self->buffer[0];
         self->in_count++;
         if (self->in_count == self->size)
-            self->in_count = 0;        
+            self->in_count = 0;
     }
 }
 
@@ -2262,10 +2268,10 @@ AllpassWG_process_aaa(AllpassWG *self) {
     int i, j;
     long ind;
     MYFLT val, y, xind, sampdel, frac, fr, feed, detune, freqshift, alpsampdel, alpsampdelin, alpdetune;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *freq = Stream_getData((Stream *)self->freq_stream);
-    MYFLT *fdb = Stream_getData((Stream *)self->feed_stream); 
+    MYFLT *fdb = Stream_getData((Stream *)self->feed_stream);
     MYFLT *det = Stream_getData((Stream *)self->detune_stream);
 
     for (i=0; i<self->bufsize; i++) {
@@ -2286,7 +2292,7 @@ AllpassWG_process_aaa(AllpassWG *self) {
             detune = 0.05;
         else if (detune > 1.0)
             detune = 1.0;
-        
+
         /* pick a new value in the delay line */
         sampdel = self->sr / (fr * freqshift);
         xind = self->in_count - sampdel;
@@ -2295,7 +2301,7 @@ AllpassWG_process_aaa(AllpassWG *self) {
         ind = (long)xind;
         frac = xind - ind;
         val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac;
-        
+
         /* all-pass filter */
         alpdetune = detune * self->alpsize;
         for (j=0; j<3; j++) {
@@ -2315,19 +2321,19 @@ AllpassWG_process_aaa(AllpassWG *self) {
             if (self->alp_in_count[j] == self->alpsize)
                 self->alp_in_count[j] = 0;
         }
-        
+
         /* DC filtering and output */
         y = val - self->xn1 + 0.995 * self->yn1;
         self->xn1 = val;
         self->data[i] = self->yn1 = y;
-        
+
         /* write current value in the delay line */
         self->buffer[self->in_count] = in[i] + val * feed;
         if (self->in_count == 0)
             self->buffer[self->size] = self->buffer[0];
         self->in_count++;
         if (self->in_count == self->size)
-            self->in_count = 0;        
+            self->in_count = 0;
     }
 }
 
@@ -2347,68 +2353,68 @@ AllpassWG_setProcMode(AllpassWG *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = AllpassWG_process_iii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = AllpassWG_process_aii;
             break;
-        case 10:    
+        case 10:
             self->proc_func_ptr = AllpassWG_process_iai;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = AllpassWG_process_aai;
             break;
-        case 100:    
+        case 100:
             self->proc_func_ptr = AllpassWG_process_iia;
             break;
-        case 101:    
+        case 101:
             self->proc_func_ptr = AllpassWG_process_aia;
             break;
-        case 110:    
+        case 110:
             self->proc_func_ptr = AllpassWG_process_iaa;
             break;
-        case 111:    
+        case 111:
             self->proc_func_ptr = AllpassWG_process_aaa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = AllpassWG_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = AllpassWG_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = AllpassWG_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = AllpassWG_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = AllpassWG_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = AllpassWG_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = AllpassWG_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = AllpassWG_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = AllpassWG_postprocessing_revareva;
             break;
-    } 
+    }
 }
 
 static void
 AllpassWG_compute_next_data_frame(AllpassWG *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -2417,28 +2423,28 @@ AllpassWG_traverse(AllpassWG *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->input);
-    Py_VISIT(self->input_stream);    
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
-    Py_VISIT(self->feed);    
-    Py_VISIT(self->feed_stream);    
-    Py_VISIT(self->detune);    
-    Py_VISIT(self->detune_stream);    
+    Py_VISIT(self->input_stream);
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->feed);
+    Py_VISIT(self->feed_stream);
+    Py_VISIT(self->detune);
+    Py_VISIT(self->detune_stream);
     return 0;
 }
 
-static int 
+static int
 AllpassWG_clear(AllpassWG *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
-    Py_CLEAR(self->input_stream);    
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
-    Py_CLEAR(self->feed);    
-    Py_CLEAR(self->feed_stream);    
-    Py_CLEAR(self->detune);    
-    Py_CLEAR(self->detune_stream);    
+    Py_CLEAR(self->input_stream);
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->feed);
+    Py_CLEAR(self->feed_stream);
+    Py_CLEAR(self->detune);
+    Py_CLEAR(self->detune_stream);
     return 0;
 }
 
@@ -2452,7 +2458,7 @@ AllpassWG_dealloc(AllpassWG* self)
         free(self->alpbuffer[i]);
     }
     AllpassWG_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2462,7 +2468,7 @@ AllpassWG_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *feedtmp=NULL, *detunetmp=NULL, *multmp=NULL, *addtmp=NULL;
     AllpassWG *self;
     self = (AllpassWG *)type->tp_alloc(type, 0);
-    
+
     self->freq = PyFloat_FromDouble(100);
     self->feed = PyFloat_FromDouble(0.);
     self->detune = PyFloat_FromDouble(0.5);
@@ -2475,47 +2481,47 @@ AllpassWG_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
 	self->modebuffer[4] = 0;
-    
+
     INIT_OBJECT_COMMON
-    
+
     self->nyquist = (MYFLT)self->sr * 0.45;
 
     Stream_setFunctionPtr(self->stream, AllpassWG_compute_next_data_frame);
     self->mode_func_ptr = AllpassWG_setProcMode;
 
     static char *kwlist[] = {"input", "freq", "feed", "detune", "minfreq", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_OOOFOO, kwlist, &inputtmp, &freqtmp, &feedtmp, &detunetmp, &self->minfreq, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    
+
     if (feedtmp) {
         PyObject_CallMethod((PyObject *)self, "setFeed", "O", feedtmp);
     }
     if (detunetmp) {
         PyObject_CallMethod((PyObject *)self, "setDetune", "O", detunetmp);
     }
-    
+
     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->size = (long)(1.0 / self->minfreq * self->sr + 0.5);    
+
+    self->size = (long)(1.0 / self->minfreq * self->sr + 0.5);
     self->buffer = (MYFLT *)realloc(self->buffer, (self->size+1) * sizeof(MYFLT));
     for (i=0; i<(self->size+1); i++) {
         self->buffer[i] = 0.;
-    }    
+    }
 
     self->alpsize = (int)(self->sr * 0.0025);
     for (i=0; i<3; i++) {
@@ -2523,19 +2529,19 @@ AllpassWG_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         for (j=0; j<(self->alpsize+1); j++) {
             self->alpbuffer[i][j] = 0.;
         }
-    }    
-    
-    (*self->mode_func_ptr)(self);
-    
+    }
+
+    (*self->mode_func_ptr)(self);
+
     return (PyObject *)self;
 }
 
 static PyObject * AllpassWG_getServer(AllpassWG* self) { GET_SERVER };
 static PyObject * AllpassWG_getStream(AllpassWG* self) { GET_STREAM };
-static PyObject * AllpassWG_setMul(AllpassWG *self, PyObject *arg) { SET_MUL };	
-static PyObject * AllpassWG_setAdd(AllpassWG *self, PyObject *arg) { SET_ADD };	
-static PyObject * AllpassWG_setSub(AllpassWG *self, PyObject *arg) { SET_SUB };	
-static PyObject * AllpassWG_setDiv(AllpassWG *self, PyObject *arg) { SET_DIV };	
+static PyObject * AllpassWG_setMul(AllpassWG *self, PyObject *arg) { SET_MUL };
+static PyObject * AllpassWG_setAdd(AllpassWG *self, PyObject *arg) { SET_ADD };
+static PyObject * AllpassWG_setSub(AllpassWG *self, PyObject *arg) { SET_SUB };
+static PyObject * AllpassWG_setDiv(AllpassWG *self, PyObject *arg) { SET_DIV };
 
 static PyObject * AllpassWG_play(AllpassWG *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * AllpassWG_out(AllpassWG *self, PyObject *args, PyObject *kwds) { OUT };
@@ -2551,17 +2557,32 @@ static PyObject * AllpassWG_div(AllpassWG *self, PyObject *arg) { DIV };
 static PyObject * AllpassWG_inplace_div(AllpassWG *self, PyObject *arg) { INPLACE_DIV };
 
 static PyObject *
+AllpassWG_reset(AllpassWG *self)
+{
+    int i, j;
+    for (i=0; i<(self->size+1); i++) {
+        self->buffer[i] = 0.;
+    }
+    for (i=0; i<3; i++) {
+        for (j=0; j<(self->alpsize+1); j++) {
+            self->alpbuffer[i][j] = 0.;
+        }
+    }
+    self->in_count = self->alp_in_count[0] = self->alp_in_count[1] = self->alp_in_count[2] = 0;
+    self->xn1 = self->yn1 = 0.0;
+
+	Py_RETURN_NONE;
+}
+
+static PyObject *
 AllpassWG_setFreq(AllpassWG *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-    
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -2577,25 +2598,22 @@ AllpassWG_setFreq(AllpassWG *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 AllpassWG_setFeed(AllpassWG *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-    
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->feed);
@@ -2611,25 +2629,22 @@ AllpassWG_setFeed(AllpassWG *self, PyObject *arg)
         self->feed_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 AllpassWG_setDetune(AllpassWG *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-    
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->detune);
@@ -2645,12 +2660,12 @@ AllpassWG_setDetune(AllpassWG *self, PyObject *arg)
         self->detune_stream = (Stream *)streamtmp;
 		self->modebuffer[4] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef AllpassWG_members[] = {
     {"server", T_OBJECT_EX, offsetof(AllpassWG, server), 0, "Pyo server."},
@@ -2670,6 +2685,7 @@ static PyMethodDef AllpassWG_methods[] = {
     {"play", (PyCFunction)AllpassWG_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
     {"out", (PyCFunction)AllpassWG_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
     {"stop", (PyCFunction)AllpassWG_stop, METH_NOARGS, "Stops computing."},
+    {"reset", (PyCFunction)AllpassWG_reset, METH_NOARGS, "Reset the delay line."},
     {"setFreq", (PyCFunction)AllpassWG_setFreq, METH_O, "Sets freq time in seconds."},
     {"setFeed", (PyCFunction)AllpassWG_setFeed, METH_O, "Sets feed value between 0 -> 1."},
     {"setDetune", (PyCFunction)AllpassWG_setDetune, METH_O, "Sets detune value between 0 -> 1."},
@@ -2684,7 +2700,7 @@ static PyNumberMethods AllpassWG_as_number = {
     (binaryfunc)AllpassWG_add,                      /*nb_add*/
     (binaryfunc)AllpassWG_sub,                 /*nb_subtract*/
     (binaryfunc)AllpassWG_multiply,                 /*nb_multiply*/
-    (binaryfunc)AllpassWG_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -2698,16 +2714,16 @@ static PyNumberMethods AllpassWG_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)AllpassWG_inplace_add,              /*inplace_add*/
     (binaryfunc)AllpassWG_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)AllpassWG_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)AllpassWG_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -2716,15 +2732,14 @@ static PyNumberMethods AllpassWG_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)AllpassWG_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)AllpassWG_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject AllpassWGType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.AllpassWG_base",         /*tp_name*/
     sizeof(AllpassWG),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -2732,7 +2747,7 @@ PyTypeObject AllpassWGType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &AllpassWG_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -2771,7 +2786,7 @@ typedef struct {
     pyo_audio_HEAD
     PyObject *input;
     Stream *input_stream;
-    int modebuffer[2]; // need at least 2 slots for mul & add 
+    int modebuffer[2]; // need at least 2 slots for mul & add
     MYFLT x1;
 } Delay1;
 
@@ -2801,44 +2816,44 @@ Delay1_setProcMode(Delay1 *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-       
+
     self->proc_func_ptr = Delay1_filters;
 
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Delay1_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Delay1_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Delay1_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Delay1_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Delay1_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Delay1_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Delay1_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Delay1_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Delay1_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Delay1_compute_next_data_frame(Delay1 *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -2851,7 +2866,7 @@ Delay1_traverse(Delay1 *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Delay1_clear(Delay1 *self)
 {
     pyo_CLEAR
@@ -2865,7 +2880,7 @@ Delay1_dealloc(Delay1* self)
 {
     pyo_DEALLOC
     Delay1_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2875,32 +2890,32 @@ Delay1_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     Delay1 *self;
     self = (Delay1 *)type->tp_alloc(type, 0);
-    
+
     self->x1 = 0.0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Delay1_compute_next_data_frame);
     self->mode_func_ptr = Delay1_setProcMode;
 
     static char *kwlist[] = {"input", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
 
     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;
@@ -2908,10 +2923,10 @@ Delay1_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Delay1_getServer(Delay1* self) { GET_SERVER };
 static PyObject * Delay1_getStream(Delay1* self) { GET_STREAM };
-static PyObject * Delay1_setMul(Delay1 *self, PyObject *arg) { SET_MUL };	
-static PyObject * Delay1_setAdd(Delay1 *self, PyObject *arg) { SET_ADD };	
-static PyObject * Delay1_setSub(Delay1 *self, PyObject *arg) { SET_SUB };	
-static PyObject * Delay1_setDiv(Delay1 *self, PyObject *arg) { SET_DIV };	
+static PyObject * Delay1_setMul(Delay1 *self, PyObject *arg) { SET_MUL };
+static PyObject * Delay1_setAdd(Delay1 *self, PyObject *arg) { SET_ADD };
+static PyObject * Delay1_setSub(Delay1 *self, PyObject *arg) { SET_SUB };
+static PyObject * Delay1_setDiv(Delay1 *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Delay1_play(Delay1 *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Delay1_out(Delay1 *self, PyObject *args, PyObject *kwds) { OUT };
@@ -2952,7 +2967,7 @@ static PyNumberMethods Delay1_as_number = {
 (binaryfunc)Delay1_add,                         /*nb_add*/
 (binaryfunc)Delay1_sub,                         /*nb_subtract*/
 (binaryfunc)Delay1_multiply,                    /*nb_multiply*/
-(binaryfunc)Delay1_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -2966,16 +2981,16 @@ static PyNumberMethods Delay1_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)Delay1_inplace_add,                 /*inplace_add*/
 (binaryfunc)Delay1_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)Delay1_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)Delay1_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -2984,15 +2999,14 @@ static PyNumberMethods Delay1_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)Delay1_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)Delay1_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject Delay1Type = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Delay1_base",                                   /*tp_name*/
 sizeof(Delay1),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -3000,7 +3014,7 @@ sizeof(Delay1),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &Delay1_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -3031,3 +3045,705 @@ Delay1_members,                                 /* tp_members */
 0,                                              /* tp_alloc */
 Delay1_new,                                     /* tp_new */
 };
+
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *input;
+    Stream *input_stream;
+    PyObject *delay;
+    Stream *delay_stream;
+    PyObject *feedback;
+    Stream *feedback_stream;
+    MYFLT crossfade;
+    MYFLT maxdelay;
+    MYFLT oneOverSr;
+    MYFLT amp1;
+    MYFLT amp2;
+    MYFLT inc1;
+    MYFLT inc2;
+    int current;
+    long timer;
+    long size;
+    long in_count;
+    long sampdel;
+    MYFLT sampdel1;
+    MYFLT sampdel2;
+    int modebuffer[4];
+    MYFLT *buffer; // samples memory
+} SmoothDelay;
+
+static void
+SmoothDelay_process_ii(SmoothDelay *self) {
+    MYFLT val, xind, frac, sum;
+    int i;
+    long ind, xsamps = 0;
+
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+    MYFLT del = PyFloat_AS_DOUBLE(self->delay);
+    MYFLT feed = PyFloat_AS_DOUBLE(self->feedback);
+
+    if (del < self->oneOverSr) del = self->oneOverSr;
+    else if (del > self->maxdelay) del = self->maxdelay;
+
+    if (feed < 0) feed = 0.0;
+    else if (feed > 1) feed = 1.0;
+
+    for (i=0; i<self->bufsize; i++) {
+        if (self->timer == 0) {
+            self->current = (self->current + 1) % 2;
+            self->sampdel = (long)(del * self->sr + 0.5);
+            xsamps = (long)(self->crossfade * self->sr + 0.5);
+            if (xsamps > self->sampdel) xsamps = self->sampdel;
+            if (xsamps <= 0) xsamps = 1;
+            if (self->current == 0) {
+                self->sampdel1 = del * self->sr;
+                self->inc1 = 1.0 / xsamps;
+                self->inc2 = -self->inc1;
+            }
+            else {
+                self->sampdel2 = del * self->sr;
+                self->inc2 = 1.0 / xsamps;
+                self->inc1 = -self->inc2;
+            }
+        }
+
+        xind = self->in_count - self->sampdel1;
+        while (xind < 0)
+            xind += self->size;
+        ind = (long)xind;
+        frac = xind - ind;
+        val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac;
+        sum = val * self->amp1;
+        self->amp1 += self->inc1;
+        if (self->amp1 < 0) self->amp1 = 0.0;
+        else if (self->amp1 > 1) self->amp1 = 1.0;
+
+        xind = self->in_count - self->sampdel2;
+        while (xind < 0)
+            xind += self->size;
+        ind = (long)xind;
+        frac = xind - ind;
+        val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac;
+        sum += val * self->amp2;
+        self->amp2 += self->inc2;
+        if (self->amp2 < 0) self->amp2 = 0.0;
+        else if (self->amp2 > 1) self->amp2 = 1.0;
+
+        self->data[i] = sum;
+
+        self->buffer[self->in_count] = in[i] + (sum * feed);
+        if (self->in_count == 0)
+            self->buffer[self->size] = self->buffer[0];
+        self->in_count++;
+        if (self->in_count >= self->size)
+            self->in_count = 0;
+
+        self->timer++;
+        if (self->timer == self->sampdel)
+            self->timer = 0;
+    }
+}
+
+static void
+SmoothDelay_process_ai(SmoothDelay *self) {
+    MYFLT val, xind, frac, sum, del;
+    int i;
+    long ind, xsamps = 0;
+
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+    MYFLT *dl = Stream_getData((Stream *)self->delay_stream);
+    MYFLT feed = PyFloat_AS_DOUBLE(self->feedback);
+
+    if (feed < 0) feed = 0.0;
+    else if (feed > 1) feed = 1.0;
+
+    for (i=0; i<self->bufsize; i++) {
+        if (self->timer == 0) {
+            del = dl[i];
+            if (del < self->oneOverSr) del = self->oneOverSr;
+            else if (del > self->maxdelay) del = self->maxdelay;
+            self->current = (self->current + 1) % 2;
+            self->sampdel = (long)(del * self->sr + 0.5);
+            xsamps = (long)(self->crossfade * self->sr + 0.5);
+            if (xsamps > self->sampdel) xsamps = self->sampdel;
+            if (xsamps <= 0) xsamps = 1;
+            if (self->current == 0) {
+                self->sampdel1 = del * self->sr;
+                self->inc1 = 1.0 / xsamps;
+                self->inc2 = -self->inc1;
+            }
+            else {
+                self->sampdel2 = del * self->sr;
+                self->inc2 = 1.0 / xsamps;
+                self->inc1 = -self->inc2;
+            }
+        }
+
+        xind = self->in_count - self->sampdel1;
+        while (xind < 0)
+            xind += self->size;
+        ind = (long)xind;
+        frac = xind - ind;
+        val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac;
+        sum = val * self->amp1;
+        self->amp1 += self->inc1;
+        if (self->amp1 < 0) self->amp1 = 0.0;
+        else if (self->amp1 > 1) self->amp1 = 1.0;
+
+        xind = self->in_count - self->sampdel2;
+        while (xind < 0)
+            xind += self->size;
+        ind = (long)xind;
+        frac = xind - ind;
+        val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac;
+        sum += val * self->amp2;
+        self->amp2 += self->inc2;
+        if (self->amp2 < 0) self->amp2 = 0.0;
+        else if (self->amp2 > 1) self->amp2 = 1.0;
+
+        self->data[i] = sum;
+
+        self->buffer[self->in_count] = in[i] + (sum * feed);
+        if (self->in_count == 0)
+            self->buffer[self->size] = self->buffer[0];
+        self->in_count++;
+        if (self->in_count >= self->size)
+            self->in_count = 0;
+
+        self->timer++;
+        if (self->timer == self->sampdel)
+            self->timer = 0;
+    }
+}
+
+static void
+SmoothDelay_process_ia(SmoothDelay *self) {
+    MYFLT val, xind, frac, sum, feed;
+    int i;
+    long ind, xsamps = 0;
+
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+    MYFLT del = PyFloat_AS_DOUBLE(self->delay);
+    MYFLT *fd = Stream_getData((Stream *)self->feedback_stream);
+
+    if (del < self->oneOverSr) del = self->oneOverSr;
+    else if (del > self->maxdelay) del = self->maxdelay;
+
+    for (i=0; i<self->bufsize; i++) {
+        feed = fd[i];
+        if (feed < 0) feed = 0.0;
+        else if (feed > 1) feed = 1.0;
+        if (self->timer == 0) {
+            self->current = (self->current + 1) % 2;
+            self->sampdel = (long)(del * self->sr + 0.5);
+            xsamps = (long)(self->crossfade * self->sr + 0.5);
+            if (xsamps > self->sampdel) xsamps = self->sampdel;
+            if (xsamps <= 0) xsamps = 1;
+            if (self->current == 0) {
+                self->sampdel1 = del * self->sr;
+                self->inc1 = 1.0 / xsamps;
+                self->inc2 = -self->inc1;
+            }
+            else {
+                self->sampdel2 = del * self->sr;
+                self->inc2 = 1.0 / xsamps;
+                self->inc1 = -self->inc2;
+            }
+        }
+
+        xind = self->in_count - self->sampdel1;
+        while (xind < 0)
+            xind += self->size;
+        ind = (long)xind;
+        frac = xind - ind;
+        val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac;
+        sum = val * self->amp1;
+        self->amp1 += self->inc1;
+        if (self->amp1 < 0) self->amp1 = 0.0;
+        else if (self->amp1 > 1) self->amp1 = 1.0;
+
+        xind = self->in_count - self->sampdel2;
+        while (xind < 0)
+            xind += self->size;
+        ind = (long)xind;
+        frac = xind - ind;
+        val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac;
+        sum += val * self->amp2;
+        self->amp2 += self->inc2;
+        if (self->amp2 < 0) self->amp2 = 0.0;
+        else if (self->amp2 > 1) self->amp2 = 1.0;
+
+        self->data[i] = sum;
+
+        self->buffer[self->in_count] = in[i] + (sum * feed);
+        if (self->in_count == 0)
+            self->buffer[self->size] = self->buffer[0];
+        self->in_count++;
+        if (self->in_count >= self->size)
+            self->in_count = 0;
+
+        self->timer++;
+        if (self->timer == self->sampdel)
+            self->timer = 0;
+    }
+}
+
+static void
+SmoothDelay_process_aa(SmoothDelay *self) {
+    MYFLT val, xind, frac, sum, del, feed;
+    int i;
+    long ind, xsamps = 0;
+
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+    MYFLT *dl = Stream_getData((Stream *)self->delay_stream);
+    MYFLT *fd = Stream_getData((Stream *)self->feedback_stream);
+
+    for (i=0; i<self->bufsize; i++) {
+        feed = fd[i];
+        if (feed < 0) feed = 0.0;
+        else if (feed > 1) feed = 1.0;
+        if (self->timer == 0) {
+            del = dl[i];
+            if (del < self->oneOverSr) del = self->oneOverSr;
+            else if (del > self->maxdelay) del = self->maxdelay;
+            self->current = (self->current + 1) % 2;
+            self->sampdel = (long)(del * self->sr + 0.5);
+            xsamps = (long)(self->crossfade * self->sr + 0.5);
+            if (xsamps > self->sampdel) xsamps = self->sampdel;
+            if (xsamps <= 0) xsamps = 1;
+            if (self->current == 0) {
+                self->sampdel1 = del * self->sr;
+                self->inc1 = 1.0 / xsamps;
+                self->inc2 = -self->inc1;
+            }
+            else {
+                self->sampdel2 = del * self->sr;
+                self->inc2 = 1.0 / xsamps;
+                self->inc1 = -self->inc2;
+            }
+        }
+
+        xind = self->in_count - self->sampdel1;
+        while (xind < 0)
+            xind += self->size;
+        ind = (long)xind;
+        frac = xind - ind;
+        val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac;
+        sum = val * self->amp1;
+        self->amp1 += self->inc1;
+        if (self->amp1 < 0) self->amp1 = 0.0;
+        else if (self->amp1 > 1) self->amp1 = 1.0;
+
+        xind = self->in_count - self->sampdel2;
+        while (xind < 0)
+            xind += self->size;
+        ind = (long)xind;
+        frac = xind - ind;
+        val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac;
+        sum += val * self->amp2;
+        self->amp2 += self->inc2;
+        if (self->amp2 < 0) self->amp2 = 0.0;
+        else if (self->amp2 > 1) self->amp2 = 1.0;
+
+        self->data[i] = sum;
+
+        self->buffer[self->in_count] = in[i] + (sum * feed);
+        if (self->in_count == 0)
+            self->buffer[self->size] = self->buffer[0];
+        self->in_count++;
+        if (self->in_count >= self->size)
+            self->in_count = 0;
+
+        self->timer++;
+        if (self->timer == self->sampdel)
+            self->timer = 0;
+    }
+}
+
+static void SmoothDelay_postprocessing_ii(SmoothDelay *self) { POST_PROCESSING_II };
+static void SmoothDelay_postprocessing_ai(SmoothDelay *self) { POST_PROCESSING_AI };
+static void SmoothDelay_postprocessing_ia(SmoothDelay *self) { POST_PROCESSING_IA };
+static void SmoothDelay_postprocessing_aa(SmoothDelay *self) { POST_PROCESSING_AA };
+static void SmoothDelay_postprocessing_ireva(SmoothDelay *self) { POST_PROCESSING_IREVA };
+static void SmoothDelay_postprocessing_areva(SmoothDelay *self) { POST_PROCESSING_AREVA };
+static void SmoothDelay_postprocessing_revai(SmoothDelay *self) { POST_PROCESSING_REVAI };
+static void SmoothDelay_postprocessing_revaa(SmoothDelay *self) { POST_PROCESSING_REVAA };
+static void SmoothDelay_postprocessing_revareva(SmoothDelay *self) { POST_PROCESSING_REVAREVA };
+
+static void
+SmoothDelay_setProcMode(SmoothDelay *self)
+{
+    int procmode, muladdmode;
+    procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+	switch (procmode) {
+        case 0:
+            self->proc_func_ptr = SmoothDelay_process_ii;
+            break;
+        case 1:
+            self->proc_func_ptr = SmoothDelay_process_ai;
+            break;
+        case 10:
+            self->proc_func_ptr = SmoothDelay_process_ia;
+            break;
+        case 11:
+            self->proc_func_ptr = SmoothDelay_process_aa;
+            break;
+    }
+	switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = SmoothDelay_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = SmoothDelay_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = SmoothDelay_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = SmoothDelay_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = SmoothDelay_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = SmoothDelay_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = SmoothDelay_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = SmoothDelay_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = SmoothDelay_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+SmoothDelay_compute_next_data_frame(SmoothDelay *self)
+{
+    (*self->proc_func_ptr)(self);
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+SmoothDelay_traverse(SmoothDelay *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->input);
+    Py_VISIT(self->input_stream);
+    Py_VISIT(self->delay);
+    Py_VISIT(self->delay_stream);
+    Py_VISIT(self->feedback);
+    Py_VISIT(self->feedback_stream);
+    return 0;
+}
+
+static int
+SmoothDelay_clear(SmoothDelay *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->input);
+    Py_CLEAR(self->input_stream);
+    Py_CLEAR(self->delay);
+    Py_CLEAR(self->delay_stream);
+    Py_CLEAR(self->feedback);
+    Py_CLEAR(self->feedback_stream);
+    return 0;
+}
+
+static void
+SmoothDelay_dealloc(SmoothDelay* self)
+{
+    pyo_DEALLOC
+    free(self->buffer);
+    SmoothDelay_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+SmoothDelay_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *inputtmp, *input_streamtmp, *delaytmp=NULL, *feedbacktmp=NULL, *multmp=NULL, *addtmp=NULL;
+    SmoothDelay *self;
+    self = (SmoothDelay *)type->tp_alloc(type, 0);
+
+    self->delay = PyFloat_FromDouble(0.25);
+    self->feedback = PyFloat_FromDouble(0);
+    self->crossfade = 0.05;
+    self->maxdelay = 1;
+    self->in_count = 0;
+    self->current = 1;
+    self->timer = 0;
+    self->amp1 = 0.0;
+    self->amp2 = 1.0;
+    self->inc1 = self->inc2 = 0.0;
+	self->modebuffer[0] = 0;
+	self->modebuffer[1] = 0;
+	self->modebuffer[2] = 0;
+	self->modebuffer[3] = 0;
+
+    INIT_OBJECT_COMMON
+
+    self->oneOverSr = self->sampdel1 = self->sampdel2 = 1.0 / self->sr;
+
+    Stream_setFunctionPtr(self->stream, SmoothDelay_compute_next_data_frame);
+    self->mode_func_ptr = SmoothDelay_setProcMode;
+
+    static char *kwlist[] = {"input", "delay", "feedback", "crossfade", "maxdelay", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_OOFFOO, kwlist, &inputtmp, &delaytmp, &feedbacktmp, &self->crossfade, &self->maxdelay, &multmp, &addtmp))
+        Py_RETURN_NONE;
+
+    INIT_INPUT_STREAM
+
+    if (delaytmp) {
+        PyObject_CallMethod((PyObject *)self, "setDelay", "O", delaytmp);
+    }
+
+    if (feedbacktmp) {
+        PyObject_CallMethod((PyObject *)self, "setFeedback", "O", feedbacktmp);
+    }
+
+    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->size = (long)(self->maxdelay * self->sr + 0.5);
+
+    self->buffer = (MYFLT *)realloc(self->buffer, (self->size+1) * sizeof(MYFLT));
+    for (i=0; i<(self->size+1); i++) {
+        self->buffer[i] = 0.;
+    }
+
+    (*self->mode_func_ptr)(self);
+
+    return (PyObject *)self;
+}
+
+static PyObject * SmoothDelay_getServer(SmoothDelay* self) { GET_SERVER };
+static PyObject * SmoothDelay_getStream(SmoothDelay* self) { GET_STREAM };
+static PyObject * SmoothDelay_setMul(SmoothDelay *self, PyObject *arg) { SET_MUL };
+static PyObject * SmoothDelay_setAdd(SmoothDelay *self, PyObject *arg) { SET_ADD };
+static PyObject * SmoothDelay_setSub(SmoothDelay *self, PyObject *arg) { SET_SUB };
+static PyObject * SmoothDelay_setDiv(SmoothDelay *self, PyObject *arg) { SET_DIV };
+
+static PyObject * SmoothDelay_play(SmoothDelay *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * SmoothDelay_out(SmoothDelay *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * SmoothDelay_stop(SmoothDelay *self) { STOP };
+
+static PyObject * SmoothDelay_multiply(SmoothDelay *self, PyObject *arg) { MULTIPLY };
+static PyObject * SmoothDelay_inplace_multiply(SmoothDelay *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * SmoothDelay_add(SmoothDelay *self, PyObject *arg) { ADD };
+static PyObject * SmoothDelay_inplace_add(SmoothDelay *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * SmoothDelay_sub(SmoothDelay *self, PyObject *arg) { SUB };
+static PyObject * SmoothDelay_inplace_sub(SmoothDelay *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * SmoothDelay_div(SmoothDelay *self, PyObject *arg) { DIV };
+static PyObject * SmoothDelay_inplace_div(SmoothDelay *self, PyObject *arg) { INPLACE_DIV };
+
+static PyObject *
+SmoothDelay_setDelay(SmoothDelay *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->delay);
+	if (isNumber == 1) {
+		self->delay = PyNumber_Float(tmp);
+        self->modebuffer[2] = 0;
+	}
+	else {
+		self->delay = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->delay, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->delay_stream);
+        self->delay_stream = (Stream *)streamtmp;
+		self->modebuffer[2] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+SmoothDelay_setFeedback(SmoothDelay *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->feedback);
+	if (isNumber == 1) {
+		self->feedback = PyNumber_Float(tmp);
+        self->modebuffer[3] = 0;
+	}
+	else {
+		self->feedback = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->feedback, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->feedback_stream);
+        self->feedback_stream = (Stream *)streamtmp;
+		self->modebuffer[3] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+SmoothDelay_setCrossfade(SmoothDelay *self, PyObject *arg)
+{
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	if (isNumber == 1) {
+		self->crossfade = PyFloat_AsDouble(arg);
+	}
+
+	Py_RETURN_NONE;
+}
+
+static PyObject *
+SmoothDelay_reset(SmoothDelay *self)
+{
+    int i;
+    for (i=0; i<(self->size+1); i++) {
+        self->buffer[i] = 0.;
+    }
+	Py_RETURN_NONE;
+}
+
+static PyMemberDef SmoothDelay_members[] = {
+    {"server", T_OBJECT_EX, offsetof(SmoothDelay, server), 0, "Pyo server."},
+    {"stream", T_OBJECT_EX, offsetof(SmoothDelay, stream), 0, "Stream object."},
+    {"input", T_OBJECT_EX, offsetof(SmoothDelay, input), 0, "Input sound object."},
+    {"delay", T_OBJECT_EX, offsetof(SmoothDelay, delay), 0, "SmoothDelay time in seconds."},
+    {"feedback", T_OBJECT_EX, offsetof(SmoothDelay, feedback), 0, "Feedback value."},
+    {"mul", T_OBJECT_EX, offsetof(SmoothDelay, mul), 0, "Mul factor."},
+    {"add", T_OBJECT_EX, offsetof(SmoothDelay, add), 0, "Add factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef SmoothDelay_methods[] = {
+    {"getServer", (PyCFunction)SmoothDelay_getServer, METH_NOARGS, "Returns server object."},
+    {"_getStream", (PyCFunction)SmoothDelay_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)SmoothDelay_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+    {"out", (PyCFunction)SmoothDelay_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+    {"stop", (PyCFunction)SmoothDelay_stop, METH_NOARGS, "Stops computing."},
+	{"setDelay", (PyCFunction)SmoothDelay_setDelay, METH_O, "Sets delay time in seconds."},
+    {"setFeedback", (PyCFunction)SmoothDelay_setFeedback, METH_O, "Sets feedback value between 0 -> 1."},
+    {"setCrossfade", (PyCFunction)SmoothDelay_setCrossfade, METH_O, "Sets crossfade time."},
+    {"reset", (PyCFunction)SmoothDelay_reset, METH_NOARGS, "Resets the memory buffer to zeros."},
+	{"setMul", (PyCFunction)SmoothDelay_setMul, METH_O, "Sets oscillator mul factor."},
+	{"setAdd", (PyCFunction)SmoothDelay_setAdd, METH_O, "Sets oscillator add factor."},
+    {"setSub", (PyCFunction)SmoothDelay_setSub, METH_O, "Sets inverse add factor."},
+    {"setDiv", (PyCFunction)SmoothDelay_setDiv, METH_O, "Sets inverse mul factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyNumberMethods SmoothDelay_as_number = {
+    (binaryfunc)SmoothDelay_add,                      /*nb_add*/
+    (binaryfunc)SmoothDelay_sub,                 /*nb_subtract*/
+    (binaryfunc)SmoothDelay_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)SmoothDelay_inplace_add,              /*inplace_add*/
+    (binaryfunc)SmoothDelay_inplace_sub,         /*inplace_subtract*/
+    (binaryfunc)SmoothDelay_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)SmoothDelay_div,                       /*nb_true_divide*/
+    0,     /*nb_inplace_floor_divide*/
+    (binaryfunc)SmoothDelay_inplace_div,                       /*nb_inplace_true_divide*/
+    0,                     /* nb_index */
+};
+
+PyTypeObject SmoothDelayType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.SmoothDelay_base",         /*tp_name*/
+    sizeof(SmoothDelay),         /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)SmoothDelay_dealloc, /*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
+    0,                         /*tp_repr*/
+    &SmoothDelay_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*/
+    "SmoothDelay objects. Delay signal by x samples.",           /* tp_doc */
+    (traverseproc)SmoothDelay_traverse,   /* tp_traverse */
+    (inquiry)SmoothDelay_clear,           /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    SmoothDelay_methods,             /* tp_methods */
+    SmoothDelay_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 */
+    SmoothDelay_new,                 /* tp_new */
+};
\ No newline at end of file
diff --git a/src/objects/distomodule.c b/src/objects/distomodule.c
index 89cbb1c..1eb929b 100644
--- a/src/objects/distomodule.c
+++ b/src/objects/distomodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
@@ -39,9 +40,8 @@ typedef struct {
     MYFLT y1; // sample memory
 } Disto;
 
-static MYFLT
-_clip(MYFLT x)
-{
+/* old version (prior to 0.8.0) with atan2
+static MYFLT _clip(MYFLT x) {
     if (x < 0)
         return 0;
     else if (x > 1)
@@ -58,7 +58,7 @@ Disto_transform_ii(Disto *self) {
 
     MYFLT drv = .4 - _clip(PyFloat_AS_DOUBLE(self->drive)) * .3999;
     MYFLT slp = _clip(PyFloat_AS_DOUBLE(self->slope));
-    
+
     for (i=0; i<self->bufsize; i++) {
         val = MYATAN2(in[i], drv);
         self->data[i] = val;
@@ -70,72 +70,78 @@ Disto_transform_ii(Disto *self) {
         self->data[i] = val;
     }
 }
-
+*/
 static void
-Disto_transform_ai(Disto *self) {
-    MYFLT val, drv, coeff;
+Disto_transform_ii(Disto *self) {
     int i;
+    MYFLT val;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
+    MYFLT drv = PyFloat_AS_DOUBLE(self->drive);
+    MYFLT slp = PyFloat_AS_DOUBLE(self->slope);
+
+    drv = (drv < 0.0) ? 0.0 : (drv > 0.998) ? 0.998 : drv;
+    drv = (2.0 * drv) / (1 - drv);
+    slp = (slp < 0.0) ? 0.0 : (slp > 0.999) ? 0.999 : slp;
 
-    MYFLT *drive = Stream_getData((Stream *)self->drive_stream);
-    MYFLT slp = _clip(PyFloat_AS_DOUBLE(self->slope));
-    
     for (i=0; i<self->bufsize; i++) {
-        drv = .4 - _clip(drive[i]) * .3999;
-        val = MYATAN2(in[i], drv);
-        self->data[i] = val;
+        val = (1 + drv) * in[i] / (1 + drv * MYFABS(in[i]));
+        self->data[i] = self->y1 = val + (self->y1 - val) * slp;
     }
-    
-    coeff = 1.0 - slp;
+}
+
+static void
+Disto_transform_ai(Disto *self) {
+    int i;
+    MYFLT val, drv;
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+    MYFLT *drive = Stream_getData((Stream *)self->drive_stream);
+    MYFLT slp = PyFloat_AS_DOUBLE(self->slope);
+    slp = (slp < 0.0) ? 0.0 : (slp > 0.999) ? 0.999 : slp;
+
     for (i=0; i<self->bufsize; i++) {
-        val = self->data[i] * coeff + self->y1 * slp;
-        self->y1 = val;
-        self->data[i] = val;
+        drv = drive[i];
+        drv = (drv < 0.0) ? 0.0 : (drv > 0.998) ? 0.998 : drv;
+        drv = (2.0 * drv) / (1 - drv);
+        val = (1 + drv) * in[i] / (1 + drv * MYFABS(in[i]));
+        self->data[i] = self->y1 = val + (self->y1 - val) * slp;
     }
 }
 
 static void
 Disto_transform_ia(Disto *self) {
-    MYFLT val, coeff, slp;
     int i;
+    MYFLT val, slp;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
-    MYFLT drv = .4 - _clip(PyFloat_AS_DOUBLE(self->drive)) * .3999;
+    MYFLT drv = PyFloat_AS_DOUBLE(self->drive);
     MYFLT *slope = Stream_getData((Stream *)self->slope_stream);
-    
-    for (i=0; i<self->bufsize; i++) {
-        val = MYATAN2(in[i], drv);
-        self->data[i] = val;
-    }
+
+    drv = (drv < 0.0) ? 0.0 : (drv > 0.998) ? 0.998 : drv;
+    drv = (2.0 * drv) / (1 - drv);
+
     for (i=0; i<self->bufsize; i++) {
-        slp = _clip(slope[i]);
-        coeff = 1.0 - slp;
-        val = self->data[i] * coeff + self->y1 * slp;
-        self->y1 = val;
-        self->data[i] = val;
+        slp = slope[i];
+        slp = (slp < 0.0) ? 0.0 : (slp > 0.999) ? 0.999 : slp;
+        val = (1 + drv) * in[i] / (1 + drv * MYFABS(in[i]));
+        self->data[i] = self->y1 = val + (self->y1 - val) * slp;
     }
 }
 
 static void
 Disto_transform_aa(Disto *self) {
-    MYFLT val, drv, coeff, slp;
     int i;
+    MYFLT val, drv, slp;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
     MYFLT *drive = Stream_getData((Stream *)self->drive_stream);
     MYFLT *slope = Stream_getData((Stream *)self->slope_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
-        drv = .4 - _clip(drive[i]) * .3999;
-        val = MYATAN2(in[i], drv);
-        self->data[i] = val;
-    }
-    for (i=0; i<self->bufsize; i++) {
-        slp = _clip(slope[i]);
-        coeff = 1.0 - slp;
-        val = self->data[i] * coeff + self->y1 * slp;
-        self->y1 = val;
-        self->data[i] = val;
+        drv = drive[i];
+        drv = (drv < 0.0) ? 0.0 : (drv > 0.998) ? 0.998 : drv;
+        slp = slope[i];
+        slp = (slp < 0.0) ? 0.0 : (slp > 0.999) ? 0.999 : slp;
+        drv = (2.0 * drv) / (1 - drv);
+        val = (1 + drv) * in[i] / (1 + drv * MYFABS(in[i]));
+        self->data[i] = self->y1 = val + (self->y1 - val) * slp;
     }
 }
 
@@ -157,54 +163,54 @@ Disto_setProcMode(Disto *self)
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Disto_transform_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Disto_transform_ai;
             break;
-        case 10:        
+        case 10:
             self->proc_func_ptr = Disto_transform_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Disto_transform_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Disto_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Disto_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Disto_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Disto_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Disto_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Disto_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Disto_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Disto_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Disto_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Disto_compute_next_data_frame(Disto *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -213,24 +219,24 @@ Disto_traverse(Disto *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->input);
-    Py_VISIT(self->input_stream);    
-    Py_VISIT(self->drive);    
-    Py_VISIT(self->drive_stream);    
-    Py_VISIT(self->slope);    
-    Py_VISIT(self->slope_stream);    
+    Py_VISIT(self->input_stream);
+    Py_VISIT(self->drive);
+    Py_VISIT(self->drive_stream);
+    Py_VISIT(self->slope);
+    Py_VISIT(self->slope_stream);
     return 0;
 }
 
-static int 
+static int
 Disto_clear(Disto *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->drive);    
-    Py_CLEAR(self->drive_stream);    
-    Py_CLEAR(self->slope);    
-    Py_CLEAR(self->slope_stream);    
+    Py_CLEAR(self->drive);
+    Py_CLEAR(self->drive_stream);
+    Py_CLEAR(self->slope);
+    Py_CLEAR(self->slope_stream);
     return 0;
 }
 
@@ -239,7 +245,7 @@ Disto_dealloc(Disto* self)
 {
     pyo_DEALLOC
     Disto_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -268,7 +274,7 @@ Disto_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         Py_RETURN_NONE;
 
     INIT_INPUT_STREAM
-    
+
     if (drivetmp) {
         PyObject_CallMethod((PyObject *)self, "setDrive", "O", drivetmp);
     }
@@ -276,7 +282,7 @@ Disto_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (slopetmp) {
         PyObject_CallMethod((PyObject *)self, "setSlope", "O", slopetmp);
     }
-    
+
     if (multmp) {
         PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
     }
@@ -284,20 +290,20 @@ Disto_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     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 * Disto_getServer(Disto* self) { GET_SERVER };
 static PyObject * Disto_getStream(Disto* self) { GET_STREAM };
-static PyObject * Disto_setMul(Disto *self, PyObject *arg) { SET_MUL };	
-static PyObject * Disto_setAdd(Disto *self, PyObject *arg) { SET_ADD };	
-static PyObject * Disto_setSub(Disto *self, PyObject *arg) { SET_SUB };	
-static PyObject * Disto_setDiv(Disto *self, PyObject *arg) { SET_DIV };	
+static PyObject * Disto_setMul(Disto *self, PyObject *arg) { SET_MUL };
+static PyObject * Disto_setAdd(Disto *self, PyObject *arg) { SET_ADD };
+static PyObject * Disto_setSub(Disto *self, PyObject *arg) { SET_SUB };
+static PyObject * Disto_setDiv(Disto *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Disto_play(Disto *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Disto_out(Disto *self, PyObject *args, PyObject *kwds) { OUT };
@@ -316,14 +322,11 @@ static PyObject *
 Disto_setDrive(Disto *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->drive);
@@ -339,25 +342,22 @@ Disto_setDrive(Disto *self, PyObject *arg)
         self->drive_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Disto_setSlope(Disto *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->slope);
@@ -373,12 +373,12 @@ Disto_setSlope(Disto *self, PyObject *arg)
         self->slope_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Disto_members[] = {
     {"server", T_OBJECT_EX, offsetof(Disto, server), 0, "Pyo server."},
@@ -410,7 +410,7 @@ static PyNumberMethods Disto_as_number = {
     (binaryfunc)Disto_add,                      /*nb_add*/
     (binaryfunc)Disto_sub,                 /*nb_subtract*/
     (binaryfunc)Disto_multiply,                 /*nb_multiply*/
-    (binaryfunc)Disto_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -424,16 +424,16 @@ static PyNumberMethods Disto_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)Disto_inplace_add,              /*inplace_add*/
     (binaryfunc)Disto_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)Disto_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)Disto_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -442,15 +442,14 @@ static PyNumberMethods Disto_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)Disto_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)Disto_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject DistoType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Disto_base",         /*tp_name*/
     sizeof(Disto),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -458,7 +457,7 @@ PyTypeObject DistoType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &Disto_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -512,7 +511,7 @@ Clip_transform_ii(Clip *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT mi = PyFloat_AS_DOUBLE(self->min);
     MYFLT ma = PyFloat_AS_DOUBLE(self->max);
-    
+
     for (i=0; i<self->bufsize; i++) {
         val = in[i];
         if(val < mi)
@@ -531,7 +530,7 @@ Clip_transform_ai(Clip *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *mi = Stream_getData((Stream *)self->min_stream);
     MYFLT ma = PyFloat_AS_DOUBLE(self->max);
-    
+
     for (i=0; i<self->bufsize; i++) {
         val = in[i];
         mini = mi[i];
@@ -551,7 +550,7 @@ Clip_transform_ia(Clip *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT mi = PyFloat_AS_DOUBLE(self->min);
     MYFLT *ma = Stream_getData((Stream *)self->max_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         val = in[i];
         maxi = ma[i];
@@ -563,7 +562,7 @@ Clip_transform_ia(Clip *self) {
             self->data[i] = val;
     }
 }
-    
+
 static void
 Clip_transform_aa(Clip *self) {
     MYFLT val, mini, maxi;
@@ -571,7 +570,7 @@ Clip_transform_aa(Clip *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *mi = Stream_getData((Stream *)self->min_stream);
     MYFLT *ma = Stream_getData((Stream *)self->max_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         val = in[i];
         mini = mi[i];
@@ -601,56 +600,56 @@ Clip_setProcMode(Clip *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Clip_transform_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Clip_transform_ai;
             break;
-        case 10:        
+        case 10:
             self->proc_func_ptr = Clip_transform_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Clip_transform_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Clip_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Clip_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Clip_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Clip_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Clip_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Clip_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Clip_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Clip_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Clip_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Clip_compute_next_data_frame(Clip *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -659,24 +658,24 @@ Clip_traverse(Clip *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->input);
-    Py_VISIT(self->input_stream);    
-    Py_VISIT(self->min);    
-    Py_VISIT(self->min_stream);    
-    Py_VISIT(self->max);    
-    Py_VISIT(self->max_stream);    
+    Py_VISIT(self->input_stream);
+    Py_VISIT(self->min);
+    Py_VISIT(self->min_stream);
+    Py_VISIT(self->max);
+    Py_VISIT(self->max_stream);
     return 0;
 }
 
-static int 
+static int
 Clip_clear(Clip *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->min);    
-    Py_CLEAR(self->min_stream);    
-    Py_CLEAR(self->max);    
-    Py_CLEAR(self->max_stream);    
+    Py_CLEAR(self->min);
+    Py_CLEAR(self->min_stream);
+    Py_CLEAR(self->max);
+    Py_CLEAR(self->max_stream);
     return 0;
 }
 
@@ -685,7 +684,7 @@ Clip_dealloc(Clip* self)
 {
     pyo_DEALLOC
     Clip_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -695,54 +694,54 @@ Clip_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *mintmp=NULL, *maxtmp=NULL, *multmp=NULL, *addtmp=NULL;
     Clip *self;
     self = (Clip *)type->tp_alloc(type, 0);
-    
+
     self->min = PyFloat_FromDouble(-1.0);
     self->max = PyFloat_FromDouble(1.0);
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Clip_compute_next_data_frame);
     self->mode_func_ptr = Clip_setProcMode;
 
     static char *kwlist[] = {"input", "min", "max", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &mintmp, &maxtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (mintmp) {
         PyObject_CallMethod((PyObject *)self, "setMin", "O", mintmp);
     }
-    
+
     if (maxtmp) {
         PyObject_CallMethod((PyObject *)self, "setMax", "O", maxtmp);
     }
-    
+
     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 * Clip_getServer(Clip* self) { GET_SERVER };
 static PyObject * Clip_getStream(Clip* self) { GET_STREAM };
-static PyObject * Clip_setMul(Clip *self, PyObject *arg) { SET_MUL };	
-static PyObject * Clip_setAdd(Clip *self, PyObject *arg) { SET_ADD };	
-static PyObject * Clip_setSub(Clip *self, PyObject *arg) { SET_SUB };	
-static PyObject * Clip_setDiv(Clip *self, PyObject *arg) { SET_DIV };	
+static PyObject * Clip_setMul(Clip *self, PyObject *arg) { SET_MUL };
+static PyObject * Clip_setAdd(Clip *self, PyObject *arg) { SET_ADD };
+static PyObject * Clip_setSub(Clip *self, PyObject *arg) { SET_SUB };
+static PyObject * Clip_setDiv(Clip *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Clip_play(Clip *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Clip_out(Clip *self, PyObject *args, PyObject *kwds) { OUT };
@@ -761,14 +760,11 @@ static PyObject *
 Clip_setMin(Clip *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->min);
@@ -784,25 +780,22 @@ Clip_setMin(Clip *self, PyObject *arg)
         self->min_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Clip_setMax(Clip *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->max);
@@ -818,12 +811,12 @@ Clip_setMax(Clip *self, PyObject *arg)
         self->max_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Clip_members[] = {
 {"server", T_OBJECT_EX, offsetof(Clip, server), 0, "Pyo server."},
@@ -855,7 +848,7 @@ static PyNumberMethods Clip_as_number = {
 (binaryfunc)Clip_add,                      /*nb_add*/
 (binaryfunc)Clip_sub,                 /*nb_subtract*/
 (binaryfunc)Clip_multiply,                 /*nb_multiply*/
-(binaryfunc)Clip_div,                   /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -869,16 +862,16 @@ static PyNumberMethods Clip_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
 (binaryfunc)Clip_inplace_add,              /*inplace_add*/
 (binaryfunc)Clip_inplace_sub,         /*inplace_subtract*/
 (binaryfunc)Clip_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)Clip_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -887,15 +880,14 @@ static PyNumberMethods Clip_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)Clip_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)Clip_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
 PyTypeObject ClipType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Clip_base",         /*tp_name*/
 sizeof(Clip),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -903,7 +895,7 @@ sizeof(Clip),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &Clip_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -957,7 +949,7 @@ Mirror_transform_ii(Mirror *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT mi = PyFloat_AS_DOUBLE(self->min);
     MYFLT ma = PyFloat_AS_DOUBLE(self->max);
-    
+
     if (mi >= ma) {
         avg = (mi + ma) * 0.5;
         for (i=0; i<self->bufsize; i++) {
@@ -985,7 +977,7 @@ Mirror_transform_ai(Mirror *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *mini = Stream_getData((Stream *)self->min_stream);
     MYFLT ma = PyFloat_AS_DOUBLE(self->max);
-    
+
     for (i=0; i<self->bufsize; i++) {
         val = in[i];
         mi = mini[i];
@@ -1000,7 +992,7 @@ Mirror_transform_ai(Mirror *self) {
                 else
                     val = mi + mi - val;
             }
-            self->data[i] = val;            
+            self->data[i] = val;
         }
     }
 }
@@ -1012,7 +1004,7 @@ Mirror_transform_ia(Mirror *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT mi = PyFloat_AS_DOUBLE(self->min);
     MYFLT *maxi = Stream_getData((Stream *)self->max_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         val = in[i];
         ma = maxi[i];
@@ -1027,7 +1019,7 @@ Mirror_transform_ia(Mirror *self) {
                 else
                     val = mi + mi - val;
             }
-            self->data[i] = val;            
+            self->data[i] = val;
         }
     }
 }
@@ -1039,7 +1031,7 @@ Mirror_transform_aa(Mirror *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *mini = Stream_getData((Stream *)self->min_stream);
     MYFLT *maxi = Stream_getData((Stream *)self->max_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         val = in[i];
         mi = mini[i];
@@ -1055,7 +1047,7 @@ Mirror_transform_aa(Mirror *self) {
                 else
                     val = mi + mi - val;
             }
-            self->data[i] = val;            
+            self->data[i] = val;
         }
     }
 }
@@ -1076,56 +1068,56 @@ Mirror_setProcMode(Mirror *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Mirror_transform_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Mirror_transform_ai;
             break;
-        case 10:        
+        case 10:
             self->proc_func_ptr = Mirror_transform_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Mirror_transform_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Mirror_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Mirror_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Mirror_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Mirror_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Mirror_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Mirror_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Mirror_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Mirror_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Mirror_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Mirror_compute_next_data_frame(Mirror *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1134,24 +1126,24 @@ Mirror_traverse(Mirror *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->input);
-    Py_VISIT(self->input_stream);    
-    Py_VISIT(self->min);    
-    Py_VISIT(self->min_stream);    
-    Py_VISIT(self->max);    
-    Py_VISIT(self->max_stream);    
+    Py_VISIT(self->input_stream);
+    Py_VISIT(self->min);
+    Py_VISIT(self->min_stream);
+    Py_VISIT(self->max);
+    Py_VISIT(self->max_stream);
     return 0;
 }
 
-static int 
+static int
 Mirror_clear(Mirror *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->min);    
-    Py_CLEAR(self->min_stream);    
-    Py_CLEAR(self->max);    
-    Py_CLEAR(self->max_stream);    
+    Py_CLEAR(self->min);
+    Py_CLEAR(self->min_stream);
+    Py_CLEAR(self->max);
+    Py_CLEAR(self->max_stream);
     return 0;
 }
 
@@ -1160,7 +1152,7 @@ Mirror_dealloc(Mirror* self)
 {
     pyo_DEALLOC
     Mirror_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1170,54 +1162,54 @@ Mirror_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *mintmp=NULL, *maxtmp=NULL, *multmp=NULL, *addtmp=NULL;
     Mirror *self;
     self = (Mirror *)type->tp_alloc(type, 0);
-    
+
     self->min = PyFloat_FromDouble(0.0);
     self->max = PyFloat_FromDouble(1.0);
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Mirror_compute_next_data_frame);
     self->mode_func_ptr = Mirror_setProcMode;
 
     static char *kwlist[] = {"input", "min", "max", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &mintmp, &maxtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (mintmp) {
         PyObject_CallMethod((PyObject *)self, "setMin", "O", mintmp);
     }
-    
+
     if (maxtmp) {
         PyObject_CallMethod((PyObject *)self, "setMax", "O", maxtmp);
     }
-    
+
     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 * Mirror_getServer(Mirror* self) { GET_SERVER };
 static PyObject * Mirror_getStream(Mirror* self) { GET_STREAM };
-static PyObject * Mirror_setMul(Mirror *self, PyObject *arg) { SET_MUL };	
-static PyObject * Mirror_setAdd(Mirror *self, PyObject *arg) { SET_ADD };	
-static PyObject * Mirror_setSub(Mirror *self, PyObject *arg) { SET_SUB };	
-static PyObject * Mirror_setDiv(Mirror *self, PyObject *arg) { SET_DIV };	
+static PyObject * Mirror_setMul(Mirror *self, PyObject *arg) { SET_MUL };
+static PyObject * Mirror_setAdd(Mirror *self, PyObject *arg) { SET_ADD };
+static PyObject * Mirror_setSub(Mirror *self, PyObject *arg) { SET_SUB };
+static PyObject * Mirror_setDiv(Mirror *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Mirror_play(Mirror *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Mirror_out(Mirror *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1236,14 +1228,11 @@ static PyObject *
 Mirror_setMin(Mirror *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->min);
@@ -1259,25 +1248,22 @@ Mirror_setMin(Mirror *self, PyObject *arg)
         self->min_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Mirror_setMax(Mirror *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->max);
@@ -1293,12 +1279,12 @@ Mirror_setMax(Mirror *self, PyObject *arg)
         self->max_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Mirror_members[] = {
     {"server", T_OBJECT_EX, offsetof(Mirror, server), 0, "Pyo server."},
@@ -1330,7 +1316,7 @@ static PyNumberMethods Mirror_as_number = {
     (binaryfunc)Mirror_add,                      /*nb_add*/
     (binaryfunc)Mirror_sub,                 /*nb_subtract*/
     (binaryfunc)Mirror_multiply,                 /*nb_multiply*/
-    (binaryfunc)Mirror_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -1344,16 +1330,16 @@ static PyNumberMethods Mirror_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)Mirror_inplace_add,              /*inplace_add*/
     (binaryfunc)Mirror_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)Mirror_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)Mirror_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -1362,15 +1348,14 @@ static PyNumberMethods Mirror_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)Mirror_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)Mirror_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject MirrorType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Mirror_base",         /*tp_name*/
     sizeof(Mirror),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -1378,7 +1363,7 @@ PyTypeObject MirrorType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &Mirror_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -1432,7 +1417,7 @@ Wrap_transform_ii(Wrap *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT mi = PyFloat_AS_DOUBLE(self->min);
     MYFLT ma = PyFloat_AS_DOUBLE(self->max);
-    
+
     if (mi >= ma) {
         avg = (mi + ma) * 0.5;
         for (i=0; i<self->bufsize; i++) {
@@ -1453,7 +1438,7 @@ Wrap_transform_ii(Wrap *self) {
                 val = tmp * rng + mi;
                 if (val == ma)
                     val = mi;
-            }    
+            }
             self->data[i] = val;
         }
     }
@@ -1466,7 +1451,7 @@ Wrap_transform_ai(Wrap *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *mini = Stream_getData((Stream *)self->min_stream);
     MYFLT ma = PyFloat_AS_DOUBLE(self->max);
-    
+
     for (i=0; i<self->bufsize; i++) {
         val = in[i];
         mi = mini[i];
@@ -1486,8 +1471,8 @@ Wrap_transform_ai(Wrap *self) {
                 val = tmp * rng + mi;
                 if (val == ma)
                     val = mi;
-            }    
-            self->data[i] = val;            
+            }
+            self->data[i] = val;
         }
     }
 }
@@ -1499,7 +1484,7 @@ Wrap_transform_ia(Wrap *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT mi = PyFloat_AS_DOUBLE(self->min);
     MYFLT *maxi = Stream_getData((Stream *)self->max_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         val = in[i];
         ma = maxi[i];
@@ -1519,8 +1504,8 @@ Wrap_transform_ia(Wrap *self) {
                 val = tmp * rng + mi;
                 if (val == ma)
                     val = mi;
-            }    
-            self->data[i] = val;            
+            }
+            self->data[i] = val;
         }
     }
 }
@@ -1532,7 +1517,7 @@ Wrap_transform_aa(Wrap *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *mini = Stream_getData((Stream *)self->min_stream);
     MYFLT *maxi = Stream_getData((Stream *)self->max_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         val = in[i];
         mi = mini[i];
@@ -1553,8 +1538,8 @@ Wrap_transform_aa(Wrap *self) {
                 val = tmp * rng + mi;
                 if (val == ma)
                     val = mi;
-            }    
-            self->data[i] = val;            
+            }
+            self->data[i] = val;
         }
     }
 }
@@ -1575,56 +1560,56 @@ Wrap_setProcMode(Wrap *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Wrap_transform_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Wrap_transform_ai;
             break;
-        case 10:        
+        case 10:
             self->proc_func_ptr = Wrap_transform_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Wrap_transform_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Wrap_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Wrap_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Wrap_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Wrap_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Wrap_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Wrap_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Wrap_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Wrap_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Wrap_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Wrap_compute_next_data_frame(Wrap *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1633,24 +1618,24 @@ Wrap_traverse(Wrap *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->input);
-    Py_VISIT(self->input_stream);    
-    Py_VISIT(self->min);    
-    Py_VISIT(self->min_stream);    
-    Py_VISIT(self->max);    
-    Py_VISIT(self->max_stream);    
+    Py_VISIT(self->input_stream);
+    Py_VISIT(self->min);
+    Py_VISIT(self->min_stream);
+    Py_VISIT(self->max);
+    Py_VISIT(self->max_stream);
     return 0;
 }
 
-static int 
+static int
 Wrap_clear(Wrap *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->min);    
-    Py_CLEAR(self->min_stream);    
-    Py_CLEAR(self->max);    
-    Py_CLEAR(self->max_stream);    
+    Py_CLEAR(self->min);
+    Py_CLEAR(self->min_stream);
+    Py_CLEAR(self->max);
+    Py_CLEAR(self->max_stream);
     return 0;
 }
 
@@ -1659,7 +1644,7 @@ Wrap_dealloc(Wrap* self)
 {
     pyo_DEALLOC
     Wrap_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1669,54 +1654,54 @@ Wrap_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *mintmp=NULL, *maxtmp=NULL, *multmp=NULL, *addtmp=NULL;
     Wrap *self;
     self = (Wrap *)type->tp_alloc(type, 0);
-    
+
     self->min = PyFloat_FromDouble(0.0);
     self->max = PyFloat_FromDouble(1.0);
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Wrap_compute_next_data_frame);
     self->mode_func_ptr = Wrap_setProcMode;
 
     static char *kwlist[] = {"input", "min", "max", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &mintmp, &maxtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (mintmp) {
         PyObject_CallMethod((PyObject *)self, "setMin", "O", mintmp);
     }
-    
+
     if (maxtmp) {
         PyObject_CallMethod((PyObject *)self, "setMax", "O", maxtmp);
     }
-    
+
     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 * Wrap_getServer(Wrap* self) { GET_SERVER };
 static PyObject * Wrap_getStream(Wrap* self) { GET_STREAM };
-static PyObject * Wrap_setMul(Wrap *self, PyObject *arg) { SET_MUL };	
-static PyObject * Wrap_setAdd(Wrap *self, PyObject *arg) { SET_ADD };	
-static PyObject * Wrap_setSub(Wrap *self, PyObject *arg) { SET_SUB };	
-static PyObject * Wrap_setDiv(Wrap *self, PyObject *arg) { SET_DIV };	
+static PyObject * Wrap_setMul(Wrap *self, PyObject *arg) { SET_MUL };
+static PyObject * Wrap_setAdd(Wrap *self, PyObject *arg) { SET_ADD };
+static PyObject * Wrap_setSub(Wrap *self, PyObject *arg) { SET_SUB };
+static PyObject * Wrap_setDiv(Wrap *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Wrap_play(Wrap *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Wrap_out(Wrap *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1735,14 +1720,11 @@ static PyObject *
 Wrap_setMin(Wrap *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->min);
@@ -1758,25 +1740,22 @@ Wrap_setMin(Wrap *self, PyObject *arg)
         self->min_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Wrap_setMax(Wrap *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->max);
@@ -1792,12 +1771,12 @@ Wrap_setMax(Wrap *self, PyObject *arg)
         self->max_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Wrap_members[] = {
     {"server", T_OBJECT_EX, offsetof(Wrap, server), 0, "Pyo server."},
@@ -1829,7 +1808,7 @@ static PyNumberMethods Wrap_as_number = {
     (binaryfunc)Wrap_add,                      /*nb_add*/
     (binaryfunc)Wrap_sub,                 /*nb_subtract*/
     (binaryfunc)Wrap_multiply,                 /*nb_multiply*/
-    (binaryfunc)Wrap_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -1843,16 +1822,16 @@ static PyNumberMethods Wrap_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)Wrap_inplace_add,              /*inplace_add*/
     (binaryfunc)Wrap_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)Wrap_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)Wrap_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -1861,15 +1840,14 @@ static PyNumberMethods Wrap_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)Wrap_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)Wrap_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject WrapType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Wrap_base",         /*tp_name*/
     sizeof(Wrap),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -1877,7 +1855,7 @@ PyTypeObject WrapType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &Wrap_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -1926,7 +1904,7 @@ typedef struct {
     int modebuffer[4];
 } Degrade;
 
-static MYFLT 
+static MYFLT
 _bit_clip(MYFLT x) {
     if (x < 1.0)
         return 1.0;
@@ -1936,7 +1914,7 @@ _bit_clip(MYFLT x) {
         return x;
 }
 
-static MYFLT 
+static MYFLT
 _sr_clip(MYFLT x) {
     // half sr ten times
     if (x <= 0.0009765625)
@@ -1951,23 +1929,23 @@ static void
 Degrade_transform_ii(Degrade *self) {
     MYFLT bitscl, ibitscl, newsr;
     int i, nsamps, tmp;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT bitdepth = _bit_clip(PyFloat_AS_DOUBLE(self->bitdepth));
     MYFLT srscale = _sr_clip(PyFloat_AS_DOUBLE(self->srscale));
-    
+
     bitscl = MYPOW(2.0, bitdepth-1);
     ibitscl = 1.0 / bitscl;
-    
+
     newsr = self->sr * srscale;
     nsamps = (int)(self->sr / newsr);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->sampsCount++;
         if (self->sampsCount >= nsamps) {
             self->sampsCount = 0;
             tmp = (int)(in[i] * bitscl + 0.5);
-            self->value = tmp * ibitscl;    
+            self->value = tmp * ibitscl;
         }
         self->data[i] = self->value;
     }
@@ -1977,14 +1955,14 @@ static void
 Degrade_transform_ai(Degrade *self) {
     MYFLT bitscl, ibitscl, newsr;
     int i, nsamps, tmp;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *bitdepth = Stream_getData((Stream *)self->bitdepth_stream);
     MYFLT srscale = _sr_clip(PyFloat_AS_DOUBLE(self->srscale));
 
     newsr = self->sr * srscale;
     nsamps = (int)(self->sr / newsr);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->sampsCount++;
         if (self->sampsCount >= nsamps) {
@@ -1992,7 +1970,7 @@ Degrade_transform_ai(Degrade *self) {
             bitscl = MYPOW(2.0, _bit_clip(bitdepth[i])-1);
             ibitscl = 1.0 / bitscl;
             tmp = (int)(in[i] * bitscl + 0.5);
-            self->value = tmp * ibitscl;    
+            self->value = tmp * ibitscl;
         }
         self->data[i] = self->value;
     }
@@ -2002,11 +1980,11 @@ static void
 Degrade_transform_ia(Degrade *self) {
     MYFLT bitscl, ibitscl, newsr;
     int i, nsamps, tmp;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT bitdepth = _bit_clip(PyFloat_AS_DOUBLE(self->bitdepth));
     MYFLT *srscale = Stream_getData((Stream *)self->srscale_stream);
-    
+
     bitscl = MYPOW(2.0, bitdepth-1);
     ibitscl = 1.0 / bitscl;
 
@@ -2017,7 +1995,7 @@ Degrade_transform_ia(Degrade *self) {
         if (self->sampsCount >= nsamps) {
             self->sampsCount = 0;
             tmp = (int)(in[i] * bitscl + 0.5);
-            self->value = tmp * ibitscl;    
+            self->value = tmp * ibitscl;
         }
         self->data[i] = self->value;
     }
@@ -2027,7 +2005,7 @@ static void
 Degrade_transform_aa(Degrade *self) {
     MYFLT bitscl, ibitscl, newsr;
     int i, nsamps, tmp;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *bitdepth = Stream_getData((Stream *)self->bitdepth_stream);
     MYFLT *srscale = Stream_getData((Stream *)self->srscale_stream);
@@ -2041,7 +2019,7 @@ Degrade_transform_aa(Degrade *self) {
             bitscl = MYPOW(2.0, _bit_clip(bitdepth[i])-1);
             ibitscl = 1.0 / bitscl;
             tmp = (int)(in[i] * bitscl + 0.5);
-            self->value = tmp * ibitscl;    
+            self->value = tmp * ibitscl;
         }
         self->data[i] = self->value;
     }
@@ -2063,56 +2041,56 @@ Degrade_setProcMode(Degrade *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Degrade_transform_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Degrade_transform_ai;
             break;
-        case 10:        
+        case 10:
             self->proc_func_ptr = Degrade_transform_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Degrade_transform_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Degrade_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Degrade_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Degrade_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Degrade_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Degrade_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Degrade_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Degrade_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Degrade_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Degrade_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Degrade_compute_next_data_frame(Degrade *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -2121,24 +2099,24 @@ Degrade_traverse(Degrade *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->input);
-    Py_VISIT(self->input_stream);    
-    Py_VISIT(self->bitdepth);    
-    Py_VISIT(self->bitdepth_stream);    
-    Py_VISIT(self->srscale);    
-    Py_VISIT(self->srscale_stream);    
+    Py_VISIT(self->input_stream);
+    Py_VISIT(self->bitdepth);
+    Py_VISIT(self->bitdepth_stream);
+    Py_VISIT(self->srscale);
+    Py_VISIT(self->srscale_stream);
     return 0;
 }
 
-static int 
+static int
 Degrade_clear(Degrade *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->bitdepth);    
-    Py_CLEAR(self->bitdepth_stream);    
-    Py_CLEAR(self->srscale);    
-    Py_CLEAR(self->srscale_stream);    
+    Py_CLEAR(self->bitdepth);
+    Py_CLEAR(self->bitdepth_stream);
+    Py_CLEAR(self->srscale);
+    Py_CLEAR(self->srscale_stream);
     return 0;
 }
 
@@ -2147,7 +2125,7 @@ Degrade_dealloc(Degrade* self)
 {
     pyo_DEALLOC
     Degrade_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2157,7 +2135,7 @@ Degrade_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *bitdepthtmp=NULL, *srscaletmp=NULL, *multmp=NULL, *addtmp=NULL;
     Degrade *self;
     self = (Degrade *)type->tp_alloc(type, 0);
-    
+
     self->bitdepth = PyFloat_FromDouble(16);
     self->srscale = PyFloat_FromDouble(1.0);
     self->value = 0.0;
@@ -2166,47 +2144,47 @@ Degrade_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Degrade_compute_next_data_frame);
     self->mode_func_ptr = Degrade_setProcMode;
 
     static char *kwlist[] = {"input", "bitdepth", "srscale", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &bitdepthtmp, &srscaletmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (bitdepthtmp) {
         PyObject_CallMethod((PyObject *)self, "setBitdepth", "O", bitdepthtmp);
     }
-    
+
     if (srscaletmp) {
         PyObject_CallMethod((PyObject *)self, "setSrscale", "O", srscaletmp);
     }
-    
+
     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 * Degrade_getServer(Degrade* self) { GET_SERVER };
 static PyObject * Degrade_getStream(Degrade* self) { GET_STREAM };
-static PyObject * Degrade_setMul(Degrade *self, PyObject *arg) { SET_MUL };	
-static PyObject * Degrade_setAdd(Degrade *self, PyObject *arg) { SET_ADD };	
-static PyObject * Degrade_setSub(Degrade *self, PyObject *arg) { SET_SUB };	
-static PyObject * Degrade_setDiv(Degrade *self, PyObject *arg) { SET_DIV };	
+static PyObject * Degrade_setMul(Degrade *self, PyObject *arg) { SET_MUL };
+static PyObject * Degrade_setAdd(Degrade *self, PyObject *arg) { SET_ADD };
+static PyObject * Degrade_setSub(Degrade *self, PyObject *arg) { SET_SUB };
+static PyObject * Degrade_setDiv(Degrade *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Degrade_play(Degrade *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Degrade_out(Degrade *self, PyObject *args, PyObject *kwds) { OUT };
@@ -2225,14 +2203,11 @@ static PyObject *
 Degrade_setBitdepth(Degrade *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->bitdepth);
@@ -2248,25 +2223,22 @@ Degrade_setBitdepth(Degrade *self, PyObject *arg)
         self->bitdepth_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Degrade_setSrscale(Degrade *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->srscale);
@@ -2282,12 +2254,12 @@ Degrade_setSrscale(Degrade *self, PyObject *arg)
         self->srscale_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Degrade_members[] = {
 {"server", T_OBJECT_EX, offsetof(Degrade, server), 0, "Pyo server."},
@@ -2319,7 +2291,7 @@ static PyNumberMethods Degrade_as_number = {
 (binaryfunc)Degrade_add,                      /*nb_add*/
 (binaryfunc)Degrade_sub,                 /*nb_subtract*/
 (binaryfunc)Degrade_multiply,                 /*nb_multiply*/
-(binaryfunc)Degrade_div,                   /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -2333,16 +2305,16 @@ static PyNumberMethods Degrade_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
 (binaryfunc)Degrade_inplace_add,              /*inplace_add*/
 (binaryfunc)Degrade_inplace_sub,         /*inplace_subtract*/
 (binaryfunc)Degrade_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)Degrade_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -2351,15 +2323,14 @@ static PyNumberMethods Degrade_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)Degrade_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)Degrade_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
 PyTypeObject DegradeType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Degrade_base",         /*tp_name*/
 sizeof(Degrade),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -2367,7 +2338,7 @@ sizeof(Degrade),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &Degrade_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -2408,7 +2379,7 @@ typedef struct {
     Stream *input_stream;
     PyObject *comp;
     Stream *comp_stream;
-    int modebuffer[3]; // need at least 2 slots for mul & add 
+    int modebuffer[3]; // need at least 2 slots for mul & add
 } Min;
 
 static void
@@ -2427,7 +2398,7 @@ Min_process_a(Min *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *cp = Stream_getData((Stream *)self->comp_stream);
-        
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = in[i] < cp[i] ? in[i] : cp[i];
     }
@@ -2449,50 +2420,50 @@ Min_setProcMode(Min *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2];
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Min_process_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Min_process_a;
             break;
-    } 
+    }
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Min_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Min_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Min_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Min_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Min_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Min_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Min_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Min_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Min_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Min_compute_next_data_frame(Min *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -2502,19 +2473,19 @@ Min_traverse(Min *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->comp);    
-    Py_VISIT(self->comp_stream);    
+    Py_VISIT(self->comp);
+    Py_VISIT(self->comp_stream);
     return 0;
 }
 
-static int 
+static int
 Min_clear(Min *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->comp);    
-    Py_CLEAR(self->comp_stream);    
+    Py_CLEAR(self->comp);
+    Py_CLEAR(self->comp_stream);
     return 0;
 }
 
@@ -2523,7 +2494,7 @@ Min_dealloc(Min* self)
 {
     pyo_DEALLOC
     Min_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2533,38 +2504,38 @@ Min_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *comptmp=NULL, *multmp=NULL, *addtmp=NULL;
     Min *self;
     self = (Min *)type->tp_alloc(type, 0);
-    
+
     self->comp = PyFloat_FromDouble(0.5);
     self->modebuffer[0] = 0;
     self->modebuffer[1] = 0;
     self->modebuffer[2] = 0;
-    
+
     INIT_OBJECT_COMMON
 
     Stream_setFunctionPtr(self->stream, Min_compute_next_data_frame);
     self->mode_func_ptr = Min_setProcMode;
 
     static char *kwlist[] = {"input", "comp", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &comptmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (comptmp) {
         PyObject_CallMethod((PyObject *)self, "setComp", "O", comptmp);
     }
-    
+
     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;
@@ -2572,10 +2543,10 @@ Min_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Min_getServer(Min* self) { GET_SERVER };
 static PyObject * Min_getStream(Min* self) { GET_STREAM };
-static PyObject * Min_setMul(Min *self, PyObject *arg) { SET_MUL };    
-static PyObject * Min_setAdd(Min *self, PyObject *arg) { SET_ADD };    
-static PyObject * Min_setSub(Min *self, PyObject *arg) { SET_SUB };    
-static PyObject * Min_setDiv(Min *self, PyObject *arg) { SET_DIV };    
+static PyObject * Min_setMul(Min *self, PyObject *arg) { SET_MUL };
+static PyObject * Min_setAdd(Min *self, PyObject *arg) { SET_ADD };
+static PyObject * Min_setSub(Min *self, PyObject *arg) { SET_SUB };
+static PyObject * Min_setDiv(Min *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Min_play(Min *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Min_out(Min *self, PyObject *args, PyObject *kwds) { OUT };
@@ -2594,14 +2565,11 @@ static PyObject *
 Min_setComp(Min *self, PyObject *arg)
 {
     PyObject *tmp, *streamtmp;
-    
-    if (arg == NULL) {
-        Py_INCREF(Py_None);
-        return Py_None;
-    }
-    
+
+    ASSERT_ARG_NOT_NULL
+
     int isNumber = PyNumber_Check(arg);
-    
+
     tmp = arg;
     Py_INCREF(tmp);
     Py_DECREF(self->comp);
@@ -2617,9 +2585,9 @@ Min_setComp(Min *self, PyObject *arg)
         self->comp_stream = (Stream *)streamtmp;
         self->modebuffer[2] = 1;
     }
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -2652,7 +2620,7 @@ static PyNumberMethods Min_as_number = {
 (binaryfunc)Min_add,                         /*nb_add*/
 (binaryfunc)Min_sub,                         /*nb_subtract*/
 (binaryfunc)Min_multiply,                    /*nb_multiply*/
-(binaryfunc)Min_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -2666,16 +2634,16 @@ static PyNumberMethods Min_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)Min_inplace_add,                 /*inplace_add*/
 (binaryfunc)Min_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)Min_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)Min_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -2684,15 +2652,14 @@ static PyNumberMethods Min_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)Min_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)Min_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject MinType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Min_base",                                   /*tp_name*/
 sizeof(Min),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -2700,7 +2667,7 @@ sizeof(Min),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &Min_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -2741,7 +2708,7 @@ typedef struct {
     Stream *input_stream;
     PyObject *comp;
     Stream *comp_stream;
-    int modebuffer[3]; // need at least 2 slots for mul & add 
+    int modebuffer[3]; // need at least 2 slots for mul & add
 } Max;
 
 static void
@@ -2760,7 +2727,7 @@ Max_process_a(Max *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *cp = Stream_getData((Stream *)self->comp_stream);
-        
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = in[i] > cp[i] ? in[i] : cp[i];
     }
@@ -2782,50 +2749,50 @@ Max_setProcMode(Max *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2];
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Max_process_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Max_process_a;
             break;
-    } 
+    }
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Max_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Max_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Max_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Max_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Max_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Max_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Max_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Max_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Max_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Max_compute_next_data_frame(Max *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -2835,19 +2802,19 @@ Max_traverse(Max *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->comp);    
-    Py_VISIT(self->comp_stream);    
+    Py_VISIT(self->comp);
+    Py_VISIT(self->comp_stream);
     return 0;
 }
 
-static int 
+static int
 Max_clear(Max *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->comp);    
-    Py_CLEAR(self->comp_stream);    
+    Py_CLEAR(self->comp);
+    Py_CLEAR(self->comp_stream);
     return 0;
 }
 
@@ -2856,7 +2823,7 @@ Max_dealloc(Max* self)
 {
     pyo_DEALLOC
     Max_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2866,38 +2833,38 @@ Max_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *comptmp=NULL, *multmp=NULL, *addtmp=NULL;
     Max *self;
     self = (Max *)type->tp_alloc(type, 0);
-    
+
     self->comp = PyFloat_FromDouble(0.5);
     self->modebuffer[0] = 0;
     self->modebuffer[1] = 0;
     self->modebuffer[2] = 0;
-    
+
     INIT_OBJECT_COMMON
 
     Stream_setFunctionPtr(self->stream, Max_compute_next_data_frame);
     self->mode_func_ptr = Max_setProcMode;
 
     static char *kwlist[] = {"input", "comp", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &comptmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (comptmp) {
         PyObject_CallMethod((PyObject *)self, "setComp", "O", comptmp);
     }
-    
+
     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;
@@ -2905,10 +2872,10 @@ Max_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Max_getServer(Max* self) { GET_SERVER };
 static PyObject * Max_getStream(Max* self) { GET_STREAM };
-static PyObject * Max_setMul(Max *self, PyObject *arg) { SET_MUL };    
-static PyObject * Max_setAdd(Max *self, PyObject *arg) { SET_ADD };    
-static PyObject * Max_setSub(Max *self, PyObject *arg) { SET_SUB };    
-static PyObject * Max_setDiv(Max *self, PyObject *arg) { SET_DIV };    
+static PyObject * Max_setMul(Max *self, PyObject *arg) { SET_MUL };
+static PyObject * Max_setAdd(Max *self, PyObject *arg) { SET_ADD };
+static PyObject * Max_setSub(Max *self, PyObject *arg) { SET_SUB };
+static PyObject * Max_setDiv(Max *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Max_play(Max *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Max_out(Max *self, PyObject *args, PyObject *kwds) { OUT };
@@ -2927,14 +2894,11 @@ static PyObject *
 Max_setComp(Max *self, PyObject *arg)
 {
     PyObject *tmp, *streamtmp;
-    
-    if (arg == NULL) {
-        Py_INCREF(Py_None);
-        return Py_None;
-    }
-    
+
+    ASSERT_ARG_NOT_NULL
+
     int isNumber = PyNumber_Check(arg);
-    
+
     tmp = arg;
     Py_INCREF(tmp);
     Py_DECREF(self->comp);
@@ -2950,9 +2914,9 @@ Max_setComp(Max *self, PyObject *arg)
         self->comp_stream = (Stream *)streamtmp;
         self->modebuffer[2] = 1;
     }
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -2985,7 +2949,7 @@ static PyNumberMethods Max_as_number = {
 (binaryfunc)Max_add,                         /*nb_add*/
 (binaryfunc)Max_sub,                         /*nb_subtract*/
 (binaryfunc)Max_multiply,                    /*nb_multiply*/
-(binaryfunc)Max_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -2999,16 +2963,16 @@ static PyNumberMethods Max_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)Max_inplace_add,                 /*inplace_add*/
 (binaryfunc)Max_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)Max_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)Max_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -3017,15 +2981,14 @@ static PyNumberMethods Max_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)Max_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)Max_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject MaxType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Max_base",                                   /*tp_name*/
 sizeof(Max),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -3033,7 +2996,7 @@ sizeof(Max),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &Max_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -3063,4 +3026,4 @@ Max_members,                                 /* tp_members */
 0,                          /* tp_init */
 0,                                              /* tp_alloc */
 Max_new,                                     /* tp_new */
-};
+};
\ No newline at end of file
diff --git a/src/objects/exprmodule.c b/src/objects/exprmodule.c
new file mode 100644
index 0000000..5d5a7ff
--- /dev/null
+++ b/src/objects/exprmodule.c
@@ -0,0 +1,861 @@
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
+ * This file is part of pyo, a python module to help digital signal       *
+ * processing script creation.                                            *
+ *                                                                        *
+ * pyo is free software: you can redistribute it and/or modify            *
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
+ *                                                                        *
+ * pyo is distributed in the hope that it will be useful,                 *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ * GNU 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/>.   *
+ *************************************************************************/
+
+#include <Python.h>
+#include "py2to3.h"
+#include "structmember.h"
+#include <math.h>
+#include "pyomodule.h"
+#include "streammodule.h"
+#include "servermodule.h"
+#include "dummymodule.h"
+
+// arithmetic operators
+#define OP_ADD 0
+#define OP_SUB 1
+#define OP_MUL 2
+#define OP_DIV 3
+#define OP_EXP 4
+#define OP_MOD 5
+#define OP_NEG 6
+
+// moving phase operators
+#define OP_INC 7
+#define OP_DEC 8
+#define OP_PHS 9
+
+// trigonometric functions
+#define OP_SIN 10
+#define OP_COS 11
+#define OP_TAN 12
+#define OP_TANH 13
+#define OP_ATAN 14
+#define OP_ATAN2 15
+
+// conditional operators
+#define OP_LT 40
+#define OP_LE 41
+#define OP_GT 42
+#define OP_GE 43
+#define OP_EQ 44
+#define OP_NE 45
+#define OP_IF 46
+#define OP_AND 47
+#define OP_OR 48
+
+// power and logarithmic functions
+#define OP_SQRT 50
+#define OP_LOG 51
+#define OP_LOG2 52
+#define OP_LOG10 53
+#define OP_POW 54
+#define OP_FABS 55
+#define OP_FLOOR 56
+#define OP_CEIL 57
+#define OP_EEXP 58
+#define OP_ROUND 59
+#define OP_MIN 60
+#define OP_MAX 61
+#define OP_WRAP 62
+
+// filters
+#define OP_RPOLE 70
+#define OP_RZERO 71
+
+// random functions
+#define OP_RANDF 80
+#define OP_RANDI 81
+
+// sample-and-hold functions
+#define OP_SAH 90
+
+// math constants
+#define OP_CONST 99
+#define OP_PI 100
+#define OP_TWOPI 101
+#define OP_E 102
+
+typedef struct t_expr {
+    int type_op;
+    int num;
+    int *nodes;
+    int *vars;
+    int *input;
+    int *output;
+    MYFLT *values;
+    MYFLT *previous;
+    MYFLT result;
+} expr;
+
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *input;
+    Stream *input_stream;
+    PyObject *variables;
+    int count;
+    MYFLT oneOverSr;
+    MYFLT *input_buffer;
+    MYFLT *output_buffer;
+    expr lexp[1024];
+    int modebuffer[2];
+} Expr;
+
+void 
+clearexpr(expr ex)
+{
+    if (ex.nodes) { free(ex.nodes); }
+    if (ex.vars) { free(ex.vars); }
+    if (ex.input) { free(ex.input); }
+    if (ex.output) { free(ex.output); }
+    if (ex.values) { free(ex.values); }
+    if (ex.previous) { free(ex.previous); }
+}
+
+expr
+initexpr(const char *op, int size)
+{
+    expr ex;
+    int i, value = -1, num = 0;
+    if      (strcmp(op, "+") == 0) { value = OP_ADD; num = 2; }
+    else if (strcmp(op, "-") == 0) { value = OP_SUB; num = 2; }
+    else if (strcmp(op, "*") == 0) {value = OP_MUL; num = 2; }
+    else if (strcmp(op, "/") == 0) {value = OP_DIV; num = 2; }
+    else if (strcmp(op, "^") == 0) {value = OP_EXP; num = 2; }
+    else if (strcmp(op, "%") == 0) {value = OP_MOD; num = 2; }
+    else if (strcmp(op, "neg") == 0) {value = OP_NEG; num = 1; }
+    else if (strcmp(op, "++") == 0) {value = OP_INC; num = 2; }
+    else if (strcmp(op, "--") == 0) {value = OP_DEC; num = 2; }
+    else if (strcmp(op, "~") == 0) {value = OP_PHS; num = 2; }
+    else if (strcmp(op, "sin") == 0) {value = OP_SIN; num = 1; }
+    else if (strcmp(op, "cos") == 0) {value = OP_COS; num = 1; }
+    else if (strcmp(op, "tan") == 0) {value = OP_TAN; num = 1; }
+    else if (strcmp(op, "tanh") == 0) {value = OP_TANH; num = 1; }
+    else if (strcmp(op, "atan") == 0) {value = OP_ATAN; num = 1; }
+    else if (strcmp(op, "atan2") == 0) {value = OP_ATAN2; num = 2; }
+    else if (strcmp(op, "<") == 0) {value = OP_LT; num = 2; }
+    else if (strcmp(op, "<=") == 0) {value = OP_LE; num = 2; }
+    else if (strcmp(op, ">") == 0) {value = OP_GT; num = 2; }
+    else if (strcmp(op, ">=") == 0) {value = OP_GE; num = 2; }
+    else if (strcmp(op, "==") == 0) {value = OP_EQ; num = 2; }
+    else if (strcmp(op, "!=") == 0) {value = OP_NE; num = 2; }
+    else if (strcmp(op, "if") == 0) {value = OP_IF; num = 3; }
+    else if (strcmp(op, "and") == 0) {value = OP_AND; num = 2; }
+    else if (strcmp(op, "or") == 0) {value = OP_OR; num = 2; }
+    else if (strcmp(op, "sqrt") == 0) {value = OP_SQRT; num = 1; }
+    else if (strcmp(op, "log") == 0) {value = OP_LOG; num = 1; }
+    else if (strcmp(op, "log2") == 0) {value = OP_LOG2; num = 1; }
+    else if (strcmp(op, "log10") == 0) {value = OP_LOG10; num = 1; }
+    else if (strcmp(op, "pow") == 0) {value = OP_POW; num = 2; }
+    else if (strcmp(op, "abs") == 0) {value = OP_FABS; num = 1; }
+    else if (strcmp(op, "floor") == 0) {value = OP_FLOOR; num = 1; }
+    else if (strcmp(op, "ceil") == 0) {value = OP_CEIL; num = 1; }
+    else if (strcmp(op, "exp") == 0) {value = OP_EEXP; num = 1; }
+    else if (strcmp(op, "round") == 0) {value = OP_ROUND; num = 1; }
+    else if (strcmp(op, "min") == 0) {value = OP_MIN; num = 2; }
+    else if (strcmp(op, "max") == 0) {value = OP_MAX; num = 2; }
+    else if (strcmp(op, "wrap") == 0) {value = OP_WRAP; num = 1; }
+    else if (strcmp(op, "randf") == 0) {value = OP_RANDF; num = 2; }
+    else if (strcmp(op, "randi") == 0) {value = OP_RANDI; num = 2; }
+    else if (strcmp(op, "sah") == 0) {value = OP_SAH; num = 2; } // stream, trigger
+    else if (strcmp(op, "rpole") == 0) {value = OP_RPOLE; num = 2; }
+    else if (strcmp(op, "rzero") == 0) {value = OP_RZERO; num = 2; }
+    else if (strcmp(op, "const") == 0) {value = OP_CONST; num = 1; }
+    else if (strcmp(op, "pi") == 0) {value = OP_PI; num = 0; }
+    else if (strcmp(op, "twopi") == 0) {value = OP_TWOPI; num = 0; }
+    else if (strcmp(op, "e") == 0) {value = OP_E; num = 0; }
+    else if (size == 1) {value = OP_CONST; num = 1; }
+    ex.type_op = value;
+    ex.num = num;
+    ex.nodes = (int *)malloc(num);
+    ex.vars = (int *)malloc(num);
+    ex.input = (int *)malloc(num);
+    ex.output = (int *)malloc(num);
+    ex.values = (MYFLT *)malloc(num);
+    ex.previous = (MYFLT *)malloc(num);
+    for (i=0; i<num; i++) {
+        ex.nodes[i] = ex.vars[i] = -1;
+        ex.input[i] = ex.output[i] = 1;
+        ex.values[i] = ex.previous[i] = 0.0;
+    }
+    ex.result = 0.0;
+    return ex;
+}
+
+void
+print_expr(expr ex, int node)
+{
+    int i;
+    PySys_WriteStdout("=== Node # %d ===\n", node);
+    PySys_WriteStdout("Operator: %d\nNodes: ", ex.type_op);
+    for (i=0; i<ex.num; i++) { PySys_WriteStdout("%d, ", ex.nodes[i]); }
+    PySys_WriteStdout("\nVars: ");
+    for (i=0; i<ex.num; i++) { PySys_WriteStdout("%d, ", ex.vars[i]); }
+    PySys_WriteStdout("\nInputs: ");
+    for (i=0; i<ex.num; i++) { PySys_WriteStdout("%d, ", ex.input[i]); }
+    PySys_WriteStdout("\nOutputs: ");
+    for (i=0; i<ex.num; i++) { PySys_WriteStdout("%d, ", ex.output[i]); }
+    PySys_WriteStdout("\nValues: ");
+    for (i=0; i<ex.num; i++) { PySys_WriteStdout("%f, ", ex.values[i]); }
+    PySys_WriteStdout("\n\n");
+}
+
+static void
+Expr_process(Expr *self) {
+    int i, j, k, pos = 0;
+    MYFLT tmp = 0.0, result = 0.0;
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+
+    if (self->count == 0) {
+        for (i=0; i<self->bufsize; i++) {
+            self->data[i] = in[i];
+        }
+    }
+    else {
+        for (i=0; i<self->bufsize; i++) {
+            self->input_buffer[i] = in[i];
+            for (j=0; j<self->count; j++) {
+                for (k=0; k<self->lexp[j].num; k++) {
+                    if (self->lexp[j].nodes[k] != -1) {
+                        self->lexp[j].values[k] = self->lexp[self->lexp[j].nodes[k]].result;
+                    }
+                    else if (self->lexp[j].vars[k] != -1) {
+                        self->lexp[j].values[k] = self->lexp[self->lexp[j].vars[k]].result;
+                    }
+                    else if (self->lexp[j].input[k] < 1) {
+                        pos = i + self->lexp[j].input[k];
+                        if (pos < 0)
+                            pos += self->bufsize;
+                        self->lexp[j].values[k] = self->input_buffer[pos];
+                    }
+                    else if (self->lexp[j].output[k] < 0) {
+                        pos = i + self->lexp[j].output[k];
+                        if (pos < 0)
+                            pos += self->bufsize;
+                        self->lexp[j].values[k] = self->output_buffer[pos];
+                    }
+                }
+                switch (self->lexp[j].type_op) {
+                    case OP_ADD:
+                        self->lexp[j].result = self->lexp[j].values[0] + self->lexp[j].values[1];
+                        break;
+                    case OP_SUB:
+                        self->lexp[j].result = self->lexp[j].values[0] - self->lexp[j].values[1];
+                        break;
+                    case OP_MUL:
+                        self->lexp[j].result = self->lexp[j].values[0] * self->lexp[j].values[1];
+                        break;
+                    case OP_DIV:
+                        self->lexp[j].result = self->lexp[j].values[0] / self->lexp[j].values[1];
+                        break;
+                    case OP_EXP:
+                        self->lexp[j].result = MYPOW(self->lexp[j].values[0], self->lexp[j].values[1]);
+                        break;
+                    case OP_MOD:
+                        self->lexp[j].result = MYFMOD(self->lexp[j].values[0], self->lexp[j].values[1]);
+                        break;
+                    case OP_NEG:
+                        self->lexp[j].result = -self->lexp[j].values[0];
+                        break;
+                    case OP_INC:
+                        self->lexp[j].result = self->lexp[j].previous[0];
+                        self->lexp[j].previous[0] = MYFMOD(self->lexp[j].previous[0] + self->lexp[j].values[0], self->lexp[j].values[1]);
+                        break;
+                    case OP_DEC:
+                        self->lexp[j].result -= self->lexp[j].values[0];
+                        if (self->lexp[j].result < 0) { self->lexp[j].result += self->lexp[j].values[1]; }
+                        break;
+                    case OP_PHS:
+                        tmp = self->lexp[j].previous[0] + self->lexp[j].values[1];
+                        if (tmp >= 1) { tmp -= 1.0; }
+                        self->lexp[j].result = tmp;
+                        self->lexp[j].previous[0] += (self->lexp[j].values[0] * self->oneOverSr);
+                        if (self->lexp[j].previous[0] >= 1) { self->lexp[j].previous[0] -= 1.0; }
+                        break;
+                    case OP_SIN:
+                        self->lexp[j].result = MYSIN(self->lexp[j].values[0]);
+                        break;
+                    case OP_COS:
+                        self->lexp[j].result = MYCOS(self->lexp[j].values[0]);
+                        break;
+                    case OP_TAN:
+                        self->lexp[j].result = MYTAN(self->lexp[j].values[0]);
+                        break;
+                    case OP_TANH:
+                        self->lexp[j].result = MYTANH(self->lexp[j].values[0]);
+                        break;
+                    case OP_ATAN:
+                        self->lexp[j].result = MYATAN(self->lexp[j].values[0]);
+                        break;
+                    case OP_ATAN2:
+                        self->lexp[j].result = MYATAN2(self->lexp[j].values[0], self->lexp[j].values[1]);
+                        break;
+                    case OP_LT:
+                        self->lexp[j].result = self->lexp[j].values[0] < self->lexp[j].values[1] ? 1.0 : 0.0;
+                        break;
+                    case OP_LE:
+                        self->lexp[j].result = self->lexp[j].values[0] <= self->lexp[j].values[1] ? 1.0 : 0.0;
+                        break;
+                    case OP_GT:
+                        self->lexp[j].result = self->lexp[j].values[0] > self->lexp[j].values[1] ? 1.0 : 0.0;
+                        break;
+                    case OP_GE:
+                        self->lexp[j].result = self->lexp[j].values[0] >= self->lexp[j].values[1] ? 1.0 : 0.0;
+                        break;
+                    case OP_EQ:
+                        self->lexp[j].result = self->lexp[j].values[0] == self->lexp[j].values[1] ? 1.0 : 0.0;
+                        break;
+                    case OP_NE:
+                        self->lexp[j].result = self->lexp[j].values[0] != self->lexp[j].values[1] ? 1.0 : 0.0;
+                        break;
+                    case OP_IF:
+                        self->lexp[j].result = self->lexp[j].values[0] != 0 ? self->lexp[j].values[1] : self->lexp[j].values[2];
+                        break;
+                    case OP_AND:
+                        self->lexp[j].result = self->lexp[j].values[0] != 0 && self->lexp[j].values[1] != 0 ? 1.0 : 0.0;
+                        break;
+                    case OP_OR:
+                        self->lexp[j].result = self->lexp[j].values[0] != 0 || self->lexp[j].values[1] != 0 ? 1.0 : 0.0;
+                        break;
+                    case OP_SQRT:
+                        self->lexp[j].result = MYSQRT(self->lexp[j].values[0]);
+                        break;
+                    case OP_LOG:
+                        self->lexp[j].result = MYLOG(self->lexp[j].values[0]);
+                        break;
+                    case OP_LOG2:
+                        self->lexp[j].result = MYLOG2(self->lexp[j].values[0]);
+                        break;
+                    case OP_LOG10:
+                        self->lexp[j].result = MYLOG10(self->lexp[j].values[0]);
+                        break;
+                    case OP_POW:
+                        self->lexp[j].result = MYPOW(self->lexp[j].values[0], self->lexp[j].values[1]);
+                        break;
+                    case OP_FABS:
+                        self->lexp[j].result = MYFABS(self->lexp[j].values[0]);
+                        break;
+                    case OP_FLOOR:
+                        self->lexp[j].result = MYFLOOR(self->lexp[j].values[0]);
+                        break;
+                    case OP_CEIL:
+                        self->lexp[j].result = MYCEIL(self->lexp[j].values[0]);
+                        break;
+                    case OP_EEXP:
+                        self->lexp[j].result = MYEXP(self->lexp[j].values[0]);
+                        break;
+                    case OP_ROUND:
+                        self->lexp[j].result = MYROUND(self->lexp[j].values[0]);
+                        break;
+                    case OP_MIN:
+                        self->lexp[j].result = self->lexp[j].values[0] < self->lexp[j].values[1] ? self->lexp[j].values[0] : self->lexp[j].values[1];
+                        break;
+                    case OP_MAX:
+                        self->lexp[j].result = self->lexp[j].values[0] > self->lexp[j].values[1] ? self->lexp[j].values[0] : self->lexp[j].values[1];
+                        break;
+                    case OP_WRAP:
+                        tmp = self->lexp[j].values[0];
+                        while (tmp < 0.0) {tmp += 1.0; }
+                        while (tmp >= 1.0) {tmp -= 1.0; }
+                        self->lexp[j].result = tmp;
+                        break;
+                    case OP_RANDF:
+                        self->lexp[j].result = RANDOM_UNIFORM * (self->lexp[j].values[1] - self->lexp[j].values[0]) + self->lexp[j].values[0];
+                        break;
+                    case OP_RANDI:
+                        self->lexp[j].result = MYFLOOR(RANDOM_UNIFORM * (self->lexp[j].values[1] - self->lexp[j].values[0]) + self->lexp[j].values[0]);
+                        break;
+                    case OP_SAH:
+                        self->lexp[j].result = self->lexp[j].values[1] < self->lexp[j].previous[1] ? self->lexp[j].values[0] : self->lexp[j].result;
+                        self->lexp[j].previous[1] = self->lexp[j].values[1];
+                        break;
+                    case OP_RPOLE:
+                        self->lexp[j].result = self->lexp[j].values[0] + self->lexp[j].result * self->lexp[j].values[1];
+                        break;
+                    case OP_RZERO:
+                        self->lexp[j].result = self->lexp[j].values[0] - self->lexp[j].previous[0] * self->lexp[j].values[1];
+                        self->lexp[j].previous[0] = self->lexp[j].values[0];
+                        break;
+                    case OP_CONST:
+                        self->lexp[j].result = self->lexp[j].values[0];
+                        break;
+                    case OP_PI:
+                        self->lexp[j].result = PI;
+                        break;
+                    case OP_TWOPI:
+                        self->lexp[j].result = TWOPI;
+                        break;
+                    case OP_E:
+                        self->lexp[j].result = E;
+                        break;
+                }
+                result = self->lexp[j].result;
+            }
+            self->data[i] = self->output_buffer[i] = result;
+        }
+    }
+}
+
+static void Expr_postprocessing_ii(Expr *self) { POST_PROCESSING_II };
+static void Expr_postprocessing_ai(Expr *self) { POST_PROCESSING_AI };
+static void Expr_postprocessing_ia(Expr *self) { POST_PROCESSING_IA };
+static void Expr_postprocessing_aa(Expr *self) { POST_PROCESSING_AA };
+static void Expr_postprocessing_ireva(Expr *self) { POST_PROCESSING_IREVA };
+static void Expr_postprocessing_areva(Expr *self) { POST_PROCESSING_AREVA };
+static void Expr_postprocessing_revai(Expr *self) { POST_PROCESSING_REVAI };
+static void Expr_postprocessing_revaa(Expr *self) { POST_PROCESSING_REVAA };
+static void Expr_postprocessing_revareva(Expr *self) { POST_PROCESSING_REVAREVA };
+
+static void
+Expr_setProcMode(Expr *self)
+{
+    int muladdmode;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+    self->proc_func_ptr = Expr_process;
+
+	switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = Expr_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = Expr_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = Expr_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = Expr_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = Expr_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = Expr_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = Expr_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = Expr_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = Expr_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+Expr_compute_next_data_frame(Expr *self)
+{
+    (*self->proc_func_ptr)(self);
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+Expr_traverse(Expr *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->input);
+    Py_VISIT(self->input_stream);
+    Py_VISIT(self->variables);
+    return 0;
+}
+
+static int
+Expr_clear(Expr *self)
+{
+    int i;
+    pyo_CLEAR
+    for (i=0; i<self->count; i++) { 
+        clearexpr(self->lexp[i]); 
+    }
+    free(self->input_buffer);
+    free(self->output_buffer);
+    Py_CLEAR(self->input);
+    Py_CLEAR(self->variables);
+    return 0;
+}
+
+static void
+Expr_dealloc(Expr* self)
+{
+    pyo_DEALLOC
+    Expr_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+Expr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *inputtmp, *input_streamtmp, *exprtmp=NULL, *multmp=NULL, *addtmp=NULL;
+    Expr *self;
+    self = (Expr *)type->tp_alloc(type, 0);
+
+	self->modebuffer[0] = 0;
+	self->modebuffer[1] = 0;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, Expr_compute_next_data_frame);
+    self->mode_func_ptr = Expr_setProcMode;
+
+    self->oneOverSr = 1.0 / self->sr;
+    
+    self->variables = PyDict_New();
+
+    static char *kwlist[] = {"input", "expr", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &exprtmp, &multmp, &addtmp))
+        Py_RETURN_NONE;
+
+    INIT_INPUT_STREAM
+
+    if (exprtmp) {
+        PyObject_CallMethod((PyObject *)self, "setExpr", "O", exprtmp);
+    }
+
+    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->input_buffer = (MYFLT *)realloc(self->input_buffer, self->bufsize * sizeof(MYFLT));
+    self->output_buffer = (MYFLT *)realloc(self->output_buffer, self->bufsize * sizeof(MYFLT));
+    for (i=0; i<self->bufsize; i++) {
+        self->input_buffer[i] = self->output_buffer[i] = 0.0;
+    }
+
+    (*self->mode_func_ptr)(self);
+
+    return (PyObject *)self;
+}
+
+static PyObject * Expr_getServer(Expr* self) { GET_SERVER };
+static PyObject * Expr_getStream(Expr* self) { GET_STREAM };
+static PyObject * Expr_setMul(Expr *self, PyObject *arg) { SET_MUL };
+static PyObject * Expr_setAdd(Expr *self, PyObject *arg) { SET_ADD };
+static PyObject * Expr_setSub(Expr *self, PyObject *arg) { SET_SUB };
+static PyObject * Expr_setDiv(Expr *self, PyObject *arg) { SET_DIV };
+
+static PyObject * Expr_play(Expr *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * Expr_out(Expr *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * Expr_stop(Expr *self) { STOP };
+
+static PyObject * Expr_multiply(Expr *self, PyObject *arg) { MULTIPLY };
+static PyObject * Expr_inplace_multiply(Expr *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * Expr_add(Expr *self, PyObject *arg) { ADD };
+static PyObject * Expr_inplace_add(Expr *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * Expr_sub(Expr *self, PyObject *arg) { SUB };
+static PyObject * Expr_inplace_sub(Expr *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * Expr_div(Expr *self, PyObject *arg) { DIV };
+static PyObject * Expr_inplace_div(Expr *self, PyObject *arg) { INPLACE_DIV };
+
+static PyObject *
+Expr_setExpr(Expr *self, PyObject *arg)
+{
+    int i, j = 0, count = 0;
+    PyObject *sentence = NULL, *exp = NULL, *explist = NULL, *tmpstr = NULL;
+    PyObject *varDict = NULL, *waitingDict = NULL, *waitingList = NULL;
+    Py_ssize_t len, start, end;
+
+    PyDict_Clear(self->variables);
+    varDict = PyDict_New();
+    waitingDict = PyDict_New();
+
+    if (PY_STRING_CHECK(arg)) {
+        Py_INCREF(arg);
+        Py_XDECREF(sentence);
+        sentence = arg;
+        len = PyUnicode_GetSize(sentence);
+        if (len == 0) {
+            Py_RETURN_NONE;            
+        }
+        if (PyUnicode_Count(sentence, PyUnicode_FromString(")"), 0, len) != PyUnicode_Count(sentence, PyUnicode_FromString("("), 0, len)) {
+            PySys_WriteStdout("Expr: mismatched brackets, expression bypassed.\n");
+            Py_RETURN_NONE;            
+        }
+        for (i=0; i<self->count; i++) { 
+            clearexpr(self->lexp[i]); 
+        }
+        self->count = 0;
+        while (PyUnicode_Find(sentence, PyUnicode_FromString(")"), 0, len, 1) != -1) {
+            end = PyUnicode_Find(sentence, PyUnicode_FromString(")"), 0, len, 1) + 1;
+            start = PyUnicode_Find(sentence, PyUnicode_FromString("("), 0, end, -1);
+            exp = PySequence_GetSlice(sentence, start, end);
+            if (PyUnicode_Contains(exp, PyUnicode_FromString("let ")) || PyUnicode_Contains(exp, PyUnicode_FromString("var "))) {
+                sentence = PyUnicode_Concat(PySequence_GetSlice(sentence, 0, start), PySequence_GetSlice(sentence, end, len));
+            }
+            else {
+                sentence = PyUnicode_Replace(sentence, exp, PyUnicode_Format(PyUnicode_FromString("_%d"), PyInt_FromLong(self->count)), 1);
+            }
+            exp = PyUnicode_Replace(exp, PyUnicode_FromString("("), PyUnicode_FromString(""), -1);
+            exp = PyUnicode_Replace(exp, PyUnicode_FromString(")"), PyUnicode_FromString(""), -1);
+            explist = PyUnicode_Split(exp, NULL, -1);
+            // Prepare variable from "var" function
+            if (PyUnicode_Compare(PyList_GetItem(explist, 0), PyUnicode_FromString("var")) == 0) {
+                PyList_SetItem(explist, 0, PyUnicode_FromString("const"));
+                PyDict_SetItem(self->variables, PyList_GetItem(explist, 1), PyInt_FromLong(self->count));
+                PySequence_DelItem(explist, 1);
+            }
+            // Prepare variable from "let" function
+            if (PyUnicode_Compare(PyList_GetItem(explist, 0), PyUnicode_FromString("let")) == 0) {
+                PyList_SetItem(explist, 0, PyUnicode_FromString("const"));
+                if (PyDict_GetItem(waitingDict, PyList_GetItem(explist, 1)) != NULL) {
+                    waitingList = PyDict_GetItem(waitingDict, PyList_GetItem(explist, 1));
+                    for (j=0; j<PyList_Size(waitingList); j++) {
+                        count = PyInt_AsLong(PyTuple_GetItem(PyList_GetItem(waitingList, j), 0));
+                        i = PyInt_AsLong(PyTuple_GetItem(PyList_GetItem(waitingList, j), 1));
+                        self->lexp[count].vars[i] = self->count;
+                    }
+                    PyDict_DelItem(waitingDict, PyList_GetItem(explist, 1));
+                }
+                PyDict_SetItem(varDict, PyList_GetItem(explist, 1), PyInt_FromLong(self->count));
+                PySequence_DelItem(explist, 1);
+            }
+            // Initialize expression node
+            self->lexp[self->count] = initexpr(PY_STRING_AS_STRING(PyList_GetItem(explist, 0)), PyList_Size(explist));
+            if (PyList_Size(explist) == 1 && self->lexp[self->count].type_op == OP_CONST) {
+                PyList_Insert(explist, 0, PyUnicode_FromString("const"));
+            }
+            while (PyList_Size(explist) < (self->lexp[self->count].num+1)) {
+                PyList_Append(explist, PyUnicode_FromString("0.0"));
+            }
+            for (i=0; i<self->lexp[self->count].num; i++) {
+                if (PyUnicode_Contains(PyList_GetItem(explist, i+1), PyUnicode_FromString("_"))) {
+                    tmpstr = PyUnicode_Replace(PyList_GetItem(explist, i+1), PyUnicode_FromString("_"), PyUnicode_FromString(""), -1);
+                    self->lexp[self->count].nodes[i] = PyInt_AsLong(PyInt_FromString(PY_STRING_AS_STRING(tmpstr), NULL, 0));
+                }
+                else if (PyUnicode_Contains(PyList_GetItem(explist, i+1), PyUnicode_FromString("#"))) {
+                    if (PyDict_GetItem(self->variables, PyList_GetItem(explist, i+1)) != NULL) {
+                        self->lexp[self->count].vars[i] = PyInt_AsLong(PyDict_GetItem(self->variables, PyList_GetItem(explist, i+1)));
+                    }
+                    else if (PyDict_GetItem(varDict, PyList_GetItem(explist, i+1)) != NULL) {
+                        self->lexp[self->count].vars[i] = PyInt_AsLong(PyDict_GetItem(varDict, PyList_GetItem(explist, i+1)));
+                    }
+                    else {
+                        if (PyDict_GetItem(waitingDict, PyList_GetItem(explist, i+1)) == NULL)
+                            waitingList = PyList_New(0);
+                        else
+                            waitingList = PyDict_GetItem(waitingDict, PyList_GetItem(explist, i+1));
+                        PyList_Append(waitingList, PyTuple_Pack(2, PyInt_FromLong(self->count), PyInt_FromLong(i)));
+                        PyDict_SetItem(waitingDict, PyList_GetItem(explist, i+1), waitingList);
+                    }
+                }
+                else if (PyUnicode_Contains(PyList_GetItem(explist, i+1), PyUnicode_FromString("$x"))) {
+                    tmpstr = PyUnicode_Replace(PyList_GetItem(explist, i+1), PyUnicode_FromString("$x"), PyUnicode_FromString(""), -1);
+                    tmpstr = PyUnicode_Replace(tmpstr, PyUnicode_FromString("["), PyUnicode_FromString(""), -1);
+                    tmpstr = PyUnicode_Replace(tmpstr, PyUnicode_FromString("]"), PyUnicode_FromString(""), -1);
+                    self->lexp[self->count].input[i] = PyInt_AsLong(PyInt_FromString(PY_STRING_AS_STRING(tmpstr), NULL, 0));
+                }
+                else if (PyUnicode_Contains(PyList_GetItem(explist, i+1), PyUnicode_FromString("$y"))) {
+                    tmpstr = PyUnicode_Replace(PyList_GetItem(explist, i+1), PyUnicode_FromString("$y"), PyUnicode_FromString(""), -1);
+                    tmpstr = PyUnicode_Replace(tmpstr, PyUnicode_FromString("["), PyUnicode_FromString(""), -1);
+                    tmpstr = PyUnicode_Replace(tmpstr, PyUnicode_FromString("]"), PyUnicode_FromString(""), -1);
+                    self->lexp[self->count].output[i] = PyInt_AsLong(PyInt_FromString(PY_STRING_AS_STRING(tmpstr), NULL, 0));
+                }
+                else {
+                    self->lexp[self->count].values[i] = PyFloat_AsDouble(PyFloat_FromString(PyList_GetItem(explist, i+1), NULL));
+                }
+            }
+            len = PyUnicode_GetSize(sentence);
+            self->count++;
+        }
+
+        explist = PyUnicode_Split(sentence, NULL, -1);
+        if (PyList_Size(explist) == 1) 
+            PyList_Insert(explist, 0, PyUnicode_FromString("const"));
+        // Initialize last expression node
+        self->lexp[self->count] = initexpr(PY_STRING_AS_STRING(PyList_GetItem(explist, 0)), PyList_Size(explist));
+        for (i=0; i<self->lexp[self->count].num; i++) {
+            if (PyUnicode_Contains(PyList_GetItem(explist, i+1), PyUnicode_FromString("_"))) {
+                tmpstr = PyUnicode_Replace(PyList_GetItem(explist, i+1), PyUnicode_FromString("_"), PyUnicode_FromString(""), -1);
+                self->lexp[self->count].nodes[i] = PyInt_AsLong(PyInt_FromString(PY_STRING_AS_STRING(tmpstr), NULL, 0));
+            }
+            else if (PyUnicode_Contains(PyList_GetItem(explist, i+1), PyUnicode_FromString("#"))) {
+                self->lexp[self->count].vars[i] = PyInt_AsLong(PyDict_GetItem(varDict, PyList_GetItem(explist, i+1)));
+            }
+            else if (PyUnicode_Contains(PyList_GetItem(explist, i+1), PyUnicode_FromString("$x"))) {
+                tmpstr = PyUnicode_Replace(PyList_GetItem(explist, i+1), PyUnicode_FromString("$x"), PyUnicode_FromString(""), -1);
+                tmpstr = PyUnicode_Replace(tmpstr, PyUnicode_FromString("["), PyUnicode_FromString(""), -1);
+                tmpstr = PyUnicode_Replace(tmpstr, PyUnicode_FromString("]"), PyUnicode_FromString(""), -1);
+                self->lexp[self->count].input[i] = PyInt_AsLong(PyInt_FromString(PY_STRING_AS_STRING(tmpstr), NULL, 0));
+            }
+            else if (PyUnicode_Contains(PyList_GetItem(explist, i+1), PyUnicode_FromString("$y"))) {
+                tmpstr = PyUnicode_Replace(PyList_GetItem(explist, i+1), PyUnicode_FromString("$y"), PyUnicode_FromString(""), -1);
+                tmpstr = PyUnicode_Replace(tmpstr, PyUnicode_FromString("["), PyUnicode_FromString(""), -1);
+                tmpstr = PyUnicode_Replace(tmpstr, PyUnicode_FromString("]"), PyUnicode_FromString(""), -1);
+                self->lexp[self->count].output[i] = PyInt_AsLong(PyInt_FromString(PY_STRING_AS_STRING(tmpstr), NULL, 0));
+            }
+            else {
+                self->lexp[self->count].values[i] = PyFloat_AsDouble(PyFloat_FromString(PyList_GetItem(explist, i+1), NULL));
+            }
+        }
+
+        self->count++;
+    }
+
+    Py_XDECREF(sentence);
+    Py_XDECREF(exp);
+    Py_XDECREF(explist);
+    Py_XDECREF(tmpstr);
+    Py_XDECREF(varDict);
+    Py_XDECREF(waitingDict);
+    Py_XDECREF(waitingList);
+    
+	Py_RETURN_NONE;
+}
+
+static PyObject * 
+Expr_setVar(Expr *self, PyObject *args, PyObject *kwds)
+{
+    int index;
+    PyObject *varname = NULL, *value = NULL;
+    static char *kwlist[] = {"varname", "value", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &varname, &value))
+        Py_RETURN_NONE;
+
+    if (PyDict_GetItem(self->variables, varname)) {
+        index = PyInt_AsLong(PyDict_GetItem(self->variables, varname));
+        self->lexp[index].values[0] = PyFloat_AsDouble(value);
+    }
+	Py_RETURN_NONE;
+}
+
+static PyObject * 
+Expr_printNodes(Expr *self) { 
+    int i;
+    for (i=0; i<self->count; i++) {
+        print_expr(self->lexp[i], i);
+    }
+	Py_RETURN_NONE;
+};
+
+static PyMemberDef Expr_members[] = {
+    {"server", T_OBJECT_EX, offsetof(Expr, server), 0, "Pyo server."},
+    {"stream", T_OBJECT_EX, offsetof(Expr, stream), 0, "Stream object."},
+    {"input", T_OBJECT_EX, offsetof(Expr, input), 0, "Input sound object."},
+    {"mul", T_OBJECT_EX, offsetof(Expr, mul), 0, "Mul factor."},
+    {"add", T_OBJECT_EX, offsetof(Expr, add), 0, "Add factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef Expr_methods[] = {
+    {"getServer", (PyCFunction)Expr_getServer, METH_NOARGS, "Returns server object."},
+    {"_getStream", (PyCFunction)Expr_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)Expr_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+    {"out", (PyCFunction)Expr_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+    {"stop", (PyCFunction)Expr_stop, METH_NOARGS, "Stops computing."},
+    {"printNodes", (PyCFunction)Expr_printNodes, METH_NOARGS, "Print the list of nodes."},
+	{"setVar", (PyCFunction)Expr_setVar, METH_VARARGS|METH_KEYWORDS, "Sets a variable value."},
+	{"setExpr", (PyCFunction)Expr_setExpr, METH_O, "Sets a new expression."},
+	{"setMul", (PyCFunction)Expr_setMul, METH_O, "Sets oscillator mul factor."},
+	{"setAdd", (PyCFunction)Expr_setAdd, METH_O, "Sets oscillator add factor."},
+    {"setSub", (PyCFunction)Expr_setSub, METH_O, "Sets inverse add factor."},
+    {"setDiv", (PyCFunction)Expr_setDiv, METH_O, "Sets inverse mul factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyNumberMethods Expr_as_number = {
+    (binaryfunc)Expr_add,                      /*nb_add*/
+    (binaryfunc)Expr_sub,                 /*nb_subtract*/
+    (binaryfunc)Expr_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)Expr_inplace_add,              /*inplace_add*/
+    (binaryfunc)Expr_inplace_sub,         /*inplace_subtract*/
+    (binaryfunc)Expr_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)Expr_div,                       /*nb_true_divide*/
+    0,     /*nb_inplace_floor_divide*/
+    (binaryfunc)Expr_inplace_div,                       /*nb_inplace_true_divide*/
+    0,                     /* nb_index */
+};
+
+PyTypeObject ExprType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.Expr_base",         /*tp_name*/
+    sizeof(Expr),         /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)Expr_dealloc, /*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
+    0,                         /*tp_repr*/
+    &Expr_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*/
+    "Expr objects. Resolve a prefix notation sentence at audio rate.",           /* tp_doc */
+    (traverseproc)Expr_traverse,   /* tp_traverse */
+    (inquiry)Expr_clear,           /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    Expr_methods,             /* tp_methods */
+    Expr_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 */
+    Expr_new,                 /* tp_new */
+};
diff --git a/src/objects/fadermodule.c b/src/objects/fadermodule.c
index 906d3c8..2a7519b 100644
--- a/src/objects/fadermodule.c
+++ b/src/objects/fadermodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include "pyomodule.h"
 #include "streammodule.h"
@@ -29,15 +30,19 @@ typedef struct {
     pyo_audio_HEAD
     int modebuffer[2];
     int fademode;
+    int ended;
     MYFLT topValue;
     MYFLT attack;
     MYFLT release;
     MYFLT duration;
+    MYFLT exp;
+    MYFLT offset;
+    MYFLT currentVal;
     double currentTime;
     MYFLT sampleToSec;
 } Fader;
 
-static void Fader_internal_stop(Fader *self) { 
+static void Fader_internal_stop(Fader *self) {
     int i;
     Stream_setStreamActive(self->stream, 0);
     Stream_setStreamChnl(self->stream, 0);
@@ -49,49 +54,76 @@ static void Fader_internal_stop(Fader *self) {
 
 static void
 Fader_generate_auto(Fader *self) {
-    MYFLT val;
+    MYFLT val, iatt, irel;
     int i;
+    
+    iatt = 1.0 / self->attack;
+    irel = 1.0 / self->release;
+
+    if (self->ended == 1) {
+        Fader_internal_stop((Fader *)self);
+        return;
+    }
 
     for (i=0; i<self->bufsize; i++) {
         if (self->currentTime <= self->attack)
-            val = self->currentTime / self->attack;
-        else if (self->currentTime > self->duration)
+            val = self->currentTime * iatt * (1.0 - self->offset) + self->offset;
+        else if (self->currentTime > self->duration) {
             val = 0.;
+            self->ended = 1;
+        }
         else if (self->currentTime >= (self->duration - self->release))
-            val = (self->duration - self->currentTime) / self->release;
+            val = (self->duration - self->currentTime) * irel;
         else
             val = 1.;
-        
-        self->data[i] = val;
+
+        self->data[i] = self->currentVal = val;
         self->currentTime += self->sampleToSec;
     }
+
+    if (self->exp != 1.0) {
+        for (i=0; i<self->bufsize; i++) {
+            self->data[i] = MYPOW(self->data[i], self->exp);
+        }
+    }
 }
 
 static void
 Fader_generate_wait(Fader *self) {
-    MYFLT val;
+    MYFLT val, iatt, irel;
     int i;
-    
+
+    iatt = 1.0 / self->attack;
+    irel = 1.0 / self->release;
+
+    if (self->fademode == 1 && self->currentTime > self->release) {
+        Fader_internal_stop((Fader *)self);
+        return;
+    }
+
     for (i=0; i<self->bufsize; i++) {
         if (self->fademode == 0) {
-            
             if (self->currentTime <= self->attack)
-                val = self->currentTime / self->attack;
+                val = self->currentTime * iatt * (1.0 - self->offset) + self->offset;
             else
                 val = 1.;
-            self->topValue = val;    
-        }    
-        else {  
+            self->topValue = val;
+        }
+        else {
             if (self->currentTime <= self->release)
-                val = (1. - self->currentTime / self->release) * self->topValue;
-            else 
+                val = (1. - self->currentTime * irel) * self->topValue;
+            else
                 val = 0.;
-        }    
-        self->data[i] = val;
-        self->currentTime += self->sampleToSec;    
+        }
+        self->data[i] = self->currentVal = val;
+        self->currentTime += self->sampleToSec;
+    }
+    
+    if (self->exp != 1.0) {
+        for (i=0; i<self->bufsize; i++) {
+            self->data[i] = MYPOW(self->data[i], self->exp);
+        }
     }
-    if (self->fademode == 1 && self->currentTime > self->release)
-        Fader_internal_stop((Fader *)self);
 }
 
 static void Fader_postprocessing_ii(Fader *self) { POST_PROCESSING_II };
@@ -109,47 +141,47 @@ Fader_setProcMode(Fader *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     if (self->duration == 0.0)
         self->proc_func_ptr = Fader_generate_wait;
     else
-        self->proc_func_ptr = Fader_generate_auto;        
-        
-	switch (muladdmode) {
-        case 0:        
+        self->proc_func_ptr = Fader_generate_auto;
+
+    switch (muladdmode) {
+        case 0:
             self->muladd_func_ptr = Fader_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Fader_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Fader_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Fader_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Fader_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Fader_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Fader_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Fader_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Fader_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Fader_compute_next_data_frame(Fader *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -160,7 +192,7 @@ Fader_traverse(Fader *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Fader_clear(Fader *self)
 {
     pyo_CLEAR
@@ -172,7 +204,7 @@ Fader_dealloc(Fader* self)
 {
     pyo_DEALLOC
     Fader_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -182,55 +214,59 @@ Fader_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *multmp=NULL, *addtmp=NULL;
     Fader *self;
     self = (Fader *)type->tp_alloc(type, 0);
-    
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
     self->topValue = 0.0;
     self->fademode = 0;
+    self->ended = 0;
     self->attack = 0.01;
     self->release = 0.1;
     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};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__FFFOO, kwlist, &self->attack, &self->release, &self->duration, &multmp, &addtmp))
         Py_RETURN_NONE;
- 
+
     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 * Fader_getServer(Fader* self) { GET_SERVER };
 static PyObject * Fader_getStream(Fader* self) { GET_STREAM };
-static PyObject * Fader_setMul(Fader *self, PyObject *arg) { SET_MUL };	
-static PyObject * Fader_setAdd(Fader *self, PyObject *arg) { SET_ADD };	
-static PyObject * Fader_setSub(Fader *self, PyObject *arg) { SET_SUB };	
-static PyObject * Fader_setDiv(Fader *self, PyObject *arg) { SET_DIV };	
+static PyObject * Fader_setMul(Fader *self, PyObject *arg) { SET_MUL };
+static PyObject * Fader_setAdd(Fader *self, PyObject *arg) { SET_ADD };
+static PyObject * Fader_setSub(Fader *self, PyObject *arg) { SET_SUB };
+static PyObject * Fader_setDiv(Fader *self, PyObject *arg) { SET_DIV };
 
-static PyObject * Fader_play(Fader *self, PyObject *args, PyObject *kwds) 
+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
 };
@@ -282,6 +318,16 @@ Fader_setDur(Fader *self, PyObject *arg)
     return Py_None;
 }
 
+static PyObject *
+Fader_setExp(Fader *self, PyObject *arg)
+{
+    MYFLT tmp = PyFloat_AsDouble(arg);
+    if (tmp > 0.0)
+        self->exp = tmp;
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
 static PyMemberDef Fader_members[] = {
 {"server", T_OBJECT_EX, offsetof(Fader, server), 0, "Pyo server."},
 {"stream", T_OBJECT_EX, offsetof(Fader, stream), 0, "Stream object."},
@@ -301,6 +347,7 @@ static PyMethodDef Fader_methods[] = {
 {"setFadein", (PyCFunction)Fader_setFadein, METH_O, "Sets fadein time in seconds."},
 {"setFadeout", (PyCFunction)Fader_setFadeout, METH_O, "Sets fadeout time in seconds."},
 {"setDur", (PyCFunction)Fader_setDur, METH_O, "Sets duration in seconds (0 means wait for stop method to start fadeout)."},
+{"setExp", (PyCFunction)Fader_setExp, METH_O, "Sets the exponent factor for exponential envelope."},
 {"setDiv", (PyCFunction)Fader_setDiv, METH_O, "Sets inverse mul factor."},
 {NULL}  /* Sentinel */
 };
@@ -309,7 +356,7 @@ static PyNumberMethods Fader_as_number = {
 (binaryfunc)Fader_add,                      /*nb_add*/
 (binaryfunc)Fader_sub,                 /*nb_subtract*/
 (binaryfunc)Fader_multiply,                 /*nb_multiply*/
-(binaryfunc)Fader_div,                   /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -323,16 +370,16 @@ static PyNumberMethods Fader_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
 (binaryfunc)Fader_inplace_add,              /*inplace_add*/
 (binaryfunc)Fader_inplace_sub,         /*inplace_subtract*/
 (binaryfunc)Fader_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)Fader_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -341,15 +388,14 @@ static PyNumberMethods Fader_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)Fader_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)Fader_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
 PyTypeObject FaderType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Fader_base",         /*tp_name*/
 sizeof(Fader),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -357,7 +403,7 @@ sizeof(Fader),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &Fader_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -399,11 +445,14 @@ typedef struct {
     MYFLT sustain;
     MYFLT release;
     MYFLT duration;
+    MYFLT exp;
+    MYFLT offset;
+    MYFLT currentVal;
     double currentTime;
     MYFLT sampleToSec;
 } Adsr;
 
-static void Adsr_internal_stop(Adsr *self) { 
+static void Adsr_internal_stop(Adsr *self) {
     int i;
     Stream_setStreamActive(self->stream, 0);
     Stream_setStreamChnl(self->stream, 0);
@@ -417,14 +466,17 @@ static void
 Adsr_generate_auto(Adsr *self) {
     MYFLT val, invatt, invdec, invrel;
     int i;
-    
+
+    if (self->currentTime > self->duration)
+        Adsr_internal_stop((Adsr *)self);
+
     invatt = 1.0 / self->attack;
     invdec = 1.0 / self->decay;
     invrel = 1.0 / self->release;
 
     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)
@@ -433,10 +485,16 @@ Adsr_generate_auto(Adsr *self) {
             val = (self->duration - self->currentTime) * invrel * self->sustain;
         else
             val = self->sustain;
-        
-        self->data[i] = val;
+
+        self->data[i] = self->currentVal = val;
         self->currentTime += self->sampleToSec;
     }
+
+    if (self->exp != 1.0) {
+        for (i=0; i<self->bufsize; i++) {
+            self->data[i] = MYPOW(self->data[i], self->exp);
+        }
+    }
 }
 
 static void
@@ -446,31 +504,36 @@ Adsr_generate_wait(Adsr *self) {
 
     if (self->fademode == 1 && self->currentTime > self->release)
         Adsr_internal_stop((Adsr *)self);
-    
+
     invatt = 1.0 / self->attack;
     invdec = 1.0 / self->decay;
     invrel = 1.0 / self->release;
 
     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
                 val = self->sustain;
             self->topValue = val;
-        }    
-        else {  
+        }
+        else {
             if (self->currentTime <= self->release) {
                 val = self->topValue * (1. - self->currentTime * invrel);
             }
-            else 
+            else
                 val = 0.;
-        }    
-        self->data[i] = val;
-        self->currentTime += self->sampleToSec;    
+        }
+        self->data[i] = self->currentVal = val;
+        self->currentTime += self->sampleToSec;
+    }
+
+    if (self->exp != 1.0) {
+        for (i=0; i<self->bufsize; i++) {
+            self->data[i] = MYPOW(self->data[i], self->exp);
+        }
     }
 }
 
@@ -489,47 +552,47 @@ Adsr_setProcMode(Adsr *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     if (self->duration == 0.0)
         self->proc_func_ptr = Adsr_generate_wait;
     else
-        self->proc_func_ptr = Adsr_generate_auto;        
-    
-	switch (muladdmode) {
-        case 0:        
+        self->proc_func_ptr = Adsr_generate_auto;
+
+    switch (muladdmode) {
+        case 0:
             self->muladd_func_ptr = Adsr_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Adsr_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Adsr_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Adsr_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Adsr_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Adsr_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Adsr_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Adsr_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Adsr_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Adsr_compute_next_data_frame(Adsr *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -540,7 +603,7 @@ Adsr_traverse(Adsr *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Adsr_clear(Adsr *self)
 {
     pyo_CLEAR
@@ -552,7 +615,7 @@ Adsr_dealloc(Adsr* self)
 {
     pyo_DEALLOC
     Adsr_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -562,7 +625,7 @@ Adsr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *multmp=NULL, *addtmp=NULL;
     Adsr *self;
     self = (Adsr *)type->tp_alloc(type, 0);
-    
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
     self->topValue = 0.0;
@@ -572,31 +635,32 @@ Adsr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->sustain = 0.707;
     self->release = 0.1;
     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};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__FFFFFOO, kwlist, &self->attack, &self->decay, &self->sustain, &self->release, &self->duration, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     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);
-    
+
     if (self->attack < 0.000001)
         self->attack = 0.000001;
     if (self->decay < 0.000001)
@@ -609,21 +673,22 @@ Adsr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         self->sustain = 1.0;
 
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * Adsr_getServer(Adsr* self) { GET_SERVER };
 static PyObject * Adsr_getStream(Adsr* self) { GET_STREAM };
-static PyObject * Adsr_setMul(Adsr *self, PyObject *arg) { SET_MUL };	
-static PyObject * Adsr_setAdd(Adsr *self, PyObject *arg) { SET_ADD };	
-static PyObject * Adsr_setSub(Adsr *self, PyObject *arg) { SET_SUB };	
-static PyObject * Adsr_setDiv(Adsr *self, PyObject *arg) { SET_DIV };	
+static PyObject * Adsr_setMul(Adsr *self, PyObject *arg) { SET_MUL };
+static PyObject * Adsr_setAdd(Adsr *self, PyObject *arg) { SET_ADD };
+static PyObject * Adsr_setSub(Adsr *self, PyObject *arg) { SET_SUB };
+static PyObject * Adsr_setDiv(Adsr *self, PyObject *arg) { SET_DIV };
 
-static PyObject * Adsr_play(Adsr *self, PyObject *args, PyObject *kwds) 
+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
 };
@@ -637,7 +702,7 @@ Adsr_stop(Adsr *self)
     }
     else
         Adsr_internal_stop((Adsr *)self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -654,9 +719,11 @@ static PyObject * Adsr_inplace_div(Adsr *self, PyObject *arg) { INPLACE_DIV };
 static PyObject *
 Adsr_setAttack(Adsr *self, PyObject *arg)
 {
-    self->attack = PyFloat_AsDouble(PyNumber_Float(arg));
-    if (self->attack < 0.000001)
-        self->attack = 0.000001;
+	if (PyNumber_Check(arg)) {
+        self->attack = PyFloat_AsDouble(arg);
+        if (self->attack < 0.000001)
+            self->attack = 0.000001;
+    }
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -664,9 +731,11 @@ Adsr_setAttack(Adsr *self, PyObject *arg)
 static PyObject *
 Adsr_setDecay(Adsr *self, PyObject *arg)
 {
-    self->decay = PyFloat_AsDouble(PyNumber_Float(arg));
-    if (self->decay < 0.000001)
-        self->decay = 0.000001;
+	if (PyNumber_Check(arg)) {
+        self->decay = PyFloat_AsDouble(arg);
+        if (self->decay < 0.000001)
+            self->decay = 0.000001;
+    }
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -674,11 +743,13 @@ Adsr_setDecay(Adsr *self, PyObject *arg)
 static PyObject *
 Adsr_setSustain(Adsr *self, PyObject *arg)
 {
-    self->sustain = PyFloat_AsDouble(PyNumber_Float(arg));
-    if (self->sustain < 0.0)
-        self->sustain = 0.0;
-    else if (self->sustain > 1.0)
-        self->sustain = 1.0;
+	if (PyNumber_Check(arg)) {
+        self->sustain = PyFloat_AsDouble(arg);
+        if (self->sustain < 0.0)
+            self->sustain = 0.0;
+        else if (self->sustain > 1.0)
+            self->sustain = 1.0;
+    }
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -686,9 +757,11 @@ Adsr_setSustain(Adsr *self, PyObject *arg)
 static PyObject *
 Adsr_setRelease(Adsr *self, PyObject *arg)
 {
-    self->release = PyFloat_AsDouble(PyNumber_Float(arg));
-    if (self->release < 0.000001)
-        self->release = 0.000001;
+	if (PyNumber_Check(arg)) {
+        self->release = PyFloat_AsDouble(arg);
+        if (self->release < 0.000001)
+            self->release = 0.000001;
+    }
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -696,7 +769,20 @@ Adsr_setRelease(Adsr *self, PyObject *arg)
 static PyObject *
 Adsr_setDur(Adsr *self, PyObject *arg)
 {
-    self->duration = PyFloat_AsDouble(PyNumber_Float(arg));
+	if (PyNumber_Check(arg)) 
+        self->duration = PyFloat_AsDouble(arg);
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *
+Adsr_setExp(Adsr *self, PyObject *arg)
+{
+	if (PyNumber_Check(arg)) {
+        MYFLT tmp = PyFloat_AsDouble(arg);
+        if (tmp > 0.0)
+            self->exp = tmp;
+    }
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -722,6 +808,7 @@ static PyMethodDef Adsr_methods[] = {
 {"setSustain", (PyCFunction)Adsr_setSustain, METH_O, "Sets attack time in seconds."},
 {"setRelease", (PyCFunction)Adsr_setRelease, METH_O, "Sets release time in seconds."},
 {"setDur", (PyCFunction)Adsr_setDur, METH_O, "Sets duration in seconds (0 means wait for stop method to start fadeout)."},
+{"setExp", (PyCFunction)Adsr_setExp, METH_O, "Sets the exponent factor for exponential envelope."},
 {"setDiv", (PyCFunction)Adsr_setDiv, METH_O, "Sets inverse mul factor."},
 {NULL}  /* Sentinel */
 };
@@ -730,7 +817,7 @@ static PyNumberMethods Adsr_as_number = {
 (binaryfunc)Adsr_add,                      /*nb_add*/
 (binaryfunc)Adsr_sub,                 /*nb_subtract*/
 (binaryfunc)Adsr_multiply,                 /*nb_multiply*/
-(binaryfunc)Adsr_div,                   /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -744,16 +831,16 @@ static PyNumberMethods Adsr_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
 (binaryfunc)Adsr_inplace_add,              /*inplace_add*/
 (binaryfunc)Adsr_inplace_sub,         /*inplace_subtract*/
 (binaryfunc)Adsr_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)Adsr_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -762,15 +849,14 @@ static PyNumberMethods Adsr_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)Adsr_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)Adsr_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
 PyTypeObject AdsrType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Adsr_base",         /*tp_name*/
 sizeof(Adsr),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -778,7 +864,7 @@ sizeof(Adsr),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &Adsr_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -825,6 +911,7 @@ typedef struct {
     int newlist;
     int loop;
     int listsize;
+    int okToPause;
 } Linseg;
 
 static void
@@ -837,27 +924,28 @@ Linseg_convert_pointslist(Linseg *self) {
     self->times = (MYFLT *)realloc(self->times, self->listsize * sizeof(MYFLT));
     for (i=0; i<self->listsize; i++) {
         tup = PyList_GET_ITEM(self->pointslist, i);
-        self->times[i] = PyFloat_AsDouble(PyNumber_Float(PyTuple_GET_ITEM(tup, 0)));
-        self->targets[i] = PyFloat_AsDouble(PyNumber_Float(PyTuple_GET_ITEM(tup, 1)));
+        self->times[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 0));
+        self->targets[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 1));
     }
 }
 
-static void 
+static void
 Linseg_reinit(Linseg *self) {
     if (self->newlist == 1) {
         Linseg_convert_pointslist((Linseg *)self);
         self->newlist = 0;
-    }    
+    }
     self->currentTime = 0.0;
     self->currentValue = self->targets[0];
     self->which = 0;
     self->flag = 1;
+    self->okToPause = 1;
 }
 
 static void
 Linseg_generate(Linseg *self) {
     int i;
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (self->flag == 1) {
             if (self->currentTime >= self->times[self->which]) {
@@ -867,9 +955,10 @@ Linseg_generate(Linseg *self) {
                         Linseg_reinit((Linseg *)self);
                     else {
                         self->flag = 0;
+                        self->okToPause = 0;
                         self->currentValue = self->targets[self->which-1];
-                    }    
-                }    
+                    }
+                }
                 else {
                     if ((self->times[self->which] - self->times[self->which-1]) <= 0)
                         self->increment = self->targets[self->which] - self->currentValue;
@@ -878,9 +967,9 @@ Linseg_generate(Linseg *self) {
                 }
             }
             if (self->currentTime <= self->times[self->listsize-1])
-                self->currentValue += self->increment;            
+                self->currentValue += self->increment;
             self->data[i] = (MYFLT)self->currentValue;
-            self->currentTime += self->sampleToSec;    
+            self->currentTime += self->sampleToSec;
         }
         else
             self->data[i] = (MYFLT)self->currentValue;
@@ -902,44 +991,44 @@ Linseg_setProcMode(Linseg *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = Linseg_generate;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Linseg_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Linseg_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Linseg_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Linseg_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Linseg_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Linseg_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Linseg_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Linseg_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Linseg_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Linseg_compute_next_data_frame(Linseg *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -951,7 +1040,7 @@ Linseg_traverse(Linseg *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Linseg_clear(Linseg *self)
 {
     pyo_CLEAR
@@ -966,7 +1055,7 @@ Linseg_dealloc(Linseg* self)
     free(self->targets);
     free(self->times);
     Linseg_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -976,22 +1065,21 @@ Linseg_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *pointslist=NULL, *multmp=NULL, *addtmp=NULL;
     Linseg *self;
     self = (Linseg *)type->tp_alloc(type, 0);
-    
+
     self->loop = 0;
     self->newlist = 1;
+    self->okToPause = 0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     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};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iiOO", kwlist, &pointslist, &self->loop, &initToFirstVal, &multmp, &addtmp))
         Py_RETURN_NONE;
 
@@ -999,42 +1087,55 @@ Linseg_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     Py_XDECREF(self->pointslist);
     self->pointslist = pointslist;
     Linseg_convert_pointslist((Linseg *)self);
-    
+
     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);
-    
+
     if (initToFirstVal) {
         for (i=0; i<self->bufsize; i++) {
             self->data[i] = self->targets[0];
         }
     }
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * Linseg_getServer(Linseg* self) { GET_SERVER };
 static PyObject * Linseg_getStream(Linseg* self) { GET_STREAM };
-static PyObject * Linseg_setMul(Linseg *self, PyObject *arg) { SET_MUL };	
-static PyObject * Linseg_setAdd(Linseg *self, PyObject *arg) { SET_ADD };	
-static PyObject * Linseg_setSub(Linseg *self, PyObject *arg) { SET_SUB };	
-static PyObject * Linseg_setDiv(Linseg *self, PyObject *arg) { SET_DIV };	
+static PyObject * Linseg_setMul(Linseg *self, PyObject *arg) { SET_MUL };
+static PyObject * Linseg_setAdd(Linseg *self, PyObject *arg) { SET_ADD };
+static PyObject * Linseg_setSub(Linseg *self, PyObject *arg) { SET_SUB };
+static PyObject * Linseg_setDiv(Linseg *self, PyObject *arg) { SET_DIV };
 
-static PyObject * Linseg_play(Linseg *self, PyObject *args, PyObject *kwds) 
+static PyObject * Linseg_play(Linseg *self, PyObject *args, PyObject *kwds)
 {
     Linseg_reinit((Linseg *)self);
     PLAY
 };
 
-static PyObject * Linseg_stop(Linseg *self) { STOP };
+static PyObject * Linseg_stop(Linseg *self) 
+{ 
+    self->okToPause = 0;
+    STOP 
+};
+
+static PyObject * Linseg_pause(Linseg *self) 
+{ 
+    if (self->okToPause == 1)
+        self->flag = 1 - self->flag;
+
+    Py_INCREF(Py_None);
+    return Py_None;
+};
 
 static PyObject * Linseg_multiply(Linseg *self, PyObject *arg) { MULTIPLY };
 static PyObject * Linseg_inplace_multiply(Linseg *self, PyObject *arg) { INPLACE_MULTIPLY };
@@ -1052,18 +1153,18 @@ Linseg_setList(Linseg *self, PyObject *value)
         PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyList_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The points list attribute value must be a list of tuples.");
         return PyInt_FromLong(-1);
     }
-    
+
     Py_INCREF(value);
     Py_DECREF(self->pointslist);
-    self->pointslist = value; 
-    
+    self->pointslist = value;
+
     self->newlist = 1;
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1071,13 +1172,10 @@ Linseg_setList(Linseg *self, PyObject *value)
 static PyObject *
 Linseg_setLoop(Linseg *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
     self->loop = PyInt_AsLong(arg);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1096,6 +1194,7 @@ static PyMethodDef Linseg_methods[] = {
 {"_getStream", (PyCFunction)Linseg_getStream, METH_NOARGS, "Returns stream object."},
 {"play", (PyCFunction)Linseg_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
 {"stop", (PyCFunction)Linseg_stop, METH_NOARGS, "Starts fadeout and stops computing."},
+{"pause", (PyCFunction)Linseg_pause, METH_NOARGS, "Toggles between play and stop without reset."},
 {"setList", (PyCFunction)Linseg_setList, METH_O, "Sets target points list."},
 {"setLoop", (PyCFunction)Linseg_setLoop, METH_O, "Sets looping mode."},
 {"setMul", (PyCFunction)Linseg_setMul, METH_O, "Sets Linseg mul factor."},
@@ -1109,7 +1208,7 @@ static PyNumberMethods Linseg_as_number = {
 (binaryfunc)Linseg_add,                      /*nb_add*/
 (binaryfunc)Linseg_sub,                 /*nb_subtract*/
 (binaryfunc)Linseg_multiply,                 /*nb_multiply*/
-(binaryfunc)Linseg_div,                   /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -1123,16 +1222,16 @@ static PyNumberMethods Linseg_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
 (binaryfunc)Linseg_inplace_add,              /*inplace_add*/
 (binaryfunc)Linseg_inplace_sub,         /*inplace_subtract*/
 (binaryfunc)Linseg_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)Linseg_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -1141,15 +1240,14 @@ static PyNumberMethods Linseg_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)Linseg_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)Linseg_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
 PyTypeObject LinsegType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Linseg_base",         /*tp_name*/
 sizeof(Linseg),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -1157,7 +1255,7 @@ sizeof(Linseg),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &Linseg_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -1211,42 +1309,44 @@ typedef struct {
     double exp_tmp;
     int inverse;
     int inverse_tmp;
+    int okToPause;
 } Expseg;
 
 static void
 Expseg_convert_pointslist(Expseg *self) {
     int i;
     PyObject *tup;
-    
+
     self->listsize = PyList_Size(self->pointslist);
     self->targets = (MYFLT *)realloc(self->targets, self->listsize * sizeof(MYFLT));
     self->times = (MYFLT *)realloc(self->times, self->listsize * sizeof(MYFLT));
     for (i=0; i<self->listsize; i++) {
         tup = PyList_GET_ITEM(self->pointslist, i);
-        self->times[i] = PyFloat_AsDouble(PyNumber_Float(PyTuple_GET_ITEM(tup, 0)));
-        self->targets[i] = PyFloat_AsDouble(PyNumber_Float(PyTuple_GET_ITEM(tup, 1)));
+        self->times[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 0));
+        self->targets[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 1));
     }
 }
 
-static void 
+static void
 Expseg_reinit(Expseg *self) {
     if (self->newlist == 1) {
         Expseg_convert_pointslist((Expseg *)self);
         self->newlist = 0;
-    }    
+    }
     self->currentTime = 0.0;
     self->currentValue = self->targets[0];
     self->which = 0;
     self->flag = 1;
     self->exp = self->exp_tmp;
     self->inverse = self->inverse_tmp;
+    self->okToPause = 1;
 }
 
 static void
 Expseg_generate(Expseg *self) {
     int i;
     double scl;
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (self->flag == 1) {
             if (self->currentTime >= self->times[self->which]) {
@@ -1257,8 +1357,9 @@ Expseg_generate(Expseg *self) {
                     else {
                         self->flag = 0;
                         self->currentValue = self->targets[self->which-1];
-                    }    
-                }    
+                        self->okToPause = 0;
+                    }
+                }
                 else {
                     self->range = self->targets[self->which] - self->targets[self->which-1];
                     self->steps = (self->times[self->which] - self->times[self->which-1]) * self->sr;
@@ -1266,8 +1367,8 @@ Expseg_generate(Expseg *self) {
                         self->inc = 1.0;
                     else
                         self->inc = 1.0 / self->steps;
-                }    
-                self->pointer = 0.0;   
+                }
+                self->pointer = 0.0;
             }
             if (self->currentTime <= self->times[self->listsize-1]) {
                 if (self->pointer >= 1.0)
@@ -1279,9 +1380,9 @@ Expseg_generate(Expseg *self) {
 
                 self->currentValue = scl * self->range + self->targets[self->which-1];
                 self->pointer += self->inc;
-            }    
+            }
             self->data[i] = (MYFLT)self->currentValue;
-            self->currentTime += self->sampleToSec;    
+            self->currentTime += self->sampleToSec;
         }
         else
             self->data[i] = (MYFLT)self->currentValue;
@@ -1303,44 +1404,44 @@ Expseg_setProcMode(Expseg *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = Expseg_generate;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Expseg_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Expseg_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Expseg_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Expseg_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Expseg_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Expseg_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Expseg_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Expseg_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Expseg_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Expseg_compute_next_data_frame(Expseg *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1352,7 +1453,7 @@ Expseg_traverse(Expseg *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Expseg_clear(Expseg *self)
 {
     pyo_CLEAR
@@ -1367,7 +1468,7 @@ Expseg_dealloc(Expseg* self)
     free(self->targets);
     free(self->times);
     Expseg_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1377,40 +1478,39 @@ Expseg_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *pointslist=NULL, *multmp=NULL, *addtmp=NULL;
     Expseg *self;
     self = (Expseg *)type->tp_alloc(type, 0);
-    
+
     self->loop = 0;
     self->newlist = 1;
     self->exp = self->exp_tmp = 10;
     self->inverse = self->inverse_tmp = 1;
+    self->okToPause = 0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     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};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|idiiOO", kwlist, &pointslist, &self->loop, &self->exp_tmp, &self->inverse_tmp, &initToFirstVal, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     Py_INCREF(pointslist);
     Py_XDECREF(self->pointslist);
     self->pointslist = pointslist;
     Expseg_convert_pointslist((Expseg *)self);
-    
+
     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);
 
     if (initToFirstVal) {
@@ -1420,24 +1520,37 @@ Expseg_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     }
 
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * Expseg_getServer(Expseg* self) { GET_SERVER };
 static PyObject * Expseg_getStream(Expseg* self) { GET_STREAM };
-static PyObject * Expseg_setMul(Expseg *self, PyObject *arg) { SET_MUL };	
-static PyObject * Expseg_setAdd(Expseg *self, PyObject *arg) { SET_ADD };	
-static PyObject * Expseg_setSub(Expseg *self, PyObject *arg) { SET_SUB };	
-static PyObject * Expseg_setDiv(Expseg *self, PyObject *arg) { SET_DIV };	
+static PyObject * Expseg_setMul(Expseg *self, PyObject *arg) { SET_MUL };
+static PyObject * Expseg_setAdd(Expseg *self, PyObject *arg) { SET_ADD };
+static PyObject * Expseg_setSub(Expseg *self, PyObject *arg) { SET_SUB };
+static PyObject * Expseg_setDiv(Expseg *self, PyObject *arg) { SET_DIV };
 
-static PyObject * Expseg_play(Expseg *self, PyObject *args, PyObject *kwds) 
+static PyObject * Expseg_play(Expseg *self, PyObject *args, PyObject *kwds)
 {
     Expseg_reinit((Expseg *)self);
     PLAY
 };
 
-static PyObject * Expseg_stop(Expseg *self) { STOP };
+static PyObject * Expseg_stop(Expseg *self)
+{ 
+    self->okToPause = 0;
+    STOP 
+};
+
+static PyObject * Expseg_pause(Expseg *self) 
+{ 
+    if (self->okToPause == 1)
+        self->flag = 1 - self->flag;
+
+    Py_INCREF(Py_None);
+    return Py_None;
+};
 
 static PyObject * Expseg_multiply(Expseg *self, PyObject *arg) { MULTIPLY };
 static PyObject * Expseg_inplace_multiply(Expseg *self, PyObject *arg) { INPLACE_MULTIPLY };
@@ -1455,18 +1568,18 @@ Expseg_setList(Expseg *self, PyObject *value)
         PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyList_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The points list attribute value must be a list of tuples.");
         return PyInt_FromLong(-1);
     }
-    
+
     Py_INCREF(value);
     Py_DECREF(self->pointslist);
-    self->pointslist = value; 
-    
+    self->pointslist = value;
+
     self->newlist = 1;
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1474,13 +1587,10 @@ Expseg_setList(Expseg *self, PyObject *value)
 static PyObject *
 Expseg_setLoop(Expseg *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
     self->loop = PyInt_AsLong(arg);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1488,13 +1598,11 @@ Expseg_setLoop(Expseg *self, PyObject *arg)
 static PyObject *
 Expseg_setExp(Expseg *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-    self->exp_tmp = PyFloat_AsDouble(PyNumber_Float(arg));
-    
+    ASSERT_ARG_NOT_NULL
+
+	if (PyNumber_Check(arg))
+        self->exp_tmp = PyFloat_AsDouble(arg);
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1502,13 +1610,11 @@ Expseg_setExp(Expseg *self, PyObject *arg)
 static PyObject *
 Expseg_setInverse(Expseg *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-    self->inverse_tmp = PyInt_AsLong(PyNumber_Int(arg));
-    
+    ASSERT_ARG_NOT_NULL
+
+	if (PyNumber_Check(arg))
+        self->inverse_tmp = PyInt_AsLong(PyNumber_Int(arg));
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1527,6 +1633,7 @@ static PyMethodDef Expseg_methods[] = {
     {"_getStream", (PyCFunction)Expseg_getStream, METH_NOARGS, "Returns stream object."},
     {"play", (PyCFunction)Expseg_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
     {"stop", (PyCFunction)Expseg_stop, METH_NOARGS, "Starts fadeout and stops computing."},
+    {"pause", (PyCFunction)Expseg_pause, METH_NOARGS, "Toggles between play and stop without reset."},
     {"setList", (PyCFunction)Expseg_setList, METH_O, "Sets target points list."},
     {"setLoop", (PyCFunction)Expseg_setLoop, METH_O, "Sets looping mode."},
     {"setExp", (PyCFunction)Expseg_setExp, METH_O, "Sets exponent factor."},
@@ -1542,7 +1649,7 @@ static PyNumberMethods Expseg_as_number = {
     (binaryfunc)Expseg_add,                      /*nb_add*/
     (binaryfunc)Expseg_sub,                 /*nb_subtract*/
     (binaryfunc)Expseg_multiply,                 /*nb_multiply*/
-    (binaryfunc)Expseg_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -1556,16 +1663,16 @@ static PyNumberMethods Expseg_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)Expseg_inplace_add,              /*inplace_add*/
     (binaryfunc)Expseg_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)Expseg_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)Expseg_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -1574,15 +1681,14 @@ static PyNumberMethods Expseg_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)Expseg_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)Expseg_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject ExpsegType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Expseg_base",         /*tp_name*/
     sizeof(Expseg),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -1590,7 +1696,7 @@ PyTypeObject ExpsegType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &Expseg_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
diff --git a/src/objects/fftmodule.c b/src/objects/fftmodule.c
index 39ca586..f02b6c3 100644
--- a/src/objects/fftmodule.c
+++ b/src/objects/fftmodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
@@ -29,7 +30,7 @@
 #include "wind.h"
 #include "sndfile.h"
 
-static int 
+static int
 isPowerOfTwo(int x) {
     return (x != 0) && ((x & (x - 1)) == 0);
 }
@@ -57,7 +58,7 @@ FFTMain_realloc_memories(FFTMain *self) {
     self->hsize = self->size / 2;
     n8 = self->size >> 3;
     self->inframe = (MYFLT *)realloc(self->inframe, self->size * sizeof(MYFLT));
-    self->outframe = (MYFLT *)realloc(self->outframe, self->size * sizeof(MYFLT));    
+    self->outframe = (MYFLT *)realloc(self->outframe, self->size * sizeof(MYFLT));
     for (i=0; i<self->size; i++)
         self->inframe[i] = self->outframe[i] = 0.0;
     self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, 3 * self->bufsize * sizeof(MYFLT));
@@ -78,7 +79,7 @@ static void
 FFTMain_filters(FFTMain *self) {
     int i, incount;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-   
+
     incount = self->incount;
 
     for (i=0; i<self->bufsize; i++) {
@@ -99,10 +100,10 @@ FFTMain_filters(FFTMain *self) {
         }
         incount++;
         if (incount >= self->size) {
-            incount -= self->size;      
+            incount -= self->size;
             realfft_split(self->inframe, self->outframe, self->size, self->twiddle);
         }
-    } 
+    }
 
     /*
     for (i=0; i<self->bufsize; i++) {
@@ -113,12 +114,12 @@ FFTMain_filters(FFTMain *self) {
                 self->buffer_streams[i+self->bufsize] = self->outframe[incount*2+1];
             }
             else
-                self->buffer_streams[i] = self->buffer_streams[i+self->bufsize] = 0.0; 
+                self->buffer_streams[i] = self->buffer_streams[i+self->bufsize] = 0.0;
             self->buffer_streams[i+self->bufsize*2] = (MYFLT)incount;
         }
         incount++;
         if (incount >= self->size) {
-            incount -= self->size;      
+            incount -= self->size;
             realfft_packed(self->inframe, self->outframe, self->size, self->twiddle2);
         }
     }
@@ -130,18 +131,18 @@ MYFLT *
 FFTMain_getSamplesBuffer(FFTMain *self)
 {
     return (MYFLT *)self->buffer_streams;
-}    
+}
 
 static void
 FFTMain_setProcMode(FFTMain *self)
-{        
-    self->proc_func_ptr = FFTMain_filters;  
+{
+    self->proc_func_ptr = FFTMain_filters;
 }
 
 static void
 FFTMain_compute_next_data_frame(FFTMain *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -153,7 +154,7 @@ FFTMain_traverse(FFTMain *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 FFTMain_clear(FFTMain *self)
 {
     pyo_CLEAR
@@ -177,7 +178,7 @@ FFTMain_dealloc(FFTMain* self)
     free(self->twiddle);
     free(self->twiddle2);
     FFTMain_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -187,7 +188,7 @@ FFTMain_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp;
     FFTMain *self;
     self = (FFTMain *)type->tp_alloc(type, 0);
-    
+
     self->size = 1024;
     self->wintype = 2;
     INIT_OBJECT_COMMON
@@ -195,12 +196,12 @@ FFTMain_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = FFTMain_setProcMode;
 
     static char *kwlist[] = {"input", "size", "hopsize", "wintype", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iii", kwlist, &inputtmp, &self->size, &self->hopsize, &self->wintype))
         Py_RETURN_NONE;
 
     INIT_INPUT_STREAM
- 
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     FFTMain_realloc_memories(self);
@@ -219,7 +220,7 @@ static PyObject * FFTMain_stop(FFTMain *self) { STOP };
 static PyObject *
 FFTMain_setSize(FFTMain *self, PyObject *args, PyObject *kwds)
 {
-    int size, hopsize;    
+    int size, hopsize;
 
     static char *kwlist[] = {"size", "hopsize", NULL};
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwlist, &size, &hopsize)) {
@@ -233,20 +234,20 @@ FFTMain_setSize(FFTMain *self, PyObject *args, PyObject *kwds)
         FFTMain_realloc_memories(self);
     }
     else
-        printf("FFT size must be a power of two!\n");
-    
+        PySys_WriteStdout("FFT size must be a power of two!\n");
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
 static PyObject *
 FFTMain_setWinType(FFTMain *self, PyObject *arg)
-{    
+{
     if (PyLong_Check(arg) || PyInt_Check(arg)) {
         self->wintype = PyLong_AsLong(arg);
         gen_window(self->window, self->size, self->wintype);
-    }    
-    
+    }
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -269,8 +270,7 @@ static PyMethodDef FFTMain_methods[] = {
 };
 
 PyTypeObject FFTMainType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.FFTMain_base",                                   /*tp_name*/
 sizeof(FFTMain),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -278,7 +278,7 @@ sizeof(FFTMain),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 0,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -335,33 +335,33 @@ FFT_setProcMode(FFT *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = FFT_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = FFT_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = FFT_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = FFT_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = FFT_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = FFT_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = FFT_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = FFT_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = FFT_postprocessing_revareva;
             break;
     }
@@ -376,7 +376,7 @@ FFT_compute_next_data_frame(FFT *self)
     tmp = FFTMain_getSamplesBuffer((FFTMain *)self->mainSplitter);
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = tmp[i + offset];
-    }    
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -388,11 +388,11 @@ FFT_traverse(FFT *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 FFT_clear(FFT *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->mainSplitter);    
+    Py_CLEAR(self->mainSplitter);
     return 0;
 }
 
@@ -401,7 +401,7 @@ FFT_dealloc(FFT* self)
 {
     pyo_DEALLOC
     FFT_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -411,33 +411,33 @@ FFT_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL;
     FFT *self;
     self = (FFT *)type->tp_alloc(type, 0);
-    
+
     self->modebuffer[0] = 0;
     self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, FFT_compute_next_data_frame);
     self->mode_func_ptr = FFT_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 = (FFTMain *)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;
@@ -445,10 +445,10 @@ FFT_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * FFT_getServer(FFT* self) { GET_SERVER };
 static PyObject * FFT_getStream(FFT* self) { GET_STREAM };
-static PyObject * FFT_setMul(FFT *self, PyObject *arg) { SET_MUL };    
-static PyObject * FFT_setAdd(FFT *self, PyObject *arg) { SET_ADD };    
-static PyObject * FFT_setSub(FFT *self, PyObject *arg) { SET_SUB };    
-static PyObject * FFT_setDiv(FFT *self, PyObject *arg) { SET_DIV };    
+static PyObject * FFT_setMul(FFT *self, PyObject *arg) { SET_MUL };
+static PyObject * FFT_setAdd(FFT *self, PyObject *arg) { SET_ADD };
+static PyObject * FFT_setSub(FFT *self, PyObject *arg) { SET_SUB };
+static PyObject * FFT_setDiv(FFT *self, PyObject *arg) { SET_DIV };
 
 static PyObject * FFT_play(FFT *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * FFT_stop(FFT *self) { STOP };
@@ -486,7 +486,7 @@ static PyNumberMethods FFT_as_number = {
 (binaryfunc)FFT_add,                      /*nb_add*/
 (binaryfunc)FFT_sub,                 /*nb_subtract*/
 (binaryfunc)FFT_multiply,                 /*nb_multiply*/
-(binaryfunc)FFT_div,                   /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -500,16 +500,16 @@ static PyNumberMethods FFT_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
 (binaryfunc)FFT_inplace_add,              /*inplace_add*/
 (binaryfunc)FFT_inplace_sub,         /*inplace_subtract*/
 (binaryfunc)FFT_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)FFT_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -518,15 +518,14 @@ static PyNumberMethods FFT_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)FFT_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)FFT_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
 PyTypeObject FFTType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.FFT_base",         /*tp_name*/
 sizeof(FFT),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -534,7 +533,7 @@ sizeof(FFT),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &FFT_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -578,7 +577,7 @@ typedef struct {
     int wintype;
     int incount;
     MYFLT *inframe;
-    MYFLT *outframe;    
+    MYFLT *outframe;
     MYFLT *window;
     MYFLT **twiddle;
     MYFLT *twiddle2;
@@ -591,7 +590,7 @@ IFFT_realloc_memories(IFFT *self) {
     self->hsize = self->size / 2;
     n8 = self->size >> 3;
     self->inframe = (MYFLT *)realloc(self->inframe, self->size * sizeof(MYFLT));
-    self->outframe = (MYFLT *)realloc(self->outframe, self->size * sizeof(MYFLT));    
+    self->outframe = (MYFLT *)realloc(self->outframe, self->size * sizeof(MYFLT));
     for (i=0; i<self->size; i++)
         self->inframe[i] = self->outframe[i] = 0.0;
     self->twiddle = (MYFLT **)realloc(self->twiddle, 4 * sizeof(MYFLT *));
@@ -627,7 +626,7 @@ IFFT_filters(IFFT *self) {
         }
         incount++;
         if (incount >= self->size) {
-            incount -= self->size;      
+            incount -= self->size;
             irealfft_split(self->inframe, self->outframe, self->size, self->twiddle);
         }
     }
@@ -642,11 +641,11 @@ IFFT_filters(IFFT *self) {
         }
         incount++;
         if (incount >= self->size) {
-            incount -= self->size;      
+            incount -= self->size;
             irealfft_packed(self->inframe, self->outframe, self->size, self->twiddle2);
         }
     }
-    */ 
+    */
     self->incount = incount;
 }
 
@@ -667,42 +666,42 @@ IFFT_setProcMode(IFFT *self)
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
     self->proc_func_ptr = IFFT_filters;
-    
+
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = IFFT_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = IFFT_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = IFFT_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = IFFT_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = IFFT_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = IFFT_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = IFFT_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = IFFT_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = IFFT_postprocessing_revareva;
             break;
-    } 
+    }
 }
 
 static void
 IFFT_compute_next_data_frame(IFFT *self)
-{   
-    (*self->proc_func_ptr)(self);    
+{
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -717,7 +716,7 @@ IFFT_traverse(IFFT *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 IFFT_clear(IFFT *self)
 {
     pyo_CLEAR
@@ -742,7 +741,7 @@ IFFT_dealloc(IFFT* self)
     free(self->twiddle);
     free(self->twiddle2);
     IFFT_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -780,7 +779,7 @@ IFFT_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     Py_INCREF(inreal_streamtmp);
     Py_XDECREF(self->inreal_stream);
     self->inreal_stream = (Stream *)inreal_streamtmp;
- 
+
     if (multmp) {
         PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
     }
@@ -788,22 +787,22 @@ IFFT_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (addtmp) {
         PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
     }
-            
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
-    IFFT_realloc_memories(self);    
+    IFFT_realloc_memories(self);
 
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * IFFT_getServer(IFFT* self) { GET_SERVER };
 static PyObject * IFFT_getStream(IFFT* self) { GET_STREAM };
-static PyObject * IFFT_setMul(IFFT *self, PyObject *arg) { SET_MUL };    
-static PyObject * IFFT_setAdd(IFFT *self, PyObject *arg) { SET_ADD };    
-static PyObject * IFFT_setSub(IFFT *self, PyObject *arg) { SET_SUB };    
-static PyObject * IFFT_setDiv(IFFT *self, PyObject *arg) { SET_DIV };    
+static PyObject * IFFT_setMul(IFFT *self, PyObject *arg) { SET_MUL };
+static PyObject * IFFT_setAdd(IFFT *self, PyObject *arg) { SET_ADD };
+static PyObject * IFFT_setSub(IFFT *self, PyObject *arg) { SET_SUB };
+static PyObject * IFFT_setDiv(IFFT *self, PyObject *arg) { SET_DIV };
 
 static PyObject * IFFT_play(IFFT *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * IFFT_out(IFFT *self, PyObject *args, PyObject *kwds) { OUT };
@@ -821,7 +820,7 @@ static PyObject * IFFT_inplace_div(IFFT *self, PyObject *arg) { INPLACE_DIV };
 static PyObject *
 IFFT_setSize(IFFT *self, PyObject *args, PyObject *kwds)
 {
-    int size, hopsize;    
+    int size, hopsize;
 
     static char *kwlist[] = {"size", "hopsize", NULL};
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwlist, &size, &hopsize)) {
@@ -835,20 +834,20 @@ IFFT_setSize(IFFT *self, PyObject *args, PyObject *kwds)
         IFFT_realloc_memories(self);
     }
     else
-        printf("IFFT size must be a power of two!\n");
-    
+        PySys_WriteStdout("IFFT size must be a power of two!\n");
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
 static PyObject *
 IFFT_setWinType(IFFT *self, PyObject *arg)
-{    
+{
     if (PyLong_Check(arg) || PyInt_Check(arg)) {
         self->wintype = PyLong_AsLong(arg);
         gen_window(self->window, self->size, self->wintype);
-    }    
-    
+    }
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -882,7 +881,7 @@ static PyNumberMethods IFFT_as_number = {
     (binaryfunc)IFFT_add,                      /*nb_add*/
     (binaryfunc)IFFT_sub,                 /*nb_subtract*/
     (binaryfunc)IFFT_multiply,                 /*nb_multiply*/
-    (binaryfunc)IFFT_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -896,16 +895,16 @@ static PyNumberMethods IFFT_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)IFFT_inplace_add,              /*inplace_add*/
     (binaryfunc)IFFT_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)IFFT_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)IFFT_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -914,15 +913,14 @@ static PyNumberMethods IFFT_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)IFFT_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)IFFT_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject IFFTType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.IFFT_base",         /*tp_name*/
     sizeof(IFFT),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -930,7 +928,7 @@ PyTypeObject IFFTType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &IFFT_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -1005,35 +1003,35 @@ CarToPol_setProcMode(CarToPol *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = CarToPol_generate;
 
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = CarToPol_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = CarToPol_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = CarToPol_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = CarToPol_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = CarToPol_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = CarToPol_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = CarToPol_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = CarToPol_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = CarToPol_postprocessing_revareva;
             break;
     }
@@ -1042,7 +1040,7 @@ CarToPol_setProcMode(CarToPol *self)
 static void
 CarToPol_compute_next_data_frame(CarToPol *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1057,7 +1055,7 @@ CarToPol_traverse(CarToPol *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 CarToPol_clear(CarToPol *self)
 {
     pyo_CLEAR
@@ -1073,7 +1071,7 @@ CarToPol_dealloc(CarToPol* self)
 {
     pyo_DEALLOC
     CarToPol_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1083,49 +1081,49 @@ CarToPol_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *input2tmp, *input2_streamtmp, *multmp=NULL, *addtmp=NULL;
     CarToPol *self;
     self = (CarToPol *)type->tp_alloc(type, 0);
-    
+
     self->modebuffer[0] = 0;
     self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, CarToPol_compute_next_data_frame);
     self->mode_func_ptr = CarToPol_setProcMode;
 
     static char *kwlist[] = {"input", "input2", "chnl", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OOi|OO", kwlist, &inputtmp, &input2tmp, &self->chnl, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     Py_XDECREF(self->input2);
     self->input2 = input2tmp;
     input2_streamtmp = PyObject_CallMethod((PyObject *)self->input2, "_getStream", NULL);
     Py_INCREF(input2_streamtmp);
     Py_XDECREF(self->input2_stream);
     self->input2_stream = (Stream *)input2_streamtmp;
-    
+
     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 * CarToPol_getServer(CarToPol* self) { GET_SERVER };
 static PyObject * CarToPol_getStream(CarToPol* self) { GET_STREAM };
-static PyObject * CarToPol_setMul(CarToPol *self, PyObject *arg) { SET_MUL };    
-static PyObject * CarToPol_setAdd(CarToPol *self, PyObject *arg) { SET_ADD };    
-static PyObject * CarToPol_setSub(CarToPol *self, PyObject *arg) { SET_SUB };    
-static PyObject * CarToPol_setDiv(CarToPol *self, PyObject *arg) { SET_DIV };    
+static PyObject * CarToPol_setMul(CarToPol *self, PyObject *arg) { SET_MUL };
+static PyObject * CarToPol_setAdd(CarToPol *self, PyObject *arg) { SET_ADD };
+static PyObject * CarToPol_setSub(CarToPol *self, PyObject *arg) { SET_SUB };
+static PyObject * CarToPol_setDiv(CarToPol *self, PyObject *arg) { SET_DIV };
 
 static PyObject * CarToPol_play(CarToPol *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * CarToPol_stop(CarToPol *self) { STOP };
@@ -1165,7 +1163,7 @@ static PyNumberMethods CarToPol_as_number = {
     (binaryfunc)CarToPol_add,                      /*nb_add*/
     (binaryfunc)CarToPol_sub,                 /*nb_subtract*/
     (binaryfunc)CarToPol_multiply,                 /*nb_multiply*/
-    (binaryfunc)CarToPol_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -1179,16 +1177,16 @@ static PyNumberMethods CarToPol_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)CarToPol_inplace_add,              /*inplace_add*/
     (binaryfunc)CarToPol_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)CarToPol_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)CarToPol_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -1197,15 +1195,14 @@ static PyNumberMethods CarToPol_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)CarToPol_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)CarToPol_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject CarToPolType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.CarToPol_base",         /*tp_name*/
     sizeof(CarToPol),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -1213,7 +1210,7 @@ PyTypeObject CarToPolType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &CarToPol_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -1260,7 +1257,7 @@ PolToCar_generate(PolToCar *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *in2 = Stream_getData((Stream *)self->input2_stream);
-    
+
     if (self->chnl == 0) {
         for (i=0; i<self->bufsize; i++) {
             self->data[i] = in[i] * MYCOS(in2[i]);
@@ -1288,35 +1285,35 @@ PolToCar_setProcMode(PolToCar *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = PolToCar_generate;
-    
+
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = PolToCar_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = PolToCar_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = PolToCar_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = PolToCar_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = PolToCar_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = PolToCar_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = PolToCar_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = PolToCar_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = PolToCar_postprocessing_revareva;
             break;
     }
@@ -1325,7 +1322,7 @@ PolToCar_setProcMode(PolToCar *self)
 static void
 PolToCar_compute_next_data_frame(PolToCar *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1340,7 +1337,7 @@ PolToCar_traverse(PolToCar *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 PolToCar_clear(PolToCar *self)
 {
     pyo_CLEAR
@@ -1356,7 +1353,7 @@ PolToCar_dealloc(PolToCar* self)
 {
     pyo_DEALLOC
     PolToCar_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1366,49 +1363,49 @@ PolToCar_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *input2tmp, *input2_streamtmp, *multmp=NULL, *addtmp=NULL;
     PolToCar *self;
     self = (PolToCar *)type->tp_alloc(type, 0);
-    
+
     self->modebuffer[0] = 0;
     self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, PolToCar_compute_next_data_frame);
     self->mode_func_ptr = PolToCar_setProcMode;
 
     static char *kwlist[] = {"input", "input2", "chnl", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OOi|OO", kwlist, &inputtmp, &input2tmp, &self->chnl, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     Py_XDECREF(self->input2);
     self->input2 = input2tmp;
     input2_streamtmp = PyObject_CallMethod((PyObject *)self->input2, "_getStream", NULL);
     Py_INCREF(input2_streamtmp);
     Py_XDECREF(self->input2_stream);
     self->input2_stream = (Stream *)input2_streamtmp;
-    
+
     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 * PolToCar_getServer(PolToCar* self) { GET_SERVER };
 static PyObject * PolToCar_getStream(PolToCar* self) { GET_STREAM };
-static PyObject * PolToCar_setMul(PolToCar *self, PyObject *arg) { SET_MUL };    
-static PyObject * PolToCar_setAdd(PolToCar *self, PyObject *arg) { SET_ADD };    
-static PyObject * PolToCar_setSub(PolToCar *self, PyObject *arg) { SET_SUB };    
-static PyObject * PolToCar_setDiv(PolToCar *self, PyObject *arg) { SET_DIV };    
+static PyObject * PolToCar_setMul(PolToCar *self, PyObject *arg) { SET_MUL };
+static PyObject * PolToCar_setAdd(PolToCar *self, PyObject *arg) { SET_ADD };
+static PyObject * PolToCar_setSub(PolToCar *self, PyObject *arg) { SET_SUB };
+static PyObject * PolToCar_setDiv(PolToCar *self, PyObject *arg) { SET_DIV };
 
 static PyObject * PolToCar_play(PolToCar *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * PolToCar_stop(PolToCar *self) { STOP };
@@ -1448,7 +1445,7 @@ static PyNumberMethods PolToCar_as_number = {
     (binaryfunc)PolToCar_add,                      /*nb_add*/
     (binaryfunc)PolToCar_sub,                 /*nb_subtract*/
     (binaryfunc)PolToCar_multiply,                 /*nb_multiply*/
-    (binaryfunc)PolToCar_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -1462,16 +1459,16 @@ static PyNumberMethods PolToCar_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)PolToCar_inplace_add,              /*inplace_add*/
     (binaryfunc)PolToCar_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)PolToCar_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)PolToCar_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -1480,15 +1477,14 @@ static PyNumberMethods PolToCar_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)PolToCar_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)PolToCar_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject PolToCarType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.PolToCar_base",         /*tp_name*/
     sizeof(PolToCar),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -1496,7 +1492,7 @@ PyTypeObject PolToCarType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &PolToCar_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -1530,10 +1526,10 @@ PyTypeObject PolToCarType = {
 
 typedef struct {
     pyo_audio_HEAD
-    PyObject *input; 
+    PyObject *input;
     int inputSize;
     int modebuffer[2];
-    int frameSize; 
+    int frameSize;
     int overlaps;
     int hopsize;
     int count;
@@ -1552,7 +1548,7 @@ FrameDeltaMain_generate(FrameDeltaMain *self) {
         for (i=0; i<self->bufsize; i++) {
             ins[j][i] = in[i];
         }
-    }   
+    }
     for (i=0; i<self->bufsize; i++) {
         for (j=0; j<self->overlaps; j++) {
             curPhase = ins[j][i];
@@ -1570,7 +1566,7 @@ FrameDeltaMain_generate(FrameDeltaMain *self) {
             while (diff > PI) {
                 diff -= TWOPI;
             }
-            self->frameBuffer[j][self->count] = curPhase;            
+            self->frameBuffer[j][self->count] = curPhase;
             self->buffer_streams[i+j*self->bufsize] = diff;
         }
         self->count++;
@@ -1583,18 +1579,18 @@ MYFLT *
 FrameDeltaMain_getSamplesBuffer(FrameDeltaMain *self)
 {
     return (MYFLT *)self->buffer_streams;
-}    
+}
 
 static void
 FrameDeltaMain_setProcMode(FrameDeltaMain *self)
-{    
+{
     self->proc_func_ptr = FrameDeltaMain_generate;
 }
 
 static void
 FrameDeltaMain_compute_next_data_frame(FrameDeltaMain *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -1605,7 +1601,7 @@ FrameDeltaMain_traverse(FrameDeltaMain *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 FrameDeltaMain_clear(FrameDeltaMain *self)
 {
     pyo_CLEAR
@@ -1624,7 +1620,7 @@ FrameDeltaMain_dealloc(FrameDeltaMain* self)
     free(self->frameBuffer);
     free(self->buffer_streams);
     FrameDeltaMain_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1634,24 +1630,24 @@ FrameDeltaMain_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp;
     FrameDeltaMain *self;
     self = (FrameDeltaMain *)type->tp_alloc(type, 0);
-    
+
     self->count = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, FrameDeltaMain_compute_next_data_frame);
     self->mode_func_ptr = FrameDeltaMain_setProcMode;
 
     static char *kwlist[] = {"input", "frameSize", "overlaps", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "Oii", kwlist, &inputtmp, &self->frameSize, &self->overlaps))
         Py_RETURN_NONE;
-    
+
     if (inputtmp) {
         PyObject_CallMethod((PyObject *)self, "setInput", "O", inputtmp);
     }
 
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     self->hopsize = self->frameSize / self->overlaps;
     self->frameBuffer = (MYFLT **)realloc(self->frameBuffer, self->overlaps * sizeof(MYFLT *));
     for(i=0; i<self->overlaps; i++) {
@@ -1666,7 +1662,7 @@ FrameDeltaMain_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     }
 
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
@@ -1680,29 +1676,29 @@ static PyObject *
 FrameDeltaMain_setInput(FrameDeltaMain *self, PyObject *arg)
 {
     PyObject *tmp;
-    
+
     if (! PyList_Check(arg)) {
         PyErr_SetString(PyExc_TypeError, "The inputs attribute must be a list.");
         Py_INCREF(Py_None);
         return Py_None;
     }
-    
+
     tmp = arg;
     self->inputSize = PyList_Size(tmp);
     Py_INCREF(tmp);
     Py_XDECREF(self->input);
     self->input = tmp;
-    
+
     Py_INCREF(Py_None);
     return Py_None;
-}    
+}
 
 static PyObject *
 FrameDeltaMain_setFrameSize(FrameDeltaMain *self, PyObject *arg)
-{    
+{
     int i, j, tmp;
 
-    if (PyInt_Check(arg)) { 
+    if (PyInt_Check(arg)) {
         tmp = PyLong_AsLong(arg);
         if (isPowerOfTwo(tmp)) {
             self->frameSize = tmp;
@@ -1720,8 +1716,8 @@ FrameDeltaMain_setFrameSize(FrameDeltaMain *self, PyObject *arg)
         }
     }
     else
-        printf("frameSize must be a power of two!\n");
-    
+        PySys_WriteStdout("frameSize must be a power of two!\n");
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1744,8 +1740,7 @@ static PyMethodDef FrameDeltaMain_methods[] = {
 };
 
 PyTypeObject FrameDeltaMainType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.FrameDeltaMain_base",         /*tp_name*/
     sizeof(FrameDeltaMain),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -1753,7 +1748,7 @@ PyTypeObject FrameDeltaMainType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     0,                         /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -1810,33 +1805,33 @@ FrameDelta_setProcMode(FrameDelta *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = FrameDelta_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = FrameDelta_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = FrameDelta_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = FrameDelta_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = FrameDelta_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = FrameDelta_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = FrameDelta_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = FrameDelta_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = FrameDelta_postprocessing_revareva;
             break;
     }
@@ -1851,7 +1846,7 @@ FrameDelta_compute_next_data_frame(FrameDelta *self)
     tmp = FrameDeltaMain_getSamplesBuffer((FrameDeltaMain *)self->mainSplitter);
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = tmp[i + offset];
-    }    
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1863,11 +1858,11 @@ FrameDelta_traverse(FrameDelta *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 FrameDelta_clear(FrameDelta *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->mainSplitter);    
+    Py_CLEAR(self->mainSplitter);
     return 0;
 }
 
@@ -1876,7 +1871,7 @@ FrameDelta_dealloc(FrameDelta* self)
 {
     pyo_DEALLOC
     FrameDelta_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1886,44 +1881,44 @@ FrameDelta_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL;
     FrameDelta *self;
     self = (FrameDelta *)type->tp_alloc(type, 0);
-    
+
     self->modebuffer[0] = 0;
     self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, FrameDelta_compute_next_data_frame);
     self->mode_func_ptr = FrameDelta_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 = (FrameDeltaMain *)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 * FrameDelta_getServer(FrameDelta* self) { GET_SERVER };
 static PyObject * FrameDelta_getStream(FrameDelta* self) { GET_STREAM };
-static PyObject * FrameDelta_setMul(FrameDelta *self, PyObject *arg) { SET_MUL };    
-static PyObject * FrameDelta_setAdd(FrameDelta *self, PyObject *arg) { SET_ADD };    
-static PyObject * FrameDelta_setSub(FrameDelta *self, PyObject *arg) { SET_SUB };    
-static PyObject * FrameDelta_setDiv(FrameDelta *self, PyObject *arg) { SET_DIV };    
+static PyObject * FrameDelta_setMul(FrameDelta *self, PyObject *arg) { SET_MUL };
+static PyObject * FrameDelta_setAdd(FrameDelta *self, PyObject *arg) { SET_ADD };
+static PyObject * FrameDelta_setSub(FrameDelta *self, PyObject *arg) { SET_SUB };
+static PyObject * FrameDelta_setDiv(FrameDelta *self, PyObject *arg) { SET_DIV };
 
 static PyObject * FrameDelta_play(FrameDelta *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * FrameDelta_out(FrameDelta *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1963,7 +1958,7 @@ static PyNumberMethods FrameDelta_as_number = {
     (binaryfunc)FrameDelta_add,                      /*nb_add*/
     (binaryfunc)FrameDelta_sub,                 /*nb_subtract*/
     (binaryfunc)FrameDelta_multiply,                 /*nb_multiply*/
-    (binaryfunc)FrameDelta_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -1977,16 +1972,16 @@ static PyNumberMethods FrameDelta_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)FrameDelta_inplace_add,              /*inplace_add*/
     (binaryfunc)FrameDelta_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)FrameDelta_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)FrameDelta_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -1995,15 +1990,14 @@ static PyNumberMethods FrameDelta_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)FrameDelta_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)FrameDelta_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject FrameDeltaType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.FrameDelta_base",         /*tp_name*/
     sizeof(FrameDelta),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -2011,7 +2005,7 @@ PyTypeObject FrameDeltaType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &FrameDelta_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -2045,10 +2039,10 @@ PyTypeObject FrameDeltaType = {
 
 typedef struct {
     pyo_audio_HEAD
-    PyObject *input; 
+    PyObject *input;
     int inputSize;
     int modebuffer[2];
-    int frameSize; 
+    int frameSize;
     int overlaps;
     int hopsize;
     int count;
@@ -2060,14 +2054,14 @@ static void
 FrameAccumMain_generate(FrameAccumMain *self) {
     int i, j, which, where;
     MYFLT curPhase, lastPhase, diff;
-    
+
     MYFLT ins[self->overlaps][self->bufsize];
     for (j=0; j<self->overlaps; j++) {
         MYFLT *in = Stream_getData((Stream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->input, j), "_getStream", NULL));
         for (i=0; i<self->bufsize; i++) {
             ins[j][i] = in[i];
         }
-    }   
+    }
     for (i=0; i<self->bufsize; i++) {
         for (j=0; j<self->overlaps; j++) {
             curPhase = ins[j][i];
@@ -2079,7 +2073,7 @@ FrameAccumMain_generate(FrameAccumMain *self) {
                 where += self->frameSize;
             lastPhase = self->frameBuffer[which][where];
             diff = curPhase + lastPhase;
-            self->frameBuffer[j][self->count] = diff;            
+            self->frameBuffer[j][self->count] = diff;
             self->buffer_streams[i+j*self->bufsize] = diff;
         }
         self->count++;
@@ -2092,18 +2086,18 @@ MYFLT *
 FrameAccumMain_getSamplesBuffer(FrameAccumMain *self)
 {
     return (MYFLT *)self->buffer_streams;
-}    
+}
 
 static void
 FrameAccumMain_setProcMode(FrameAccumMain *self)
-{    
+{
     self->proc_func_ptr = FrameAccumMain_generate;
 }
 
 static void
 FrameAccumMain_compute_next_data_frame(FrameAccumMain *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -2114,7 +2108,7 @@ FrameAccumMain_traverse(FrameAccumMain *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 FrameAccumMain_clear(FrameAccumMain *self)
 {
     pyo_CLEAR
@@ -2133,7 +2127,7 @@ FrameAccumMain_dealloc(FrameAccumMain* self)
     free(self->frameBuffer);
     free(self->buffer_streams);
     FrameAccumMain_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2143,24 +2137,24 @@ FrameAccumMain_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp;
     FrameAccumMain *self;
     self = (FrameAccumMain *)type->tp_alloc(type, 0);
-    
+
     self->count = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, FrameAccumMain_compute_next_data_frame);
     self->mode_func_ptr = FrameAccumMain_setProcMode;
 
     static char *kwlist[] = {"input", "framesize", "overlaps", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "Oii", kwlist, &inputtmp, &self->frameSize, &self->overlaps))
         Py_RETURN_NONE;
-    
+
     if (inputtmp) {
         PyObject_CallMethod((PyObject *)self, "setInput", "O", inputtmp);
     }
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     self->hopsize = self->frameSize / self->overlaps;
     self->frameBuffer = (MYFLT **)realloc(self->frameBuffer, self->overlaps * sizeof(MYFLT *));
     for(i=0; i<self->overlaps; i++) {
@@ -2173,9 +2167,9 @@ FrameAccumMain_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     for (i=0; i<(self->overlaps*self->bufsize); i++) {
         self->buffer_streams[i] = 0.0;
     }
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
@@ -2189,34 +2183,34 @@ static PyObject *
 FrameAccumMain_setInput(FrameAccumMain *self, PyObject *arg)
 {
     PyObject *tmp;
-    
+
     if (! PyList_Check(arg)) {
         PyErr_SetString(PyExc_TypeError, "The inputs attribute must be a list.");
         Py_INCREF(Py_None);
         return Py_None;
     }
-    
+
     tmp = arg;
     self->inputSize = PyList_Size(tmp);
     Py_INCREF(tmp);
     Py_XDECREF(self->input);
     self->input = tmp;
-    
+
     Py_INCREF(Py_None);
     return Py_None;
-}    
+}
 
 static PyObject *
 FrameAccumMain_setFrameSize(FrameAccumMain *self, PyObject *arg)
-{    
+{
     int i, j, tmp;
-    
-    if (PyInt_Check(arg)) { 
+
+    if (PyInt_Check(arg)) {
         tmp = PyLong_AsLong(arg);
         if (isPowerOfTwo(tmp)) {
             self->frameSize = tmp;
             self->hopsize = self->frameSize / self->overlaps;
-            
+
             self->frameBuffer = (MYFLT **)realloc(self->frameBuffer, self->overlaps * sizeof(MYFLT *));
             for(i=0; i<self->overlaps; i++) {
                 self->frameBuffer[i] = (MYFLT *)malloc(self->frameSize * sizeof(MYFLT));
@@ -2224,13 +2218,13 @@ FrameAccumMain_setFrameSize(FrameAccumMain *self, PyObject *arg)
                     self->frameBuffer[i][j] = 0.0;
                 }
             }
-            
+
             self->count = 0;
         }
     }
     else
-        printf("frameSize must be a power of two!\n");
-    
+        PySys_WriteStdout("frameSize must be a power of two!\n");
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -2253,8 +2247,7 @@ static PyMethodDef FrameAccumMain_methods[] = {
 };
 
 PyTypeObject FrameAccumMainType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.FrameAccumMain_base",         /*tp_name*/
     sizeof(FrameAccumMain),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -2262,7 +2255,7 @@ PyTypeObject FrameAccumMainType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     0,                         /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -2319,33 +2312,33 @@ FrameAccum_setProcMode(FrameAccum *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = FrameAccum_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = FrameAccum_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = FrameAccum_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = FrameAccum_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = FrameAccum_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = FrameAccum_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = FrameAccum_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = FrameAccum_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = FrameAccum_postprocessing_revareva;
             break;
     }
@@ -2360,7 +2353,7 @@ FrameAccum_compute_next_data_frame(FrameAccum *self)
     tmp = FrameAccumMain_getSamplesBuffer((FrameAccumMain *)self->mainSplitter);
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = tmp[i + offset];
-    }    
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -2372,11 +2365,11 @@ FrameAccum_traverse(FrameAccum *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 FrameAccum_clear(FrameAccum *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->mainSplitter);    
+    Py_CLEAR(self->mainSplitter);
     return 0;
 }
 
@@ -2385,7 +2378,7 @@ FrameAccum_dealloc(FrameAccum* self)
 {
     pyo_DEALLOC
     FrameAccum_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2395,44 +2388,44 @@ FrameAccum_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL;
     FrameAccum *self;
     self = (FrameAccum *)type->tp_alloc(type, 0);
-    
+
     self->modebuffer[0] = 0;
     self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, FrameAccum_compute_next_data_frame);
     self->mode_func_ptr = FrameAccum_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 = (FrameAccumMain *)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 * FrameAccum_getServer(FrameAccum* self) { GET_SERVER };
 static PyObject * FrameAccum_getStream(FrameAccum* self) { GET_STREAM };
-static PyObject * FrameAccum_setMul(FrameAccum *self, PyObject *arg) { SET_MUL };    
-static PyObject * FrameAccum_setAdd(FrameAccum *self, PyObject *arg) { SET_ADD };    
-static PyObject * FrameAccum_setSub(FrameAccum *self, PyObject *arg) { SET_SUB };    
-static PyObject * FrameAccum_setDiv(FrameAccum *self, PyObject *arg) { SET_DIV };    
+static PyObject * FrameAccum_setMul(FrameAccum *self, PyObject *arg) { SET_MUL };
+static PyObject * FrameAccum_setAdd(FrameAccum *self, PyObject *arg) { SET_ADD };
+static PyObject * FrameAccum_setSub(FrameAccum *self, PyObject *arg) { SET_SUB };
+static PyObject * FrameAccum_setDiv(FrameAccum *self, PyObject *arg) { SET_DIV };
 
 static PyObject * FrameAccum_play(FrameAccum *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * FrameAccum_out(FrameAccum *self, PyObject *args, PyObject *kwds) { OUT };
@@ -2472,7 +2465,7 @@ static PyNumberMethods FrameAccum_as_number = {
     (binaryfunc)FrameAccum_add,                      /*nb_add*/
     (binaryfunc)FrameAccum_sub,                 /*nb_subtract*/
     (binaryfunc)FrameAccum_multiply,                 /*nb_multiply*/
-    (binaryfunc)FrameAccum_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -2486,16 +2479,16 @@ static PyNumberMethods FrameAccum_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)FrameAccum_inplace_add,              /*inplace_add*/
     (binaryfunc)FrameAccum_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)FrameAccum_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)FrameAccum_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -2504,15 +2497,14 @@ static PyNumberMethods FrameAccum_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)FrameAccum_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)FrameAccum_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject FrameAccumType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.FrameAccum_base",         /*tp_name*/
     sizeof(FrameAccum),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -2520,7 +2512,7 @@ PyTypeObject FrameAccumType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &FrameAccum_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -2554,7 +2546,7 @@ PyTypeObject FrameAccumType = {
 
 typedef struct {
     pyo_audio_HEAD
-    PyObject *input; 
+    PyObject *input;
     PyObject *up;
     Stream *up_stream;
     PyObject *down;
@@ -2563,7 +2555,7 @@ typedef struct {
     Stream *damp_stream;
     int inputSize;
     int modebuffer[5];
-    int frameSize; 
+    int frameSize;
     int overlaps;
     int hopsize;
     int count;
@@ -2575,9 +2567,9 @@ static void
 VectralMain_generate(VectralMain *self) {
     int i, j, which, where, bin, halfSize;
     MYFLT curMag, lastMag, diff, slope, up, down, damp;
-    
+
     halfSize = self->frameSize / 2;
-    
+
     if (self->modebuffer[2] == 0)
         up = PyFloat_AS_DOUBLE(self->up);
     else
@@ -2607,14 +2599,14 @@ VectralMain_generate(VectralMain *self) {
     else if (damp > 1.0)
         damp = 1.0;
     damp = damp * 0.1 + 0.9;
-    
+
     MYFLT ins[self->overlaps][self->bufsize];
     for (j=0; j<self->overlaps; j++) {
         MYFLT *in = Stream_getData((Stream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->input, j), "_getStream", NULL));
         for (i=0; i<self->bufsize; i++) {
             ins[j][i] = in[i];
         }
-    }   
+    }
     for (i=0; i<self->bufsize; i++) {
         for (j=0; j<self->overlaps; j++) {
             which = j - 1;
@@ -2634,7 +2626,7 @@ VectralMain_generate(VectralMain *self) {
                 curMag = curMag * down + lastMag * (1.0 - down);
             else if (diff >= 0.0)
                 curMag = curMag * up + lastMag * (1.0 - up);
-            self->frameBuffer[j][self->count] = curMag;            
+            self->frameBuffer[j][self->count] = curMag;
             self->buffer_streams[i+j*self->bufsize] = curMag;
         }
         self->count++;
@@ -2647,18 +2639,18 @@ MYFLT *
 VectralMain_getSamplesBuffer(VectralMain *self)
 {
     return (MYFLT *)self->buffer_streams;
-}    
+}
 
 static void
 VectralMain_setProcMode(VectralMain *self)
-{    
+{
     self->proc_func_ptr = VectralMain_generate;
 }
 
 static void
 VectralMain_compute_next_data_frame(VectralMain *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -2666,26 +2658,26 @@ VectralMain_traverse(VectralMain *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->input);
-    Py_VISIT(self->up);    
-    Py_VISIT(self->up_stream);    
-    Py_VISIT(self->down);    
-    Py_VISIT(self->down_stream);    
-    Py_VISIT(self->damp);    
-    Py_VISIT(self->damp_stream);    
+    Py_VISIT(self->up);
+    Py_VISIT(self->up_stream);
+    Py_VISIT(self->down);
+    Py_VISIT(self->down_stream);
+    Py_VISIT(self->damp);
+    Py_VISIT(self->damp_stream);
     return 0;
 }
 
-static int 
+static int
 VectralMain_clear(VectralMain *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
-    Py_CLEAR(self->up);    
-    Py_CLEAR(self->up_stream);    
-    Py_CLEAR(self->down);    
-    Py_CLEAR(self->down_stream);    
-    Py_CLEAR(self->damp);    
-    Py_CLEAR(self->damp_stream);    
+    Py_CLEAR(self->up);
+    Py_CLEAR(self->up_stream);
+    Py_CLEAR(self->down);
+    Py_CLEAR(self->down_stream);
+    Py_CLEAR(self->damp);
+    Py_CLEAR(self->damp_stream);
     return 0;
 }
 
@@ -2700,7 +2692,7 @@ VectralMain_dealloc(VectralMain* self)
     free(self->frameBuffer);
     free(self->buffer_streams);
     VectralMain_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2710,7 +2702,7 @@ VectralMain_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *uptmp=NULL, *downtmp=NULL, *damptmp=NULL;
     VectralMain *self;
     self = (VectralMain *)type->tp_alloc(type, 0);
-    
+
     self->up = PyFloat_FromDouble(1.0);
     self->down = PyFloat_FromDouble(0.7);
     self->damp = PyFloat_FromDouble(0.9);
@@ -2720,16 +2712,16 @@ VectralMain_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->modebuffer[2] = 0;
     self->modebuffer[3] = 0;
     self->modebuffer[4] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, VectralMain_compute_next_data_frame);
     self->mode_func_ptr = VectralMain_setProcMode;
 
     static char *kwlist[] = {"input", "frameSize", "overlaps", "up", "down", "damp", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "Oii|OOO", kwlist, &inputtmp, &self->frameSize, &self->overlaps, &uptmp, &downtmp, &damptmp))
         Py_RETURN_NONE;
-    
+
     if (inputtmp) {
         PyObject_CallMethod((PyObject *)self, "setInput", "O", inputtmp);
     }
@@ -2745,9 +2737,9 @@ VectralMain_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (damptmp) {
         PyObject_CallMethod((PyObject *)self, "setDamp", "O", damptmp);
     }
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     self->hopsize = self->frameSize / self->overlaps;
     self->frameBuffer = (MYFLT **)realloc(self->frameBuffer, self->overlaps * sizeof(MYFLT *));
     for(i=0; i<self->overlaps; i++) {
@@ -2760,9 +2752,9 @@ VectralMain_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     for (i=0; i<(self->overlaps*self->bufsize); i++) {
         self->buffer_streams[i] = 0.0;
     }
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
@@ -2776,29 +2768,29 @@ static PyObject *
 VectralMain_setInput(VectralMain *self, PyObject *arg)
 {
     PyObject *tmp;
-    
+
     if (! PyList_Check(arg)) {
         PyErr_SetString(PyExc_TypeError, "The inputs attribute must be a list.");
         Py_INCREF(Py_None);
         return Py_None;
     }
-    
+
     tmp = arg;
     self->inputSize = PyList_Size(tmp);
     Py_INCREF(tmp);
     Py_XDECREF(self->input);
     self->input = tmp;
-    
+
     Py_INCREF(Py_None);
     return Py_None;
-}    
+}
 
 static PyObject *
 VectralMain_setFrameSize(VectralMain *self, PyObject *arg)
-{    
+{
     int i, j, tmp;
-    
-    if (PyInt_Check(arg)) { 
+
+    if (PyInt_Check(arg)) {
         tmp = PyLong_AsLong(arg);
         if (isPowerOfTwo(tmp)) {
             self->frameSize = tmp;
@@ -2811,13 +2803,13 @@ VectralMain_setFrameSize(VectralMain *self, PyObject *arg)
                     self->frameBuffer[i][j] = 0.0;
                 }
             }
-            
+
             self->count = 0;
         }
     }
     else
-        printf("frameSize must be a power of two!\n");
-    
+        PySys_WriteStdout("frameSize must be a power of two!\n");
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -2826,14 +2818,11 @@ static PyObject *
 VectralMain_setUp(VectralMain *self, PyObject *arg)
 {
     PyObject *tmp, *streamtmp;
-    
-    if (arg == NULL) {
-        Py_INCREF(Py_None);
-        return Py_None;
-    }
-    
+
+    ASSERT_ARG_NOT_NULL
+
     int isNumber = PyNumber_Check(arg);
-    
+
     tmp = arg;
     Py_INCREF(tmp);
     Py_DECREF(self->up);
@@ -2849,23 +2838,20 @@ VectralMain_setUp(VectralMain *self, PyObject *arg)
         self->up_stream = (Stream *)streamtmp;
         self->modebuffer[2] = 1;
     }
-    
+
     Py_INCREF(Py_None);
     return Py_None;
-}    
+}
 
 static PyObject *
 VectralMain_setDown(VectralMain *self, PyObject *arg)
 {
     PyObject *tmp, *streamtmp;
-    
-    if (arg == NULL) {
-        Py_INCREF(Py_None);
-        return Py_None;
-    }
-    
+
+    ASSERT_ARG_NOT_NULL
+
     int isNumber = PyNumber_Check(arg);
-    
+
     tmp = arg;
     Py_INCREF(tmp);
     Py_DECREF(self->down);
@@ -2881,23 +2867,20 @@ VectralMain_setDown(VectralMain *self, PyObject *arg)
         self->down_stream = (Stream *)streamtmp;
         self->modebuffer[3] = 1;
     }
-    
+
     Py_INCREF(Py_None);
     return Py_None;
-}    
+}
 
 static PyObject *
 VectralMain_setDamp(VectralMain *self, PyObject *arg)
 {
     PyObject *tmp, *streamtmp;
-    
-    if (arg == NULL) {
-        Py_INCREF(Py_None);
-        return Py_None;
-    }
-    
+
+    ASSERT_ARG_NOT_NULL
+
     int isNumber = PyNumber_Check(arg);
-    
+
     tmp = arg;
     Py_INCREF(tmp);
     Py_DECREF(self->damp);
@@ -2913,10 +2896,10 @@ VectralMain_setDamp(VectralMain *self, PyObject *arg)
         self->damp_stream = (Stream *)streamtmp;
         self->modebuffer[4] = 1;
     }
-    
+
     Py_INCREF(Py_None);
     return Py_None;
-}    
+}
 
 static PyMemberDef VectralMain_members[] = {
     {"server", T_OBJECT_EX, offsetof(VectralMain, server), 0, "Pyo server."},
@@ -2939,8 +2922,7 @@ static PyMethodDef VectralMain_methods[] = {
 };
 
 PyTypeObject VectralMainType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.VectralMain_base",         /*tp_name*/
     sizeof(VectralMain),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -2948,7 +2930,7 @@ PyTypeObject VectralMainType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     0,                         /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -3005,33 +2987,33 @@ Vectral_setProcMode(Vectral *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Vectral_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Vectral_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Vectral_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Vectral_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Vectral_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Vectral_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Vectral_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Vectral_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Vectral_postprocessing_revareva;
             break;
     }
@@ -3046,7 +3028,7 @@ Vectral_compute_next_data_frame(Vectral *self)
     tmp = VectralMain_getSamplesBuffer((VectralMain *)self->mainSplitter);
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = tmp[i + offset];
-    }    
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -3058,11 +3040,11 @@ Vectral_traverse(Vectral *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Vectral_clear(Vectral *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->mainSplitter);    
+    Py_CLEAR(self->mainSplitter);
     return 0;
 }
 
@@ -3071,7 +3053,7 @@ Vectral_dealloc(Vectral* self)
 {
     pyo_DEALLOC
     Vectral_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -3081,44 +3063,44 @@ Vectral_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL;
     Vectral *self;
     self = (Vectral *)type->tp_alloc(type, 0);
-    
+
     self->modebuffer[0] = 0;
     self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Vectral_compute_next_data_frame);
     self->mode_func_ptr = Vectral_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 = (VectralMain *)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 * Vectral_getServer(Vectral* self) { GET_SERVER };
 static PyObject * Vectral_getStream(Vectral* self) { GET_STREAM };
-static PyObject * Vectral_setMul(Vectral *self, PyObject *arg) { SET_MUL };    
-static PyObject * Vectral_setAdd(Vectral *self, PyObject *arg) { SET_ADD };    
-static PyObject * Vectral_setSub(Vectral *self, PyObject *arg) { SET_SUB };    
-static PyObject * Vectral_setDiv(Vectral *self, PyObject *arg) { SET_DIV };    
+static PyObject * Vectral_setMul(Vectral *self, PyObject *arg) { SET_MUL };
+static PyObject * Vectral_setAdd(Vectral *self, PyObject *arg) { SET_ADD };
+static PyObject * Vectral_setSub(Vectral *self, PyObject *arg) { SET_SUB };
+static PyObject * Vectral_setDiv(Vectral *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Vectral_play(Vectral *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Vectral_out(Vectral *self, PyObject *args, PyObject *kwds) { OUT };
@@ -3158,7 +3140,7 @@ static PyNumberMethods Vectral_as_number = {
     (binaryfunc)Vectral_add,                      /*nb_add*/
     (binaryfunc)Vectral_sub,                 /*nb_subtract*/
     (binaryfunc)Vectral_multiply,                 /*nb_multiply*/
-    (binaryfunc)Vectral_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -3172,16 +3154,16 @@ static PyNumberMethods Vectral_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)Vectral_inplace_add,              /*inplace_add*/
     (binaryfunc)Vectral_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)Vectral_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)Vectral_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -3190,15 +3172,14 @@ static PyNumberMethods Vectral_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)Vectral_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)Vectral_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject VectralType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Vectral_base",         /*tp_name*/
     sizeof(Vectral),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -3206,7 +3187,7 @@ PyTypeObject VectralType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &Vectral_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -3274,13 +3255,13 @@ CvlVerb_alloc_memories(CvlVerb *self) {
     self->hsize = self->size / 2;
     self->size2 = self->size * 2;
     n8 = self->size2 >> 3;
-    self->real = (MYFLT *)realloc(self->real, self->size * sizeof(MYFLT));    
-    self->imag = (MYFLT *)realloc(self->imag, self->size * sizeof(MYFLT));    
+    self->real = (MYFLT *)realloc(self->real, self->size * sizeof(MYFLT));
+    self->imag = (MYFLT *)realloc(self->imag, self->size * sizeof(MYFLT));
     self->inframe = (MYFLT *)realloc(self->inframe, self->size2 * sizeof(MYFLT));
-    self->outframe = (MYFLT *)realloc(self->outframe, self->size2 * sizeof(MYFLT));       
-    self->last_half_frame = (MYFLT *)realloc(self->last_half_frame, self->size * sizeof(MYFLT));    
-    self->input_buffer = (MYFLT *)realloc(self->output_buffer, self->size * sizeof(MYFLT));    
-    self->output_buffer = (MYFLT *)realloc(self->output_buffer, self->size2 * sizeof(MYFLT));    
+    self->outframe = (MYFLT *)realloc(self->outframe, self->size2 * sizeof(MYFLT));
+    self->last_half_frame = (MYFLT *)realloc(self->last_half_frame, self->size * sizeof(MYFLT));
+    self->input_buffer = (MYFLT *)realloc(self->input_buffer, self->size * sizeof(MYFLT));
+    self->output_buffer = (MYFLT *)realloc(self->output_buffer, self->size2 * sizeof(MYFLT));
     for (i=0; i<self->size2; i++)
         self->inframe[i] = self->outframe[i] = self->output_buffer[i] = 0.0;
     for (i=0; i<self->size; i++)
@@ -3301,16 +3282,16 @@ CvlVerb_analyse_impulse(CvlVerb *self) {
     info.format = 0;
     sf = sf_open(self->impulse_path, SFM_READ, &info);
     if (sf == NULL) {
-        printf("CvlVerb failed to open the impulse file %s.\n", self->impulse_path);
+        PySys_WriteStdout("CvlVerb failed to open the impulse file %s.\n", self->impulse_path);
         return;
     }
     snd_size = info.frames;
     snd_sr = info.samplerate;
     snd_chnls = info.channels;
     num_items = snd_size * snd_chnls;
-    
+
     if (snd_sr != self->sr) {
-        printf("CvlVerb warning : Impulse sampling rate does't match the sampling rate of the server.\n");
+        PySys_WriteStdout("CvlVerb warning: Impulse sampling rate does't match the sampling rate of the server.\n");
     }
 
     self->num_iter = (int)MYCEIL((MYFLT)snd_size / self->size);
@@ -3331,8 +3312,8 @@ CvlVerb_analyse_impulse(CvlVerb *self) {
 
     self->impulse_real = (MYFLT **)realloc(self->impulse_real, self->num_iter * sizeof(MYFLT *));
     self->impulse_imag = (MYFLT **)realloc(self->impulse_imag, self->num_iter * sizeof(MYFLT *));
-    self->accum_real = (MYFLT **)realloc(self->accum_real, self->num_iter * sizeof(MYFLT *));    
-    self->accum_imag = (MYFLT **)realloc(self->accum_imag, self->num_iter * sizeof(MYFLT *)); 
+    self->accum_real = (MYFLT **)realloc(self->accum_real, self->num_iter * sizeof(MYFLT *));
+    self->accum_imag = (MYFLT **)realloc(self->accum_imag, self->num_iter * sizeof(MYFLT *));
     for(i=0; i<self->num_iter; i++) {
         self->impulse_real[i] = (MYFLT *)malloc(self->size * sizeof(MYFLT));
         self->impulse_imag[i] = (MYFLT *)malloc(self->size * sizeof(MYFLT));
@@ -3346,7 +3327,7 @@ CvlVerb_analyse_impulse(CvlVerb *self) {
 
     inframe = (MYFLT *)malloc(self->size2 * sizeof(MYFLT));
     outframe = (MYFLT *)malloc(self->size2 * sizeof(MYFLT));
-    
+
     for (j=0; j<self->num_iter; j++) {
         num = j * self->size;
         for (i=0; i<self->size; i++) {
@@ -3354,7 +3335,7 @@ CvlVerb_analyse_impulse(CvlVerb *self) {
         }
         for (i=self->size; i<self->size2; i++) {
             inframe[i] = 0.0;
-        }        
+        }
         realfft_split(inframe, outframe, self->size2, self->twiddle);
         self->impulse_real[j][0] = outframe[0];
         self->impulse_imag[j][0] = 0.0;
@@ -3363,7 +3344,7 @@ CvlVerb_analyse_impulse(CvlVerb *self) {
             self->impulse_imag[j][i] = outframe[self->size2 - i];
         }
     }
-    
+
     free(tmp);
     free(tmp2);
     free(inframe);
@@ -3385,11 +3366,11 @@ CvlVerb_process_i(CvlVerb *self) {
     for (i=0; i<self->bufsize; i++) {
         self->input_buffer[self->incount] = in[i];
         self->data[i] = (self->output_buffer[self->incount] * 100 * bal) + (in[i] * gdry);
-        
+
         self->incount++;
         if (self->incount == self->size) {
             self->incount = 0;
-            
+
             k = self->current_iter - 1;
             if (k < 0)
                 k += self->num_iter;
@@ -3430,7 +3411,7 @@ CvlVerb_process_i(CvlVerb *self) {
             if (self->current_iter == self->num_iter)
                 self->current_iter = 0;
         }
-    } 
+    }
 }
 
 static void
@@ -3449,11 +3430,11 @@ CvlVerb_process_a(CvlVerb *self) {
         gdry = 1.0 - gwet;
         self->input_buffer[self->incount] = in[i];
         self->data[i] = (self->output_buffer[self->incount] * 100 * gwet) + in[i] * gdry;
-        
+
         self->incount++;
         if (self->incount == self->size) {
             self->incount = 0;
-            
+
             k = self->current_iter - 1;
             if (k < 0)
                 k += self->num_iter;
@@ -3494,7 +3475,7 @@ CvlVerb_process_a(CvlVerb *self) {
             if (self->current_iter == self->num_iter)
                 self->current_iter = 0;
         }
-    } 
+    }
 }
 
 static void CvlVerb_postprocessing_ii(CvlVerb *self) { POST_PROCESSING_II };
@@ -3509,46 +3490,46 @@ static void CvlVerb_postprocessing_revareva(CvlVerb *self) { POST_PROCESSING_REV
 
 static void
 CvlVerb_setProcMode(CvlVerb *self)
-{        
+{
     int procmode, muladdmode;
     procmode = self->modebuffer[2];
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
     switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = CvlVerb_process_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = CvlVerb_process_a;
             break;
-    }     
-      
+    }
+
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = CvlVerb_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = CvlVerb_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = CvlVerb_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = CvlVerb_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = CvlVerb_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = CvlVerb_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = CvlVerb_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = CvlVerb_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = CvlVerb_postprocessing_revareva;
             break;
     }
@@ -3557,7 +3538,7 @@ CvlVerb_setProcMode(CvlVerb *self)
 static void
 CvlVerb_compute_next_data_frame(CvlVerb *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -3572,7 +3553,7 @@ CvlVerb_traverse(CvlVerb *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 CvlVerb_clear(CvlVerb *self)
 {
     pyo_CLEAR
@@ -3602,7 +3583,7 @@ CvlVerb_dealloc(CvlVerb* self)
         free(self->impulse_imag[i]);
         free(self->accum_real[i]);
         free(self->accum_imag[i]);
-    }    
+    }
     free(self->impulse_real);
     free(self->impulse_imag);
     free(self->accum_real);
@@ -3610,17 +3591,18 @@ CvlVerb_dealloc(CvlVerb* self)
     free(self->real);
     free(self->imag);
     CvlVerb_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
 CvlVerb_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i, k;
+    Py_ssize_t psize;
     PyObject *inputtmp, *input_streamtmp, *baltmp=NULL, *multmp=NULL, *addtmp=NULL;
     CvlVerb *self;
     self = (CvlVerb *)type->tp_alloc(type, 0);
-    
+
     self->bal = PyFloat_FromDouble(0.25);
     self->size = 1024;
     self->chnl = 0;
@@ -3631,15 +3613,15 @@ CvlVerb_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = CvlVerb_setProcMode;
 
     static char *kwlist[] = {"input", "impulse", "bal", "size", "chnl", "mul", "add", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "Os|OiiOO", kwlist, &inputtmp, &self->impulse_path, &baltmp, &self->size, &self->chnl, &multmp, &addtmp))
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "Os#|OiiOO", kwlist, &inputtmp, &self->impulse_path, &psize, &baltmp, &self->size, &self->chnl, &multmp, &addtmp))
         Py_RETURN_NONE;
 
     if (self->size < self->bufsize) {
-        printf("Warning : CvlVerb size less than buffer size!\nCvlVerb size set to buffersize: %d\n", self->bufsize);
+        PySys_WriteStdout("Warning: CvlVerb size less than buffer size!\nCvlVerb size set to buffersize: %d\n", self->bufsize);
         self->size = self->bufsize;
     }
-    
+
     k = 1;
     while (k < self->size)
         k <<= 1;
@@ -3654,13 +3636,13 @@ CvlVerb_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     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);
-    
+
     CvlVerb_alloc_memories(self);
     CvlVerb_analyse_impulse(self);
 
@@ -3673,14 +3655,11 @@ static PyObject *
 CvlVerb_setBal(CvlVerb *self, PyObject *arg)
 {
     PyObject *tmp, *streamtmp;
-    
-    if (arg == NULL) {
-        Py_INCREF(Py_None);
-        return Py_None;
-    }
-    
+
+    ASSERT_ARG_NOT_NULL
+
     int isNumber = PyNumber_Check(arg);
-    
+
     tmp = arg;
     Py_INCREF(tmp);
     Py_DECREF(self->bal);
@@ -3698,17 +3677,17 @@ CvlVerb_setBal(CvlVerb *self, PyObject *arg)
     }
 
     (*self->mode_func_ptr)(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
-}    
+}
 
 static PyObject * CvlVerb_getServer(CvlVerb* self) { GET_SERVER };
 static PyObject * CvlVerb_getStream(CvlVerb* self) { GET_STREAM };
-static PyObject * CvlVerb_setMul(CvlVerb *self, PyObject *arg) { SET_MUL };    
-static PyObject * CvlVerb_setAdd(CvlVerb *self, PyObject *arg) { SET_ADD };    
-static PyObject * CvlVerb_setSub(CvlVerb *self, PyObject *arg) { SET_SUB };    
-static PyObject * CvlVerb_setDiv(CvlVerb *self, PyObject *arg) { SET_DIV };    
+static PyObject * CvlVerb_setMul(CvlVerb *self, PyObject *arg) { SET_MUL };
+static PyObject * CvlVerb_setAdd(CvlVerb *self, PyObject *arg) { SET_ADD };
+static PyObject * CvlVerb_setSub(CvlVerb *self, PyObject *arg) { SET_SUB };
+static PyObject * CvlVerb_setDiv(CvlVerb *self, PyObject *arg) { SET_DIV };
 
 static PyObject * CvlVerb_play(CvlVerb *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * CvlVerb_out(CvlVerb *self, PyObject *args, PyObject *kwds) { OUT };
@@ -3752,7 +3731,7 @@ static PyNumberMethods CvlVerb_as_number = {
     (binaryfunc)CvlVerb_add,                      /*nb_add*/
     (binaryfunc)CvlVerb_sub,                 /*nb_subtract*/
     (binaryfunc)CvlVerb_multiply,                 /*nb_multiply*/
-    (binaryfunc)CvlVerb_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -3766,16 +3745,16 @@ static PyNumberMethods CvlVerb_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)CvlVerb_inplace_add,              /*inplace_add*/
     (binaryfunc)CvlVerb_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)CvlVerb_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)CvlVerb_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -3784,15 +3763,14 @@ static PyNumberMethods CvlVerb_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)CvlVerb_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)CvlVerb_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject CvlVerbType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.CvlVerb_base",                                   /*tp_name*/
 sizeof(CvlVerb),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -3800,7 +3778,7 @@ sizeof(CvlVerb),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &CvlVerb_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -3852,9 +3830,9 @@ typedef struct {
     MYFLT *input_buffer;
     MYFLT *inframe;
     MYFLT *outframe;
-    MYFLT *magnitude;    
-    MYFLT *last_magnitude;    
-    MYFLT *tmpmag;    
+    MYFLT *magnitude;
+    MYFLT *last_magnitude;
+    MYFLT *tmpmag;
     MYFLT *window;
     MYFLT **twiddle;
 } Spectrum;
@@ -3866,12 +3844,12 @@ Spectrum_realloc_memories(Spectrum *self) {
     n8 = self->size >> 3;
     self->input_buffer = (MYFLT *)realloc(self->input_buffer, self->size * sizeof(MYFLT));
     self->inframe = (MYFLT *)realloc(self->inframe, self->size * sizeof(MYFLT));
-    self->outframe = (MYFLT *)realloc(self->outframe, self->size * sizeof(MYFLT));    
+    self->outframe = (MYFLT *)realloc(self->outframe, self->size * sizeof(MYFLT));
     for (i=0; i<self->size; i++)
         self->input_buffer[i] = self->inframe[i] = self->outframe[i] = 0.0;
-    self->magnitude = (MYFLT *)realloc(self->magnitude, self->hsize * sizeof(MYFLT));    
-    self->last_magnitude = (MYFLT *)realloc(self->last_magnitude, self->hsize * sizeof(MYFLT));    
-    self->tmpmag = (MYFLT *)realloc(self->tmpmag, (self->hsize+6) * sizeof(MYFLT));    
+    self->magnitude = (MYFLT *)realloc(self->magnitude, self->hsize * sizeof(MYFLT));
+    self->last_magnitude = (MYFLT *)realloc(self->last_magnitude, self->hsize * sizeof(MYFLT));
+    self->tmpmag = (MYFLT *)realloc(self->tmpmag, (self->hsize+6) * sizeof(MYFLT));
     for (i=0; i<self->hsize; i++)
         self->magnitude[i] = self->last_magnitude[i] = self->tmpmag[i+3] = 0.0;
     self->twiddle = (MYFLT **)realloc(self->twiddle, 4 * sizeof(MYFLT *));
@@ -3890,7 +3868,7 @@ Spectrum_display(Spectrum *self) {
     MYFLT pos, step, frac, iw, mag, h4;
     MYFLT logmin, logrange;
     PyObject *points, *tuple;
-    
+
     b1 = (int)(self->freqone / self->freqPerBin);
     b2 = (int)(self->freqtwo / self->freqPerBin);
     bins = b2 - b1;
@@ -3928,7 +3906,7 @@ Spectrum_display(Spectrum *self) {
             tuple = PyTuple_New(2);
             mag = ((self->magnitude[p1] + (self->magnitude[p1+1] - self->magnitude[p1]) * frac) * 0.7 * self->gain);
             mag = mag > 0.001 ? mag : 0.001;
-            mag = (60.0 + (20.0 * MYLOG10(mag))) * 0.01666 * h4; 
+            mag = (60.0 + (20.0 * MYLOG10(mag))) * 0.01666 * h4;
             PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(i));
             PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->height - (int)mag));
             PyList_SET_ITEM(points, i+1, tuple);
@@ -3962,13 +3940,13 @@ Spectrum_display(Spectrum *self) {
             tuple = PyTuple_New(2);
             mag = ((self->magnitude[p1] + (self->magnitude[p1+1] - self->magnitude[p1]) * frac) * 0.7 * self->gain);
             mag = mag > 0.001 ? mag : 0.001;
-            mag = (60.0 + (20.0 * MYLOG10(mag))) * 0.01666 * self->height; 
+            mag = (60.0 + (20.0 * MYLOG10(mag))) * 0.01666 * self->height;
             PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(i));
             PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(self->height - (int)mag));
             PyList_SET_ITEM(points, i+1, tuple);
         }
     }
-    
+
     return points;
 }
 
@@ -3977,7 +3955,7 @@ Spectrum_filters(Spectrum *self) {
     int i, j = 0, impos = 0;
     MYFLT tmp = 0.0;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->input_buffer[self->incount] = in[i];
         self->incount++;
@@ -3996,9 +3974,9 @@ Spectrum_filters(Spectrum *self) {
                 self->tmpmag[j+3] = self->last_magnitude[j] = tmp + self->last_magnitude[j] * 0.5;
             }
             for (j=0; j<self->hsize; j++) {
-                tmp =   (self->tmpmag[j] + self->tmpmag[j+6]) * 0.05 + 
-                        (self->tmpmag[j+1] + self->tmpmag[j+5]) * 0.15 + 
-                        (self->tmpmag[j+2] + self->tmpmag[j+4])* 0.3 + 
+                tmp =   (self->tmpmag[j] + self->tmpmag[j+6]) * 0.05 +
+                        (self->tmpmag[j+1] + self->tmpmag[j+5]) * 0.15 +
+                        (self->tmpmag[j+2] + self->tmpmag[j+4])* 0.3 +
                         self->tmpmag[j+3] * 0.5;
                 self->magnitude[j] = tmp;
                 self->input_buffer[j] = self->input_buffer[j+self->hsize];
@@ -4009,14 +3987,14 @@ Spectrum_filters(Spectrum *self) {
 
 static void
 Spectrum_setProcMode(Spectrum *self)
-{        
-    self->proc_func_ptr = Spectrum_filters;  
+{
+    self->proc_func_ptr = Spectrum_filters;
 }
 
 static void
 Spectrum_compute_next_data_frame(Spectrum *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -4028,7 +4006,7 @@ Spectrum_traverse(Spectrum *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Spectrum_clear(Spectrum *self)
 {
     pyo_CLEAR
@@ -4054,7 +4032,7 @@ Spectrum_dealloc(Spectrum* self)
     }
     free(self->twiddle);
     Spectrum_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -4064,7 +4042,7 @@ Spectrum_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp;
     Spectrum *self;
     self = (Spectrum *)type->tp_alloc(type, 0);
-    
+
     self->size = 1024;
     self->wintype = 2;
 
@@ -4078,17 +4056,17 @@ Spectrum_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->height = 400;
     self->fscaling = 0;
     self->mscaling = 1;
-    
+
     Stream_setFunctionPtr(self->stream, Spectrum_compute_next_data_frame);
     self->mode_func_ptr = Spectrum_setProcMode;
 
     static char *kwlist[] = {"input", "size", "wintype", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|ii", kwlist, &inputtmp, &self->size, &self->wintype))
         Py_RETURN_NONE;
 
     INIT_INPUT_STREAM
- 
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     if (!isPowerOfTwo(self->size)) {
@@ -4096,7 +4074,7 @@ Spectrum_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         while (k < self->size)
             k *= 2;
         self->size = k;
-        printf("size must be a power-of-2, using the next power-of-2 greater than size : %d\n", self->size);
+        PySys_WriteStdout("Spectrum: size argument must be a power-of-2, using the next power-of-2 greater than size : %d\n", self->size);
     }
 
     Spectrum_realloc_memories(self);
@@ -4113,7 +4091,7 @@ static PyObject * Spectrum_stop(Spectrum *self) { STOP };
 
 static PyObject *
 Spectrum_setSize(Spectrum *self, PyObject *arg)
-{    
+{
     int tmp;
     if (PyLong_Check(arg) || PyInt_Check(arg)) {
         tmp = PyInt_AsLong(arg);
@@ -4122,36 +4100,36 @@ Spectrum_setSize(Spectrum *self, PyObject *arg)
             Spectrum_realloc_memories(self);
         }
         else
-            printf("FFT size must be a power of two!\n");
-    }    
-    
+            PySys_WriteStdout("FFT size must be a power of two!\n");
+    }
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
 static PyObject *
 Spectrum_setWinType(Spectrum *self, PyObject *arg)
-{    
+{
     if (PyLong_Check(arg) || PyInt_Check(arg)) {
         self->wintype = PyLong_AsLong(arg);
         gen_window(self->window, self->size, self->wintype);
-    }    
-    
+    }
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
 static PyObject *
 Spectrum_setLowbound(Spectrum *self, PyObject *arg)
-{    
+{
     MYFLT tmp;
     if (PyNumber_Check(arg)) {
-        tmp = PyFloat_AsDouble(PyNumber_Float(arg));
+        tmp = PyFloat_AsDouble(arg);
         if (tmp >= 0.0 && tmp <= 0.5)
             self->freqone = tmp * self->sr;
         else
             self->freqone = 0.0;
-    }    
+    }
     else
         self->freqone = 0.0;
 
@@ -4166,10 +4144,10 @@ Spectrum_getLowfreq(Spectrum *self)
 
 static PyObject *
 Spectrum_setHighbound(Spectrum *self, PyObject *arg)
-{    
+{
     MYFLT tmp;
     if (PyNumber_Check(arg)) {
-        tmp = PyFloat_AsDouble(PyNumber_Float(arg));
+        tmp = PyFloat_AsDouble(arg);
         if (tmp >= 0.0 && tmp <= 0.5)
             self->freqtwo = tmp * self->sr;
         else
@@ -4177,7 +4155,7 @@ Spectrum_setHighbound(Spectrum *self, PyObject *arg)
     }
     else
         self->freqtwo = self->sr * 0.5;
-    
+
     return PyFloat_FromDouble(MYFLOOR(self->freqtwo / self->freqPerBin) * self->freqPerBin);
 }
 
@@ -4189,50 +4167,50 @@ Spectrum_getHighfreq(Spectrum *self)
 
 static PyObject *
 Spectrum_setWidth(Spectrum *self, PyObject *arg)
-{    
+{
     if (PyInt_Check(arg) || PyLong_Check(arg))
         self->width = PyLong_AsLong(arg);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
 static PyObject *
 Spectrum_setHeight(Spectrum *self, PyObject *arg)
-{    
+{
     if (PyInt_Check(arg) || PyLong_Check(arg))
         self->height = PyLong_AsLong(arg);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
 static PyObject *
 Spectrum_setFscaling(Spectrum *self, PyObject *arg)
-{    
+{
     if (PyInt_Check(arg) || PyLong_Check(arg))
         self->fscaling = PyLong_AsLong(arg);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
 static PyObject *
 Spectrum_setMscaling(Spectrum *self, PyObject *arg)
-{    
+{
     if (PyInt_Check(arg) || PyLong_Check(arg))
         self->mscaling = PyLong_AsLong(arg);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
 static PyObject *
 Spectrum_setGain(Spectrum *self, PyObject *arg)
-{    
+{
     if (PyNumber_Check(arg))
-        self->gain = PyFloat_AsDouble(PyNumber_Float(arg));
-    
+        self->gain = PyFloat_AsDouble(arg);
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -4265,8 +4243,7 @@ static PyMethodDef Spectrum_methods[] = {
 };
 
 PyTypeObject SpectrumType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Spectrum_base",                                   /*tp_name*/
 sizeof(Spectrum),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -4274,7 +4251,7 @@ sizeof(Spectrum),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 0,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -4304,4 +4281,4 @@ Spectrum_members,                                 /* tp_members */
 0,                          /* tp_init */
 0,                                              /* tp_alloc */
 Spectrum_new,                                     /* tp_new */
-};
+};
\ No newline at end of file
diff --git a/src/objects/filtremodule.c b/src/objects/filtremodule.c
index d848581..cece39e 100644
--- a/src/objects/filtremodule.c
+++ b/src/objects/filtremodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
@@ -26,7 +27,7 @@
 #include "servermodule.h"
 #include "dummymodule.h"
 
-static MYFLT HALF_COS_ARRAY[513] = {1.0, 0.99998110153278696, 0.99992440684545181, 0.99982991808087995, 0.99969763881045715, 0.99952757403393411, 0.99931973017923825, 0.99907411510222999, 0.99879073808640628, 0.99846960984254973, 0.99811074250832332, 0.99771414964781235, 0.99727984625101107, 0.99680784873325645, 0.99629817493460782, 0.99575084411917214, 0.99516587697437664, 0.99454329561018584, 0.99388312355826691, 0.9931853857710996, 0.99245010862103322, 0.99167731989928998, 0.99086704881491472, 0.99001932599367026, 0.98913418347688054, 0.98821165472021921, 0.9872517745924454, 0.98625457937408512, 0.98522010675606064, 0.98414839583826585, 0.98303948712808786, 0.98189342253887657, 0.98071024538836005, 0.97949000039700762, 0.97823273368633901, 0.9769384927771817, 0.97560732658787452, 0.97423928543241856, 0.97283442101857576, 0.97139278644591409, 0.96991443620380113, 0.96839942616934394, 0.96684781360527761, 0.96525965715780015, 0.96363501685435693, 0.96197395410137099, 0.96027653168192206, 0.95854281375337425, 0.95677286584495025, 0.95496675485525528, 0.95312454904974775, 0.95124631805815985, 0.94933213287186513, 0.94738206584119555, 0.94539619067270686, 0.9433745824263926, 0.94131731751284708, 0.9392244736903772, 0.93709613006206383, 0.9349323670727715, 0.93273326650610799, 0.93049891148133324, 0.92822938645021758, 0.92592477719384991, 0.92358517081939495, 0.92121065575680161, 0.91880132175545981, 0.91635725988080907, 0.91387856251089561, 0.91136532333288145, 0.90881763733950294, 0.9062356008254806, 0.90361931138387919, 0.90096886790241915, 0.89828437055973898, 0.89556592082160869, 0.89281362143709486, 0.89002757643467667, 0.88720789111831455, 0.8843546720634694, 0.88146802711307481, 0.87854806537346075, 0.87559489721022943, 0.8726086342440843, 0.86958938934661101, 0.86653727663601088, 0.86345241147278784, 0.86033491045538835, 0.85718489141579368, 0.85400247341506719, 0.8507877767388532, 0.84754092289283123, 0.8442620345981231, 0.84095123578665476, 0.8376086515964718, 0.83423440836700968, 0.83082863363431847, 0.82739145612624232, 0.82392300575755428, 0.82042341362504534, 0.81689281200256991, 0.81333133433604599, 0.80973911523841147, 0.80611629048453592, 0.80246299700608914, 0.79877937288636502, 0.7950655573550629, 0.79132169078302494, 0.78754791467693042, 0.78374437167394739, 0.77991120553634141, 0.77604856114604148, 0.77215658449916424, 0.76823542270049605, 0.76428522395793219, 0.7603061375768756, 0.75629831395459302, 0.75226190457453135, 0.74819706200059122, 0.7441039398713607, 0.73998269289430851, 0.73583347683993672, 0.73165644853589207, 0.72745176586103977, 0.72321958773949491, 0.71896007413461649, 0.71467338604296105, 0.71035968548819706, 0.70601913551498185, 0.70165190018279788, 0.69725814455975277, 0.69283803471633953, 0.68839173771916018, 0.68391942162461061, 0.6794212554725293, 0.67489740927980701, 0.67034805403396192, 0.66577336168667567, 0.66117350514729512, 0.65654865827629605, 0.65189899587871258, 0.64722469369752944, 0.6425259284070397, 0.63780287760616672, 0.63305571981175202, 0.62828463445180749, 0.62348980185873359, 0.61867140326250347, 0.61382962078381298, 0.60896463742719675, 0.60407663707411186, 0.59916580447598711, 0.59423232524724023, 0.58927638585826192, 0.58429817362836856, 0.57929787671872113, 0.57427568412521424, 0.56923178567133192, 0.56416637200097319, 0.55907963457124654, 0.55397176564523298, 0.5488429582847193, 0.5436934063429012, 0.53852330445705543, 0.53333284804118442, 0.52812223327862839, 0.52289165711465235, 0.51764131724900009, 0.51237141212842374, 0.50708214093918114, 0.50177370359950879, 0.49644630075206486, 0.49110013375634509, 0.48573540468107329, 0.48035231629656205, 0.47495107206705045, 0.46953187614301212, 0.46409493335344021, 0.45864044919810504, 0.45316862983978612, 0.44767968209648135, 0.44217381343358825, 0.43665123195606403, 0.43111214640055828, 0.42555676612752463, 0.41998530111330729, 0.41439796194220363, 0.40879495979850627, 0.40317650645851943, 0.39754281428255606, 0.3918940962069094, 0.38623056573580644, 0.38055243693333718, 0.3748599244153632, 0.36915324334140731, 0.36343260940651945, 0.35769823883312568, 0.35195034836285416, 0.34618915524834432, 0.34041487724503472, 0.33462773260293199, 0.32882794005836308, 0.32301571882570607, 0.31719128858910622, 0.31135486949417079, 0.30550668213964982, 0.29964694756909749, 0.29377588726251663, 0.28789372312798917, 0.28200067749328667, 0.27609697309746906, 0.27018283308246382, 0.26425848098463345, 0.25832414072632598, 0.25238003660741054, 0.24642639329680122, 0.24046343582396335, 0.23449138957040974, 0.22851048026118126, 0.22252093395631445, 0.21652297704229864, 0.21051683622351761, 0.20450273851368242, 0.19848091122724945, 0.19245158197082995, 0.18641497863458675, 0.1803713293836198, 0.17432086264934399, 0.16826380712085329, 0.16220039173627876, 0.15613084567413366, 0.1500553983446527, 0.14397427938112045, 0.13788771863119115, 0.13179594614820278, 0.12569919218247999, 0.11959768717263308, 0.11349166173684638, 0.10738134666416307, 0.10126697290576155, 0.095148771566225324, 0.089026973894809708, 0.082901811276699419, 0.076773515224264705, 0.070642317368309157, 0.064508449449316344, 0.058372143308689985, 0.052233630879990445, 0.046093144180169916, 0.039950915300801082, 0.033807176399306589, 0.027662159690182372, 0.021516097436222258, 0.01536922193973846, 0.0092217655337806046, 0.0030739605733557966, -0.0030739605733554522, -0.0092217655337804832, -0.015369221939738116, -0.021516097436222133, -0.027662159690182025, -0.033807176399306464, -0.039950915300800735, -0.046093144180169791, -0.052233630879990098, -0.05837214330868986, -0.064508449449316232, -0.07064231736830906, -0.076773515224264371, -0.082901811276699308, -0.089026973894809375, -0.095148771566225213, -0.10126697290576121, -0.10738134666416296, -0.11349166173684605, -0.11959768717263299, -0.12569919218247966, -0.13179594614820267, -0.13788771863119104, -0.14397427938112034, -0.15005539834465259, -0.15613084567413354, -0.16220039173627843, -0.16826380712085318, -0.17432086264934366, -0.18037132938361969, -0.18641497863458642, -0.19245158197082984, -0.19848091122724912, -0.20450273851368231, -0.21051683622351727, -0.21652297704229853, -0.22252093395631434, -0.22851048026118118, -0.23449138957040966, -0.24046343582396323, -0.24642639329680088, -0.25238003660741043, -0.25832414072632565, -0.26425848098463334, -0.27018283308246349, -0.27609697309746895, -0.28200067749328633, -0.28789372312798905, -0.2937758872625163, -0.29964694756909738, -0.30550668213964971, -0.31135486949417068, -0.31719128858910589, -0.32301571882570601, -0.32882794005836274, -0.33462773260293188, -0.34041487724503444, -0.3461891552483442, -0.35195034836285388, -0.35769823883312557, -0.36343260940651911, -0.3691532433414072, -0.37485992441536287, -0.38055243693333707, -0.38623056573580633, -0.39189409620690935, -0.39754281428255578, -0.40317650645851938, -0.408794959798506, -0.41439796194220352, -0.41998530111330723, -0.42555676612752458, -0.43111214640055795, -0.43665123195606392, -0.44217381343358819, -0.44767968209648107, -0.45316862983978584, -0.45864044919810493, -0.46409493335344015, -0.46953187614301223, -0.47495107206704995, -0.48035231629656183, -0.4857354046810729, -0.49110013375634509, -0.4964463007520647, -0.50177370359950857, -0.5070821409391808, -0.51237141212842352, -0.51764131724899998, -0.52289165711465191, -0.52812223327862795, -0.53333284804118419, -0.53852330445705532, -0.5436934063429012, -0.54884295828471885, -0.55397176564523276, -0.55907963457124621, -0.56416637200097308, -0.5692317856713317, -0.57427568412521401, -0.57929787671872079, -0.58429817362836844, -0.5892763858582617, -0.5942323252472399, -0.59916580447598666, -0.60407663707411174, -0.60896463742719653, -0.61382962078381298, -0.61867140326250303, -0.62348980185873337, -0.62828463445180716, -0.6330557198117519, -0.6378028776061665, -0.64252592840703937, -0.64722469369752911, -0.65189899587871247, -0.65654865827629583, -0.66117350514729478, -0.66577336168667522, -0.67034805403396169, -0.67489740927980679, -0.6794212554725293, -0.68391942162461028, -0.68839173771915996, -0.6928380347163392, -0.69725814455975266, -0.70165190018279777, -0.70601913551498163, -0.71035968548819683, -0.71467338604296105, -0.71896007413461638, -0.72321958773949468, -0.72745176586103955, -0.73165644853589207, -0.73583347683993661, -0.73998269289430874, -0.74410393987136036, -0.74819706200059111, -0.75226190457453113, -0.75629831395459302, -0.76030613757687548, -0.76428522395793208, -0.76823542270049594, -0.77215658449916424, -0.77604856114604126, -0.77991120553634119, -0.78374437167394717, -0.78754791467693031, -0.79132169078302472, -0.7950655573550629, -0.79877937288636469, -0.80246299700608903, -0.80611629048453581, -0.80973911523841147, -0.81333133433604599, -0.8168928120025698, -0.82042341362504512, -0.82392300575755417, -0.82739145612624221, -0.83082863363431825, -0.83423440836700946, -0.8376086515964718, -0.84095123578665465, -0.8442620345981231, -0.84754092289283089, -0.85078777673885309, -0.85400247341506696, -0.85718489141579368, -0.86033491045538824, -0.86345241147278773, -0.86653727663601066, -0.86958938934661101, -0.87260863424408419, -0.87559489721022921, -0.87854806537346053, -0.88146802711307481, -0.88435467206346929, -0.88720789111831455, -0.89002757643467667, -0.89281362143709475, -0.89556592082160857, -0.89828437055973898, -0.90096886790241903, -0.90361931138387908, -0.90623560082548038, -0.90881763733950294, -0.91136532333288134, -0.9138785625108955, -0.91635725988080885, -0.91880132175545981, -0.92121065575680139, -0.92358517081939495, -0.9259247771938498, -0.92822938645021758, -0.93049891148133312, -0.93273326650610799, -0.9349323670727715, -0.93709613006206383, -0.93922447369037709, -0.94131731751284708, -0.9433745824263926, -0.94539619067270697, -0.94738206584119544, -0.94933213287186502, -0.95124631805815973, -0.95312454904974775, -0.95496675485525517, -0.95677286584495025, -0.95854281375337413, -0.96027653168192206, -0.96197395410137099, -0.96363501685435693, -0.96525965715780004, -0.9668478136052775, -0.96839942616934394, -0.96991443620380113, -0.97139278644591398, -0.97283442101857565, -0.97423928543241844, -0.97560732658787452, -0.9769384927771817, -0.9782327336863389, -0.97949000039700751, -0.98071024538836005, -0.98189342253887657, -0.98303948712808775, -0.98414839583826574, -0.98522010675606064, -0.98625457937408501, -0.9872517745924454, -0.98821165472021921, -0.98913418347688054, -0.99001932599367015, -0.99086704881491472, -0.99167731989928998, -0.99245010862103311, -0.99318538577109949, -0.99388312355826691, -0.99454329561018584, -0.99516587697437653, -0.99575084411917214, -0.99629817493460782, -0.99680784873325645, -0.99727984625101107, -0.99771414964781235, -0.99811074250832332, -0.99846960984254973, -0.99879073808640628, -0.99907411510222999, -0.99931973017923825, -0.99952757403393411, -0.99969763881045715, -0.99982991808087995, -0.99992440684545181, -0.99998110153278685, -1.0, -1.0}; 
+static MYFLT HALF_COS_ARRAY[513] = {1.0, 0.99998110153278696, 0.99992440684545181, 0.99982991808087995, 0.99969763881045715, 0.99952757403393411, 0.99931973017923825, 0.99907411510222999, 0.99879073808640628, 0.99846960984254973, 0.99811074250832332, 0.99771414964781235, 0.99727984625101107, 0.99680784873325645, 0.99629817493460782, 0.99575084411917214, 0.99516587697437664, 0.99454329561018584, 0.99388312355826691, 0.9931853857710996, 0.99245010862103322, 0.99167731989928998, 0.99086704881491472, 0.99001932599367026, 0.98913418347688054, 0.98821165472021921, 0.9872517745924454, 0.98625457937408512, 0.98522010675606064, 0.98414839583826585, 0.98303948712808786, 0.98189342253887657, 0.98071024538836005, 0.97949000039700762, 0.97823273368633901, 0.9769384927771817, 0.97560732658787452, 0.97423928543241856, 0.97283442101857576, 0.97139278644591409, 0.96991443620380113, 0.96839942616934394, 0.96684781360527761, 0.96525965715780015, 0.96363501685435693, 0.96197395410137099, 0.96027653168192206, 0.95854281375337425, 0.95677286584495025, 0.95496675485525528, 0.95312454904974775, 0.95124631805815985, 0.94933213287186513, 0.94738206584119555, 0.94539619067270686, 0.9433745824263926, 0.94131731751284708, 0.9392244736903772, 0.93709613006206383, 0.9349323670727715, 0.93273326650610799, 0.93049891148133324, 0.92822938645021758, 0.92592477719384991, 0.92358517081939495, 0.92121065575680161, 0.91880132175545981, 0.91635725988080907, 0.91387856251089561, 0.91136532333288145, 0.90881763733950294, 0.9062356008254806, 0.90361931138387919, 0.90096886790241915, 0.89828437055973898, 0.89556592082160869, 0.89281362143709486, 0.89002757643467667, 0.88720789111831455, 0.8843546720634694, 0.88146802711307481, 0.87854806537346075, 0.87559489721022943, 0.8726086342440843, 0.86958938934661101, 0.86653727663601088, 0.86345241147278784, 0.86033491045538835, 0.85718489141579368, 0.85400247341506719, 0.8507877767388532, 0.84754092289283123, 0.8442620345981231, 0.84095123578665476, 0.8376086515964718, 0.83423440836700968, 0.83082863363431847, 0.82739145612624232, 0.82392300575755428, 0.82042341362504534, 0.81689281200256991, 0.81333133433604599, 0.80973911523841147, 0.80611629048453592, 0.80246299700608914, 0.79877937288636502, 0.7950655573550629, 0.79132169078302494, 0.78754791467693042, 0.78374437167394739, 0.77991120553634141, 0.77604856114604148, 0.77215658449916424, 0.76823542270049605, 0.76428522395793219, 0.7603061375768756, 0.75629831395459302, 0.75226190457453135, 0.74819706200059122, 0.7441039398713607, 0.73998269289430851, 0.73583347683993672, 0.73165644853589207, 0.72745176586103977, 0.72321958773949491, 0.71896007413461649, 0.71467338604296105, 0.71035968548819706, 0.70601913551498185, 0.70165190018279788, 0.69725814455975277, 0.69283803471633953, 0.68839173771916018, 0.68391942162461061, 0.6794212554725293, 0.67489740927980701, 0.67034805403396192, 0.66577336168667567, 0.66117350514729512, 0.65654865827629605, 0.65189899587871258, 0.64722469369752944, 0.6425259284070397, 0.63780287760616672, 0.63305571981175202, 0.62828463445180749, 0.62348980185873359, 0.61867140326250347, 0.61382962078381298, 0.60896463742719675, 0.60407663707411186, 0.59916580447598711, 0.59423232524724023, 0.58927638585826192, 0.58429817362836856, 0.57929787671872113, 0.57427568412521424, 0.56923178567133192, 0.56416637200097319, 0.55907963457124654, 0.55397176564523298, 0.5488429582847193, 0.5436934063429012, 0.53852330445705543, 0.53333284804118442, 0.52812223327862839, 0.52289165711465235, 0.51764131724900009, 0.51237141212842374, 0.50708214093918114, 0.50177370359950879, 0.49644630075206486, 0.49110013375634509, 0.48573540468107329, 0.48035231629656205, 0.47495107206705045, 0.46953187614301212, 0.46409493335344021, 0.45864044919810504, 0.45316862983978612, 0.44767968209648135, 0.44217381343358825, 0.43665123195606403, 0.43111214640055828, 0.42555676612752463, 0.41998530111330729, 0.41439796194220363, 0.40879495979850627, 0.40317650645851943, 0.39754281428255606, 0.3918940962069094, 0.38623056573580644, 0.38055243693333718, 0.3748599244153632, 0.36915324334140731, 0.36343260940651945, 0.35769823883312568, 0.35195034836285416, 0.34618915524834432, 0.34041487724503472, 0.33462773260293199, 0.32882794005836308, 0.32301571882570607, 0.31719128858910622, 0.31135486949417079, 0.30550668213964982, 0.29964694756909749, 0.29377588726251663, 0.28789372312798917, 0.28200067749328667, 0.27609697309746906, 0.27018283308246382, 0.26425848098463345, 0.25832414072632598, 0.25238003660741054, 0.24642639329680122, 0.24046343582396335, 0.23449138957040974, 0.22851048026118126, 0.22252093395631445, 0.21652297704229864, 0.21051683622351761, 0.20450273851368242, 0.19848091122724945, 0.19245158197082995, 0.18641497863458675, 0.1803713293836198, 0.17432086264934399, 0.16826380712085329, 0.16220039173627876, 0.15613084567413366, 0.1500553983446527, 0.14397427938112045, 0.13788771863119115, 0.13179594614820278, 0.12569919218247999, 0.11959768717263308, 0.11349166173684638, 0.10738134666416307, 0.10126697290576155, 0.095148771566225324, 0.089026973894809708, 0.082901811276699419, 0.076773515224264705, 0.070642317368309157, 0.064508449449316344, 0.058372143308689985, 0.052233630879990445, 0.046093144180169916, 0.039950915300801082, 0.033807176399306589, 0.027662159690182372, 0.021516097436222258, 0.01536922193973846, 0.0092217655337806046, 0.0030739605733557966, -0.0030739605733554522, -0.0092217655337804832, -0.015369221939738116, -0.021516097436222133, -0.027662159690182025, -0.033807176399306464, -0.039950915300800735, -0.046093144180169791, -0.052233630879990098, -0.05837214330868986, -0.064508449449316232, -0.07064231736830906, -0.076773515224264371, -0.082901811276699308, -0.089026973894809375, -0.095148771566225213, -0.10126697290576121, -0.10738134666416296, -0.11349166173684605, -0.11959768717263299, -0.12569919218247966, -0.13179594614820267, -0.13788771863119104, -0.14397427938112034, -0.15005539834465259, -0.15613084567413354, -0.16220039173627843, -0.16826380712085318, -0.17432086264934366, -0.18037132938361969, -0.18641497863458642, -0.19245158197082984, -0.19848091122724912, -0.20450273851368231, -0.21051683622351727, -0.21652297704229853, -0.22252093395631434, -0.22851048026118118, -0.23449138957040966, -0.24046343582396323, -0.24642639329680088, -0.25238003660741043, -0.25832414072632565, -0.26425848098463334, -0.27018283308246349, -0.27609697309746895, -0.28200067749328633, -0.28789372312798905, -0.2937758872625163, -0.29964694756909738, -0.30550668213964971, -0.31135486949417068, -0.31719128858910589, -0.32301571882570601, -0.32882794005836274, -0.33462773260293188, -0.34041487724503444, -0.3461891552483442, -0.35195034836285388, -0.35769823883312557, -0.36343260940651911, -0.3691532433414072, -0.37485992441536287, -0.38055243693333707, -0.38623056573580633, -0.39189409620690935, -0.39754281428255578, -0.40317650645851938, -0.408794959798506, -0.41439796194220352, -0.41998530111330723, -0.42555676612752458, -0.43111214640055795, -0.43665123195606392, -0.44217381343358819, -0.44767968209648107, -0.45316862983978584, -0.45864044919810493, -0.46409493335344015, -0.46953187614301223, -0.47495107206704995, -0.48035231629656183, -0.4857354046810729, -0.49110013375634509, -0.4964463007520647, -0.50177370359950857, -0.5070821409391808, -0.51237141212842352, -0.51764131724899998, -0.52289165711465191, -0.52812223327862795, -0.53333284804118419, -0.53852330445705532, -0.5436934063429012, -0.54884295828471885, -0.55397176564523276, -0.55907963457124621, -0.56416637200097308, -0.5692317856713317, -0.57427568412521401, -0.57929787671872079, -0.58429817362836844, -0.5892763858582617, -0.5942323252472399, -0.59916580447598666, -0.60407663707411174, -0.60896463742719653, -0.61382962078381298, -0.61867140326250303, -0.62348980185873337, -0.62828463445180716, -0.6330557198117519, -0.6378028776061665, -0.64252592840703937, -0.64722469369752911, -0.65189899587871247, -0.65654865827629583, -0.66117350514729478, -0.66577336168667522, -0.67034805403396169, -0.67489740927980679, -0.6794212554725293, -0.68391942162461028, -0.68839173771915996, -0.6928380347163392, -0.69725814455975266, -0.70165190018279777, -0.70601913551498163, -0.71035968548819683, -0.71467338604296105, -0.71896007413461638, -0.72321958773949468, -0.72745176586103955, -0.73165644853589207, -0.73583347683993661, -0.73998269289430874, -0.74410393987136036, -0.74819706200059111, -0.75226190457453113, -0.75629831395459302, -0.76030613757687548, -0.76428522395793208, -0.76823542270049594, -0.77215658449916424, -0.77604856114604126, -0.77991120553634119, -0.78374437167394717, -0.78754791467693031, -0.79132169078302472, -0.7950655573550629, -0.79877937288636469, -0.80246299700608903, -0.80611629048453581, -0.80973911523841147, -0.81333133433604599, -0.8168928120025698, -0.82042341362504512, -0.82392300575755417, -0.82739145612624221, -0.83082863363431825, -0.83423440836700946, -0.8376086515964718, -0.84095123578665465, -0.8442620345981231, -0.84754092289283089, -0.85078777673885309, -0.85400247341506696, -0.85718489141579368, -0.86033491045538824, -0.86345241147278773, -0.86653727663601066, -0.86958938934661101, -0.87260863424408419, -0.87559489721022921, -0.87854806537346053, -0.88146802711307481, -0.88435467206346929, -0.88720789111831455, -0.89002757643467667, -0.89281362143709475, -0.89556592082160857, -0.89828437055973898, -0.90096886790241903, -0.90361931138387908, -0.90623560082548038, -0.90881763733950294, -0.91136532333288134, -0.9138785625108955, -0.91635725988080885, -0.91880132175545981, -0.92121065575680139, -0.92358517081939495, -0.9259247771938498, -0.92822938645021758, -0.93049891148133312, -0.93273326650610799, -0.9349323670727715, -0.93709613006206383, -0.93922447369037709, -0.94131731751284708, -0.9433745824263926, -0.94539619067270697, -0.94738206584119544, -0.94933213287186502, -0.95124631805815973, -0.95312454904974775, -0.95496675485525517, -0.95677286584495025, -0.95854281375337413, -0.96027653168192206, -0.96197395410137099, -0.96363501685435693, -0.96525965715780004, -0.9668478136052775, -0.96839942616934394, -0.96991443620380113, -0.97139278644591398, -0.97283442101857565, -0.97423928543241844, -0.97560732658787452, -0.9769384927771817, -0.9782327336863389, -0.97949000039700751, -0.98071024538836005, -0.98189342253887657, -0.98303948712808775, -0.98414839583826574, -0.98522010675606064, -0.98625457937408501, -0.9872517745924454, -0.98821165472021921, -0.98913418347688054, -0.99001932599367015, -0.99086704881491472, -0.99167731989928998, -0.99245010862103311, -0.99318538577109949, -0.99388312355826691, -0.99454329561018584, -0.99516587697437653, -0.99575084411917214, -0.99629817493460782, -0.99680784873325645, -0.99727984625101107, -0.99771414964781235, -0.99811074250832332, -0.99846960984254973, -0.99879073808640628, -0.99907411510222999, -0.99931973017923825, -0.99952757403393411, -0.99969763881045715, -0.99982991808087995, -0.99992440684545181, -0.99998110153278685, -1.0, -1.0};
 
 typedef struct {
     pyo_audio_HEAD
@@ -38,9 +39,10 @@ typedef struct {
     Stream *q_stream;
     void (*coeffs_func_ptr)();
     int init;
-    int modebuffer[4]; // need at least 2 slots for mul & add 
+    int modebuffer[4]; // need at least 2 slots for mul & add
     int filtertype;
     MYFLT nyquist;
+    MYFLT twoPiOverSr;
     // sample memories
     MYFLT x1;
     MYFLT x2;
@@ -59,67 +61,68 @@ typedef struct {
     MYFLT a2;
 } Biquad;
 
-static void 
+static void
 Biquad_compute_coeffs_lp(Biquad *self)
 {
     self->b0 = self->b2 = (1 - self->c) / 2;
     self->b1 = 1 - self->c;
-    self->a0 = 1 + self->alpha;
+    self->a0 = 1.0 / (1 + self->alpha);
     self->a1 = -2 * self->c;
     self->a2 = 1 - self->alpha;
 }
 
-static void 
+static void
 Biquad_compute_coeffs_hp(Biquad *self)
 {
     self->b0 = (1 + self->c) / 2;
     self->b1 = -(1 + self->c);
     self->b2 = self->b0;
-    self->a0 = 1 + self->alpha;
+    self->a0 = 1.0 / (1 + self->alpha);
     self->a1 = -2 * self->c;
     self->a2 = 1 - self->alpha;
 }
 
-static void 
+static void
 Biquad_compute_coeffs_bp(Biquad *self)
 {
     self->b0 = self->alpha;
     self->b1 = 0;
     self->b2 = -self->alpha;
-    self->a0 = 1 + self->alpha;
+    self->a0 = 1.0 / (1 + self->alpha);
     self->a1 = -2 * self->c;
     self->a2 = 1 - self->alpha;
 }
 
-static void 
+static void
 Biquad_compute_coeffs_bs(Biquad *self)
 {
     self->b0 = 1;
     self->b1 = self->a1 = -2 * self->c;
     self->b2 = 1;
-    self->a0 = 1 + self->alpha;
+    self->a0 = 1.0 / (1 + self->alpha);
     self->a2 = 1 - self->alpha;
 }
 
-static void 
+static void
 Biquad_compute_coeffs_ap(Biquad *self)
 {
     self->b0 = self->a2 = 1 - self->alpha;
     self->b1 = self->a1 = -2 * self->c;
-    self->b2 = self->a0 = 1 + self->alpha;
+    self->b2 = 1 + self->alpha;
+    self->a0 = 1.0 / (1 + self->alpha);
 }
 
 static void
 Biquad_compute_variables(Biquad *self, MYFLT freq, MYFLT q)
-{    
-    if (freq <= 1) 
+{
+    if (freq <= 1)
         freq = 1;
     else if (freq >= self->nyquist)
         freq = self->nyquist;
     if (q < 0.1)
         q = 0.1;
-    
-    self->w0 = TWOPI * freq / self->sr;
+
+    self->w0 = freq * self->twoPiOverSr;
     self->c = MYCOS(self->w0);
     self->alpha = MYSIN(self->w0) / (2 * q);
     (*self->coeffs_func_ptr)(self);
@@ -135,14 +138,13 @@ Biquad_filters_ii(Biquad *self) {
         self->x1 = self->x2 = self->y1 = self->y2 = in[0];
         self->init = 0;
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
-        val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
+        val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) * self->a0;
         self->y2 = self->y1;
-        self->y1 = val;
+        self->data[i] = self->y1 = val;
         self->x2 = self->x1;
         self->x1 = in[i];
-        self->data[i] = val;
     }
 }
 
@@ -151,7 +153,7 @@ Biquad_filters_ai(Biquad *self) {
     MYFLT val, q;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->init == 1) {
         self->x1 = self->x2 = self->y1 = self->y2 = in[0];
         self->init = 0;
@@ -159,15 +161,14 @@ Biquad_filters_ai(Biquad *self) {
 
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
     q = PyFloat_AS_DOUBLE(self->q);
-    
+
     for (i=0; i<self->bufsize; i++) {
         Biquad_compute_variables(self, fr[i], q);
-        val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
+        val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) * self->a0;
         self->y2 = self->y1;
-        self->y1 = val;
+        self->data[i] = self->y1 = val;
         self->x2 = self->x1;
         self->x1 = in[i];
-        self->data[i] = val;
     }
 }
 
@@ -176,23 +177,22 @@ Biquad_filters_ia(Biquad *self) {
     MYFLT val, fr;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->init == 1) {
         self->x1 = self->x2 = self->y1 = self->y2 = in[0];
         self->init = 0;
     }
-    
+
     fr = PyFloat_AS_DOUBLE(self->freq);
     MYFLT *q = Stream_getData((Stream *)self->q_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         Biquad_compute_variables(self, fr, q[i]);
-        val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
+        val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) * self->a0;
         self->y2 = self->y1;
-        self->y1 = val;
+        self->data[i] = self->y1 = val;
         self->x2 = self->x1;
         self->x1 = in[i];
-        self->data[i] = val;
     }
 }
 
@@ -201,7 +201,7 @@ Biquad_filters_aa(Biquad *self) {
     MYFLT val;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->init == 1) {
         self->x1 = self->x2 = self->y1 = self->y2 = in[0];
         self->init = 0;
@@ -212,12 +212,11 @@ Biquad_filters_aa(Biquad *self) {
 
     for (i=0; i<self->bufsize; i++) {
         Biquad_compute_variables(self, fr[i], q[i]);
-        val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
+        val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) * self->a0;
         self->y2 = self->y1;
-        self->y1 = val;
+        self->data[i] = self->y1 = val;
         self->x2 = self->x1;
         self->x1 = in[i];
-        self->data[i] = val;
     }
 }
 
@@ -255,57 +254,57 @@ Biquad_setProcMode(Biquad *self)
             self->coeffs_func_ptr = Biquad_compute_coeffs_ap;
             break;
     }
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             Biquad_compute_variables(self, PyFloat_AS_DOUBLE(self->freq), PyFloat_AS_DOUBLE(self->q));
             self->proc_func_ptr = Biquad_filters_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Biquad_filters_ai;
             break;
-        case 10:        
+        case 10:
             self->proc_func_ptr = Biquad_filters_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Biquad_filters_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Biquad_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Biquad_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Biquad_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Biquad_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Biquad_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Biquad_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Biquad_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Biquad_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Biquad_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Biquad_compute_next_data_frame(Biquad *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -315,23 +314,23 @@ Biquad_traverse(Biquad *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
-    Py_VISIT(self->q);    
-    Py_VISIT(self->q_stream);    
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->q);
+    Py_VISIT(self->q_stream);
     return 0;
 }
 
-static int 
+static int
 Biquad_clear(Biquad *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
-    Py_CLEAR(self->q);    
-    Py_CLEAR(self->q_stream);    
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->q);
+    Py_CLEAR(self->q_stream);
     return 0;
 }
 
@@ -340,7 +339,7 @@ Biquad_dealloc(Biquad* self)
 {
     pyo_DEALLOC
     Biquad_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -350,7 +349,7 @@ Biquad_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *qtmp=NULL, *multmp=NULL, *addtmp=NULL;
     Biquad *self;
     self = (Biquad *)type->tp_alloc(type, 0);
-        
+
     self->freq = PyFloat_FromDouble(1000);
     self->q = PyFloat_FromDouble(1);
     self->filtertype = 0;
@@ -361,9 +360,10 @@ Biquad_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->init = 1;
 
     INIT_OBJECT_COMMON
-    
+
     self->nyquist = (MYFLT)self->sr * 0.49;
-    
+    self->twoPiOverSr = TWOPI / (MYFLT)self->sr;
+
     Stream_setFunctionPtr(self->stream, Biquad_compute_next_data_frame);
     self->mode_func_ptr = Biquad_setProcMode;
 
@@ -373,7 +373,7 @@ Biquad_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         Py_RETURN_NONE;
 
     INIT_INPUT_STREAM
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
@@ -381,7 +381,7 @@ Biquad_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (qtmp) {
         PyObject_CallMethod((PyObject *)self, "setQ", "O", qtmp);
     }
-    
+
     if (multmp) {
         PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
     }
@@ -389,7 +389,7 @@ Biquad_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (addtmp) {
         PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
     }
-            
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     (*self->mode_func_ptr)(self);
@@ -399,10 +399,10 @@ Biquad_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Biquad_getServer(Biquad* self) { GET_SERVER };
 static PyObject * Biquad_getStream(Biquad* self) { GET_STREAM };
-static PyObject * Biquad_setMul(Biquad *self, PyObject *arg) { SET_MUL };	
-static PyObject * Biquad_setAdd(Biquad *self, PyObject *arg) { SET_ADD };	
-static PyObject * Biquad_setSub(Biquad *self, PyObject *arg) { SET_SUB };	
-static PyObject * Biquad_setDiv(Biquad *self, PyObject *arg) { SET_DIV };	
+static PyObject * Biquad_setMul(Biquad *self, PyObject *arg) { SET_MUL };
+static PyObject * Biquad_setAdd(Biquad *self, PyObject *arg) { SET_ADD };
+static PyObject * Biquad_setSub(Biquad *self, PyObject *arg) { SET_SUB };
+static PyObject * Biquad_setDiv(Biquad *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Biquad_play(Biquad *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Biquad_out(Biquad *self, PyObject *args, PyObject *kwds) { OUT };
@@ -421,14 +421,11 @@ static PyObject *
 Biquad_setFreq(Biquad *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -444,25 +441,22 @@ Biquad_setFreq(Biquad *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Biquad_setQ(Biquad *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->q);
@@ -478,33 +472,29 @@ Biquad_setQ(Biquad *self, PyObject *arg)
         self->q_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Biquad_setType(Biquad *self, PyObject *arg)
 {
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	
+    ASSERT_ARG_NOT_NULL
+
 	int isInt = PyInt_Check(arg);
-    
+
 	if (isInt == 1) {
 		self->filtertype = PyInt_AsLong(arg);
 	}
 
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Biquad_members[] = {
     {"server", T_OBJECT_EX, offsetof(Biquad, server), 0, "Pyo server."},
@@ -537,7 +527,7 @@ static PyNumberMethods Biquad_as_number = {
     (binaryfunc)Biquad_add,                         /*nb_add*/
     (binaryfunc)Biquad_sub,                         /*nb_subtract*/
     (binaryfunc)Biquad_multiply,                    /*nb_multiply*/
-    (binaryfunc)Biquad_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -551,16 +541,16 @@ static PyNumberMethods Biquad_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Biquad_inplace_add,                 /*inplace_add*/
     (binaryfunc)Biquad_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Biquad_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Biquad_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -569,15 +559,14 @@ static PyNumberMethods Biquad_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Biquad_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Biquad_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject BiquadType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Biquad_base",                                   /*tp_name*/
     sizeof(Biquad),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -585,7 +574,7 @@ PyTypeObject BiquadType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &Biquad_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -627,7 +616,7 @@ typedef struct {
     Stream *q_stream;
     void (*coeffs_func_ptr)();
     int init;
-    int modebuffer[4]; // need at least 2 slots for mul & add 
+    int modebuffer[4]; // need at least 2 slots for mul & add
     int filtertype;
     int stages;
     MYFLT nyquist;
@@ -659,66 +648,67 @@ Biquadx_allocate_memories(Biquadx *self)
     self->init = 1;
 }
 
-static void 
+static void
 Biquadx_compute_coeffs_lp(Biquadx *self)
 {
     self->b0 = self->b2 = (1 - self->c) / 2;
     self->b1 = 1 - self->c;
-    self->a0 = 1 + self->alpha;
+    self->a0 = 1.0 / (1 + self->alpha);
     self->a1 = -2 * self->c;
     self->a2 = 1 - self->alpha;
 }
 
-static void 
+static void
 Biquadx_compute_coeffs_hp(Biquadx *self)
 {
     self->b0 = (1 + self->c) / 2;
     self->b1 = -(1 + self->c);
     self->b2 = self->b0;
-    self->a0 = 1 + self->alpha;
+    self->a0 = 1.0 / (1 + self->alpha);
     self->a1 = -2 * self->c;
     self->a2 = 1 - self->alpha;
 }
 
-static void 
+static void
 Biquadx_compute_coeffs_bp(Biquadx *self)
 {
     self->b0 = self->alpha;
     self->b1 = 0;
     self->b2 = -self->alpha;
-    self->a0 = 1 + self->alpha;
+    self->a0 = 1.0 / (1 + self->alpha);
     self->a1 = -2 * self->c;
     self->a2 = 1 - self->alpha;
 }
 
-static void 
+static void
 Biquadx_compute_coeffs_bs(Biquadx *self)
 {
     self->b0 = 1;
     self->b1 = self->a1 = -2 * self->c;
     self->b2 = 1;
-    self->a0 = 1 + self->alpha;
+    self->a0 = 1.0 / (1 + self->alpha);
     self->a2 = 1 - self->alpha;
 }
 
-static void 
+static void
 Biquadx_compute_coeffs_ap(Biquadx *self)
 {
     self->b0 = self->a2 = 1 - self->alpha;
     self->b1 = self->a1 = -2 * self->c;
-    self->b2 = self->a0 = 1 + self->alpha;
+    self->b2 = 1 + self->alpha;
+    self->a0 = 1.0 / (1 + self->alpha);
 }
 
 static void
 Biquadx_compute_variables(Biquadx *self, MYFLT freq, MYFLT q)
-{    
-    if (freq <= 1) 
+{
+    if (freq <= 1)
         freq = 1;
     else if (freq >= self->nyquist)
         freq = self->nyquist;
     if (q < 0.1)
         q = 0.1;
-    
+
     self->w0 = TWOPI * freq / self->sr;
     self->c = MYCOS(self->w0);
     self->alpha = MYSIN(self->w0) / (2 * q);
@@ -730,19 +720,19 @@ Biquadx_filters_ii(Biquadx *self) {
     MYFLT vin, vout;
     int i, j;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->init == 1) {
         for (i=0; i<self->stages; i++) {
             self->x1[i] = self->x2[i] = self->y1[i] = self->y2[i] = in[0];
-        }    
+        }
         self->init = 0;
     }
-    
+
     vout = 0.0;
     for (i=0; i<self->bufsize; i++) {
         vin = in[i];
-        for (j=0; j<self->stages; j++) {   
-            vout = ( (self->b0 * vin) + (self->b1 * self->x1[j]) + (self->b2 * self->x2[j]) - (self->a1 * self->y1[j]) - (self->a2 * self->y2[j]) ) / self->a0;
+        for (j=0; j<self->stages; j++) {
+            vout = ( (self->b0 * vin) + (self->b1 * self->x1[j]) + (self->b2 * self->x2[j]) - (self->a1 * self->y1[j]) - (self->a2 * self->y2[j]) ) * self->a0;
             self->x2[j] = self->x1[j];
             self->x1[j] = vin;
             self->y2[j] = self->y1[j];
@@ -757,23 +747,23 @@ Biquadx_filters_ai(Biquadx *self) {
     MYFLT vin, vout, q;
     int i, j;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->init == 1) {
         for (i=0; i<self->stages; i++) {
             self->x1[i] = self->x2[i] = self->y1[i] = self->y2[i] = in[0];
-        }    
+        }
         self->init = 0;
     }
-    
+
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
     q = PyFloat_AS_DOUBLE(self->q);
-    
+
     vout = 0.0;
     for (i=0; i<self->bufsize; i++) {
         Biquadx_compute_variables(self, fr[i], q);
         vin = in[i];
-        for (j=0; j<self->stages; j++) {   
-            vout = ( (self->b0 * vin) + (self->b1 * self->x1[j]) + (self->b2 * self->x2[j]) - (self->a1 * self->y1[j]) - (self->a2 * self->y2[j]) ) / self->a0;
+        for (j=0; j<self->stages; j++) {
+            vout = ( (self->b0 * vin) + (self->b1 * self->x1[j]) + (self->b2 * self->x2[j]) - (self->a1 * self->y1[j]) - (self->a2 * self->y2[j]) ) * self->a0;
             self->x2[j] = self->x1[j];
             self->x1[j] = vin;
             self->y2[j] = self->y1[j];
@@ -788,23 +778,23 @@ Biquadx_filters_ia(Biquadx *self) {
     MYFLT vin, vout, fr;
     int i, j;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->init == 1) {
         for (i=0; i<self->stages; i++) {
             self->x1[i] = self->x2[i] = self->y1[i] = self->y2[i] = in[0];
-        }    
+        }
         self->init = 0;
     }
-    
+
     fr = PyFloat_AS_DOUBLE(self->freq);
     MYFLT *q = Stream_getData((Stream *)self->q_stream);
-    
+
     vout = 0.0;
     for (i=0; i<self->bufsize; i++) {
         Biquadx_compute_variables(self, fr, q[i]);
         vin = in[i];
-        for (j=0; j<self->stages; j++) {   
-            vout = ( (self->b0 * vin) + (self->b1 * self->x1[j]) + (self->b2 * self->x2[j]) - (self->a1 * self->y1[j]) - (self->a2 * self->y2[j]) ) / self->a0;
+        for (j=0; j<self->stages; j++) {
+            vout = ( (self->b0 * vin) + (self->b1 * self->x1[j]) + (self->b2 * self->x2[j]) - (self->a1 * self->y1[j]) - (self->a2 * self->y2[j]) ) * self->a0;
             self->x2[j] = self->x1[j];
             self->x1[j] = vin;
             self->y2[j] = self->y1[j];
@@ -819,23 +809,23 @@ Biquadx_filters_aa(Biquadx *self) {
     MYFLT vin, vout;
     int i, j;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->init == 1) {
         for (i=0; i<self->stages; i++) {
             self->x1[i] = self->x2[i] = self->y1[i] = self->y2[i] = in[0];
-        }    
+        }
         self->init = 0;
     }
-    
+
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
     MYFLT *q = Stream_getData((Stream *)self->q_stream);
-    
+
     vout = 0.0;
     for (i=0; i<self->bufsize; i++) {
         Biquadx_compute_variables(self, fr[i], q[i]);
         vin = in[i];
-        for (j=0; j<self->stages; j++) {   
-            vout = ( (self->b0 * vin) + (self->b1 * self->x1[j]) + (self->b2 * self->x2[j]) - (self->a1 * self->y1[j]) - (self->a2 * self->y2[j]) ) / self->a0;
+        for (j=0; j<self->stages; j++) {
+            vout = ( (self->b0 * vin) + (self->b1 * self->x1[j]) + (self->b2 * self->x2[j]) - (self->a1 * self->y1[j]) - (self->a2 * self->y2[j]) ) * self->a0;
             self->x2[j] = self->x1[j];
             self->x1[j] = vin;
             self->y2[j] = self->y1[j];
@@ -861,7 +851,7 @@ Biquadx_setProcMode(Biquadx *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     switch (self->filtertype) {
         case 0:
             self->coeffs_func_ptr = Biquadx_compute_coeffs_lp;
@@ -879,57 +869,57 @@ Biquadx_setProcMode(Biquadx *self)
             self->coeffs_func_ptr = Biquadx_compute_coeffs_ap;
             break;
     }
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             Biquadx_compute_variables(self, PyFloat_AS_DOUBLE(self->freq), PyFloat_AS_DOUBLE(self->q));
             self->proc_func_ptr = Biquadx_filters_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Biquadx_filters_ai;
             break;
-        case 10:        
+        case 10:
             self->proc_func_ptr = Biquadx_filters_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Biquadx_filters_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Biquadx_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Biquadx_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Biquadx_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Biquadx_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Biquadx_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Biquadx_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Biquadx_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Biquadx_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Biquadx_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Biquadx_compute_next_data_frame(Biquadx *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -939,23 +929,23 @@ Biquadx_traverse(Biquadx *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
-    Py_VISIT(self->q);    
-    Py_VISIT(self->q_stream);    
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->q);
+    Py_VISIT(self->q_stream);
     return 0;
 }
 
-static int 
+static int
 Biquadx_clear(Biquadx *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
-    Py_CLEAR(self->q);    
-    Py_CLEAR(self->q_stream);    
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->q);
+    Py_CLEAR(self->q_stream);
     return 0;
 }
 
@@ -968,7 +958,7 @@ Biquadx_dealloc(Biquadx* self)
     free(self->y1);
     free(self->y2);
     Biquadx_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -978,7 +968,7 @@ Biquadx_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *qtmp=NULL, *multmp=NULL, *addtmp=NULL;
     Biquadx *self;
     self = (Biquadx *)type->tp_alloc(type, 0);
-    
+
     self->freq = PyFloat_FromDouble(1000);
     self->q = PyFloat_FromDouble(1);
     self->filtertype = 0;
@@ -988,37 +978,37 @@ Biquadx_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
     self->init = 1;
-    
+
     INIT_OBJECT_COMMON
-    
+
     self->nyquist = (MYFLT)self->sr * 0.49;
 
     Stream_setFunctionPtr(self->stream, Biquadx_compute_next_data_frame);
     self->mode_func_ptr = Biquadx_setProcMode;
 
     static char *kwlist[] = {"input", "freq", "q", "type", "stages", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOiiOO", kwlist, &inputtmp, &freqtmp, &qtmp, &self->filtertype, &self->stages, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    
+
     if (qtmp) {
         PyObject_CallMethod((PyObject *)self, "setQ", "O", qtmp);
     }
-    
+
     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);
 
     Biquadx_allocate_memories(self);
@@ -1030,10 +1020,10 @@ Biquadx_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Biquadx_getServer(Biquadx* self) { GET_SERVER };
 static PyObject * Biquadx_getStream(Biquadx* self) { GET_STREAM };
-static PyObject * Biquadx_setMul(Biquadx *self, PyObject *arg) { SET_MUL };	
-static PyObject * Biquadx_setAdd(Biquadx *self, PyObject *arg) { SET_ADD };	
-static PyObject * Biquadx_setSub(Biquadx *self, PyObject *arg) { SET_SUB };	
-static PyObject * Biquadx_setDiv(Biquadx *self, PyObject *arg) { SET_DIV };	
+static PyObject * Biquadx_setMul(Biquadx *self, PyObject *arg) { SET_MUL };
+static PyObject * Biquadx_setAdd(Biquadx *self, PyObject *arg) { SET_ADD };
+static PyObject * Biquadx_setSub(Biquadx *self, PyObject *arg) { SET_SUB };
+static PyObject * Biquadx_setDiv(Biquadx *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Biquadx_play(Biquadx *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Biquadx_out(Biquadx *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1052,14 +1042,11 @@ static PyObject *
 Biquadx_setFreq(Biquadx *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -1075,25 +1062,22 @@ Biquadx_setFreq(Biquadx *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Biquadx_setQ(Biquadx *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->q);
@@ -1109,45 +1093,37 @@ Biquadx_setQ(Biquadx *self, PyObject *arg)
         self->q_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Biquadx_setType(Biquadx *self, PyObject *arg)
 {
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	
+    ASSERT_ARG_NOT_NULL
+
 	int isInt = PyInt_Check(arg);
-    
+
 	if (isInt == 1) {
 		self->filtertype = PyInt_AsLong(arg);
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Biquadx_setStages(Biquadx *self, PyObject *arg)
 {
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	
+    ASSERT_ARG_NOT_NULL
+
 	int isInt = PyInt_Check(arg);
-    
+
 	if (isInt == 1) {
 		self->stages = PyInt_AsLong(arg);
         Biquadx_allocate_memories(self);
@@ -1155,7 +1131,7 @@ Biquadx_setStages(Biquadx *self, PyObject *arg)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Biquadx_members[] = {
     {"server", T_OBJECT_EX, offsetof(Biquadx, server), 0, "Pyo server."},
@@ -1189,7 +1165,7 @@ static PyNumberMethods Biquadx_as_number = {
     (binaryfunc)Biquadx_add,                         /*nb_add*/
     (binaryfunc)Biquadx_sub,                         /*nb_subtract*/
     (binaryfunc)Biquadx_multiply,                    /*nb_multiply*/
-    (binaryfunc)Biquadx_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -1203,16 +1179,16 @@ static PyNumberMethods Biquadx_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Biquadx_inplace_add,                 /*inplace_add*/
     (binaryfunc)Biquadx_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Biquadx_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Biquadx_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -1221,15 +1197,14 @@ static PyNumberMethods Biquadx_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Biquadx_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Biquadx_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject BiquadxType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Biquadx_base",                                   /*tp_name*/
     sizeof(Biquadx),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -1237,7 +1212,7 @@ PyTypeObject BiquadxType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &Biquadx_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -1282,7 +1257,7 @@ typedef struct {
     Stream *a1_stream;
     Stream *a2_stream;
     int init;
-    int modebuffer[2]; // need at least 2 slots for mul & add 
+    int modebuffer[2]; // need at least 2 slots for mul & add
     // sample memories
     MYFLT x1;
     MYFLT x2;
@@ -1306,7 +1281,7 @@ Biquada_filters(Biquada *self) {
         self->x1 = self->x2 = self->y1 = self->y2 = in[0];
         self->init = 0;
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         val = ( (b0[i] * in[i]) + (b1[i] * self->x1) + (b2[i] * self->x2) - (a1[i] * self->y1) - (a2[i] * self->y2) ) / a0[i];
         self->y2 = self->y1;
@@ -1331,44 +1306,44 @@ Biquada_setProcMode(Biquada *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = Biquada_filters;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Biquada_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Biquada_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Biquada_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Biquada_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Biquada_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Biquada_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Biquada_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Biquada_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Biquada_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Biquada_compute_next_data_frame(Biquada *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1387,7 +1362,7 @@ Biquada_traverse(Biquada *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Biquada_clear(Biquada *self)
 {
     pyo_CLEAR
@@ -1407,7 +1382,7 @@ Biquada_dealloc(Biquada* self)
 {
     pyo_DEALLOC
     Biquada_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1417,21 +1392,21 @@ Biquada_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *b0tmp, *b1tmp, *b2tmp, *a0tmp, *a1tmp, *a2tmp, *multmp=NULL, *addtmp=NULL;
     Biquada *self;
     self = (Biquada *)type->tp_alloc(type, 0);
-    
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
     self->init = 1;
-    
+
     INIT_OBJECT_COMMON
-    
+
     Stream_setFunctionPtr(self->stream, Biquada_compute_next_data_frame);
     self->mode_func_ptr = Biquada_setProcMode;
 
     static char *kwlist[] = {"input", "b0", "b1", "b2", "a0", "a1", "a2", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OOOOOOOOO", kwlist, &inputtmp, &b0tmp, &b1tmp, &b2tmp, &a0tmp, &a1tmp, &a2tmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
 
     if (b0tmp)
@@ -1450,9 +1425,9 @@ Biquada_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         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;
@@ -1460,10 +1435,10 @@ Biquada_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Biquada_getServer(Biquada* self) { GET_SERVER };
 static PyObject * Biquada_getStream(Biquada* self) { GET_STREAM };
-static PyObject * Biquada_setMul(Biquada *self, PyObject *arg) { SET_MUL };	
-static PyObject * Biquada_setAdd(Biquada *self, PyObject *arg) { SET_ADD };	
-static PyObject * Biquada_setSub(Biquada *self, PyObject *arg) { SET_SUB };	
-static PyObject * Biquada_setDiv(Biquada *self, PyObject *arg) { SET_DIV };	
+static PyObject * Biquada_setMul(Biquada *self, PyObject *arg) { SET_MUL };
+static PyObject * Biquada_setAdd(Biquada *self, PyObject *arg) { SET_ADD };
+static PyObject * Biquada_setSub(Biquada *self, PyObject *arg) { SET_SUB };
+static PyObject * Biquada_setDiv(Biquada *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Biquada_play(Biquada *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Biquada_out(Biquada *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1480,99 +1455,93 @@ static PyObject * Biquada_inplace_div(Biquada *self, PyObject *arg) { INPLACE_DI
 
 static PyObject *
 Biquada_setB0(Biquada *self, PyObject *arg)
-{	
+{
 	PyObject *streamtmp;
 
-	if (arg == NULL)
-		Py_RETURN_NONE;
-    
+    ASSERT_ARG_NOT_NULL
+
     streamtmp = PyObject_CallMethod((PyObject *)arg, "_getStream", NULL);
     Py_INCREF(streamtmp);
     Py_XDECREF(self->b0_stream);
     self->b0_stream = (Stream *)streamtmp;
-    
+
 	Py_RETURN_NONE;
-}	
+}
 
 static PyObject *
 Biquada_setB1(Biquada *self, PyObject *arg)
-{	
+{
 	PyObject *streamtmp;
 
-	if (arg == NULL)
-		Py_RETURN_NONE;
-    
+    ASSERT_ARG_NOT_NULL
+
     streamtmp = PyObject_CallMethod((PyObject *)arg, "_getStream", NULL);
     Py_INCREF(streamtmp);
     Py_XDECREF(self->b1_stream);
     self->b1_stream = (Stream *)streamtmp;
-    
+
 	Py_RETURN_NONE;
-}	
+}
 
 static PyObject *
 Biquada_setB2(Biquada *self, PyObject *arg)
-{	
+{
 	PyObject *streamtmp;
-    
-	if (arg == NULL)
-		Py_RETURN_NONE;
-    
+
+    ASSERT_ARG_NOT_NULL
+
     streamtmp = PyObject_CallMethod((PyObject *)arg, "_getStream", NULL);
     Py_INCREF(streamtmp);
     Py_XDECREF(self->b2_stream);
     self->b2_stream = (Stream *)streamtmp;
-    
+
 	Py_RETURN_NONE;
-}	
+}
 
 static PyObject *
 Biquada_setA0(Biquada *self, PyObject *arg)
-{	
+{
 	PyObject *streamtmp;
-    
-	if (arg == NULL)
-		Py_RETURN_NONE;
-    
+
+    ASSERT_ARG_NOT_NULL
+
     streamtmp = PyObject_CallMethod((PyObject *)arg, "_getStream", NULL);
     Py_INCREF(streamtmp);
     Py_XDECREF(self->a0_stream);
     self->a0_stream = (Stream *)streamtmp;
-    
+
 	Py_RETURN_NONE;
-}	
+}
 
 static PyObject *
 Biquada_setA1(Biquada *self, PyObject *arg)
-{	
+{
 	PyObject *streamtmp;
-    
-	if (arg == NULL)
-		Py_RETURN_NONE;
-    
+
+    ASSERT_ARG_NOT_NULL
+
     streamtmp = PyObject_CallMethod((PyObject *)arg, "_getStream", NULL);
     Py_INCREF(streamtmp);
     Py_XDECREF(self->a1_stream);
     self->a1_stream = (Stream *)streamtmp;
-    
+
 	Py_RETURN_NONE;
-}	
+}
 
 static PyObject *
 Biquada_setA2(Biquada *self, PyObject *arg)
-{	
+{
 	PyObject *streamtmp;
-    
-	if (arg == NULL)
-		Py_RETURN_NONE;
-    
+
+    ASSERT_ARG_NOT_NULL
+
     streamtmp = PyObject_CallMethod((PyObject *)arg, "_getStream", NULL);
     Py_INCREF(streamtmp);
     Py_XDECREF(self->a2_stream);
     self->a2_stream = (Stream *)streamtmp;
-    
+
 	Py_RETURN_NONE;
-}	
+}
 
 static PyMemberDef Biquada_members[] = {
     {"server", T_OBJECT_EX, offsetof(Biquada, server), 0, "Pyo server."},
@@ -1606,7 +1575,7 @@ static PyNumberMethods Biquada_as_number = {
     (binaryfunc)Biquada_add,                         /*nb_add*/
     (binaryfunc)Biquada_sub,                         /*nb_subtract*/
     (binaryfunc)Biquada_multiply,                    /*nb_multiply*/
-    (binaryfunc)Biquada_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -1620,16 +1589,16 @@ static PyNumberMethods Biquada_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Biquada_inplace_add,                 /*inplace_add*/
     (binaryfunc)Biquada_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Biquada_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Biquada_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -1638,15 +1607,14 @@ static PyNumberMethods Biquada_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Biquada_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Biquada_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject BiquadaType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Biquada_base",                                   /*tp_name*/
     sizeof(Biquada),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -1654,7 +1622,7 @@ PyTypeObject BiquadaType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &Biquada_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -1699,9 +1667,10 @@ typedef struct {
     Stream *boost_stream;
     void (*coeffs_func_ptr)();
     int init;
-    int modebuffer[5]; // need at least 2 slots for mul & add 
+    int modebuffer[5]; // need at least 2 slots for mul & add
     int filtertype;
     MYFLT nyquist;
+    MYFLT twoPiOverSr;
     // sample memories
     MYFLT x1;
     MYFLT x2;
@@ -1721,59 +1690,59 @@ typedef struct {
     MYFLT a2;
 } EQ;
 
-static void 
+static void
 EQ_compute_coeffs_peak(EQ *self)
 {
     MYFLT alphaMul = self->alpha * self->A;
     MYFLT alphaDiv = self->alpha / self->A;
-    
+
     self->b0 = 1.0 + alphaMul;
     self->b1 = self->a1 = -2.0 * self->c;
     self->b2 = 1.0 - alphaMul;
-    self->a0 = 1.0 + alphaDiv;
+    self->a0 = 1.0 / (1.0 + alphaDiv);
     self->a2 = 1.0 - alphaDiv;
 }
 
 static void
-EQ_compute_coeffs_lowshelf(EQ *self) 
+EQ_compute_coeffs_lowshelf(EQ *self)
 {
     MYFLT twoSqrtAAlpha = MYSQRT(self->A * 2.0)*self->alpha;
     MYFLT AminOneC = (self->A - 1.0) * self->c;
     MYFLT AAddOneC = (self->A + 1.0) * self->c;
-    
+
     self->b0 = self->A * ((self->A + 1.0) - AminOneC + twoSqrtAAlpha);
     self->b1 = 2.0 * self->A * ((self->A - 1.0) - AAddOneC);
     self->b2 = self->A * ((self->A + 1.0) - AminOneC - twoSqrtAAlpha);
-    self->a0 = (self->A + 1.0) + AminOneC + twoSqrtAAlpha;
+    self->a0 = 1.0 / ((self->A + 1.0) + AminOneC + twoSqrtAAlpha);
     self->a1 = -2.0 * ((self->A - 1.0) + AAddOneC);
     self->a2 = (self->A + 1.0) + AminOneC - twoSqrtAAlpha;
-}    
+}
 
 static void
-EQ_compute_coeffs_highshelf(EQ *self) 
+EQ_compute_coeffs_highshelf(EQ *self)
 {
     MYFLT twoSqrtAAlpha = MYSQRT(self->A * 2.0)*self->alpha;
     MYFLT AminOneC = (self->A - 1.0) * self->c;
     MYFLT AAddOneC = (self->A + 1.0) * self->c;
-    
+
     self->b0 = self->A * ((self->A + 1.0) + AminOneC + twoSqrtAAlpha);
     self->b1 = -2.0 * self->A * ((self->A - 1.0) + AAddOneC);
     self->b2 = self->A * ((self->A + 1.0) + AminOneC - twoSqrtAAlpha);
-    self->a0 = (self->A + 1.0) - AminOneC + twoSqrtAAlpha;
+    self->a0 = 1.0 / ((self->A + 1.0) - AminOneC + twoSqrtAAlpha);
     self->a1 = 2.0 * ((self->A - 1.0) - AAddOneC);
     self->a2 = (self->A + 1.0) - AminOneC - twoSqrtAAlpha;
-}    
+}
 
 static void
 EQ_compute_variables(EQ *self, MYFLT freq, MYFLT q, MYFLT boost)
-{    
-    if (freq <= 1) 
+{
+    if (freq <= 1)
         freq = 1;
     else if (freq >= self->nyquist)
         freq = self->nyquist;
-    
+
     self->A = MYPOW(10.0, boost/40.0);
-    self->w0 = TWOPI * freq / self->sr;
+    self->w0 = freq * self->twoPiOverSr;
     self->c = MYCOS(self->w0);
     self->alpha = MYSIN(self->w0) / (2 * q);
     (*self->coeffs_func_ptr)(self);
@@ -1784,19 +1753,18 @@ EQ_filters_iii(EQ *self) {
     MYFLT val;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->init == 1) {
         self->x1 = self->x2 = self->y1 = self->y2 = in[0];
         self->init = 0;
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
-        val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
+        val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) * self->a0;
         self->y2 = self->y1;
-        self->y1 = val;
+        self->data[i] = self->y1 = val;
         self->x2 = self->x1;
         self->x1 = in[i];
-        self->data[i] = val;
     }
 }
 
@@ -1805,24 +1773,23 @@ EQ_filters_aii(EQ *self) {
     MYFLT val, q, boost;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->init == 1) {
         self->x1 = self->x2 = self->y1 = self->y2 = in[0];
         self->init = 0;
     }
-    
+
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
     q = PyFloat_AS_DOUBLE(self->q);
     boost = PyFloat_AS_DOUBLE(self->boost);
-    
+
     for (i=0; i<self->bufsize; i++) {
         EQ_compute_variables(self, fr[i], q, boost);
-        val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
+        val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) * self->a0;
         self->y2 = self->y1;
-        self->y1 = val;
+        self->data[i] = self->y1 = val;
         self->x2 = self->x1;
         self->x1 = in[i];
-        self->data[i] = val;
     }
 }
 
@@ -1831,24 +1798,23 @@ EQ_filters_iai(EQ *self) {
     MYFLT val, fr, boost;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->init == 1) {
         self->x1 = self->x2 = self->y1 = self->y2 = in[0];
         self->init = 0;
     }
-    
+
     fr = PyFloat_AS_DOUBLE(self->freq);
     MYFLT *q = Stream_getData((Stream *)self->q_stream);
     boost = PyFloat_AS_DOUBLE(self->boost);
-    
+
     for (i=0; i<self->bufsize; i++) {
         EQ_compute_variables(self, fr, q[i], boost);
-        val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
+        val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) * self->a0;
         self->y2 = self->y1;
-        self->y1 = val;
+        self->data[i] = self->y1 = val;
         self->x2 = self->x1;
         self->x1 = in[i];
-        self->data[i] = val;
     }
 }
 
@@ -1857,24 +1823,23 @@ EQ_filters_aai(EQ *self) {
     MYFLT val, boost;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->init == 1) {
         self->x1 = self->x2 = self->y1 = self->y2 = in[0];
         self->init = 0;
     }
-    
+
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
     MYFLT *q = Stream_getData((Stream *)self->q_stream);
     boost = PyFloat_AS_DOUBLE(self->boost);
-    
+
     for (i=0; i<self->bufsize; i++) {
         EQ_compute_variables(self, fr[i], q[i], boost);
-        val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
+        val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) * self->a0;
         self->y2 = self->y1;
-        self->y1 = val;
+        self->data[i] = self->y1 = val;
         self->x2 = self->x1;
         self->x1 = in[i];
-        self->data[i] = val;
     }
 }
 
@@ -1883,7 +1848,7 @@ EQ_filters_iia(EQ *self) {
     MYFLT val, fr, q;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->init == 1) {
         self->x1 = self->x2 = self->y1 = self->y2 = in[0];
         self->init = 0;
@@ -1895,12 +1860,11 @@ EQ_filters_iia(EQ *self) {
 
     for (i=0; i<self->bufsize; i++) {
         EQ_compute_variables(self, fr, q, boost[i]);
-        val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
+        val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) * self->a0;
         self->y2 = self->y1;
-        self->y1 = val;
+        self->data[i] = self->y1 = val;
         self->x2 = self->x1;
         self->x1 = in[i];
-        self->data[i] = val;
     }
 }
 
@@ -1909,24 +1873,23 @@ EQ_filters_aia(EQ *self) {
     MYFLT val, q;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->init == 1) {
         self->x1 = self->x2 = self->y1 = self->y2 = in[0];
         self->init = 0;
     }
-    
+
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
     q = PyFloat_AS_DOUBLE(self->q);
     MYFLT *boost = Stream_getData((Stream *)self->boost_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         EQ_compute_variables(self, fr[i], q, boost[i]);
-        val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
+        val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) * self->a0;
         self->y2 = self->y1;
-        self->y1 = val;
+        self->data[i] = self->y1 = val;
         self->x2 = self->x1;
         self->x1 = in[i];
-        self->data[i] = val;
     }
 }
 
@@ -1935,24 +1898,23 @@ EQ_filters_iaa(EQ *self) {
     MYFLT val, fr;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->init == 1) {
         self->x1 = self->x2 = self->y1 = self->y2 = in[0];
         self->init = 0;
     }
-    
+
     fr = PyFloat_AS_DOUBLE(self->freq);
     MYFLT *q = Stream_getData((Stream *)self->q_stream);
     MYFLT *boost = Stream_getData((Stream *)self->boost_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         EQ_compute_variables(self, fr, q[i], boost[i]);
-        val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
+        val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) * self->a0;
         self->y2 = self->y1;
-        self->y1 = val;
+        self->data[i] = self->y1 = val;
         self->x2 = self->x1;
         self->x1 = in[i];
-        self->data[i] = val;
     }
 }
 
@@ -1961,24 +1923,23 @@ EQ_filters_aaa(EQ *self) {
     MYFLT val;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->init == 1) {
         self->x1 = self->x2 = self->y1 = self->y2 = in[0];
         self->init = 0;
     }
-    
+
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
     MYFLT *q = Stream_getData((Stream *)self->q_stream);
     MYFLT *boost = Stream_getData((Stream *)self->boost_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         EQ_compute_variables(self, fr[i], q[i], boost[i]);
-        val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
+        val = ( (self->b0 * in[i]) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) * self->a0;
         self->y2 = self->y1;
-        self->y1 = val;
+        self->data[i] = self->y1 = val;
         self->x2 = self->x1;
         self->x1 = in[i];
-        self->data[i] = val;
     }
 }
 
@@ -1998,7 +1959,7 @@ EQ_setProcMode(EQ *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     switch (self->filtertype) {
         case 0:
             self->coeffs_func_ptr = EQ_compute_coeffs_peak;
@@ -2010,69 +1971,69 @@ EQ_setProcMode(EQ *self)
             self->coeffs_func_ptr = EQ_compute_coeffs_highshelf;
             break;
     }
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             EQ_compute_variables(self, PyFloat_AS_DOUBLE(self->freq), PyFloat_AS_DOUBLE(self->q), PyFloat_AS_DOUBLE(self->boost));
             self->proc_func_ptr = EQ_filters_iii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = EQ_filters_aii;
             break;
-        case 10:        
+        case 10:
             self->proc_func_ptr = EQ_filters_iai;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = EQ_filters_aai;
             break;
-        case 100:    
+        case 100:
             self->proc_func_ptr = EQ_filters_iia;
             break;
-        case 101:    
+        case 101:
             self->proc_func_ptr = EQ_filters_aia;
             break;
-        case 110:        
+        case 110:
             self->proc_func_ptr = EQ_filters_iaa;
             break;
-        case 111:    
+        case 111:
             self->proc_func_ptr = EQ_filters_aaa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = EQ_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = EQ_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = EQ_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = EQ_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = EQ_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = EQ_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = EQ_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = EQ_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = EQ_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 EQ_compute_next_data_frame(EQ *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -2082,24 +2043,24 @@ EQ_traverse(EQ *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
-    Py_VISIT(self->q);    
-    Py_VISIT(self->q_stream);    
-    Py_VISIT(self->boost);    
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->q);
+    Py_VISIT(self->q_stream);
+    Py_VISIT(self->boost);
     Py_VISIT(self->boost_stream);
     return 0;
 }
 
-static int 
+static int
 EQ_clear(EQ *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
-    Py_CLEAR(self->q);    
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->q);
     Py_CLEAR(self->q_stream);
     Py_CLEAR(self->boost);
     Py_CLEAR(self->boost_stream);
@@ -2111,7 +2072,7 @@ EQ_dealloc(EQ* self)
 {
     pyo_DEALLOC
     EQ_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2121,7 +2082,7 @@ EQ_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *qtmp=NULL, *boosttmp=NULL, *multmp=NULL, *addtmp=NULL;
     EQ *self;
     self = (EQ *)type->tp_alloc(type, 0);
-    
+
     self->freq = PyFloat_FromDouble(1000);
     self->q = PyFloat_FromDouble(1);
     self->boost = PyFloat_FromDouble(-3.0);
@@ -2132,25 +2093,26 @@ EQ_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[3] = 0;
 	self->modebuffer[4] = 0;
     self->init = 1;
-    
+
     INIT_OBJECT_COMMON
 
     self->nyquist = (MYFLT)self->sr * 0.49;
+    self->twoPiOverSr = TWOPI / (MYFLT)self->sr;
 
     Stream_setFunctionPtr(self->stream, EQ_compute_next_data_frame);
     self->mode_func_ptr = EQ_setProcMode;
 
     static char *kwlist[] = {"input", "freq", "q", "boost", "type", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOiOO", kwlist, &inputtmp, &freqtmp, &qtmp, &boosttmp, &self->filtertype, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    
+
     if (qtmp) {
         PyObject_CallMethod((PyObject *)self, "setQ", "O", qtmp);
     }
@@ -2158,17 +2120,17 @@ EQ_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (boosttmp) {
         PyObject_CallMethod((PyObject *)self, "setBoost", "O", boosttmp);
     }
-    
+
     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;
@@ -2176,10 +2138,10 @@ EQ_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * EQ_getServer(EQ* self) { GET_SERVER };
 static PyObject * EQ_getStream(EQ* self) { GET_STREAM };
-static PyObject * EQ_setMul(EQ *self, PyObject *arg) { SET_MUL };	
-static PyObject * EQ_setAdd(EQ *self, PyObject *arg) { SET_ADD };	
-static PyObject * EQ_setSub(EQ *self, PyObject *arg) { SET_SUB };	
-static PyObject * EQ_setDiv(EQ *self, PyObject *arg) { SET_DIV };	
+static PyObject * EQ_setMul(EQ *self, PyObject *arg) { SET_MUL };
+static PyObject * EQ_setAdd(EQ *self, PyObject *arg) { SET_ADD };
+static PyObject * EQ_setSub(EQ *self, PyObject *arg) { SET_SUB };
+static PyObject * EQ_setDiv(EQ *self, PyObject *arg) { SET_DIV };
 
 static PyObject * EQ_play(EQ *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * EQ_out(EQ *self, PyObject *args, PyObject *kwds) { OUT };
@@ -2198,14 +2160,11 @@ static PyObject *
 EQ_setFreq(EQ *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -2221,25 +2180,22 @@ EQ_setFreq(EQ *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 EQ_setQ(EQ *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->q);
@@ -2255,25 +2211,22 @@ EQ_setQ(EQ *self, PyObject *arg)
         self->q_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 EQ_setBoost(EQ *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	int isNumber = PyNumber_Check(arg);
-	
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->boost);
@@ -2289,33 +2242,29 @@ EQ_setBoost(EQ *self, PyObject *arg)
         self->boost_stream = (Stream *)streamtmp;
 		self->modebuffer[4] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 EQ_setType(EQ *self, PyObject *arg)
 {
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	
+    ASSERT_ARG_NOT_NULL
+
 	int isInt = PyInt_Check(arg);
-    
+
 	if (isInt == 1) {
 		self->filtertype = PyInt_AsLong(arg);
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef EQ_members[] = {
 {"server", T_OBJECT_EX, offsetof(EQ, server), 0, "Pyo server."},
@@ -2350,7 +2299,7 @@ static PyNumberMethods EQ_as_number = {
 (binaryfunc)EQ_add,                         /*nb_add*/
 (binaryfunc)EQ_sub,                         /*nb_subtract*/
 (binaryfunc)EQ_multiply,                    /*nb_multiply*/
-(binaryfunc)EQ_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -2364,16 +2313,16 @@ static PyNumberMethods EQ_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)EQ_inplace_add,                 /*inplace_add*/
 (binaryfunc)EQ_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)EQ_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)EQ_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -2382,15 +2331,14 @@ static PyNumberMethods EQ_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)EQ_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)EQ_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject EQType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.EQ_base",                                   /*tp_name*/
 sizeof(EQ),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -2398,7 +2346,7 @@ sizeof(EQ),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &EQ_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -2439,13 +2387,14 @@ typedef struct {
     PyObject *falltime;
     Stream *risetime_stream;
     Stream *falltime_stream;
-    int modebuffer[4]; // need at least 2 slots for mul & add 
+    int modebuffer[4]; // need at least 2 slots for mul & add
     MYFLT y1; // sample memory
     MYFLT x1;
     int dir;
 } Port;
 
-static void 
+// inline ?
+static void
 direction(Port *self, MYFLT val)
 {
     if (val == self->x1)
@@ -2455,87 +2404,98 @@ direction(Port *self, MYFLT val)
     else
         self->dir = 0;
     self->x1 = val;
-}    
-    
+}
+
 static void
 Port_filters_ii(Port *self) {
-    MYFLT val;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT risetime = PyFloat_AS_DOUBLE(self->risetime);
     MYFLT falltime = PyFloat_AS_DOUBLE(self->falltime);
-    MYFLT risefactor = 1. / ((risetime + 0.001) * self->sr);
-    MYFLT fallfactor = 1. / ((falltime + 0.001) * self->sr);
+    if (risetime < 0)
+        risetime = 0.0;
+    if (falltime < 0)
+        falltime = 0.0;
+    MYFLT risefactor = 1.0 / ((risetime + 0.00025) * self->sr);
+    MYFLT fallfactor = 1.0 / ((falltime + 0.00025) * self->sr);
     MYFLT factors[2] = {fallfactor, risefactor};
 
     for (i=0; i<self->bufsize; i++) {
         direction(self, in[i]);
-        val = self->y1 + (in[i] - self->y1) * factors[self->dir];
-        self->y1 = val;
-        self->data[i] = val;
+        self->data[i] = self->y1 = self->y1 + (in[i] - self->y1) * factors[self->dir];
     }
 }
 
 static void
 Port_filters_ai(Port *self) {
-    MYFLT val, risefactor;
+    MYFLT risetime, risefactor;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    MYFLT *risetime = Stream_getData((Stream *)self->risetime_stream);
+    MYFLT *rt = Stream_getData((Stream *)self->risetime_stream);
     MYFLT falltime = PyFloat_AS_DOUBLE(self->falltime);
-    MYFLT fallfactor = 1. / ((falltime + 0.001) * self->sr);
-    
+    if (falltime < 0)
+        falltime = 0.0;
+    MYFLT fallfactor = 1.0 / ((falltime + 0.00025) * self->sr);
+
     for (i=0; i<self->bufsize; i++) {
         direction(self, in[i]);
-        risefactor = (*risetime++ + 0.001) * self->sr;  
+        risetime = rt[i];
+        if (risetime < 0)
+            risetime = 0.0;
+        risefactor = (risetime + 0.00025) * self->sr;
         if (self->dir == 1)
-            val = self->y1 + (*in++ - self->y1) / risefactor;
+            self->data[i] = self->y1 = self->y1 + (in[i] - self->y1) / risefactor;
         else
-            val = self->y1 + (*in++ - self->y1) * fallfactor;
-        self->y1 = val;
-        self->data[i] = val;
+            self->data[i] = self->y1 = self->y1 + (in[i] - self->y1) * fallfactor;
     }
 }
 
 static void
 Port_filters_ia(Port *self) {
-    MYFLT val, fallfactor;
+    MYFLT falltime, fallfactor;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    MYFLT *falltime = Stream_getData((Stream *)self->falltime_stream);
+    MYFLT *ft = Stream_getData((Stream *)self->falltime_stream);
     MYFLT risetime = PyFloat_AS_DOUBLE(self->risetime);
-    MYFLT risefactor = 1. / ((risetime + 0.001) * self->sr);
-    
+    if (risetime < 0)
+        risetime = 0.0;
+    MYFLT risefactor = 1.0 / ((risetime + 0.00025) * self->sr);
+
     for (i=0; i<self->bufsize; i++) {
         direction(self, in[i]);
-        fallfactor = (*falltime++ + 0.001) * self->sr;  
+        falltime = ft[i];
+        if (falltime < 0)
+            falltime = 0.0;
+        fallfactor = (falltime + 0.00025) * self->sr;
         if (self->dir == 1)
-            val = self->y1 + (*in++ - self->y1) * risefactor;
+            self->data[i] = self->y1 = self->y1 + (in[i] - self->y1) * risefactor;
         else
-            val = self->y1 + (*in++ - self->y1) / fallfactor;
-        self->y1 = val;
-        self->data[i] = val;
+            self->data[i] = self->y1 = self->y1 + (in[i] - self->y1) / fallfactor;
     }
 }
 
 static void
 Port_filters_aa(Port *self) {
-    MYFLT val, risefactor, fallfactor;
+    MYFLT risetime, falltime, risefactor, fallfactor;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    MYFLT *risetime = Stream_getData((Stream *)self->risetime_stream);
-    MYFLT *falltime = Stream_getData((Stream *)self->falltime_stream);
-    
+    MYFLT *rt = Stream_getData((Stream *)self->risetime_stream);
+    MYFLT *ft = Stream_getData((Stream *)self->falltime_stream);
+
     for (i=0; i<self->bufsize; i++) {
         direction(self, in[i]);
-        risefactor = (*risetime++ + 0.001) * self->sr;  
-        fallfactor = (*falltime++ + 0.001) * self->sr;  
+        risetime = rt[i];
+        if (risetime < 0)
+            risetime = 0.0;
+        falltime = ft[i];
+        if (falltime < 0)
+            falltime = 0.0;
+        risefactor = (risetime + 0.00025) * self->sr;
+        fallfactor = (falltime + 0.00025) * self->sr;
         if (self->dir == 1)
-            val = self->y1 + (*in++ - self->y1) / risefactor;
+            self->data[i] = self->y1 = self->y1 + (in[i] - self->y1) / risefactor;
         else
-            val = self->y1 + (*in++ - self->y1) / fallfactor;
-        self->y1 = val;
-        self->data[i] = val;
+            self->data[i] = self->y1 = self->y1 + (in[i] - self->y1) / fallfactor;
     }
 }
 
@@ -2557,54 +2517,54 @@ Port_setProcMode(Port *self)
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Port_filters_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Port_filters_ai;
             break;
-        case 10:    
+        case 10:
             self->proc_func_ptr = Port_filters_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Port_filters_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Port_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Port_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Port_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Port_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Port_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Port_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Port_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Port_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Port_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 Port_compute_next_data_frame(Port *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -2614,23 +2574,23 @@ Port_traverse(Port *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->risetime);    
-    Py_VISIT(self->risetime_stream);    
-    Py_VISIT(self->falltime);    
-    Py_VISIT(self->falltime_stream);    
+    Py_VISIT(self->risetime);
+    Py_VISIT(self->risetime_stream);
+    Py_VISIT(self->falltime);
+    Py_VISIT(self->falltime_stream);
     return 0;
 }
 
-static int 
+static int
 Port_clear(Port *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->risetime);    
-    Py_CLEAR(self->risetime_stream);    
-    Py_CLEAR(self->falltime);    
-    Py_CLEAR(self->falltime_stream);    
+    Py_CLEAR(self->risetime);
+    Py_CLEAR(self->risetime_stream);
+    Py_CLEAR(self->falltime);
+    Py_CLEAR(self->falltime_stream);
     return 0;
 }
 
@@ -2639,7 +2599,7 @@ Port_dealloc(Port* self)
 {
     pyo_DEALLOC
     Port_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2650,7 +2610,7 @@ Port_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *risetimetmp=NULL, *falltimetmp=NULL, *multmp=NULL, *addtmp=NULL;
     Port *self;
     self = (Port *)type->tp_alloc(type, 0);
-    
+
     self->risetime = PyFloat_FromDouble(0.05);
     self->falltime = PyFloat_FromDouble(0.05);
 	self->modebuffer[0] = 0;
@@ -2660,18 +2620,18 @@ Port_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->y1 = 0.0;
     self->x1 = 0.0;
     self->dir = 1;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Port_compute_next_data_frame);
     self->mode_func_ptr = Port_setProcMode;
 
     static char *kwlist[] = {"input", "risetime", "falltime", "init", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_OOFOO, kwlist, &inputtmp, &risetimetmp, &falltimetmp, &inittmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (risetimetmp) {
         PyObject_CallMethod((PyObject *)self, "setRiseTime", "O", risetimetmp);
     }
@@ -2679,20 +2639,20 @@ Port_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (falltimetmp) {
         PyObject_CallMethod((PyObject *)self, "setFallTime", "O", falltimetmp);
     }
-    
+
     if (multmp) {
         PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
     }
-    
+
     if (addtmp) {
         PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
     }
 
     if (inittmp != 0.0)
         self->x1 = self->y1 = inittmp;
-        
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
@@ -2700,10 +2660,10 @@ Port_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Port_getServer(Port* self) { GET_SERVER };
 static PyObject * Port_getStream(Port* self) { GET_STREAM };
-static PyObject * Port_setMul(Port *self, PyObject *arg) { SET_MUL };	
-static PyObject * Port_setAdd(Port *self, PyObject *arg) { SET_ADD };	
-static PyObject * Port_setSub(Port *self, PyObject *arg) { SET_SUB };	
-static PyObject * Port_setDiv(Port *self, PyObject *arg) { SET_DIV };	
+static PyObject * Port_setMul(Port *self, PyObject *arg) { SET_MUL };
+static PyObject * Port_setAdd(Port *self, PyObject *arg) { SET_ADD };
+static PyObject * Port_setSub(Port *self, PyObject *arg) { SET_SUB };
+static PyObject * Port_setDiv(Port *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Port_play(Port *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Port_out(Port *self, PyObject *args, PyObject *kwds) { OUT };
@@ -2722,14 +2682,11 @@ static PyObject *
 Port_setRiseTime(Port *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->risetime);
@@ -2745,25 +2702,22 @@ Port_setRiseTime(Port *self, PyObject *arg)
         self->risetime_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Port_setFallTime(Port *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->falltime);
@@ -2779,12 +2733,12 @@ Port_setFallTime(Port *self, PyObject *arg)
         self->falltime_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Port_members[] = {
 {"server", T_OBJECT_EX, offsetof(Port, server), 0, "Pyo server."},
@@ -2816,7 +2770,7 @@ static PyNumberMethods Port_as_number = {
 (binaryfunc)Port_add,                         /*nb_add*/
 (binaryfunc)Port_sub,                         /*nb_subtract*/
 (binaryfunc)Port_multiply,                    /*nb_multiply*/
-(binaryfunc)Port_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -2830,16 +2784,16 @@ static PyNumberMethods Port_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)Port_inplace_add,                 /*inplace_add*/
 (binaryfunc)Port_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)Port_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)Port_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -2848,15 +2802,14 @@ static PyNumberMethods Port_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)Port_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)Port_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject PortType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Port_base",                                   /*tp_name*/
 sizeof(Port),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -2864,7 +2817,7 @@ sizeof(Port),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &Port_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -2905,63 +2858,54 @@ typedef struct {
     Stream *input_stream;
     PyObject *freq;
     Stream *freq_stream;
-    int modebuffer[3]; // need at least 2 slots for mul & add 
+    int modebuffer[3]; // need at least 2 slots for mul & add
     MYFLT lastFreq;
     MYFLT nyquist;
+    MYFLT mTwoPiOverSr;
     // sample memories
     MYFLT y1;
     // variables
-    MYFLT c1;
-    MYFLT c2;
+    MYFLT c;
 } Tone;
 
 static void
 Tone_filters_i(Tone *self) {
-    MYFLT val, b;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
-        
+
     if (fr != self->lastFreq) {
-        if (fr <= 1.0)
-            fr = 1.0;
+        if (fr <= 0.1)
+            fr = 0.1;
         else if (fr >= self->nyquist)
-            fr = self->nyquist;        
+            fr = self->nyquist;
         self->lastFreq = fr;
-        b = 2.0 - MYCOS(TWOPI * fr / self->sr);
-        self->c2 = (b - MYSQRT(b * b - 1.0));
-        self->c1 = 1.0 - self->c2;
+        self->c = MYEXP(self->mTwoPiOverSr * fr);
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
-        val = self->c1 * in[i] + self->c2 * self->y1;
-        self->data[i] = val;
-        self->y1 = val;
+        self->data[i] = self->y1 = in[i] + (self->y1 - in[i]) * self->c;
     }
 }
 
 static void
 Tone_filters_a(Tone *self) {
-    MYFLT val, freq, b;
     int i;
+    MYFLT freq;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-        
+
     for (i=0; i<self->bufsize; i++) {
-        freq = fr[i];        
+        freq = fr[i];
         if (freq != self->lastFreq) {
-            if (freq <= 1.0)
-                freq = 1.0;
+            if (freq <= 0.1)
+                freq = 0.1;
             else if (freq >= self->nyquist)
-                freq = self->nyquist;            
+                freq = self->nyquist;
             self->lastFreq = freq;
-            b = 2.0 - MYCOS(TWOPI * freq / self->sr);
-            self->c2 = (b - MYSQRT(b * b - 1.0));
-            self->c1 = 1.0 - self->c2;
+            self->c = MYEXP(self->mTwoPiOverSr * freq);
         }
-        val = self->c1 * in[i] + self->c2 * self->y1;
-        self->data[i] = val;
-        self->y1 = val;
+        self->data[i] = self->y1 = in[i] + (self->y1 - in[i]) * self->c;
     }
 }
 
@@ -2981,50 +2925,50 @@ Tone_setProcMode(Tone *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2];
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Tone_filters_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Tone_filters_a;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Tone_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Tone_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Tone_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Tone_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Tone_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Tone_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Tone_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Tone_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Tone_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Tone_compute_next_data_frame(Tone *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -3034,19 +2978,19 @@ Tone_traverse(Tone *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
     return 0;
 }
 
-static int 
+static int
 Tone_clear(Tone *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
     return 0;
 }
 
@@ -3055,7 +2999,7 @@ Tone_dealloc(Tone* self)
 {
     pyo_DEALLOC
     Tone_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -3065,42 +3009,43 @@ Tone_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *multmp=NULL, *addtmp=NULL;
     Tone *self;
     self = (Tone *)type->tp_alloc(type, 0);
-    
+
     self->freq = PyFloat_FromDouble(1000);
     self->lastFreq = -1.0;
-    self->y1 = self->c1 = self->c2 = 0.0;
+    self->y1 = self->c = 0.0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
-    
+
     INIT_OBJECT_COMMON
 
     self->nyquist = (MYFLT)self->sr * 0.49;
+    self->mTwoPiOverSr = -TWOPI / (MYFLT)self->sr;
 
     Stream_setFunctionPtr(self->stream, Tone_compute_next_data_frame);
     self->mode_func_ptr = Tone_setProcMode;
 
     static char *kwlist[] = {"input", "freq", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &freqtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    
+
     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;
@@ -3108,10 +3053,10 @@ Tone_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Tone_getServer(Tone* self) { GET_SERVER };
 static PyObject * Tone_getStream(Tone* self) { GET_STREAM };
-static PyObject * Tone_setMul(Tone *self, PyObject *arg) { SET_MUL };	
-static PyObject * Tone_setAdd(Tone *self, PyObject *arg) { SET_ADD };	
-static PyObject * Tone_setSub(Tone *self, PyObject *arg) { SET_SUB };	
-static PyObject * Tone_setDiv(Tone *self, PyObject *arg) { SET_DIV };	
+static PyObject * Tone_setMul(Tone *self, PyObject *arg) { SET_MUL };
+static PyObject * Tone_setAdd(Tone *self, PyObject *arg) { SET_ADD };
+static PyObject * Tone_setSub(Tone *self, PyObject *arg) { SET_SUB };
+static PyObject * Tone_setDiv(Tone *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Tone_play(Tone *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Tone_out(Tone *self, PyObject *args, PyObject *kwds) { OUT };
@@ -3130,14 +3075,11 @@ static PyObject *
 Tone_setFreq(Tone *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -3153,9 +3095,9 @@ Tone_setFreq(Tone *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -3188,7 +3130,7 @@ static PyNumberMethods Tone_as_number = {
 (binaryfunc)Tone_add,                         /*nb_add*/
 (binaryfunc)Tone_sub,                         /*nb_subtract*/
 (binaryfunc)Tone_multiply,                    /*nb_multiply*/
-(binaryfunc)Tone_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -3202,16 +3144,16 @@ static PyNumberMethods Tone_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)Tone_inplace_add,                 /*inplace_add*/
 (binaryfunc)Tone_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)Tone_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)Tone_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -3220,15 +3162,14 @@ static PyNumberMethods Tone_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)Tone_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)Tone_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject ToneType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Tone_base",                                   /*tp_name*/
 sizeof(Tone),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -3236,7 +3177,7 @@ sizeof(Tone),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &Tone_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -3277,61 +3218,56 @@ typedef struct {
     Stream *input_stream;
     PyObject *freq;
     Stream *freq_stream;
-    int modebuffer[3]; // need at least 2 slots for mul & add 
+    int modebuffer[3]; // need at least 2 slots for mul & add
     MYFLT lastFreq;
     MYFLT nyquist;
+    MYFLT mTwoPiOverSr;
     // sample memories
     MYFLT y1;
     // variables
-    MYFLT c1;
-    MYFLT c2;
+    MYFLT c;
 } Atone;
 
 static void
 Atone_filters_i(Atone *self) {
-    MYFLT val, b;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
-        
+
     if (fr != self->lastFreq) {
-        if (fr <= 1.0)
-            fr = 1.0;
+        if (fr <= 0.1)
+            fr = 0.1;
         else if (fr >= self->nyquist)
-            fr = self->nyquist;        
+            fr = self->nyquist;
         self->lastFreq = fr;
-        b = 2.0 - MYCOS(TWOPI * fr / self->sr);
-        self->c2 = (b - MYSQRT(b * b - 1.0));
-        self->c1 = 1.0 - self->c2;
+        self->c = MYEXP(self->mTwoPiOverSr * fr);
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
-        self->y1 = val = self->c1 * in[i] + self->c2 * self->y1;
-        self->data[i] = in[i] - val;
+        self->y1 = in[i] + (self->y1 - in[i]) * self->c;
+        self->data[i] = in[i] - self->y1;
     }
 }
 
 static void
 Atone_filters_a(Atone *self) {
-    MYFLT val, freq, b;
     int i;
+    MYFLT freq;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-        
+
     for (i=0; i<self->bufsize; i++) {
-        freq = fr[i];        
+        freq = fr[i];
         if (freq != self->lastFreq) {
-            if (freq <= 1.0)
-                freq = 1.0;
+            if (freq <= 0.1)
+                freq = 0.1;
             else if (freq >= self->nyquist)
-                freq = self->nyquist;            
+                freq = self->nyquist;
             self->lastFreq = freq;
-            b = 2.0 - MYCOS(TWOPI * freq / self->sr);
-            self->c2 = (b - MYSQRT(b * b - 1.0));
-            self->c1 = 1.0 - self->c2;
+            self->c = MYEXP(self->mTwoPiOverSr * freq);
         }
-        self->y1 = val = self->c1 * in[i] + self->c2 * self->y1;
-        self->data[i] = in[i] - val;
+        self->y1 = in[i] + (self->y1 - in[i]) * self->c;
+        self->data[i] = in[i] - self->y1;
     }
 }
 
@@ -3351,50 +3287,50 @@ Atone_setProcMode(Atone *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2];
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Atone_filters_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Atone_filters_a;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Atone_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Atone_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Atone_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Atone_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Atone_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Atone_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Atone_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Atone_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Atone_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Atone_compute_next_data_frame(Atone *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -3404,19 +3340,19 @@ Atone_traverse(Atone *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
     return 0;
 }
 
-static int 
+static int
 Atone_clear(Atone *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
     return 0;
 }
 
@@ -3425,7 +3361,7 @@ Atone_dealloc(Atone* self)
 {
     pyo_DEALLOC
     Atone_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -3435,42 +3371,43 @@ Atone_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *multmp=NULL, *addtmp=NULL;
     Atone *self;
     self = (Atone *)type->tp_alloc(type, 0);
-    
+
     self->freq = PyFloat_FromDouble(1000);
     self->lastFreq = -1.0;
-    self->y1 = self->c1 = self->c2 = 0.0;
+    self->y1 = self->c = 0.0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
-    
+
     INIT_OBJECT_COMMON
 
     self->nyquist = (MYFLT)self->sr * 0.49;
+    self->mTwoPiOverSr = -TWOPI / (MYFLT)self->sr;
 
     Stream_setFunctionPtr(self->stream, Atone_compute_next_data_frame);
     self->mode_func_ptr = Atone_setProcMode;
 
     static char *kwlist[] = {"input", "freq", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &freqtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    
+
     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;
@@ -3478,10 +3415,10 @@ Atone_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Atone_getServer(Atone* self) { GET_SERVER };
 static PyObject * Atone_getStream(Atone* self) { GET_STREAM };
-static PyObject * Atone_setMul(Atone *self, PyObject *arg) { SET_MUL };	
-static PyObject * Atone_setAdd(Atone *self, PyObject *arg) { SET_ADD };	
-static PyObject * Atone_setSub(Atone *self, PyObject *arg) { SET_SUB };	
-static PyObject * Atone_setDiv(Atone *self, PyObject *arg) { SET_DIV };	
+static PyObject * Atone_setMul(Atone *self, PyObject *arg) { SET_MUL };
+static PyObject * Atone_setAdd(Atone *self, PyObject *arg) { SET_ADD };
+static PyObject * Atone_setSub(Atone *self, PyObject *arg) { SET_SUB };
+static PyObject * Atone_setDiv(Atone *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Atone_play(Atone *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Atone_out(Atone *self, PyObject *args, PyObject *kwds) { OUT };
@@ -3500,14 +3437,11 @@ static PyObject *
 Atone_setFreq(Atone *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -3523,9 +3457,9 @@ Atone_setFreq(Atone *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -3558,7 +3492,7 @@ static PyNumberMethods Atone_as_number = {
 (binaryfunc)Atone_add,                         /*nb_add*/
 (binaryfunc)Atone_sub,                         /*nb_subtract*/
 (binaryfunc)Atone_multiply,                    /*nb_multiply*/
-(binaryfunc)Atone_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -3572,16 +3506,16 @@ static PyNumberMethods Atone_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)Atone_inplace_add,                 /*inplace_add*/
 (binaryfunc)Atone_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)Atone_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)Atone_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -3590,15 +3524,14 @@ static PyNumberMethods Atone_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)Atone_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)Atone_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject AtoneType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Atone_base",                                   /*tp_name*/
 sizeof(Atone),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -3606,7 +3539,7 @@ sizeof(Atone),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &Atone_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -3645,23 +3578,19 @@ typedef struct {
     pyo_audio_HEAD
     PyObject *input;
     Stream *input_stream;
-    int modebuffer[2]; // need at least 2 slots for mul & add 
-    // sample memories
+    int modebuffer[2]; // need at least 2 slots for mul & add
     MYFLT x1;
     MYFLT y1;
 } DCBlock;
 
 static void
 DCBlock_filters(DCBlock *self) {
-    MYFLT x, y;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
     for (i=0; i<self->bufsize; i++) {
-        x = in[i];
-        y = x - self->x1 + 0.995 * self->y1;
-        self->x1 = x;
-        self->data[i] = self->y1 = y;
+        self->data[i] = self->y1 = in[i] - self->x1 + 0.995 * self->y1;
+        self->x1 = in[i];
     }
 }
 
@@ -3680,44 +3609,44 @@ DCBlock_setProcMode(DCBlock *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-       
+
     self->proc_func_ptr = DCBlock_filters;
 
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = DCBlock_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = DCBlock_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = DCBlock_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = DCBlock_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = DCBlock_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = DCBlock_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = DCBlock_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = DCBlock_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = DCBlock_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 DCBlock_compute_next_data_frame(DCBlock *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -3730,7 +3659,7 @@ DCBlock_traverse(DCBlock *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 DCBlock_clear(DCBlock *self)
 {
     pyo_CLEAR
@@ -3744,7 +3673,7 @@ DCBlock_dealloc(DCBlock* self)
 {
     pyo_DEALLOC
     DCBlock_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -3754,32 +3683,32 @@ DCBlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     DCBlock *self;
     self = (DCBlock *)type->tp_alloc(type, 0);
-    
+
     self->x1 = self->y1 = 0.0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, DCBlock_compute_next_data_frame);
     self->mode_func_ptr = DCBlock_setProcMode;
 
     static char *kwlist[] = {"input", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
 
     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;
@@ -3787,10 +3716,10 @@ DCBlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * DCBlock_getServer(DCBlock* self) { GET_SERVER };
 static PyObject * DCBlock_getStream(DCBlock* self) { GET_STREAM };
-static PyObject * DCBlock_setMul(DCBlock *self, PyObject *arg) { SET_MUL };	
-static PyObject * DCBlock_setAdd(DCBlock *self, PyObject *arg) { SET_ADD };	
-static PyObject * DCBlock_setSub(DCBlock *self, PyObject *arg) { SET_SUB };	
-static PyObject * DCBlock_setDiv(DCBlock *self, PyObject *arg) { SET_DIV };	
+static PyObject * DCBlock_setMul(DCBlock *self, PyObject *arg) { SET_MUL };
+static PyObject * DCBlock_setAdd(DCBlock *self, PyObject *arg) { SET_ADD };
+static PyObject * DCBlock_setSub(DCBlock *self, PyObject *arg) { SET_SUB };
+static PyObject * DCBlock_setDiv(DCBlock *self, PyObject *arg) { SET_DIV };
 
 static PyObject * DCBlock_play(DCBlock *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * DCBlock_out(DCBlock *self, PyObject *args, PyObject *kwds) { OUT };
@@ -3831,7 +3760,7 @@ static PyNumberMethods DCBlock_as_number = {
 (binaryfunc)DCBlock_add,                         /*nb_add*/
 (binaryfunc)DCBlock_sub,                         /*nb_subtract*/
 (binaryfunc)DCBlock_multiply,                    /*nb_multiply*/
-(binaryfunc)DCBlock_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -3845,16 +3774,16 @@ static PyNumberMethods DCBlock_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)DCBlock_inplace_add,                 /*inplace_add*/
 (binaryfunc)DCBlock_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)DCBlock_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)DCBlock_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -3863,15 +3792,14 @@ static PyNumberMethods DCBlock_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)DCBlock_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)DCBlock_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject DCBlockType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.DCBlock_base",                                   /*tp_name*/
 sizeof(DCBlock),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -3879,7 +3807,7 @@ sizeof(DCBlock),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &DCBlock_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -3928,34 +3856,35 @@ typedef struct {
 
 static void
 Allpass_process_ii(Allpass *self) {
-    MYFLT val, xind, frac;
+    MYFLT val, xind, frac, omsqrf;
     int i, ind;
-    
+
     MYFLT del = PyFloat_AS_DOUBLE(self->delay);
     MYFLT feed = PyFloat_AS_DOUBLE(self->feedback);
-    
+
     if (del < 0.)
         del = 0.;
     else if (del > self->maxDelay)
         del = self->maxDelay;
     MYFLT sampdel = del * self->sr;
-    
+
     if (feed < 0)
         feed = 0;
     else if (feed > 1)
         feed = 1;
-    
+    omsqrf = 1.0 - (feed * feed);
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         xind = self->in_count - sampdel;
         if (xind < 0)
             xind += self->size;
         ind = (int)xind;
         frac = xind - ind;
-        val = self->buffer[ind] * (1.0 - frac) + self->buffer[ind+1] * frac;
-        self->data[i] = val * (1.0 - (feed * feed)) + in[i] * -feed;
-        
+        val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac;
+        self->data[i] = val * omsqrf + in[i] * -feed;
+
         self->buffer[self->in_count] = in[i] + (val * feed);
         if (self->in_count == 0)
             self->buffer[self->size] = self->buffer[0];
@@ -3967,19 +3896,20 @@ Allpass_process_ii(Allpass *self) {
 
 static void
 Allpass_process_ai(Allpass *self) {
-    MYFLT val, xind, frac, sampdel, del;
+    MYFLT val, xind, frac, sampdel, del, omsqrf;
     int i, ind;
-    
-    MYFLT *delobj = Stream_getData((Stream *)self->delay_stream);    
+
+    MYFLT *delobj = Stream_getData((Stream *)self->delay_stream);
     MYFLT feed = PyFloat_AS_DOUBLE(self->feedback);
-    
+
     if (feed < 0)
         feed = 0;
     else if (feed > 1)
         feed = 1;
-    
+    omsqrf = 1.0 - (feed * feed);
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         del = delobj[i];
         if (del < 0.)
@@ -3992,9 +3922,9 @@ Allpass_process_ai(Allpass *self) {
             xind += self->size;
         ind = (int)xind;
         frac = xind - ind;
-        val = self->buffer[ind] * (1.0 - frac) + self->buffer[ind+1] * frac;
-        self->data[i] = val * (1.0 - (feed * feed)) + in[i] * -feed;
-        
+        val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac;
+        self->data[i] = val * omsqrf + in[i] * -feed;
+
         self->buffer[self->in_count] = in[i]  + (val * feed);
         if (self->in_count == 0)
             self->buffer[self->size] = self->buffer[0];
@@ -4008,18 +3938,18 @@ static void
 Allpass_process_ia(Allpass *self) {
     MYFLT val, xind, frac, feed;
     int i, ind;
-    
+
     MYFLT del = PyFloat_AS_DOUBLE(self->delay);
-    MYFLT *fdb = Stream_getData((Stream *)self->feedback_stream);    
-    
+    MYFLT *fdb = Stream_getData((Stream *)self->feedback_stream);
+
     if (del < 0.)
         del = 0.;
     else if (del > self->maxDelay)
         del = self->maxDelay;
     MYFLT sampdel = del * self->sr;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         feed = fdb[i];
         if (feed < 0)
@@ -4031,7 +3961,7 @@ Allpass_process_ia(Allpass *self) {
             xind += self->size;
         ind = (int)xind;
         frac = xind - ind;
-        val = self->buffer[ind] * (1.0 - frac) + self->buffer[ind+1] * frac;
+        val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac;
         self->data[i] = val * (1.0 - (feed * feed)) + in[i] * -feed;
 
         self->buffer[self->in_count] = in[i] + (val * feed);
@@ -4047,12 +3977,12 @@ static void
 Allpass_process_aa(Allpass *self) {
     MYFLT val, xind, frac, sampdel, feed, del;
     int i, ind;
-    
-    MYFLT *delobj = Stream_getData((Stream *)self->delay_stream);    
-    MYFLT *fdb = Stream_getData((Stream *)self->feedback_stream);    
-    
+
+    MYFLT *delobj = Stream_getData((Stream *)self->delay_stream);
+    MYFLT *fdb = Stream_getData((Stream *)self->feedback_stream);
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         del = delobj[i];
         feed = fdb[i];
@@ -4070,9 +4000,9 @@ Allpass_process_aa(Allpass *self) {
             xind += self->size;
         ind = (int)xind;
         frac = xind - ind;
-        val = self->buffer[ind] * (1.0 - frac) + self->buffer[ind+1] * frac;
+        val = self->buffer[ind] + (self->buffer[ind+1] - self->buffer[ind]) * frac;
         self->data[i] = val * (1.0 - (feed * feed)) + in[i] * -feed;
-          
+
         self->buffer[self->in_count] = in[i] + (val * feed);
         if (self->in_count == 0)
             self->buffer[self->size] = self->buffer[0];
@@ -4098,56 +4028,56 @@ Allpass_setProcMode(Allpass *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Allpass_process_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Allpass_process_ai;
             break;
-        case 10:    
+        case 10:
             self->proc_func_ptr = Allpass_process_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Allpass_process_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Allpass_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Allpass_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Allpass_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Allpass_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Allpass_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Allpass_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Allpass_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Allpass_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Allpass_postprocessing_revareva;
             break;
-    } 
+    }
 }
 
 static void
 Allpass_compute_next_data_frame(Allpass *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -4156,24 +4086,24 @@ Allpass_traverse(Allpass *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->input);
-    Py_VISIT(self->input_stream);    
-    Py_VISIT(self->delay);    
-    Py_VISIT(self->delay_stream);    
-    Py_VISIT(self->feedback);    
-    Py_VISIT(self->feedback_stream);    
+    Py_VISIT(self->input_stream);
+    Py_VISIT(self->delay);
+    Py_VISIT(self->delay_stream);
+    Py_VISIT(self->feedback);
+    Py_VISIT(self->feedback_stream);
     return 0;
 }
 
-static int 
+static int
 Allpass_clear(Allpass *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
-    Py_CLEAR(self->input_stream);    
-    Py_CLEAR(self->delay);    
-    Py_CLEAR(self->delay_stream);    
-    Py_CLEAR(self->feedback);    
-    Py_CLEAR(self->feedback_stream);    
+    Py_CLEAR(self->input_stream);
+    Py_CLEAR(self->delay);
+    Py_CLEAR(self->delay_stream);
+    Py_CLEAR(self->feedback);
+    Py_CLEAR(self->feedback_stream);
     return 0;
 }
 
@@ -4183,7 +4113,7 @@ Allpass_dealloc(Allpass* self)
     pyo_DEALLOC
     free(self->buffer);
     Allpass_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -4193,7 +4123,7 @@ Allpass_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *delaytmp=NULL, *feedbacktmp=NULL, *multmp=NULL, *addtmp=NULL;
     Allpass *self;
     self = (Allpass *)type->tp_alloc(type, 0);
-    
+
     self->delay = PyFloat_FromDouble(0);
     self->feedback = PyFloat_FromDouble(0);
     self->maxDelay = 1;
@@ -4202,43 +4132,43 @@ Allpass_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Allpass_compute_next_data_frame);
     self->mode_func_ptr = Allpass_setProcMode;
-    
+
     static char *kwlist[] = {"input", "delay", "feedback", "maxDelay", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_OOFOO, kwlist, &inputtmp, &delaytmp, &feedbacktmp, &self->maxDelay, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (delaytmp) {
         PyObject_CallMethod((PyObject *)self, "setDelay", "O", delaytmp);
     }
-    
+
     if (feedbacktmp) {
         PyObject_CallMethod((PyObject *)self, "setFeedback", "O", feedbacktmp);
     }
-    
+
     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->size = self->maxDelay * self->sr + 0.5;
-    
+
     self->buffer = (MYFLT *)realloc(self->buffer, (self->size+1) * sizeof(MYFLT));
     for (i=0; i<(self->size+1); i++) {
         self->buffer[i] = 0.;
-    }    
-    
+    }
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
@@ -4246,10 +4176,10 @@ Allpass_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Allpass_getServer(Allpass* self) { GET_SERVER };
 static PyObject * Allpass_getStream(Allpass* self) { GET_STREAM };
-static PyObject * Allpass_setMul(Allpass *self, PyObject *arg) { SET_MUL };	
-static PyObject * Allpass_setAdd(Allpass *self, PyObject *arg) { SET_ADD };	
-static PyObject * Allpass_setSub(Allpass *self, PyObject *arg) { SET_SUB };	
-static PyObject * Allpass_setDiv(Allpass *self, PyObject *arg) { SET_DIV };	
+static PyObject * Allpass_setMul(Allpass *self, PyObject *arg) { SET_MUL };
+static PyObject * Allpass_setAdd(Allpass *self, PyObject *arg) { SET_ADD };
+static PyObject * Allpass_setSub(Allpass *self, PyObject *arg) { SET_SUB };
+static PyObject * Allpass_setDiv(Allpass *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Allpass_play(Allpass *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Allpass_out(Allpass *self, PyObject *args, PyObject *kwds) { OUT };
@@ -4268,14 +4198,11 @@ static PyObject *
 Allpass_setDelay(Allpass *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-    
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->delay);
@@ -4291,25 +4218,22 @@ Allpass_setDelay(Allpass *self, PyObject *arg)
         self->delay_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Allpass_setFeedback(Allpass *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-    
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->feedback);
@@ -4325,12 +4249,12 @@ Allpass_setFeedback(Allpass *self, PyObject *arg)
         self->feedback_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Allpass_members[] = {
     {"server", T_OBJECT_EX, offsetof(Allpass, server), 0, "Pyo server."},
@@ -4362,7 +4286,7 @@ static PyNumberMethods Allpass_as_number = {
     (binaryfunc)Allpass_add,                      /*nb_add*/
     (binaryfunc)Allpass_sub,                 /*nb_subtract*/
     (binaryfunc)Allpass_multiply,                 /*nb_multiply*/
-    (binaryfunc)Allpass_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -4376,16 +4300,16 @@ static PyNumberMethods Allpass_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)Allpass_inplace_add,              /*inplace_add*/
     (binaryfunc)Allpass_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)Allpass_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)Allpass_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -4394,15 +4318,14 @@ static PyNumberMethods Allpass_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)Allpass_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)Allpass_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject AllpassType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Allpass_base",         /*tp_name*/
     sizeof(Allpass),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -4410,7 +4333,7 @@ PyTypeObject AllpassType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &Allpass_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -4451,8 +4374,9 @@ typedef struct {
     PyObject *bw;
     Stream *bw_stream;
     int init;
-    int modebuffer[4]; // need at least 2 slots for mul & add 
-    MYFLT oneOnSr;
+    int modebuffer[4]; // need at least 2 slots for mul & add
+    MYFLT minusPiOverSr;
+    MYFLT twoPiOverSr;
     MYFLT nyquist;
     // sample memories
     MYFLT y1;
@@ -4464,16 +4388,16 @@ typedef struct {
 
 static void
 Allpass2_compute_variables(Allpass2 *self, MYFLT freq, MYFLT bw)
-{    
+{
     MYFLT radius, angle;
-    if (freq <= 1) 
+    if (freq <= 1)
         freq = 1;
     else if (freq >= self->nyquist)
         freq = self->nyquist;
-    
-    radius = MYPOW(E, -PI * bw * self->oneOnSr);
-    angle = TWOPI * freq * self->oneOnSr;
-    
+
+    radius = MYEXP(bw * self->minusPiOverSr);
+    angle = freq * self->twoPiOverSr;
+
     self->alpha = radius * radius;
     self->beta = -2.0 * radius * MYCOS(angle);
 }
@@ -4483,12 +4407,12 @@ Allpass2_filters_ii(Allpass2 *self) {
     MYFLT val;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->init == 1) {
         self->y1 = self->y2 = in[0];
         self->init = 0;
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         val = in[i] + (self->y1 * -self->beta) + (self->y2 * -self->alpha);
         self->data[i] = (val * self->alpha) + (self->y1 * self->beta) + self->y2;
@@ -4502,15 +4426,15 @@ Allpass2_filters_ai(Allpass2 *self) {
     MYFLT val, bw;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->init == 1) {
         self->y1 = self->y2 = in[0];
         self->init = 0;
     }
-    
+
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
     bw = PyFloat_AS_DOUBLE(self->bw);
-    
+
     for (i=0; i<self->bufsize; i++) {
         Allpass2_compute_variables(self, fr[i], bw);
         val = in[i] + (self->y1 * -self->beta) + (self->y2 * -self->alpha);
@@ -4525,15 +4449,15 @@ Allpass2_filters_ia(Allpass2 *self) {
     MYFLT val, fr;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->init == 1) {
         self->y1 = self->y2 = in[0];
         self->init = 0;
     }
-    
+
     fr = PyFloat_AS_DOUBLE(self->freq);
     MYFLT *bw = Stream_getData((Stream *)self->bw_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         Allpass2_compute_variables(self, fr, bw[i]);
         val = in[i] + (self->y1 * -self->beta) + (self->y2 * -self->alpha);
@@ -4548,15 +4472,15 @@ Allpass2_filters_aa(Allpass2 *self) {
     MYFLT val;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->init == 1) {
         self->y1 = self->y2 = in[0];
         self->init = 0;
     }
-    
+
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
     MYFLT *bw = Stream_getData((Stream *)self->bw_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         Allpass2_compute_variables(self, fr[i], bw[i]);
         val = in[i] + (self->y1 * -self->beta) + (self->y2 * -self->alpha);
@@ -4584,55 +4508,55 @@ Allpass2_setProcMode(Allpass2 *self)
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
 	switch (procmode) {
-        case 0:    
+        case 0:
             Allpass2_compute_variables(self, PyFloat_AS_DOUBLE(self->freq), PyFloat_AS_DOUBLE(self->bw));
             self->proc_func_ptr = Allpass2_filters_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Allpass2_filters_ai;
             break;
-        case 10:        
+        case 10:
             self->proc_func_ptr = Allpass2_filters_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Allpass2_filters_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Allpass2_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Allpass2_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Allpass2_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Allpass2_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Allpass2_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Allpass2_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Allpass2_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Allpass2_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Allpass2_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Allpass2_compute_next_data_frame(Allpass2 *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -4642,23 +4566,23 @@ Allpass2_traverse(Allpass2 *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
-    Py_VISIT(self->bw);    
-    Py_VISIT(self->bw_stream);    
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->bw);
+    Py_VISIT(self->bw_stream);
     return 0;
 }
 
-static int 
+static int
 Allpass2_clear(Allpass2 *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
-    Py_CLEAR(self->bw);    
-    Py_CLEAR(self->bw_stream);    
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->bw);
+    Py_CLEAR(self->bw_stream);
     return 0;
 }
 
@@ -4667,7 +4591,7 @@ Allpass2_dealloc(Allpass2* self)
 {
     pyo_DEALLOC
     Allpass2_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -4677,7 +4601,7 @@ Allpass2_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *bwtmp=NULL, *multmp=NULL, *addtmp=NULL;
     Allpass2 *self;
     self = (Allpass2 *)type->tp_alloc(type, 0);
-    
+
     self->freq = PyFloat_FromDouble(1000);
     self->bw = PyFloat_FromDouble(100);
 	self->modebuffer[0] = 0;
@@ -4685,40 +4609,41 @@ Allpass2_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
     self->init = 1;
-    
+
     INIT_OBJECT_COMMON
-    
-    self->oneOnSr = 1.0 / self->sr;
+
+    self->minusPiOverSr = -PI / self->sr;
+    self->twoPiOverSr = TWOPI / self->sr;
     self->nyquist = (MYFLT)self->sr * 0.49;
 
     Stream_setFunctionPtr(self->stream, Allpass2_compute_next_data_frame);
     self->mode_func_ptr = Allpass2_setProcMode;
 
     static char *kwlist[] = {"input", "freq", "bw", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &freqtmp, &bwtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    
+
     if (bwtmp) {
         PyObject_CallMethod((PyObject *)self, "setBw", "O", bwtmp);
     }
-    
+
     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;
@@ -4726,10 +4651,10 @@ Allpass2_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Allpass2_getServer(Allpass2* self) { GET_SERVER };
 static PyObject * Allpass2_getStream(Allpass2* self) { GET_STREAM };
-static PyObject * Allpass2_setMul(Allpass2 *self, PyObject *arg) { SET_MUL };	
-static PyObject * Allpass2_setAdd(Allpass2 *self, PyObject *arg) { SET_ADD };	
-static PyObject * Allpass2_setSub(Allpass2 *self, PyObject *arg) { SET_SUB };	
-static PyObject * Allpass2_setDiv(Allpass2 *self, PyObject *arg) { SET_DIV };	
+static PyObject * Allpass2_setMul(Allpass2 *self, PyObject *arg) { SET_MUL };
+static PyObject * Allpass2_setAdd(Allpass2 *self, PyObject *arg) { SET_ADD };
+static PyObject * Allpass2_setSub(Allpass2 *self, PyObject *arg) { SET_SUB };
+static PyObject * Allpass2_setDiv(Allpass2 *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Allpass2_play(Allpass2 *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Allpass2_out(Allpass2 *self, PyObject *args, PyObject *kwds) { OUT };
@@ -4748,14 +4673,11 @@ static PyObject *
 Allpass2_setFreq(Allpass2 *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -4771,25 +4693,22 @@ Allpass2_setFreq(Allpass2 *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Allpass2_setBw(Allpass2 *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->bw);
@@ -4805,12 +4724,12 @@ Allpass2_setBw(Allpass2 *self, PyObject *arg)
         self->bw_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Allpass2_members[] = {
 {"server", T_OBJECT_EX, offsetof(Allpass2, server), 0, "Pyo server."},
@@ -4842,7 +4761,7 @@ static PyNumberMethods Allpass2_as_number = {
 (binaryfunc)Allpass2_add,                         /*nb_add*/
 (binaryfunc)Allpass2_sub,                         /*nb_subtract*/
 (binaryfunc)Allpass2_multiply,                    /*nb_multiply*/
-(binaryfunc)Allpass2_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -4856,16 +4775,16 @@ static PyNumberMethods Allpass2_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)Allpass2_inplace_add,                 /*inplace_add*/
 (binaryfunc)Allpass2_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)Allpass2_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)Allpass2_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -4874,15 +4793,14 @@ static PyNumberMethods Allpass2_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)Allpass2_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)Allpass2_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject Allpass2Type = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Allpass2_base",                                   /*tp_name*/
 sizeof(Allpass2),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -4890,7 +4808,7 @@ sizeof(Allpass2),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &Allpass2_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -4938,7 +4856,7 @@ typedef struct {
     PyObject *feedback;
     Stream *feedback_stream;
     int stages;
-    int modebuffer[6]; // need at least 2 slots for mul & add 
+    int modebuffer[6]; // need at least 2 slots for mul & add
     MYFLT halfSr;
     MYFLT minusPiOnSr;
     MYFLT twoPiOnSr;
@@ -4958,35 +4876,35 @@ Phaser_clip(MYFLT x) {
         return -1.0;
     else if (x > 1.0)
         return 1.0;
-    else 
+    else
         return x;
-}    
+}
 
 static void
 Phaser_compute_variables(Phaser *self, MYFLT freq, MYFLT spread, MYFLT q)
-{    
+{
     int i, ipart;
     MYFLT radius, angle, fr, qfactor, pos, fpart;
 
     qfactor = 1.0 / q * self->minusPiOnSr;
     fr = freq;
     for (i=0; i<self->stages; i++) {
-        if (fr <= 20) 
+        if (fr <= 20)
             fr = 20;
         else if (fr >= self->halfSr)
             fr = self->halfSr;
-    
-        radius = MYPOW(E, fr * qfactor);
+
+        radius = MYEXP(fr * qfactor);
         angle = fr * self->twoPiOnSr;
-    
+
         self->alpha[i] = radius * radius;
-        
+
         pos = angle * self->norm_arr_pos;
         ipart = (int)pos;
         fpart = pos - ipart;
-        self->beta[i] = -2.0 * radius * (HALF_COS_ARRAY[i] * (1.0 - fpart) + HALF_COS_ARRAY[i+1] * fpart);
+        self->beta[i] = -2.0 * radius * (HALF_COS_ARRAY[i] + (HALF_COS_ARRAY[i+1] - HALF_COS_ARRAY[i]) * fpart);
         fr *= spread;
-    }    
+    }
 }
 
 static void
@@ -5007,7 +4925,7 @@ Phaser_filters_iii(Phaser *self) {
             }
             self->data[i] = self->tmp;
         }
-    }    
+    }
     else {
         MYFLT *feed = Stream_getData((Stream *)self->feedback_stream);
         for (i=0; i<self->bufsize; i++) {
@@ -5031,7 +4949,7 @@ Phaser_filters_aii(Phaser *self) {
     MYFLT *freq = Stream_getData((Stream *)self->freq_stream);
     MYFLT spread = PyFloat_AS_DOUBLE(self->spread);
     MYFLT q = PyFloat_AS_DOUBLE(self->q);
-    
+
     if (self->modebuffer[5] == 0) {
         MYFLT feed = Phaser_clip(PyFloat_AS_DOUBLE(self->feedback));
         for (i=0; i<self->bufsize; i++) {
@@ -5045,7 +4963,7 @@ Phaser_filters_aii(Phaser *self) {
             }
             self->data[i] = self->tmp;
         }
-    }    
+    }
     else {
         MYFLT *feed = Stream_getData((Stream *)self->feedback_stream);
         for (i=0; i<self->bufsize; i++) {
@@ -5070,7 +4988,7 @@ Phaser_filters_iai(Phaser *self) {
     MYFLT freq = PyFloat_AS_DOUBLE(self->freq);
     MYFLT *spread = Stream_getData((Stream *)self->spread_stream);
     MYFLT q = PyFloat_AS_DOUBLE(self->q);
-    
+
     if (self->modebuffer[5] == 0) {
         MYFLT feed = Phaser_clip(PyFloat_AS_DOUBLE(self->feedback));
         for (i=0; i<self->bufsize; i++) {
@@ -5084,7 +5002,7 @@ Phaser_filters_iai(Phaser *self) {
             }
             self->data[i] = self->tmp;
         }
-    }    
+    }
     else {
         MYFLT *feed = Stream_getData((Stream *)self->feedback_stream);
         for (i=0; i<self->bufsize; i++) {
@@ -5109,7 +5027,7 @@ Phaser_filters_aai(Phaser *self) {
     MYFLT *freq = Stream_getData((Stream *)self->freq_stream);
     MYFLT *spread = Stream_getData((Stream *)self->spread_stream);
     MYFLT q = PyFloat_AS_DOUBLE(self->q);
-    
+
     if (self->modebuffer[5] == 0) {
         MYFLT feed = Phaser_clip(PyFloat_AS_DOUBLE(self->feedback));
         for (i=0; i<self->bufsize; i++) {
@@ -5123,7 +5041,7 @@ Phaser_filters_aai(Phaser *self) {
             }
             self->data[i] = self->tmp;
         }
-    }    
+    }
     else {
         MYFLT *feed = Stream_getData((Stream *)self->feedback_stream);
         for (i=0; i<self->bufsize; i++) {
@@ -5148,7 +5066,7 @@ Phaser_filters_iia(Phaser *self) {
     MYFLT freq = PyFloat_AS_DOUBLE(self->freq);
     MYFLT spread = PyFloat_AS_DOUBLE(self->spread);
     MYFLT *q = Stream_getData((Stream *)self->q_stream);
-    
+
     if (self->modebuffer[5] == 0) {
         MYFLT feed = Phaser_clip(PyFloat_AS_DOUBLE(self->feedback));
         for (i=0; i<self->bufsize; i++) {
@@ -5162,7 +5080,7 @@ Phaser_filters_iia(Phaser *self) {
             }
             self->data[i] = self->tmp;
         }
-    }    
+    }
     else {
         MYFLT *feed = Stream_getData((Stream *)self->feedback_stream);
         for (i=0; i<self->bufsize; i++) {
@@ -5187,7 +5105,7 @@ Phaser_filters_aia(Phaser *self) {
     MYFLT *freq = Stream_getData((Stream *)self->freq_stream);
     MYFLT spread = PyFloat_AS_DOUBLE(self->spread);
     MYFLT *q = Stream_getData((Stream *)self->q_stream);
-    
+
     if (self->modebuffer[5] == 0) {
         MYFLT feed = Phaser_clip(PyFloat_AS_DOUBLE(self->feedback));
         for (i=0; i<self->bufsize; i++) {
@@ -5201,7 +5119,7 @@ Phaser_filters_aia(Phaser *self) {
             }
             self->data[i] = self->tmp;
         }
-    }    
+    }
     else {
         MYFLT *feed = Stream_getData((Stream *)self->feedback_stream);
         for (i=0; i<self->bufsize; i++) {
@@ -5226,7 +5144,7 @@ Phaser_filters_iaa(Phaser *self) {
     MYFLT freq = PyFloat_AS_DOUBLE(self->freq);
     MYFLT *spread = Stream_getData((Stream *)self->spread_stream);
     MYFLT *q = Stream_getData((Stream *)self->q_stream);
-    
+
     if (self->modebuffer[5] == 0) {
         MYFLT feed = Phaser_clip(PyFloat_AS_DOUBLE(self->feedback));
         for (i=0; i<self->bufsize; i++) {
@@ -5240,7 +5158,7 @@ Phaser_filters_iaa(Phaser *self) {
             }
             self->data[i] = self->tmp;
         }
-    }    
+    }
     else {
         MYFLT *feed = Stream_getData((Stream *)self->feedback_stream);
         for (i=0; i<self->bufsize; i++) {
@@ -5265,7 +5183,7 @@ Phaser_filters_aaa(Phaser *self) {
     MYFLT *freq = Stream_getData((Stream *)self->freq_stream);
     MYFLT *spread = Stream_getData((Stream *)self->spread_stream);
     MYFLT *q = Stream_getData((Stream *)self->q_stream);
-    
+
     if (self->modebuffer[5] == 0) {
         MYFLT feed = Phaser_clip(PyFloat_AS_DOUBLE(self->feedback));
         for (i=0; i<self->bufsize; i++) {
@@ -5279,7 +5197,7 @@ Phaser_filters_aaa(Phaser *self) {
             }
             self->data[i] = self->tmp;
         }
-    }    
+    }
     else {
         MYFLT *feed = Stream_getData((Stream *)self->feedback_stream);
         for (i=0; i<self->bufsize; i++) {
@@ -5312,69 +5230,69 @@ Phaser_setProcMode(Phaser *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             Phaser_compute_variables(self, PyFloat_AS_DOUBLE(self->freq), PyFloat_AS_DOUBLE(self->spread), PyFloat_AS_DOUBLE(self->q));
             self->proc_func_ptr = Phaser_filters_iii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Phaser_filters_aii;
             break;
-        case 10:        
+        case 10:
             self->proc_func_ptr = Phaser_filters_iai;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Phaser_filters_aai;
             break;
-        case 100:    
+        case 100:
             self->proc_func_ptr = Phaser_filters_iia;
             break;
-        case 101:    
+        case 101:
             self->proc_func_ptr = Phaser_filters_aia;
             break;
-        case 110:        
+        case 110:
             self->proc_func_ptr = Phaser_filters_iaa;
             break;
-        case 111:    
+        case 111:
             self->proc_func_ptr = Phaser_filters_aaa;
-            break;            
-    } 
+            break;
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Phaser_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Phaser_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Phaser_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Phaser_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Phaser_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Phaser_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Phaser_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Phaser_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Phaser_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Phaser_compute_next_data_frame(Phaser *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -5384,31 +5302,31 @@ Phaser_traverse(Phaser *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
-    Py_VISIT(self->spread);    
-    Py_VISIT(self->spread_stream);    
-    Py_VISIT(self->q);    
-    Py_VISIT(self->q_stream);    
-    Py_VISIT(self->feedback);    
-    Py_VISIT(self->feedback_stream);    
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->spread);
+    Py_VISIT(self->spread_stream);
+    Py_VISIT(self->q);
+    Py_VISIT(self->q_stream);
+    Py_VISIT(self->feedback);
+    Py_VISIT(self->feedback_stream);
     return 0;
 }
 
-static int 
+static int
 Phaser_clear(Phaser *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
-    Py_CLEAR(self->spread);    
-    Py_CLEAR(self->spread_stream);    
-    Py_CLEAR(self->q);    
-    Py_CLEAR(self->q_stream);    
-    Py_CLEAR(self->feedback);    
-    Py_CLEAR(self->feedback_stream);    
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->spread);
+    Py_CLEAR(self->spread_stream);
+    Py_CLEAR(self->q);
+    Py_CLEAR(self->q_stream);
+    Py_CLEAR(self->feedback);
+    Py_CLEAR(self->feedback_stream);
     return 0;
 }
 
@@ -5421,7 +5339,7 @@ Phaser_dealloc(Phaser* self)
     free(self->alpha);
     free(self->beta);
     Phaser_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -5431,7 +5349,7 @@ Phaser_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *spreadtmp=NULL, *qtmp=NULL, *feedbacktmp=NULL, *multmp=NULL, *addtmp=NULL;
     Phaser *self;
     self = (Phaser *)type->tp_alloc(type, 0);
-    
+
     self->freq = PyFloat_FromDouble(1000.0);
     self->spread = PyFloat_FromDouble(1.0);
     self->q = PyFloat_FromDouble(10.0);
@@ -5444,30 +5362,30 @@ Phaser_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[3] = 0;
 	self->modebuffer[4] = 0;
 	self->modebuffer[5] = 0;
-    
+
     INIT_OBJECT_COMMON
-    
+
     self->halfSr = (MYFLT)self->sr * 0.49;
     self->minusPiOnSr = -PI / self->sr;
     self->twoPiOnSr = TWOPI / self->sr;
     self->norm_arr_pos = 1.0 / PI * 512.0;
-    
+
     Stream_setFunctionPtr(self->stream, Phaser_compute_next_data_frame);
     self->mode_func_ptr = Phaser_setProcMode;
 
     static char *kwlist[] = {"input", "freq", "spread", "q", "feedback", "num", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOOiOO", kwlist, &inputtmp, &freqtmp, &spreadtmp, &qtmp, &feedbacktmp, &self->stages, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
 
     self->y1 = (MYFLT *)realloc(self->y1, self->stages * sizeof(MYFLT));
     self->y2 = (MYFLT *)realloc(self->y2, self->stages * sizeof(MYFLT));
     self->alpha = (MYFLT *)realloc(self->alpha, self->stages * sizeof(MYFLT));
     self->beta = (MYFLT *)realloc(self->beta, self->stages * sizeof(MYFLT));
-    
-    
+
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
@@ -5475,7 +5393,7 @@ Phaser_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (spreadtmp) {
         PyObject_CallMethod((PyObject *)self, "setSpread", "O", spreadtmp);
     }
-    
+
     if (qtmp) {
         PyObject_CallMethod((PyObject *)self, "setQ", "O", qtmp);
     }
@@ -5483,19 +5401,19 @@ Phaser_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (feedbacktmp) {
         PyObject_CallMethod((PyObject *)self, "setFeedback", "O", feedbacktmp);
     }
-    
+
     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);
-    
+
     for (i=0; i<self->stages; i++) {
         self->y1[i] = self->y2[i] = 0.0;
     }
@@ -5505,10 +5423,10 @@ Phaser_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Phaser_getServer(Phaser* self) { GET_SERVER };
 static PyObject * Phaser_getStream(Phaser* self) { GET_STREAM };
-static PyObject * Phaser_setMul(Phaser *self, PyObject *arg) { SET_MUL };	
-static PyObject * Phaser_setAdd(Phaser *self, PyObject *arg) { SET_ADD };	
-static PyObject * Phaser_setSub(Phaser *self, PyObject *arg) { SET_SUB };	
-static PyObject * Phaser_setDiv(Phaser *self, PyObject *arg) { SET_DIV };	
+static PyObject * Phaser_setMul(Phaser *self, PyObject *arg) { SET_MUL };
+static PyObject * Phaser_setAdd(Phaser *self, PyObject *arg) { SET_ADD };
+static PyObject * Phaser_setSub(Phaser *self, PyObject *arg) { SET_SUB };
+static PyObject * Phaser_setDiv(Phaser *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Phaser_play(Phaser *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Phaser_out(Phaser *self, PyObject *args, PyObject *kwds) { OUT };
@@ -5527,14 +5445,11 @@ static PyObject *
 Phaser_setFreq(Phaser *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -5550,25 +5465,22 @@ Phaser_setFreq(Phaser *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Phaser_setSpread(Phaser *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->spread);
@@ -5584,25 +5496,22 @@ Phaser_setSpread(Phaser *self, PyObject *arg)
         self->spread_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Phaser_setQ(Phaser *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->q);
@@ -5618,25 +5527,22 @@ Phaser_setQ(Phaser *self, PyObject *arg)
         self->q_stream = (Stream *)streamtmp;
 		self->modebuffer[4] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Phaser_setFeedback(Phaser *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->feedback);
@@ -5655,7 +5561,7 @@ Phaser_setFeedback(Phaser *self, PyObject *arg)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Phaser_members[] = {
     {"server", T_OBJECT_EX, offsetof(Phaser, server), 0, "Pyo server."},
@@ -5691,7 +5597,7 @@ static PyNumberMethods Phaser_as_number = {
     (binaryfunc)Phaser_add,                         /*nb_add*/
     (binaryfunc)Phaser_sub,                         /*nb_subtract*/
     (binaryfunc)Phaser_multiply,                    /*nb_multiply*/
-    (binaryfunc)Phaser_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -5705,16 +5611,16 @@ static PyNumberMethods Phaser_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Phaser_inplace_add,                 /*inplace_add*/
     (binaryfunc)Phaser_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Phaser_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Phaser_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -5723,15 +5629,14 @@ static PyNumberMethods Phaser_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Phaser_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Phaser_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject PhaserType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Phaser_base",                                   /*tp_name*/
     sizeof(Phaser),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -5739,7 +5644,7 @@ PyTypeObject PhaserType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &Phaser_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -5792,9 +5697,10 @@ typedef struct {
     MYFLT factor;
     int stages;
     int last_stages;
+    int flag;
     MYFLT nyquist;
     MYFLT twoPiOnSr;
-    int modebuffer[6]; // need at least 2 slots for mul & add 
+    int modebuffer[6]; // need at least 2 slots for mul & add
     // sample memories
     MYFLT *y1;
     MYFLT *y2;
@@ -5829,26 +5735,26 @@ Vocoder_allocate_memories(Vocoder *self)
         for (j=0; j<2; j++) {
             i2j = i * 2 + j;
             self->yy1[i2j] = self->yy2[i2j] = self->y1[i2j] = self->y2[i2j] = 0.0;
-
         }
-    }    
+    }
+    self->flag = 1;
 }
 
 static void
 Vocoder_compute_variables(Vocoder *self, MYFLT base, MYFLT spread, MYFLT q)
-{    
+{
     int i;
     MYFLT w0, c, alpha, freq, invqfac;
-    
+
     invqfac = 1.0 / (2.0 * q);
 
     for (i=0; i<self->stages; i++) {
         freq = base * MYPOW(i+1, spread);
-        if (freq <= 10) 
+        if (freq <= 10)
             freq = 10.0;
         else if (freq >= self->nyquist)
             freq = self->nyquist;
-        
+
         w0 = self->twoPiOnSr * freq;
         c = MYCOS(w0);
         alpha = MYSIN(w0) * invqfac;
@@ -5859,21 +5765,21 @@ Vocoder_compute_variables(Vocoder *self, MYFLT base, MYFLT spread, MYFLT q)
         self->a2[i] = 1.0 - alpha;
     }
 }
-    
+
 static void
 Vocoder_filters_iii(Vocoder *self) {
     int i, j, j2;
     MYFLT vin, vout, vin2, vout2, w, w2, freq, spread, q, slope, output, amp;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *in2 = Stream_getData((Stream *)self->input2_stream);
-    
+
     freq = PyFloat_AS_DOUBLE(self->freq);
     spread = PyFloat_AS_DOUBLE(self->spread);
     q = PyFloat_AS_DOUBLE(self->q);
     if (q < 0.1)
         q = 0.1;
     amp = q * 10.0;
-    
+
     if (self->modebuffer[5] == 0)
         slope = PyFloat_AS_DOUBLE(self->slope);
     else
@@ -5887,14 +5793,15 @@ Vocoder_filters_iii(Vocoder *self) {
         self->factor = MYEXP(-1.0 / (self->sr / ((slope * 48.0) + 2.0)));
     }
 
-    if (freq != self->last_freq || spread != self->last_spread || q != self->last_q || self->stages != self->last_stages) {
+    if (freq != self->last_freq || spread != self->last_spread || q != self->last_q || self->stages != self->last_stages || self->flag) {
         self->last_freq = freq;
         self->last_spread = spread;
         self->last_q = q;
         self->last_stages = self->stages;
+        self->flag = 0;
         Vocoder_compute_variables(self, freq, spread, q);
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         output = 0.0;
         vin = in[i];
@@ -5906,26 +5813,26 @@ Vocoder_filters_iii(Vocoder *self) {
             vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]);
             self->y2[j2] = self->y1[j2];
             self->y1[j2] = w;
-            
+
             /* Exciter part filter 1 */
             w2 = ( vin2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j];
             vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]);
             self->yy2[j2] = self->yy1[j2];
             self->yy1[j2] = w2;
-            
+
             j2++;
             /* Analysis part filter 2 */
             w = ( vout - (self->a1[j] * self->y1[j2]) - (self->a2[j] * self->y2[j2]) ) * self->a0[j];
             vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]);
             self->y2[j2] = self->y1[j2];
             self->y1[j2] = w;
-            
+
             /* Exciter part filter 2 */
             w2 = ( vout2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j];
             vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]);
             self->yy2[j2] = self->yy1[j2];
             self->yy1[j2] = w2;
-            
+
             /* Follower */
             if (vout < 0.0)
                 vout = -vout;
@@ -5951,7 +5858,7 @@ Vocoder_filters_aii(Vocoder *self) {
     if (q < 0.1)
         q = 0.1;
     amp = q * 10.0;
-        
+
     if (self->modebuffer[5] == 0)
         slope = PyFloat_AS_DOUBLE(self->slope);
     else
@@ -5964,18 +5871,19 @@ Vocoder_filters_aii(Vocoder *self) {
         self->last_slope = slope;
         self->factor = MYEXP(-1.0 / (self->sr / ((slope * 48.0) + 2.0)));
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (count == 0)
             freq = fr[i];
         else if (count >= maxcount)
             count = 0;
         count++;
-        if (freq != self->last_freq || spread != self->last_spread || q != self->last_q || self->stages != self->last_stages) {
+        if (freq != self->last_freq || spread != self->last_spread || q != self->last_q || self->stages != self->last_stages || self->flag) {
             self->last_freq = freq;
             self->last_spread = spread;
             self->last_q = q;
             self->last_stages = self->stages;
+            self->flag = 0;
             Vocoder_compute_variables(self, freq, spread, q);
         }
         output = 0.0;
@@ -5988,26 +5896,26 @@ Vocoder_filters_aii(Vocoder *self) {
             vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]);
             self->y2[j2] = self->y1[j2];
             self->y1[j2] = w;
-                        
+
             /* Exciter part filter 1 */
             w2 = ( vin2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j];
             vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]);
             self->yy2[j2] = self->yy1[j2];
             self->yy1[j2] = w2;
-            
+
             j2++;
             /* Analysis part filter 2 */
             w = ( vout - (self->a1[j] * self->y1[j2]) - (self->a2[j] * self->y2[j2]) ) * self->a0[j];
             vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]);
             self->y2[j2] = self->y1[j2];
             self->y1[j2] = w;
-            
+
             /* Exciter part filter 2 */
             w2 = ( vout2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j];
             vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]);
             self->yy2[j2] = self->yy1[j2];
             self->yy1[j2] = w2;
-            
+
             /* Follower */
             if (vout < 0.0)
                 vout = -vout;
@@ -6025,7 +5933,7 @@ Vocoder_filters_iai(Vocoder *self) {
     MYFLT vin, vout, vin2, vout2, w, w2, freq, q, slope, output, amp;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *in2 = Stream_getData((Stream *)self->input2_stream);
-    
+
     freq = PyFloat_AS_DOUBLE(self->freq);
     MYFLT *sprd = Stream_getData((Stream *)self->spread_stream);
     MYFLT spread = sprd[0];
@@ -6033,7 +5941,7 @@ Vocoder_filters_iai(Vocoder *self) {
     if (q < 0.1)
         q = 0.1;
     amp = q * 10.0;
-    
+
     if (self->modebuffer[5] == 0)
         slope = PyFloat_AS_DOUBLE(self->slope);
     else
@@ -6046,18 +5954,19 @@ Vocoder_filters_iai(Vocoder *self) {
         self->last_slope = slope;
         self->factor = MYEXP(-1.0 / (self->sr / ((slope * 48.0) + 2.0)));
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (count == 0)
             spread = sprd[i];
         else if (count >= maxcount)
             count = 0;
         count++;
-        if (freq != self->last_freq || spread != self->last_spread || q != self->last_q || self->stages != self->last_stages) {
+        if (freq != self->last_freq || spread != self->last_spread || q != self->last_q || self->stages != self->last_stages || self->flag) {
             self->last_freq = freq;
             self->last_spread = spread;
             self->last_q = q;
             self->last_stages = self->stages;
+            self->flag = 0;
             Vocoder_compute_variables(self, freq, spread, q);
         }
         output = 0.0;
@@ -6070,26 +5979,26 @@ Vocoder_filters_iai(Vocoder *self) {
             vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]);
             self->y2[j2] = self->y1[j2];
             self->y1[j2] = w;
-            
+
             /* Exciter part filter 1 */
             w2 = ( vin2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j];
             vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]);
             self->yy2[j2] = self->yy1[j2];
             self->yy1[j2] = w2;
-            
+
             j2++;
             /* Analysis part filter 2 */
             w = ( vout - (self->a1[j] * self->y1[j2]) - (self->a2[j] * self->y2[j2]) ) * self->a0[j];
             vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]);
             self->y2[j2] = self->y1[j2];
             self->y1[j2] = w;
-            
+
             /* Exciter part filter 2 */
             w2 = ( vout2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j];
             vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]);
             self->yy2[j2] = self->yy1[j2];
             self->yy1[j2] = w2;
-            
+
             /* Follower */
             if (vout < 0.0)
                 vout = -vout;
@@ -6097,7 +6006,7 @@ Vocoder_filters_iai(Vocoder *self) {
             output += vout2 * self->follow[j];
         }
         self->data[i] = output * amp;
-    }    
+    }
 }
 
 static void
@@ -6107,7 +6016,7 @@ Vocoder_filters_aai(Vocoder *self) {
     MYFLT vin, vout, vin2, vout2, w, w2, q, slope, output, amp;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *in2 = Stream_getData((Stream *)self->input2_stream);
-    
+
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
     MYFLT freq = fr[0];
     MYFLT *sprd = Stream_getData((Stream *)self->spread_stream);
@@ -6116,7 +6025,7 @@ Vocoder_filters_aai(Vocoder *self) {
     if (q < 0.1)
         q = 0.1;
     amp = q * 10.0;
-    
+
     if (self->modebuffer[5] == 0)
         slope = PyFloat_AS_DOUBLE(self->slope);
     else
@@ -6129,7 +6038,7 @@ Vocoder_filters_aai(Vocoder *self) {
         self->last_slope = slope;
         self->factor = MYEXP(-1.0 / (self->sr / ((slope * 48.0) + 2.0)));
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (count == 0) {
             freq = fr[i];
@@ -6138,11 +6047,12 @@ Vocoder_filters_aai(Vocoder *self) {
         else if (count >= maxcount)
             count = 0;
         count++;
-        if (freq != self->last_freq || spread != self->last_spread || q != self->last_q || self->stages != self->last_stages) {
+        if (freq != self->last_freq || spread != self->last_spread || q != self->last_q || self->stages != self->last_stages || self->flag) {
             self->last_freq = freq;
             self->last_spread = spread;
             self->last_q = q;
             self->last_stages = self->stages;
+            self->flag = 0;
             Vocoder_compute_variables(self, freq, spread, q);
         }
         output = 0.0;
@@ -6155,26 +6065,26 @@ Vocoder_filters_aai(Vocoder *self) {
             vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]);
             self->y2[j2] = self->y1[j2];
             self->y1[j2] = w;
-            
+
             /* Exciter part filter 1 */
             w2 = ( vin2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j];
             vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]);
             self->yy2[j2] = self->yy1[j2];
             self->yy1[j2] = w2;
-            
+
             j2++;
             /* Analysis part filter 2 */
             w = ( vout - (self->a1[j] * self->y1[j2]) - (self->a2[j] * self->y2[j2]) ) * self->a0[j];
             vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]);
             self->y2[j2] = self->y1[j2];
             self->y1[j2] = w;
-            
+
             /* Exciter part filter 2 */
             w2 = ( vout2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j];
             vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]);
             self->yy2[j2] = self->yy1[j2];
             self->yy1[j2] = w2;
-            
+
             /* Follower */
             if (vout < 0.0)
                 vout = -vout;
@@ -6182,7 +6092,7 @@ Vocoder_filters_aai(Vocoder *self) {
             output += vout2 * self->follow[j];
         }
         self->data[i] = output * amp;
-    }    
+    }
 }
 
 static void
@@ -6192,7 +6102,7 @@ Vocoder_filters_iia(Vocoder *self) {
     MYFLT vin, vout, vin2, vout2, w, w2, freq, spread, slope, output, amp = 1.0;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *in2 = Stream_getData((Stream *)self->input2_stream);
-    
+
     freq = PyFloat_AS_DOUBLE(self->freq);
     spread = PyFloat_AS_DOUBLE(self->spread);
     MYFLT *qstr = Stream_getData((Stream *)self->q_stream);
@@ -6209,22 +6119,23 @@ Vocoder_filters_iia(Vocoder *self) {
         self->last_slope = slope;
         self->factor = MYEXP(-1.0 / (self->sr / ((slope * 48.0) + 2.0)));
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (count == 0) {
             q = qstr[i];
             if (q < 0.1)
                 q = 0.1;
-            amp = q * 10.0;            
+            amp = q * 10.0;
         }
         else if (count >= maxcount)
             count = 0;
         count++;
-        if (freq != self->last_freq || spread != self->last_spread || q != self->last_q || self->stages != self->last_stages) {
+        if (freq != self->last_freq || spread != self->last_spread || q != self->last_q || self->stages != self->last_stages || self->flag) {
             self->last_freq = freq;
             self->last_spread = spread;
             self->last_q = q;
             self->last_stages = self->stages;
+            self->flag = 0;
             Vocoder_compute_variables(self, freq, spread, q);
         }
         output = 0.0;
@@ -6237,26 +6148,26 @@ Vocoder_filters_iia(Vocoder *self) {
             vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]);
             self->y2[j2] = self->y1[j2];
             self->y1[j2] = w;
-            
+
             /* Exciter part filter 1 */
             w2 = ( vin2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j];
             vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]);
             self->yy2[j2] = self->yy1[j2];
             self->yy1[j2] = w2;
-            
+
             j2++;
             /* Analysis part filter 2 */
             w = ( vout - (self->a1[j] * self->y1[j2]) - (self->a2[j] * self->y2[j2]) ) * self->a0[j];
             vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]);
             self->y2[j2] = self->y1[j2];
             self->y1[j2] = w;
-            
+
             /* Exciter part filter 2 */
             w2 = ( vout2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j];
             vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]);
             self->yy2[j2] = self->yy1[j2];
             self->yy1[j2] = w2;
-            
+
             /* Follower */
             if (vout < 0.0)
                 vout = -vout;
@@ -6264,7 +6175,7 @@ Vocoder_filters_iia(Vocoder *self) {
             output += vout2 * self->follow[j];
         }
         self->data[i] = output * amp;
-    }    
+    }
 }
 
 static void
@@ -6274,7 +6185,7 @@ Vocoder_filters_aia(Vocoder *self) {
     MYFLT vin, vout, vin2, vout2, w, w2, spread, slope, output, amp = 1.0;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *in2 = Stream_getData((Stream *)self->input2_stream);
-    
+
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
     MYFLT freq = fr[0];
     spread = PyFloat_AS_DOUBLE(self->spread);
@@ -6292,23 +6203,24 @@ Vocoder_filters_aia(Vocoder *self) {
         self->last_slope = slope;
         self->factor = MYEXP(-1.0 / (self->sr / ((slope * 48.0) + 2.0)));
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (count == 0) {
             freq = fr[i];
             q = qstr[i];
             if (q < 0.1)
                 q = 0.1;
-            amp = q * 10.0;            
+            amp = q * 10.0;
         }
         else if (count >= maxcount)
             count = 0;
         count++;
-        if (freq != self->last_freq || spread != self->last_spread || q != self->last_q || self->stages != self->last_stages) {
+        if (freq != self->last_freq || spread != self->last_spread || q != self->last_q || self->stages != self->last_stages || self->flag) {
             self->last_freq = freq;
             self->last_spread = spread;
             self->last_q = q;
             self->last_stages = self->stages;
+            self->flag = 0;
             Vocoder_compute_variables(self, freq, spread, q);
         }
         output = 0.0;
@@ -6321,26 +6233,26 @@ Vocoder_filters_aia(Vocoder *self) {
             vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]);
             self->y2[j2] = self->y1[j2];
             self->y1[j2] = w;
-            
+
             /* Exciter part filter 1 */
             w2 = ( vin2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j];
             vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]);
             self->yy2[j2] = self->yy1[j2];
             self->yy1[j2] = w2;
-            
+
             j2++;
             /* Analysis part filter 2 */
             w = ( vout - (self->a1[j] * self->y1[j2]) - (self->a2[j] * self->y2[j2]) ) * self->a0[j];
             vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]);
             self->y2[j2] = self->y1[j2];
             self->y1[j2] = w;
-            
+
             /* Exciter part filter 2 */
             w2 = ( vout2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j];
             vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]);
             self->yy2[j2] = self->yy1[j2];
             self->yy1[j2] = w2;
-            
+
             /* Follower */
             if (vout < 0.0)
                 vout = -vout;
@@ -6348,7 +6260,7 @@ Vocoder_filters_aia(Vocoder *self) {
             output += vout2 * self->follow[j];
         }
         self->data[i] = output * amp;
-    }    
+    }
 }
 
 static void
@@ -6358,7 +6270,7 @@ Vocoder_filters_iaa(Vocoder *self) {
     MYFLT vin, vout, vin2, vout2, w, w2, freq, slope, output, amp = 1.0;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *in2 = Stream_getData((Stream *)self->input2_stream);
-    
+
     freq = PyFloat_AS_DOUBLE(self->freq);
     MYFLT *sprd = Stream_getData((Stream *)self->spread_stream);
     MYFLT spread = sprd[0];
@@ -6376,23 +6288,24 @@ Vocoder_filters_iaa(Vocoder *self) {
         self->last_slope = slope;
         self->factor = MYEXP(-1.0 / (self->sr / ((slope * 48.0) + 2.0)));
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (count == 0) {
             spread = sprd[i];
             q = qstr[i];
             if (q < 0.1)
                 q = 0.1;
-            amp = q * 10.0;            
+            amp = q * 10.0;
         }
         else if (count >= maxcount)
             count = 0;
         count++;
-        if (freq != self->last_freq || spread != self->last_spread || q != self->last_q || self->stages != self->last_stages) {
+        if (freq != self->last_freq || spread != self->last_spread || q != self->last_q || self->stages != self->last_stages || self->flag) {
             self->last_freq = freq;
             self->last_spread = spread;
             self->last_q = q;
             self->last_stages = self->stages;
+            self->flag = 0;
             Vocoder_compute_variables(self, freq, spread, q);
         }
         output = 0.0;
@@ -6405,26 +6318,26 @@ Vocoder_filters_iaa(Vocoder *self) {
             vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]);
             self->y2[j2] = self->y1[j2];
             self->y1[j2] = w;
-            
+
             /* Exciter part filter 1 */
             w2 = ( vin2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j];
             vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]);
             self->yy2[j2] = self->yy1[j2];
             self->yy1[j2] = w2;
-            
+
             j2++;
             /* Analysis part filter 2 */
             w = ( vout - (self->a1[j] * self->y1[j2]) - (self->a2[j] * self->y2[j2]) ) * self->a0[j];
             vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]);
             self->y2[j2] = self->y1[j2];
             self->y1[j2] = w;
-            
+
             /* Exciter part filter 2 */
             w2 = ( vout2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j];
             vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]);
             self->yy2[j2] = self->yy1[j2];
             self->yy1[j2] = w2;
-            
+
             /* Follower */
             if (vout < 0.0)
                 vout = -vout;
@@ -6432,7 +6345,7 @@ Vocoder_filters_iaa(Vocoder *self) {
             output += vout2 * self->follow[j];
         }
         self->data[i] = output * amp;
-    }    
+    }
 }
 
 static void
@@ -6442,7 +6355,7 @@ Vocoder_filters_aaa(Vocoder *self) {
     MYFLT vin, vout, vin2, vout2, w, w2, slope, output, amp = 1.0;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *in2 = Stream_getData((Stream *)self->input2_stream);
-    
+
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
     MYFLT freq = fr[0];
     MYFLT *sprd = Stream_getData((Stream *)self->spread_stream);
@@ -6461,7 +6374,7 @@ Vocoder_filters_aaa(Vocoder *self) {
         self->last_slope = slope;
         self->factor = MYEXP(-1.0 / (self->sr / ((slope * 99.0) + 1.0)));
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (count == 0) {
             freq = fr[i];
@@ -6469,16 +6382,17 @@ Vocoder_filters_aaa(Vocoder *self) {
             q = qstr[i];
             if (q < 0.1)
                 q = 0.1;
-            amp = q * 10.0;            
+            amp = q * 10.0;
         }
         else if (count >= maxcount)
             count = 0;
         count++;
-        if (freq != self->last_freq || spread != self->last_spread || q != self->last_q || self->stages != self->last_stages) {
+        if (freq != self->last_freq || spread != self->last_spread || q != self->last_q || self->stages != self->last_stages || self->flag) {
             self->last_freq = freq;
             self->last_spread = spread;
             self->last_q = q;
             self->last_stages = self->stages;
+            self->flag = 0;
             Vocoder_compute_variables(self, freq, spread, q);
         }
         output = 0.0;
@@ -6491,26 +6405,26 @@ Vocoder_filters_aaa(Vocoder *self) {
             vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]);
             self->y2[j2] = self->y1[j2];
             self->y1[j2] = w;
-            
+
             /* Exciter part filter 1 */
             w2 = ( vin2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j];
             vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]);
             self->yy2[j2] = self->yy1[j2];
             self->yy1[j2] = w2;
-            
+
             j2++;
             /* Analysis part filter 2 */
             w = ( vout - (self->a1[j] * self->y1[j2]) - (self->a2[j] * self->y2[j2]) ) * self->a0[j];
             vout = (self->b0[j] * w) + (self->b2[j] * self->y2[j2]);
             self->y2[j2] = self->y1[j2];
             self->y1[j2] = w;
-            
+
             /* Exciter part filter 2 */
             w2 = ( vout2 - (self->a1[j] * self->yy1[j2]) - (self->a2[j] * self->yy2[j2]) ) * self->a0[j];
             vout2 = (self->b0[j] * w2) + (self->b2[j] * self->yy2[j2]);
             self->yy2[j2] = self->yy1[j2];
             self->yy1[j2] = w2;
-            
+
             /* Follower */
             if (vout < 0.0)
                 vout = -vout;
@@ -6518,7 +6432,7 @@ Vocoder_filters_aaa(Vocoder *self) {
             output += vout2 * self->follow[j];
         }
         self->data[i] = output * amp;
-    }    
+    }
 }
 
 static void Vocoder_postprocessing_ii(Vocoder *self) { POST_PROCESSING_II };
@@ -6539,66 +6453,66 @@ Vocoder_setProcMode(Vocoder *self)
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Vocoder_filters_iii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Vocoder_filters_aii;
             break;
-        case 10:        
+        case 10:
             self->proc_func_ptr = Vocoder_filters_iai;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Vocoder_filters_aai;
             break;
-        case 100:    
+        case 100:
             self->proc_func_ptr = Vocoder_filters_iia;
             break;
-        case 101:    
+        case 101:
             self->proc_func_ptr = Vocoder_filters_aia;
             break;
-        case 110:        
+        case 110:
             self->proc_func_ptr = Vocoder_filters_iaa;
             break;
-        case 111:    
+        case 111:
             self->proc_func_ptr = Vocoder_filters_aaa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Vocoder_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Vocoder_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Vocoder_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Vocoder_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Vocoder_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Vocoder_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Vocoder_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Vocoder_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Vocoder_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Vocoder_compute_next_data_frame(Vocoder *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -6610,18 +6524,18 @@ Vocoder_traverse(Vocoder *self, visitproc visit, void *arg)
     Py_VISIT(self->input_stream);
     Py_VISIT(self->input2);
     Py_VISIT(self->input2_stream);
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
-    Py_VISIT(self->spread);    
-    Py_VISIT(self->spread_stream);    
-    Py_VISIT(self->q);    
-    Py_VISIT(self->q_stream);    
-    Py_VISIT(self->slope);    
-    Py_VISIT(self->slope_stream);    
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->spread);
+    Py_VISIT(self->spread_stream);
+    Py_VISIT(self->q);
+    Py_VISIT(self->q_stream);
+    Py_VISIT(self->slope);
+    Py_VISIT(self->slope_stream);
     return 0;
 }
 
-static int 
+static int
 Vocoder_clear(Vocoder *self)
 {
     pyo_CLEAR
@@ -6629,12 +6543,12 @@ Vocoder_clear(Vocoder *self)
     Py_CLEAR(self->input_stream);
     Py_CLEAR(self->input2);
     Py_CLEAR(self->input2_stream);
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
     Py_CLEAR(self->spread);
     Py_CLEAR(self->spread_stream);
-    Py_CLEAR(self->q);    
-    Py_CLEAR(self->q_stream);    
+    Py_CLEAR(self->q);
+    Py_CLEAR(self->q_stream);
     Py_CLEAR(self->slope);
     Py_CLEAR(self->slope_stream);
     return 0;
@@ -6655,7 +6569,7 @@ Vocoder_dealloc(Vocoder* self)
     free(self->a2);
     free(self->follow);
     Vocoder_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -6665,7 +6579,7 @@ Vocoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *input2tmp, *input2_streamtmp, *freqtmp=NULL, *spreadtmp=NULL, *qtmp=NULL, *slopetmp=NULL, *multmp=NULL, *addtmp=NULL;
     Vocoder *self;
     self = (Vocoder *)type->tp_alloc(type, 0);
-    
+
     self->freq = PyFloat_FromDouble(60);
     self->spread = PyFloat_FromDouble(1.25);
     self->q = PyFloat_FromDouble(20);
@@ -6674,42 +6588,40 @@ Vocoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->factor = 0.99;
     self->stages = 24;
     self->last_stages = -1;
+    self->flag = 0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
 	self->modebuffer[4] = 0;
 	self->modebuffer[5] = 0;
-    
+
     INIT_OBJECT_COMMON
-    
+
     self->nyquist = (MYFLT)self->sr * 0.49;
     self->twoPiOnSr = (MYFLT)(TWOPI / self->sr);
-    
+
     Stream_setFunctionPtr(self->stream, Vocoder_compute_next_data_frame);
     self->mode_func_ptr = Vocoder_setProcMode;
 
     static char *kwlist[] = {"input", "input2", "freq", "spread", "q", "slope", "stages", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOOOiOO", kwlist, &inputtmp, &input2tmp, &freqtmp, &spreadtmp, &qtmp, &slopetmp, &self->stages, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
 
     if ( PyObject_HasAttrString((PyObject *)input2tmp, "server") == 0 ) {
-        PySys_WriteStderr("TypeError: \"input2\" argument of Vocoder must be a PyoObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
-    }    
+        PyErr_SetString(PyExc_TypeError, "\"input2\" argument of Vocoder must be a PyoObject.\n");
+        Py_RETURN_NONE;
+    }
     Py_XDECREF(self->input2);
     self->input2 = input2tmp;
     input2_streamtmp = PyObject_CallMethod((PyObject *)self->input2, "_getStream", NULL);
     Py_INCREF(input2_streamtmp);
     Py_XDECREF(self->input2_stream);
     self->input2_stream = (Stream *)input2_streamtmp;
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
@@ -6717,7 +6629,7 @@ Vocoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (spreadtmp) {
         PyObject_CallMethod((PyObject *)self, "setSpread", "O", spreadtmp);
     }
-    
+
     if (qtmp) {
         PyObject_CallMethod((PyObject *)self, "setQ", "O", qtmp);
     }
@@ -6725,19 +6637,19 @@ Vocoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (slopetmp) {
         PyObject_CallMethod((PyObject *)self, "setSlope", "O", slopetmp);
     }
-    
+
     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);
-    
+
     Vocoder_allocate_memories(self);
-    
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
@@ -6745,10 +6657,10 @@ Vocoder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Vocoder_getServer(Vocoder* self) { GET_SERVER };
 static PyObject * Vocoder_getStream(Vocoder* self) { GET_STREAM };
-static PyObject * Vocoder_setMul(Vocoder *self, PyObject *arg) { SET_MUL };	
-static PyObject * Vocoder_setAdd(Vocoder *self, PyObject *arg) { SET_ADD };	
-static PyObject * Vocoder_setSub(Vocoder *self, PyObject *arg) { SET_SUB };	
-static PyObject * Vocoder_setDiv(Vocoder *self, PyObject *arg) { SET_DIV };	
+static PyObject * Vocoder_setMul(Vocoder *self, PyObject *arg) { SET_MUL };
+static PyObject * Vocoder_setAdd(Vocoder *self, PyObject *arg) { SET_ADD };
+static PyObject * Vocoder_setSub(Vocoder *self, PyObject *arg) { SET_SUB };
+static PyObject * Vocoder_setDiv(Vocoder *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Vocoder_play(Vocoder *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Vocoder_out(Vocoder *self, PyObject *args, PyObject *kwds) { OUT };
@@ -6767,14 +6679,11 @@ static PyObject *
 Vocoder_setFreq(Vocoder *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -6790,25 +6699,22 @@ Vocoder_setFreq(Vocoder *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Vocoder_setSpread(Vocoder *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->spread);
@@ -6824,25 +6730,22 @@ Vocoder_setSpread(Vocoder *self, PyObject *arg)
         self->spread_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Vocoder_setQ(Vocoder *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->q);
@@ -6858,25 +6761,22 @@ Vocoder_setQ(Vocoder *self, PyObject *arg)
         self->q_stream = (Stream *)streamtmp;
 		self->modebuffer[4] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Vocoder_setSlope(Vocoder *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->slope);
@@ -6892,32 +6792,28 @@ Vocoder_setSlope(Vocoder *self, PyObject *arg)
         self->slope_stream = (Stream *)streamtmp;
 		self->modebuffer[5] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Vocoder_setStages(Vocoder *self, PyObject *arg)
 {
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	
+    ASSERT_ARG_NOT_NULL
+
 	int isInt = PyInt_Check(arg);
-    
+
 	if (isInt == 1) {
 		self->stages = PyInt_AsLong(arg);
         Vocoder_allocate_memories(self);
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Vocoder_members[] = {
     {"server", T_OBJECT_EX, offsetof(Vocoder, server), 0, "Pyo server."},
@@ -6955,7 +6851,7 @@ static PyNumberMethods Vocoder_as_number = {
     (binaryfunc)Vocoder_add,                         /*nb_add*/
     (binaryfunc)Vocoder_sub,                         /*nb_subtract*/
     (binaryfunc)Vocoder_multiply,                    /*nb_multiply*/
-    (binaryfunc)Vocoder_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -6969,16 +6865,16 @@ static PyNumberMethods Vocoder_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Vocoder_inplace_add,                 /*inplace_add*/
     (binaryfunc)Vocoder_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Vocoder_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Vocoder_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -6987,15 +6883,14 @@ static PyNumberMethods Vocoder_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Vocoder_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Vocoder_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject VocoderType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Vocoder_base",                                   /*tp_name*/
     sizeof(Vocoder),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -7003,7 +6898,7 @@ PyTypeObject VocoderType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &Vocoder_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -7045,7 +6940,7 @@ typedef struct {
     Stream *q_stream;
     PyObject *type;
     Stream *type_stream;
-    int modebuffer[5]; // need at least 2 slots for mul & add 
+    int modebuffer[5]; // need at least 2 slots for mul & add
     MYFLT srOverSix;
     MYFLT last_freq;
     MYFLT piOverSr;
@@ -7066,21 +6961,21 @@ SVF_filters_iii(SVF *self) {
     freq = PyFloat_AS_DOUBLE(self->freq);
     q = PyFloat_AS_DOUBLE(self->q);
     type = PyFloat_AS_DOUBLE(self->type);
-    
+
     if (freq < 0.1)
         freq = 0.1;
     else if (freq > self->srOverSix)
         freq = self->srOverSix;
-    
+
     if (freq != self->last_freq) {
         self->last_freq = freq;
         self->w = 2.0 * MYSIN(freq * self->piOverSr);
     }
-    
+
     if (q < 0.5)
         q = 0.5;
     q1 = 1.0 / q;
-    
+
     if (type < 0.0)
         type = 0.0;
     else if (type > 1.0)
@@ -7117,7 +7012,7 @@ SVF_filters_aii(SVF *self) {
     if (q < 0.5)
         q = 0.5;
     q1 = 1.0 / q;
-    
+
     if (type < 0.0)
         type = 0.0;
     else if (type > 1.0)
@@ -7132,7 +7027,7 @@ SVF_filters_aii(SVF *self) {
             freq = 0.1;
         else if (freq > self->srOverSix)
             freq = self->srOverSix;
-        
+
         if (freq != self->last_freq) {
             self->last_freq = freq;
             self->w = 2.0 * MYSIN(freq * self->piOverSr);
@@ -7160,12 +7055,12 @@ SVF_filters_iai(SVF *self) {
     freq = PyFloat_AS_DOUBLE(self->freq);
     MYFLT *qst = Stream_getData((Stream *)self->q_stream);
     type = PyFloat_AS_DOUBLE(self->type);
-    
+
     if (freq < 0.1)
         freq = 0.1;
     else if (freq > self->srOverSix)
         freq = self->srOverSix;
-    
+
     if (freq != self->last_freq) {
         self->last_freq = freq;
         self->w = 2.0 * MYSIN(freq * self->piOverSr);
@@ -7207,7 +7102,7 @@ SVF_filters_aai(SVF *self) {
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
     MYFLT *qst = Stream_getData((Stream *)self->q_stream);
     type = PyFloat_AS_DOUBLE(self->type);
-    
+
     if (type < 0.0)
         type = 0.0;
     else if (type > 1.0)
@@ -7223,7 +7118,7 @@ SVF_filters_aai(SVF *self) {
             freq = 0.1;
         else if (freq > self->srOverSix)
             freq = self->srOverSix;
-        
+
         if (freq != self->last_freq) {
             self->last_freq = freq;
             self->w = 2.0 * MYSIN(freq * self->piOverSr);
@@ -7254,17 +7149,17 @@ SVF_filters_iia(SVF *self) {
     freq = PyFloat_AS_DOUBLE(self->freq);
     q = PyFloat_AS_DOUBLE(self->q);
     MYFLT *tp = Stream_getData((Stream *)self->type_stream);
-    
+
     if (freq < 0.1)
         freq = 0.1;
     else if (freq > self->srOverSix)
         freq = self->srOverSix;
-    
+
     if (freq != self->last_freq) {
         self->last_freq = freq;
         self->w = 2.0 * MYSIN(freq * self->piOverSr);
     }
-    
+
     if (q < 0.5)
         q = 0.5;
     q1 = 1.0 / q;
@@ -7313,7 +7208,7 @@ SVF_filters_aia(SVF *self) {
             freq = 0.1;
         else if (freq > self->srOverSix)
             freq = self->srOverSix;
-        
+
         if (freq != self->last_freq) {
             self->last_freq = freq;
             self->w = 2.0 * MYSIN(freq * self->piOverSr);
@@ -7324,7 +7219,7 @@ SVF_filters_aia(SVF *self) {
             type = 1.0;
         lowgain = (type <= 0.5) ? (0.5 - type) : 0.0;
         highgain = (type >= 0.5) ? (type - 0.5) : 0.0;
-        bandgain = (type <= 0.5) ? type : (1.0 - type);        
+        bandgain = (type <= 0.5) ? type : (1.0 - type);
         low = self->y2 + self->w * self->y1;
         high = in[i] - low - q1 * self->y1;
         band = self->w * high + self->y1;
@@ -7348,12 +7243,12 @@ SVF_filters_iaa(SVF *self) {
     freq = PyFloat_AS_DOUBLE(self->freq);
     MYFLT *qst = Stream_getData((Stream *)self->q_stream);
     MYFLT *tp = Stream_getData((Stream *)self->type_stream);
-    
+
     if (freq < 0.1)
         freq = 0.1;
     else if (freq > self->srOverSix)
         freq = self->srOverSix;
-    
+
     if (freq != self->last_freq) {
         self->last_freq = freq;
         self->w = 2.0 * MYSIN(freq * self->piOverSr);
@@ -7404,7 +7299,7 @@ SVF_filters_aaa(SVF *self) {
             freq = 0.1;
         else if (freq > self->srOverSix)
             freq = self->srOverSix;
-        
+
         if (freq != self->last_freq) {
             self->last_freq = freq;
             self->w = 2.0 * MYSIN(freq * self->piOverSr);
@@ -7418,7 +7313,7 @@ SVF_filters_aaa(SVF *self) {
             type = 1.0;
         lowgain = (type <= 0.5) ? (0.5 - type) : 0.0;
         highgain = (type >= 0.5) ? (type - 0.5) : 0.0;
-        bandgain = (type <= 0.5) ? type : (1.0 - type);        
+        bandgain = (type <= 0.5) ? type : (1.0 - type);
         low = self->y2 + self->w * self->y1;
         high = in[i] - low - q1 * self->y1;
         band = self->w * high + self->y1;
@@ -7450,68 +7345,68 @@ SVF_setProcMode(SVF *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = SVF_filters_iii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = SVF_filters_aii;
             break;
-        case 10:        
+        case 10:
             self->proc_func_ptr = SVF_filters_iai;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = SVF_filters_aai;
             break;
-        case 100:    
+        case 100:
             self->proc_func_ptr = SVF_filters_iia;
             break;
-        case 101:    
+        case 101:
             self->proc_func_ptr = SVF_filters_aia;
             break;
-        case 110:        
+        case 110:
             self->proc_func_ptr = SVF_filters_iaa;
             break;
-        case 111:    
+        case 111:
             self->proc_func_ptr = SVF_filters_aaa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = SVF_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = SVF_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = SVF_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = SVF_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = SVF_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = SVF_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = SVF_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = SVF_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = SVF_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 SVF_compute_next_data_frame(SVF *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -7521,27 +7416,27 @@ SVF_traverse(SVF *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
-    Py_VISIT(self->q);    
-    Py_VISIT(self->q_stream);    
-    Py_VISIT(self->type);    
-    Py_VISIT(self->type_stream);    
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->q);
+    Py_VISIT(self->q_stream);
+    Py_VISIT(self->type);
+    Py_VISIT(self->type_stream);
     return 0;
 }
 
-static int 
+static int
 SVF_clear(SVF *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
-    Py_CLEAR(self->q);    
-    Py_CLEAR(self->q_stream);    
-    Py_CLEAR(self->type);    
-    Py_CLEAR(self->type_stream);    
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->q);
+    Py_CLEAR(self->q_stream);
+    Py_CLEAR(self->type);
+    Py_CLEAR(self->type_stream);
     return 0;
 }
 
@@ -7550,7 +7445,7 @@ SVF_dealloc(SVF* self)
 {
     pyo_DEALLOC
     SVF_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -7560,7 +7455,7 @@ SVF_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *qtmp=NULL, *typetmp=NULL, *multmp=NULL, *addtmp=NULL;
     SVF *self;
     self = (SVF *)type->tp_alloc(type, 0);
-        
+
     self->freq = PyFloat_FromDouble(1000);
     self->q = PyFloat_FromDouble(1);
     self->type = PyFloat_FromDouble(0);
@@ -7573,10 +7468,10 @@ SVF_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->last_freq = -1.0;
 
     INIT_OBJECT_COMMON
-    
+
     self->srOverSix = (MYFLT)self->sr / 6.0;
     self->piOverSr = PI / self->sr;
-    
+
     Stream_setFunctionPtr(self->stream, SVF_compute_next_data_frame);
     self->mode_func_ptr = SVF_setProcMode;
 
@@ -7586,7 +7481,7 @@ SVF_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         Py_RETURN_NONE;
 
     INIT_INPUT_STREAM
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
@@ -7598,7 +7493,7 @@ SVF_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (typetmp) {
         PyObject_CallMethod((PyObject *)self, "setType", "O", typetmp);
     }
-    
+
     if (multmp) {
         PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
     }
@@ -7606,7 +7501,7 @@ SVF_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (addtmp) {
         PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
     }
-            
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     (*self->mode_func_ptr)(self);
@@ -7616,10 +7511,10 @@ SVF_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * SVF_getServer(SVF* self) { GET_SERVER };
 static PyObject * SVF_getStream(SVF* self) { GET_STREAM };
-static PyObject * SVF_setMul(SVF *self, PyObject *arg) { SET_MUL };	
-static PyObject * SVF_setAdd(SVF *self, PyObject *arg) { SET_ADD };	
-static PyObject * SVF_setSub(SVF *self, PyObject *arg) { SET_SUB };	
-static PyObject * SVF_setDiv(SVF *self, PyObject *arg) { SET_DIV };	
+static PyObject * SVF_setMul(SVF *self, PyObject *arg) { SET_MUL };
+static PyObject * SVF_setAdd(SVF *self, PyObject *arg) { SET_ADD };
+static PyObject * SVF_setSub(SVF *self, PyObject *arg) { SET_SUB };
+static PyObject * SVF_setDiv(SVF *self, PyObject *arg) { SET_DIV };
 
 static PyObject * SVF_play(SVF *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * SVF_out(SVF *self, PyObject *args, PyObject *kwds) { OUT };
@@ -7638,14 +7533,11 @@ static PyObject *
 SVF_setFreq(SVF *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -7661,25 +7553,22 @@ SVF_setFreq(SVF *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 SVF_setQ(SVF *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->q);
@@ -7695,25 +7584,22 @@ SVF_setQ(SVF *self, PyObject *arg)
         self->q_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 SVF_setType(SVF *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->type);
@@ -7729,12 +7615,12 @@ SVF_setType(SVF *self, PyObject *arg)
         self->type_stream = (Stream *)streamtmp;
 		self->modebuffer[4] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef SVF_members[] = {
     {"server", T_OBJECT_EX, offsetof(SVF, server), 0, "Pyo server."},
@@ -7768,7 +7654,7 @@ static PyNumberMethods SVF_as_number = {
     (binaryfunc)SVF_add,                         /*nb_add*/
     (binaryfunc)SVF_sub,                         /*nb_subtract*/
     (binaryfunc)SVF_multiply,                    /*nb_multiply*/
-    (binaryfunc)SVF_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -7782,16 +7668,16 @@ static PyNumberMethods SVF_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)SVF_inplace_add,                 /*inplace_add*/
     (binaryfunc)SVF_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)SVF_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)SVF_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -7800,15 +7686,14 @@ static PyNumberMethods SVF_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)SVF_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)SVF_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject SVFType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.SVF_base",                                   /*tp_name*/
     sizeof(SVF),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -7816,7 +7701,7 @@ PyTypeObject SVFType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &SVF_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -7864,7 +7749,7 @@ typedef struct {
 
 static void
 Average_process_i(Average *self) {
-    int i; 
+    int i;
 
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
 
@@ -7922,44 +7807,44 @@ Average_setProcMode(Average *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
- 
+
     self->proc_func_ptr = Average_process_i;
 
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Average_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Average_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Average_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Average_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Average_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Average_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Average_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Average_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Average_postprocessing_revareva;
             break;
-    } 
+    }
 }
 
 static void
 Average_compute_next_data_frame(Average *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -7968,16 +7853,16 @@ Average_traverse(Average *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->input);
-    Py_VISIT(self->input_stream);       
+    Py_VISIT(self->input_stream);
     return 0;
 }
 
-static int 
+static int
 Average_clear(Average *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
-    Py_CLEAR(self->input_stream);      
+    Py_CLEAR(self->input_stream);
     return 0;
 }
 
@@ -7987,7 +7872,7 @@ Average_dealloc(Average* self)
     pyo_DEALLOC
     free(self->buffer);
     Average_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -7997,7 +7882,7 @@ Average_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     Average *self;
     self = (Average *)type->tp_alloc(type, 0);
-    
+
     self->size = 10;
     self->init = 1;
     self->in_count = 0;
@@ -8010,30 +7895,30 @@ Average_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = Average_setProcMode;
 
     static char *kwlist[] = {"input", "size", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOO", kwlist, &inputtmp, &self->size, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
 
     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->halfSize = (int)(self->size / 2);
     self->oneOnSize = 1.0 / (double)self->size;
-    
+
     self->buffer = (MYFLT *)realloc(self->buffer, (self->size) * sizeof(MYFLT));
     for (i=0; i<(self->size); i++) {
         self->buffer[i] = 0.;
-    }    
-    
+    }
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
@@ -8041,10 +7926,10 @@ Average_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Average_getServer(Average* self) { GET_SERVER };
 static PyObject * Average_getStream(Average* self) { GET_STREAM };
-static PyObject * Average_setMul(Average *self, PyObject *arg) { SET_MUL };	
-static PyObject * Average_setAdd(Average *self, PyObject *arg) { SET_ADD };	
-static PyObject * Average_setSub(Average *self, PyObject *arg) { SET_SUB };	
-static PyObject * Average_setDiv(Average *self, PyObject *arg) { SET_DIV };	
+static PyObject * Average_setMul(Average *self, PyObject *arg) { SET_MUL };
+static PyObject * Average_setAdd(Average *self, PyObject *arg) { SET_ADD };
+static PyObject * Average_setSub(Average *self, PyObject *arg) { SET_SUB };
+static PyObject * Average_setDiv(Average *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Average_play(Average *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Average_out(Average *self, PyObject *args, PyObject *kwds) { OUT };
@@ -8063,29 +7948,27 @@ static PyObject *
 Average_setSize(Average *self, PyObject *arg)
 {
 	int i;
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	
+
+    ASSERT_ARG_NOT_NULL
+
 	int isInt = PyInt_Check(arg);
-    
+
 	if (isInt == 1) {
 		self->size = PyInt_AsLong(arg);
         self->halfSize = (int)(self->size / 2);
         self->oneOnSize = 1.0 / (double)self->size;
         self->init = 1;
         self->in_count = 0;
-        self->currentValue = 0.0;        
+        self->currentValue = 0.0;
         self->buffer = (MYFLT *)realloc(self->buffer, (self->size) * sizeof(MYFLT));
         for (i=0; i<(self->size); i++) {
             self->buffer[i] = 0.;
-        }    
+        }
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Average_members[] = {
     {"server", T_OBJECT_EX, offsetof(Average, server), 0, "Pyo server."},
@@ -8114,7 +7997,7 @@ static PyNumberMethods Average_as_number = {
     (binaryfunc)Average_add,                      /*nb_add*/
     (binaryfunc)Average_sub,                 /*nb_subtract*/
     (binaryfunc)Average_multiply,                 /*nb_multiply*/
-    (binaryfunc)Average_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -8128,16 +8011,16 @@ static PyNumberMethods Average_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)Average_inplace_add,              /*inplace_add*/
     (binaryfunc)Average_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)Average_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)Average_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -8146,15 +8029,14 @@ static PyNumberMethods Average_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)Average_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)Average_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject AverageType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Average_base",         /*tp_name*/
     sizeof(Average),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -8162,7 +8044,7 @@ PyTypeObject AverageType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &Average_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -8202,7 +8084,7 @@ typedef struct {
     Stream *freq_stream;
     PyObject *q;
     Stream *q_stream;
-    int modebuffer[4]; // need at least 2 slots for mul & add 
+    int modebuffer[4]; // need at least 2 slots for mul & add
     MYFLT nyquist;
     MYFLT last_freq;
     MYFLT last_q;
@@ -8218,20 +8100,20 @@ typedef struct {
     MYFLT a;
 } Reson;
 
-static void 
+static void
 Reson_compute_coeffs(Reson *self, MYFLT freq, MYFLT q)
 {
     MYFLT bw;
-    
+
     if (freq < 0.1)
         freq = 0.1;
     else if (freq > self->nyquist)
         freq = self->nyquist;
     if (q < 0.1)
         q = 0.1;
-    
+
     bw = freq / q;
-    
+
     self->b2 = MYEXP(-self->twopiOverSr * bw);
     self->b1 = (-4.0 * self->b2) / (1.0 + self->b2) * MYCOS(freq * self->twopiOverSr);
     self->a = 1.0 - MYSQRT(self->b2);
@@ -8244,7 +8126,7 @@ Reson_filters_ii(Reson *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     fr = PyFloat_AS_DOUBLE(self->freq);
     q = PyFloat_AS_DOUBLE(self->q);
-   
+
     if (fr != self->last_freq || q != self->last_q) {
         self->last_freq = fr;
         self->last_q = q;
@@ -8290,7 +8172,7 @@ Reson_filters_ia(Reson *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     fr = PyFloat_AS_DOUBLE(self->freq);
     MYFLT *qst = Stream_getData((Stream *)self->q_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         q = qst[i];
         if (fr != self->last_freq || q != self->last_q) {
@@ -8346,56 +8228,56 @@ Reson_setProcMode(Reson *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Reson_filters_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Reson_filters_ai;
             break;
-        case 10:        
+        case 10:
             self->proc_func_ptr = Reson_filters_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Reson_filters_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Reson_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Reson_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Reson_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Reson_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Reson_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Reson_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Reson_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Reson_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Reson_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Reson_compute_next_data_frame(Reson *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -8405,23 +8287,23 @@ Reson_traverse(Reson *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
-    Py_VISIT(self->q);    
-    Py_VISIT(self->q_stream);    
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->q);
+    Py_VISIT(self->q_stream);
     return 0;
 }
 
-static int 
+static int
 Reson_clear(Reson *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
-    Py_CLEAR(self->q);    
-    Py_CLEAR(self->q_stream);    
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->q);
+    Py_CLEAR(self->q_stream);
     return 0;
 }
 
@@ -8430,7 +8312,7 @@ Reson_dealloc(Reson* self)
 {
     pyo_DEALLOC
     Reson_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -8440,7 +8322,7 @@ Reson_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *qtmp=NULL, *multmp=NULL, *addtmp=NULL;
     Reson *self;
     self = (Reson *)type->tp_alloc(type, 0);
-        
+
     self->freq = PyFloat_FromDouble(1000);
     self->q = PyFloat_FromDouble(1);
     self->last_freq = self->last_q = -1.0;
@@ -8452,10 +8334,10 @@ Reson_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[3] = 0;
 
     INIT_OBJECT_COMMON
-    
+
     self->nyquist = (MYFLT)self->sr * 0.49;
     self->twopiOverSr = TWOPI / (MYFLT)self->sr;
-    
+
     Stream_setFunctionPtr(self->stream, Reson_compute_next_data_frame);
     self->mode_func_ptr = Reson_setProcMode;
 
@@ -8465,7 +8347,7 @@ Reson_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         Py_RETURN_NONE;
 
     INIT_INPUT_STREAM
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
@@ -8473,7 +8355,7 @@ Reson_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (qtmp) {
         PyObject_CallMethod((PyObject *)self, "setQ", "O", qtmp);
     }
-    
+
     if (multmp) {
         PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
     }
@@ -8481,7 +8363,7 @@ Reson_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (addtmp) {
         PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
     }
-            
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     (*self->mode_func_ptr)(self);
@@ -8491,10 +8373,10 @@ Reson_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Reson_getServer(Reson* self) { GET_SERVER };
 static PyObject * Reson_getStream(Reson* self) { GET_STREAM };
-static PyObject * Reson_setMul(Reson *self, PyObject *arg) { SET_MUL };	
-static PyObject * Reson_setAdd(Reson *self, PyObject *arg) { SET_ADD };	
-static PyObject * Reson_setSub(Reson *self, PyObject *arg) { SET_SUB };	
-static PyObject * Reson_setDiv(Reson *self, PyObject *arg) { SET_DIV };	
+static PyObject * Reson_setMul(Reson *self, PyObject *arg) { SET_MUL };
+static PyObject * Reson_setAdd(Reson *self, PyObject *arg) { SET_ADD };
+static PyObject * Reson_setSub(Reson *self, PyObject *arg) { SET_SUB };
+static PyObject * Reson_setDiv(Reson *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Reson_play(Reson *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Reson_out(Reson *self, PyObject *args, PyObject *kwds) { OUT };
@@ -8513,14 +8395,11 @@ static PyObject *
 Reson_setFreq(Reson *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -8536,25 +8415,22 @@ Reson_setFreq(Reson *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Reson_setQ(Reson *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->q);
@@ -8570,12 +8446,12 @@ Reson_setQ(Reson *self, PyObject *arg)
         self->q_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Reson_members[] = {
     {"server", T_OBJECT_EX, offsetof(Reson, server), 0, "Pyo server."},
@@ -8607,7 +8483,7 @@ static PyNumberMethods Reson_as_number = {
     (binaryfunc)Reson_add,                         /*nb_add*/
     (binaryfunc)Reson_sub,                         /*nb_subtract*/
     (binaryfunc)Reson_multiply,                    /*nb_multiply*/
-    (binaryfunc)Reson_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -8621,16 +8497,16 @@ static PyNumberMethods Reson_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Reson_inplace_add,                 /*inplace_add*/
     (binaryfunc)Reson_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Reson_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Reson_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -8639,15 +8515,14 @@ static PyNumberMethods Reson_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Reson_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Reson_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject ResonType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Reson_base",                                   /*tp_name*/
     sizeof(Reson),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -8655,7 +8530,7 @@ PyTypeObject ResonType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &Reson_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -8695,7 +8570,7 @@ typedef struct {
     Stream *freq_stream;
     PyObject *q;
     Stream *q_stream;
-    int modebuffer[4]; // need at least 2 slots for mul & add 
+    int modebuffer[4]; // need at least 2 slots for mul & add
     int stages;
     MYFLT nyquist;
     MYFLT last_freq;
@@ -8725,20 +8600,20 @@ Resonx_allocate_memories(Resonx *self)
     }
 }
 
-static void 
+static void
 Resonx_compute_coeffs(Resonx *self, MYFLT freq, MYFLT q)
 {
     MYFLT bw;
-    
+
     if (freq < 0.1)
         freq = 0.1;
     else if (freq > self->nyquist)
         freq = self->nyquist;
     if (q < 0.1)
         q = 0.1;
-    
+
     bw = freq / q;
-    
+
     self->b2 = MYEXP(-self->twopiOverSr * bw);
     self->b1 = (-4.0 * self->b2) / (1.0 + self->b2) * MYCOS(freq * self->twopiOverSr);
     self->a = 1.0 - MYSQRT(self->b2);
@@ -8751,7 +8626,7 @@ Resonx_filters_ii(Resonx *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     fr = PyFloat_AS_DOUBLE(self->freq);
     q = PyFloat_AS_DOUBLE(self->q);
-   
+
     if (fr != self->last_freq || q != self->last_q) {
         self->last_freq = fr;
         self->last_q = q;
@@ -8761,7 +8636,7 @@ Resonx_filters_ii(Resonx *self) {
     vout = 0.0;
     for (i=0; i<self->bufsize; i++) {
         vin = in[i];
-        for (j=0; j<self->stages; j++) { 
+        for (j=0; j<self->stages; j++) {
             vout = (self->a * vin) - (self->a * self->x2[j]) - (self->b1 * self->y1[j]) - (self->b2 * self->y2[j]);
             self->x2[j] = self->x1[j];
             self->x1[j] = vin;
@@ -8789,7 +8664,7 @@ Resonx_filters_ai(Resonx *self) {
             self->last_q = q;
             Resonx_compute_coeffs(self, fr, q);
         }
-        for (j=0; j<self->stages; j++) { 
+        for (j=0; j<self->stages; j++) {
             vout = (self->a * vin) - (self->a * self->x2[j]) - (self->b1 * self->y1[j]) - (self->b2 * self->y2[j]);
             self->x2[j] = self->x1[j];
             self->x1[j] = vin;
@@ -8817,7 +8692,7 @@ Resonx_filters_ia(Resonx *self) {
             self->last_q = q;
             Resonx_compute_coeffs(self, fr, q);
         }
-        for (j=0; j<self->stages; j++) { 
+        for (j=0; j<self->stages; j++) {
             vout = (self->a * vin) - (self->a * self->x2[j]) - (self->b1 * self->y1[j]) - (self->b2 * self->y2[j]);
             self->x2[j] = self->x1[j];
             self->x1[j] = vin;
@@ -8846,7 +8721,7 @@ Resonx_filters_aa(Resonx *self) {
             self->last_q = q;
             Resonx_compute_coeffs(self, fr, q);
         }
-        for (j=0; j<self->stages; j++) { 
+        for (j=0; j<self->stages; j++) {
             vout = (self->a * vin) - (self->a * self->x2[j]) - (self->b1 * self->y1[j]) - (self->b2 * self->y2[j]);
             self->x2[j] = self->x1[j];
             self->x1[j] = vin;
@@ -8873,56 +8748,56 @@ Resonx_setProcMode(Resonx *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Resonx_filters_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Resonx_filters_ai;
             break;
-        case 10:        
+        case 10:
             self->proc_func_ptr = Resonx_filters_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Resonx_filters_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Resonx_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Resonx_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Resonx_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Resonx_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Resonx_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Resonx_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Resonx_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Resonx_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Resonx_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Resonx_compute_next_data_frame(Resonx *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -8932,23 +8807,23 @@ Resonx_traverse(Resonx *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
-    Py_VISIT(self->q);    
-    Py_VISIT(self->q_stream);    
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->q);
+    Py_VISIT(self->q_stream);
     return 0;
 }
 
-static int 
+static int
 Resonx_clear(Resonx *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
-    Py_CLEAR(self->q);    
-    Py_CLEAR(self->q_stream);    
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->q);
+    Py_CLEAR(self->q_stream);
     return 0;
 }
 
@@ -8961,7 +8836,7 @@ Resonx_dealloc(Resonx* self)
     free(self->y1);
     free(self->y2);
     Resonx_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -8971,7 +8846,7 @@ Resonx_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *qtmp=NULL, *multmp=NULL, *addtmp=NULL;
     Resonx *self;
     self = (Resonx *)type->tp_alloc(type, 0);
-        
+
     self->freq = PyFloat_FromDouble(1000);
     self->q = PyFloat_FromDouble(1);
     self->last_freq = self->last_q = -1.0;
@@ -8983,10 +8858,10 @@ Resonx_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[3] = 0;
 
     INIT_OBJECT_COMMON
-    
+
     self->nyquist = (MYFLT)self->sr * 0.49;
     self->twopiOverSr = TWOPI / (MYFLT)self->sr;
-    
+
     Stream_setFunctionPtr(self->stream, Resonx_compute_next_data_frame);
     self->mode_func_ptr = Resonx_setProcMode;
 
@@ -8996,7 +8871,7 @@ Resonx_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         Py_RETURN_NONE;
 
     INIT_INPUT_STREAM
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
@@ -9004,7 +8879,7 @@ Resonx_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (qtmp) {
         PyObject_CallMethod((PyObject *)self, "setQ", "O", qtmp);
     }
-    
+
     if (multmp) {
         PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
     }
@@ -9012,7 +8887,7 @@ Resonx_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (addtmp) {
         PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
     }
-            
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     Resonx_allocate_memories(self);
@@ -9024,10 +8899,10 @@ Resonx_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Resonx_getServer(Resonx* self) { GET_SERVER };
 static PyObject * Resonx_getStream(Resonx* self) { GET_STREAM };
-static PyObject * Resonx_setMul(Resonx *self, PyObject *arg) { SET_MUL };	
-static PyObject * Resonx_setAdd(Resonx *self, PyObject *arg) { SET_ADD };	
-static PyObject * Resonx_setSub(Resonx *self, PyObject *arg) { SET_SUB };	
-static PyObject * Resonx_setDiv(Resonx *self, PyObject *arg) { SET_DIV };	
+static PyObject * Resonx_setMul(Resonx *self, PyObject *arg) { SET_MUL };
+static PyObject * Resonx_setAdd(Resonx *self, PyObject *arg) { SET_ADD };
+static PyObject * Resonx_setSub(Resonx *self, PyObject *arg) { SET_SUB };
+static PyObject * Resonx_setDiv(Resonx *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Resonx_play(Resonx *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Resonx_out(Resonx *self, PyObject *args, PyObject *kwds) { OUT };
@@ -9046,14 +8921,11 @@ static PyObject *
 Resonx_setFreq(Resonx *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -9069,25 +8941,22 @@ Resonx_setFreq(Resonx *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Resonx_setQ(Resonx *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->q);
@@ -9103,24 +8972,20 @@ Resonx_setQ(Resonx *self, PyObject *arg)
         self->q_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Resonx_setStages(Resonx *self, PyObject *arg)
 {
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	
+    ASSERT_ARG_NOT_NULL
+
 	int isInt = PyInt_Check(arg);
-    
+
 	if (isInt == 1) {
 		self->stages = PyInt_AsLong(arg);
         Resonx_allocate_memories(self);
@@ -9128,7 +8993,7 @@ Resonx_setStages(Resonx *self, PyObject *arg)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Resonx_members[] = {
     {"server", T_OBJECT_EX, offsetof(Resonx, server), 0, "Pyo server."},
@@ -9161,7 +9026,7 @@ static PyNumberMethods Resonx_as_number = {
     (binaryfunc)Resonx_add,                         /*nb_add*/
     (binaryfunc)Resonx_sub,                         /*nb_subtract*/
     (binaryfunc)Resonx_multiply,                    /*nb_multiply*/
-    (binaryfunc)Resonx_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -9175,16 +9040,16 @@ static PyNumberMethods Resonx_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Resonx_inplace_add,                 /*inplace_add*/
     (binaryfunc)Resonx_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Resonx_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Resonx_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -9193,15 +9058,14 @@ static PyNumberMethods Resonx_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Resonx_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Resonx_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject ResonxType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Resonx_base",                                   /*tp_name*/
     sizeof(Resonx),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -9209,7 +9073,7 @@ PyTypeObject ResonxType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &Resonx_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -9250,7 +9114,7 @@ typedef struct {
     Stream *input_stream;
     PyObject *freq;
     Stream *freq_stream;
-    int modebuffer[3]; // need at least 2 slots for mul & add 
+    int modebuffer[3]; // need at least 2 slots for mul & add
     MYFLT lastFreq;
     MYFLT nyquist;
     MYFLT piOnSr;
@@ -9274,12 +9138,12 @@ ButLP_filters_i(ButLP *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
-        
+
     if (fr != self->lastFreq) {
-        if (fr <= 1.0)
-            fr = 1.0;
+        if (fr < 0.1)
+            fr = 0.1;
         else if (fr >= self->nyquist)
-            fr = self->nyquist;            
+            fr = self->nyquist;
         self->lastFreq = fr;
         c = 1.0 / MYTAN(self->piOnSr * fr);
         c2 = c * c;
@@ -9304,14 +9168,14 @@ ButLP_filters_a(ButLP *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *freq = Stream_getData((Stream *)self->freq_stream);
-        
+
     for (i=0; i<self->bufsize; i++) {
-        fr = freq[i];        
+        fr = freq[i];
         if (fr != self->lastFreq) {
-            if (fr <= 1.0)
-                fr = 1.0;
+            if (fr < 0.1)
+                fr = 0.1;
             else if (fr >= self->nyquist)
-                fr = self->nyquist;            
+                fr = self->nyquist;
             self->lastFreq = fr;
             c = 1.0 / MYTAN(self->piOnSr * fr);
             c2 = c * c;
@@ -9344,50 +9208,50 @@ ButLP_setProcMode(ButLP *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2];
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = ButLP_filters_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = ButLP_filters_a;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = ButLP_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = ButLP_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = ButLP_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = ButLP_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = ButLP_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = ButLP_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = ButLP_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = ButLP_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = ButLP_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 ButLP_compute_next_data_frame(ButLP *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -9397,19 +9261,19 @@ ButLP_traverse(ButLP *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
     return 0;
 }
 
-static int 
+static int
 ButLP_clear(ButLP *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
     return 0;
 }
 
@@ -9418,7 +9282,7 @@ ButLP_dealloc(ButLP* self)
 {
     pyo_DEALLOC
     ButLP_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -9428,14 +9292,14 @@ ButLP_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *multmp=NULL, *addtmp=NULL;
     ButLP *self;
     self = (ButLP *)type->tp_alloc(type, 0);
-    
+
     self->freq = PyFloat_FromDouble(1000);
     self->lastFreq = -1.0;
     self->x1 = self->x2 = self->y1 = self->y2 = self->a0 = self->a1 = self->a2 = self->b1 = self->b2 = 0.0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
-    
+
     INIT_OBJECT_COMMON
 
     self->nyquist = (MYFLT)self->sr * 0.49;
@@ -9446,26 +9310,26 @@ ButLP_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = ButLP_setProcMode;
 
     static char *kwlist[] = {"input", "freq", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &freqtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    
+
     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;
@@ -9473,10 +9337,10 @@ ButLP_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * ButLP_getServer(ButLP* self) { GET_SERVER };
 static PyObject * ButLP_getStream(ButLP* self) { GET_STREAM };
-static PyObject * ButLP_setMul(ButLP *self, PyObject *arg) { SET_MUL };	
-static PyObject * ButLP_setAdd(ButLP *self, PyObject *arg) { SET_ADD };	
-static PyObject * ButLP_setSub(ButLP *self, PyObject *arg) { SET_SUB };	
-static PyObject * ButLP_setDiv(ButLP *self, PyObject *arg) { SET_DIV };	
+static PyObject * ButLP_setMul(ButLP *self, PyObject *arg) { SET_MUL };
+static PyObject * ButLP_setAdd(ButLP *self, PyObject *arg) { SET_ADD };
+static PyObject * ButLP_setSub(ButLP *self, PyObject *arg) { SET_SUB };
+static PyObject * ButLP_setDiv(ButLP *self, PyObject *arg) { SET_DIV };
 
 static PyObject * ButLP_play(ButLP *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * ButLP_out(ButLP *self, PyObject *args, PyObject *kwds) { OUT };
@@ -9495,14 +9359,11 @@ static PyObject *
 ButLP_setFreq(ButLP *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -9518,9 +9379,9 @@ ButLP_setFreq(ButLP *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -9553,7 +9414,7 @@ static PyNumberMethods ButLP_as_number = {
 (binaryfunc)ButLP_add,                         /*nb_add*/
 (binaryfunc)ButLP_sub,                         /*nb_subtract*/
 (binaryfunc)ButLP_multiply,                    /*nb_multiply*/
-(binaryfunc)ButLP_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -9567,16 +9428,16 @@ static PyNumberMethods ButLP_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)ButLP_inplace_add,                 /*inplace_add*/
 (binaryfunc)ButLP_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)ButLP_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)ButLP_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -9585,15 +9446,14 @@ static PyNumberMethods ButLP_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)ButLP_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)ButLP_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject ButLPType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.ButLP_base",                                   /*tp_name*/
 sizeof(ButLP),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -9601,7 +9461,7 @@ sizeof(ButLP),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &ButLP_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -9642,7 +9502,7 @@ typedef struct {
     Stream *input_stream;
     PyObject *freq;
     Stream *freq_stream;
-    int modebuffer[3]; // need at least 2 slots for mul & add 
+    int modebuffer[3]; // need at least 2 slots for mul & add
     MYFLT lastFreq;
     MYFLT nyquist;
     MYFLT piOnSr;
@@ -9666,12 +9526,12 @@ ButHP_filters_i(ButHP *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
-        
+
     if (fr != self->lastFreq) {
-        if (fr <= 1.0)
-            fr = 1.0;
+        if (fr < 0.1)
+            fr = 0.1;
         else if (fr >= self->nyquist)
-            fr = self->nyquist;            
+            fr = self->nyquist;
         self->lastFreq = fr;
         c = MYTAN(self->piOnSr * fr);
         c2 = c * c;
@@ -9696,14 +9556,14 @@ ButHP_filters_a(ButHP *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *freq = Stream_getData((Stream *)self->freq_stream);
-        
+
     for (i=0; i<self->bufsize; i++) {
-        fr = freq[i];        
+        fr = freq[i];
         if (fr != self->lastFreq) {
-            if (fr <= 1.0)
-                fr = 1.0;
+            if (fr < 0.1)
+                fr = 0.1;
             else if (fr >= self->nyquist)
-                fr = self->nyquist;            
+                fr = self->nyquist;
             self->lastFreq = fr;
             c = MYTAN(self->piOnSr * fr);
             c2 = c * c;
@@ -9736,50 +9596,50 @@ ButHP_setProcMode(ButHP *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2];
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = ButHP_filters_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = ButHP_filters_a;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = ButHP_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = ButHP_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = ButHP_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = ButHP_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = ButHP_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = ButHP_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = ButHP_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = ButHP_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = ButHP_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 ButHP_compute_next_data_frame(ButHP *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -9789,19 +9649,19 @@ ButHP_traverse(ButHP *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
     return 0;
 }
 
-static int 
+static int
 ButHP_clear(ButHP *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
     return 0;
 }
 
@@ -9810,7 +9670,7 @@ ButHP_dealloc(ButHP* self)
 {
     pyo_DEALLOC
     ButHP_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -9820,14 +9680,14 @@ ButHP_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *multmp=NULL, *addtmp=NULL;
     ButHP *self;
     self = (ButHP *)type->tp_alloc(type, 0);
-    
+
     self->freq = PyFloat_FromDouble(1000);
     self->lastFreq = -1.0;
     self->x1 = self->x2 = self->y1 = self->y2 = self->a0 = self->a1 = self->a2 = self->b1 = self->b2 = 0.0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
-    
+
     INIT_OBJECT_COMMON
 
     self->nyquist = (MYFLT)self->sr * 0.49;
@@ -9838,26 +9698,26 @@ ButHP_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = ButHP_setProcMode;
 
     static char *kwlist[] = {"input", "freq", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &freqtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    
+
     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;
@@ -9865,10 +9725,10 @@ ButHP_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * ButHP_getServer(ButHP* self) { GET_SERVER };
 static PyObject * ButHP_getStream(ButHP* self) { GET_STREAM };
-static PyObject * ButHP_setMul(ButHP *self, PyObject *arg) { SET_MUL };	
-static PyObject * ButHP_setAdd(ButHP *self, PyObject *arg) { SET_ADD };	
-static PyObject * ButHP_setSub(ButHP *self, PyObject *arg) { SET_SUB };	
-static PyObject * ButHP_setDiv(ButHP *self, PyObject *arg) { SET_DIV };	
+static PyObject * ButHP_setMul(ButHP *self, PyObject *arg) { SET_MUL };
+static PyObject * ButHP_setAdd(ButHP *self, PyObject *arg) { SET_ADD };
+static PyObject * ButHP_setSub(ButHP *self, PyObject *arg) { SET_SUB };
+static PyObject * ButHP_setDiv(ButHP *self, PyObject *arg) { SET_DIV };
 
 static PyObject * ButHP_play(ButHP *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * ButHP_out(ButHP *self, PyObject *args, PyObject *kwds) { OUT };
@@ -9887,14 +9747,11 @@ static PyObject *
 ButHP_setFreq(ButHP *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -9910,9 +9767,9 @@ ButHP_setFreq(ButHP *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -9945,7 +9802,7 @@ static PyNumberMethods ButHP_as_number = {
 (binaryfunc)ButHP_add,                         /*nb_add*/
 (binaryfunc)ButHP_sub,                         /*nb_subtract*/
 (binaryfunc)ButHP_multiply,                    /*nb_multiply*/
-(binaryfunc)ButHP_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -9959,16 +9816,16 @@ static PyNumberMethods ButHP_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)ButHP_inplace_add,                 /*inplace_add*/
 (binaryfunc)ButHP_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)ButHP_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)ButHP_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -9977,15 +9834,14 @@ static PyNumberMethods ButHP_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)ButHP_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)ButHP_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject ButHPType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.ButHP_base",                                   /*tp_name*/
 sizeof(ButHP),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -9993,7 +9849,7 @@ sizeof(ButHP),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &ButHP_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -10036,7 +9892,7 @@ typedef struct {
     Stream *freq_stream;
     PyObject *q;
     Stream *q_stream;
-    int modebuffer[4]; // need at least 2 slots for mul & add 
+    int modebuffer[4]; // need at least 2 slots for mul & add
     MYFLT nyquist;
     MYFLT last_freq;
     MYFLT last_q;
@@ -10053,22 +9909,22 @@ typedef struct {
     MYFLT b2;
 } ButBP;
 
-static void 
+static void
 ButBP_compute_coeffs(ButBP *self, MYFLT freq, MYFLT q)
 {
     MYFLT bw, c, d;
-    
+
     if (freq < 1.0)
         freq = 1.0;
     else if (freq > self->nyquist)
         freq = self->nyquist;
     if (q < 1.0)
         q = 1.0;
-    
+
     bw = freq / q;
     c = 1.0 / MYTAN(self->piOnSr * bw);
     d = 2.0 * MYCOS(2.0 * self->piOnSr * freq);
-    
+
     self->a0 = 1.0 / (1.0 + c);
     self->a2 = -self->a0;
     self->b1 = self->a2 * c * d;
@@ -10082,7 +9938,7 @@ ButBP_filters_ii(ButBP *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     fr = PyFloat_AS_DOUBLE(self->freq);
     q = PyFloat_AS_DOUBLE(self->q);
-   
+
     if (fr != self->last_freq || q != self->last_q) {
         self->last_freq = fr;
         self->last_q = q;
@@ -10128,7 +9984,7 @@ ButBP_filters_ia(ButBP *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     fr = PyFloat_AS_DOUBLE(self->freq);
     MYFLT *qst = Stream_getData((Stream *)self->q_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         q = qst[i];
         if (fr != self->last_freq || q != self->last_q) {
@@ -10184,56 +10040,56 @@ ButBP_setProcMode(ButBP *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = ButBP_filters_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = ButBP_filters_ai;
             break;
-        case 10:        
+        case 10:
             self->proc_func_ptr = ButBP_filters_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = ButBP_filters_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = ButBP_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = ButBP_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = ButBP_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = ButBP_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = ButBP_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = ButBP_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = ButBP_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = ButBP_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = ButBP_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 ButBP_compute_next_data_frame(ButBP *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -10243,23 +10099,23 @@ ButBP_traverse(ButBP *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
-    Py_VISIT(self->q);    
-    Py_VISIT(self->q_stream);    
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->q);
+    Py_VISIT(self->q_stream);
     return 0;
 }
 
-static int 
+static int
 ButBP_clear(ButBP *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
-    Py_CLEAR(self->q);    
-    Py_CLEAR(self->q_stream);    
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->q);
+    Py_CLEAR(self->q_stream);
     return 0;
 }
 
@@ -10268,7 +10124,7 @@ ButBP_dealloc(ButBP* self)
 {
     pyo_DEALLOC
     ButBP_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -10278,7 +10134,7 @@ ButBP_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *qtmp=NULL, *multmp=NULL, *addtmp=NULL;
     ButBP *self;
     self = (ButBP *)type->tp_alloc(type, 0);
-        
+
     self->freq = PyFloat_FromDouble(1000);
     self->q = PyFloat_FromDouble(1);
     self->last_freq = self->last_q = -1.0;
@@ -10290,10 +10146,10 @@ ButBP_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[3] = 0;
 
     INIT_OBJECT_COMMON
-    
+
     self->nyquist = (MYFLT)self->sr * 0.49;
     self->piOnSr = PI / (MYFLT)self->sr;
-    
+
     Stream_setFunctionPtr(self->stream, ButBP_compute_next_data_frame);
     self->mode_func_ptr = ButBP_setProcMode;
 
@@ -10303,7 +10159,7 @@ ButBP_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         Py_RETURN_NONE;
 
     INIT_INPUT_STREAM
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
@@ -10311,7 +10167,7 @@ ButBP_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (qtmp) {
         PyObject_CallMethod((PyObject *)self, "setQ", "O", qtmp);
     }
-    
+
     if (multmp) {
         PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
     }
@@ -10319,7 +10175,7 @@ ButBP_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (addtmp) {
         PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
     }
-            
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     (*self->mode_func_ptr)(self);
@@ -10329,10 +10185,10 @@ ButBP_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * ButBP_getServer(ButBP* self) { GET_SERVER };
 static PyObject * ButBP_getStream(ButBP* self) { GET_STREAM };
-static PyObject * ButBP_setMul(ButBP *self, PyObject *arg) { SET_MUL };	
-static PyObject * ButBP_setAdd(ButBP *self, PyObject *arg) { SET_ADD };	
-static PyObject * ButBP_setSub(ButBP *self, PyObject *arg) { SET_SUB };	
-static PyObject * ButBP_setDiv(ButBP *self, PyObject *arg) { SET_DIV };	
+static PyObject * ButBP_setMul(ButBP *self, PyObject *arg) { SET_MUL };
+static PyObject * ButBP_setAdd(ButBP *self, PyObject *arg) { SET_ADD };
+static PyObject * ButBP_setSub(ButBP *self, PyObject *arg) { SET_SUB };
+static PyObject * ButBP_setDiv(ButBP *self, PyObject *arg) { SET_DIV };
 
 static PyObject * ButBP_play(ButBP *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * ButBP_out(ButBP *self, PyObject *args, PyObject *kwds) { OUT };
@@ -10351,14 +10207,11 @@ static PyObject *
 ButBP_setFreq(ButBP *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -10374,25 +10227,22 @@ ButBP_setFreq(ButBP *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 ButBP_setQ(ButBP *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->q);
@@ -10408,12 +10258,12 @@ ButBP_setQ(ButBP *self, PyObject *arg)
         self->q_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef ButBP_members[] = {
     {"server", T_OBJECT_EX, offsetof(ButBP, server), 0, "Pyo server."},
@@ -10445,7 +10295,7 @@ static PyNumberMethods ButBP_as_number = {
     (binaryfunc)ButBP_add,                         /*nb_add*/
     (binaryfunc)ButBP_sub,                         /*nb_subtract*/
     (binaryfunc)ButBP_multiply,                    /*nb_multiply*/
-    (binaryfunc)ButBP_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -10459,16 +10309,16 @@ static PyNumberMethods ButBP_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)ButBP_inplace_add,                 /*inplace_add*/
     (binaryfunc)ButBP_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)ButBP_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)ButBP_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -10477,15 +10327,14 @@ static PyNumberMethods ButBP_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)ButBP_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)ButBP_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject ButBPType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.ButBP_base",                                   /*tp_name*/
     sizeof(ButBP),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -10493,7 +10342,7 @@ PyTypeObject ButBPType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &ButBP_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -10536,7 +10385,7 @@ typedef struct {
     Stream *freq_stream;
     PyObject *q;
     Stream *q_stream;
-    int modebuffer[4]; // need at least 2 slots for mul & add 
+    int modebuffer[4]; // need at least 2 slots for mul & add
     MYFLT nyquist;
     MYFLT last_freq;
     MYFLT last_q;
@@ -10554,22 +10403,22 @@ typedef struct {
     MYFLT b2;
 } ButBR;
 
-static void 
+static void
 ButBR_compute_coeffs(ButBR *self, MYFLT freq, MYFLT q)
 {
     MYFLT bw, c, d;
-    
+
     if (freq < 1.0)
         freq = 1.0;
     else if (freq > self->nyquist)
         freq = self->nyquist;
     if (q < 1.0)
         q = 1.0;
-    
+
     bw = freq / q;
     c = MYTAN(self->piOnSr * bw);
     d = 2.0 * MYCOS(2.0 * self->piOnSr * freq);
-    
+
     self->a0 = self->a2 = 1.0 / (1.0 + c);
     self->a1 = self->b1 = -self->a0 * d;
     self->b2 = self->a0 * (1.0 - c);
@@ -10582,7 +10431,7 @@ ButBR_filters_ii(ButBR *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     fr = PyFloat_AS_DOUBLE(self->freq);
     q = PyFloat_AS_DOUBLE(self->q);
-   
+
     if (fr != self->last_freq || q != self->last_q) {
         self->last_freq = fr;
         self->last_q = q;
@@ -10628,7 +10477,7 @@ ButBR_filters_ia(ButBR *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     fr = PyFloat_AS_DOUBLE(self->freq);
     MYFLT *qst = Stream_getData((Stream *)self->q_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         q = qst[i];
         if (fr != self->last_freq || q != self->last_q) {
@@ -10684,56 +10533,56 @@ ButBR_setProcMode(ButBR *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = ButBR_filters_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = ButBR_filters_ai;
             break;
-        case 10:        
+        case 10:
             self->proc_func_ptr = ButBR_filters_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = ButBR_filters_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = ButBR_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = ButBR_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = ButBR_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = ButBR_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = ButBR_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = ButBR_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = ButBR_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = ButBR_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = ButBR_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 ButBR_compute_next_data_frame(ButBR *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -10743,23 +10592,23 @@ ButBR_traverse(ButBR *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
-    Py_VISIT(self->q);    
-    Py_VISIT(self->q_stream);    
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->q);
+    Py_VISIT(self->q_stream);
     return 0;
 }
 
-static int 
+static int
 ButBR_clear(ButBR *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
-    Py_CLEAR(self->q);    
-    Py_CLEAR(self->q_stream);    
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->q);
+    Py_CLEAR(self->q_stream);
     return 0;
 }
 
@@ -10768,7 +10617,7 @@ ButBR_dealloc(ButBR* self)
 {
     pyo_DEALLOC
     ButBR_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -10778,7 +10627,7 @@ ButBR_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *qtmp=NULL, *multmp=NULL, *addtmp=NULL;
     ButBR *self;
     self = (ButBR *)type->tp_alloc(type, 0);
-        
+
     self->freq = PyFloat_FromDouble(1000);
     self->q = PyFloat_FromDouble(1);
     self->last_freq = self->last_q = -1.0;
@@ -10790,10 +10639,10 @@ ButBR_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[3] = 0;
 
     INIT_OBJECT_COMMON
-    
+
     self->nyquist = (MYFLT)self->sr * 0.49;
     self->piOnSr = PI / (MYFLT)self->sr;
-    
+
     Stream_setFunctionPtr(self->stream, ButBR_compute_next_data_frame);
     self->mode_func_ptr = ButBR_setProcMode;
 
@@ -10803,7 +10652,7 @@ ButBR_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         Py_RETURN_NONE;
 
     INIT_INPUT_STREAM
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
@@ -10811,7 +10660,7 @@ ButBR_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (qtmp) {
         PyObject_CallMethod((PyObject *)self, "setQ", "O", qtmp);
     }
-    
+
     if (multmp) {
         PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
     }
@@ -10819,7 +10668,7 @@ ButBR_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (addtmp) {
         PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
     }
-            
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     (*self->mode_func_ptr)(self);
@@ -10829,10 +10678,10 @@ ButBR_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * ButBR_getServer(ButBR* self) { GET_SERVER };
 static PyObject * ButBR_getStream(ButBR* self) { GET_STREAM };
-static PyObject * ButBR_setMul(ButBR *self, PyObject *arg) { SET_MUL };	
-static PyObject * ButBR_setAdd(ButBR *self, PyObject *arg) { SET_ADD };	
-static PyObject * ButBR_setSub(ButBR *self, PyObject *arg) { SET_SUB };	
-static PyObject * ButBR_setDiv(ButBR *self, PyObject *arg) { SET_DIV };	
+static PyObject * ButBR_setMul(ButBR *self, PyObject *arg) { SET_MUL };
+static PyObject * ButBR_setAdd(ButBR *self, PyObject *arg) { SET_ADD };
+static PyObject * ButBR_setSub(ButBR *self, PyObject *arg) { SET_SUB };
+static PyObject * ButBR_setDiv(ButBR *self, PyObject *arg) { SET_DIV };
 
 static PyObject * ButBR_play(ButBR *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * ButBR_out(ButBR *self, PyObject *args, PyObject *kwds) { OUT };
@@ -10851,14 +10700,11 @@ static PyObject *
 ButBR_setFreq(ButBR *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -10874,25 +10720,22 @@ ButBR_setFreq(ButBR *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 ButBR_setQ(ButBR *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->q);
@@ -10908,12 +10751,12 @@ ButBR_setQ(ButBR *self, PyObject *arg)
         self->q_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef ButBR_members[] = {
     {"server", T_OBJECT_EX, offsetof(ButBR, server), 0, "Pyo server."},
@@ -10945,7 +10788,7 @@ static PyNumberMethods ButBR_as_number = {
     (binaryfunc)ButBR_add,                         /*nb_add*/
     (binaryfunc)ButBR_sub,                         /*nb_subtract*/
     (binaryfunc)ButBR_multiply,                    /*nb_multiply*/
-    (binaryfunc)ButBR_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -10959,16 +10802,16 @@ static PyNumberMethods ButBR_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)ButBR_inplace_add,                 /*inplace_add*/
     (binaryfunc)ButBR_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)ButBR_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)ButBR_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -10977,15 +10820,14 @@ static PyNumberMethods ButBR_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)ButBR_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)ButBR_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject ButBRType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.ButBR_base",                                   /*tp_name*/
     sizeof(ButBR),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -10993,7 +10835,7 @@ PyTypeObject ButBRType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &ButBR_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -11024,3 +10866,1010 @@ PyTypeObject ButBRType = {
     0,                                              /* tp_alloc */
     ButBR_new,                                     /* tp_new */
 };
+
+/****************/
+/** ComplexRes **/
+/****************/
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *input;
+    Stream *input_stream;
+    PyObject *freq;
+    Stream *freq_stream;
+    PyObject *decay;
+    Stream *decay_stream;
+    int modebuffer[4]; // need at least 2 slots for mul & add
+    MYFLT last_freq;
+    MYFLT last_decay;
+    MYFLT oneOnSr;
+    // variables
+    MYFLT res;
+    MYFLT norm;
+    MYFLT coeffx;
+    MYFLT coeffy;
+    // sample memories
+    MYFLT x;
+    MYFLT y;
+} ComplexRes;
+
+static void
+ComplexRes_filters_ii(ComplexRes *self) {
+    int i;
+    MYFLT ang, x, y;
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+    MYFLT freq = PyFloat_AS_DOUBLE(self->freq);
+    MYFLT decay = PyFloat_AS_DOUBLE(self->decay);
+
+    if (decay <= 0.0001)
+        decay = 0.0001;
+
+    if (decay != self->last_decay || freq != self->last_freq) {
+        self->res = MYEXP(-1.0/(decay*self->sr));
+        //self->norm = (1.0-self->res*self->res)/self->res;
+        self->last_decay = decay;
+        ang = (freq*self->oneOnSr)*TWOPI;
+        self->coeffx = self->res * MYCOS(ang);
+        self->coeffy = self->res * MYSIN(ang);
+        self->last_freq = freq;
+    }
+
+    for (i=0; i<self->bufsize; i++) {
+        x = self->coeffx * self->x - self->coeffy * self->y + in[i];
+        y = self->coeffy * self->x + self->coeffx * self->y;
+        self->data[i] = y * self->norm;
+        self->x = x;
+        self->y = y;
+    }
+}
+
+static void
+ComplexRes_filters_ai(ComplexRes *self) {
+    int i, check = 0;
+    MYFLT freq, ang, x, y;
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
+    MYFLT decay = PyFloat_AS_DOUBLE(self->decay);
+
+    if (decay <= 0.0001)
+        decay = 0.0001;
+
+    if (decay != self->last_decay) {
+        self->res = MYEXP(-1.0/(decay*self->sr));
+        //self->norm = (1.0-self->res*self->res)/self->res;
+        self->last_decay = decay;
+        check = 1;
+    }
+
+    for (i=0; i<self->bufsize; i++) {
+        freq = fr[i];
+        if (freq != self->last_freq || check) {
+            ang = (freq*self->oneOnSr)*TWOPI;
+            self->coeffx = self->res * MYCOS(ang);
+            self->coeffy = self->res * MYSIN(ang);
+            self->last_freq = freq;
+            check = 0;
+        }
+        x = self->coeffx * self->x - self->coeffy * self->y + in[i];
+        y = self->coeffy * self->x + self->coeffx * self->y;
+        self->data[i] = y * self->norm;
+        self->x = x;
+        self->y = y;
+    }
+}
+
+static void
+ComplexRes_filters_ia(ComplexRes *self) {
+    int i;
+    MYFLT decay, ang, x, y;
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+    MYFLT freq = PyFloat_AS_DOUBLE(self->freq);
+    MYFLT *dec = Stream_getData((Stream *)self->decay_stream);
+
+    for (i=0; i<self->bufsize; i++) {
+        decay = dec[i];
+        if (decay <= 0.0001)
+            decay = 0.0001;
+        if (freq != self->last_freq || decay != self->last_decay) {
+            self->res = MYEXP(-1.0/(decay*self->sr));
+            //self->norm = (1.0-self->res*self->res)/self->res;
+            self->last_decay = decay;
+            ang = (freq*self->oneOnSr)*TWOPI;
+            self->coeffx = self->res * MYCOS(ang);
+            self->coeffy = self->res * MYSIN(ang);
+            self->last_freq = freq;
+        }
+        x = self->coeffx * self->x - self->coeffy * self->y + in[i];
+        y = self->coeffy * self->x + self->coeffx * self->y;
+        self->data[i] = y * self->norm;
+        self->x = x;
+        self->y = y;
+    }
+}
+
+static void
+ComplexRes_filters_aa(ComplexRes *self) {
+    int i;
+    MYFLT freq, decay, ang, x, y;
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
+    MYFLT *dec = Stream_getData((Stream *)self->decay_stream);
+
+    for (i=0; i<self->bufsize; i++) {
+        freq = fr[i];
+        decay = dec[i];
+        if (decay <= 0.0001)
+            decay = 0.0001;
+        if (freq != self->last_freq || decay != self->last_decay) {
+            self->res = MYEXP(-1.0/(decay*self->sr));
+            //self->norm = (1.0-self->res*self->res)/self->res;
+            self->last_decay = decay;
+            ang = (freq*self->oneOnSr)*TWOPI;
+            self->coeffx = self->res * MYCOS(ang);
+            self->coeffy = self->res * MYSIN(ang);
+            self->last_freq = freq;
+        }
+        x = self->coeffx * self->x - self->coeffy * self->y + in[i];
+        y = self->coeffy * self->x + self->coeffx * self->y;
+        self->data[i] = y * self->norm;
+        self->x = x;
+        self->y = y;
+    }
+}
+
+static void ComplexRes_postprocessing_ii(ComplexRes *self) { POST_PROCESSING_II };
+static void ComplexRes_postprocessing_ai(ComplexRes *self) { POST_PROCESSING_AI };
+static void ComplexRes_postprocessing_ia(ComplexRes *self) { POST_PROCESSING_IA };
+static void ComplexRes_postprocessing_aa(ComplexRes *self) { POST_PROCESSING_AA };
+static void ComplexRes_postprocessing_ireva(ComplexRes *self) { POST_PROCESSING_IREVA };
+static void ComplexRes_postprocessing_areva(ComplexRes *self) { POST_PROCESSING_AREVA };
+static void ComplexRes_postprocessing_revai(ComplexRes *self) { POST_PROCESSING_REVAI };
+static void ComplexRes_postprocessing_revaa(ComplexRes *self) { POST_PROCESSING_REVAA };
+static void ComplexRes_postprocessing_revareva(ComplexRes *self) { POST_PROCESSING_REVAREVA };
+
+static void
+ComplexRes_setProcMode(ComplexRes *self)
+{
+    int procmode, muladdmode;
+    procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+	switch (procmode) {
+        case 0:
+            self->proc_func_ptr = ComplexRes_filters_ii;
+            break;
+        case 1:
+            self->proc_func_ptr = ComplexRes_filters_ai;
+            break;
+        case 10:
+            self->proc_func_ptr = ComplexRes_filters_ia;
+            break;
+        case 11:
+            self->proc_func_ptr = ComplexRes_filters_aa;
+            break;
+    }
+	switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = ComplexRes_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = ComplexRes_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = ComplexRes_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = ComplexRes_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = ComplexRes_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = ComplexRes_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = ComplexRes_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = ComplexRes_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = ComplexRes_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+ComplexRes_compute_next_data_frame(ComplexRes *self)
+{
+    (*self->proc_func_ptr)(self);
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+ComplexRes_traverse(ComplexRes *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->input);
+    Py_VISIT(self->input_stream);
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->decay);
+    Py_VISIT(self->decay_stream);
+    return 0;
+}
+
+static int
+ComplexRes_clear(ComplexRes *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->input);
+    Py_CLEAR(self->input_stream);
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->decay);
+    Py_CLEAR(self->decay_stream);
+    return 0;
+}
+
+static void
+ComplexRes_dealloc(ComplexRes* self)
+{
+    pyo_DEALLOC
+    ComplexRes_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+ComplexRes_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *decaytmp=NULL, *multmp=NULL, *addtmp=NULL;
+    ComplexRes *self;
+    self = (ComplexRes *)type->tp_alloc(type, 0);
+
+    self->freq = PyFloat_FromDouble(1000);
+    self->decay = PyFloat_FromDouble(.25);
+    self->last_freq = self->last_decay = -1.0;
+    self->x = self->y = 0.0;
+    self->res = 1.0;
+    self->norm = 0.01; /* normalization factor fixed at -40 dB */
+    self->coeffx = self->coeffy = 0.0;
+	self->modebuffer[0] = 0;
+	self->modebuffer[1] = 0;
+	self->modebuffer[2] = 0;
+	self->modebuffer[3] = 0;
+
+    INIT_OBJECT_COMMON
+
+    self->oneOnSr = 1.0 / self->sr;
+
+    Stream_setFunctionPtr(self->stream, ComplexRes_compute_next_data_frame);
+    self->mode_func_ptr = ComplexRes_setProcMode;
+
+    static char *kwlist[] = {"input", "freq", "decay", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &freqtmp, &decaytmp, &multmp, &addtmp))
+        Py_RETURN_NONE;
+
+    INIT_INPUT_STREAM
+
+    if (freqtmp) {
+        PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
+    }
+
+    if (decaytmp) {
+        PyObject_CallMethod((PyObject *)self, "setDecay", "O", decaytmp);
+    }
+
+    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 * ComplexRes_getServer(ComplexRes* self) { GET_SERVER };
+static PyObject * ComplexRes_getStream(ComplexRes* self) { GET_STREAM };
+static PyObject * ComplexRes_setMul(ComplexRes *self, PyObject *arg) { SET_MUL };
+static PyObject * ComplexRes_setAdd(ComplexRes *self, PyObject *arg) { SET_ADD };
+static PyObject * ComplexRes_setSub(ComplexRes *self, PyObject *arg) { SET_SUB };
+static PyObject * ComplexRes_setDiv(ComplexRes *self, PyObject *arg) { SET_DIV };
+
+static PyObject * ComplexRes_play(ComplexRes *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * ComplexRes_out(ComplexRes *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * ComplexRes_stop(ComplexRes *self) { STOP };
+
+static PyObject * ComplexRes_multiply(ComplexRes *self, PyObject *arg) { MULTIPLY };
+static PyObject * ComplexRes_inplace_multiply(ComplexRes *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * ComplexRes_add(ComplexRes *self, PyObject *arg) { ADD };
+static PyObject * ComplexRes_inplace_add(ComplexRes *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * ComplexRes_sub(ComplexRes *self, PyObject *arg) { SUB };
+static PyObject * ComplexRes_inplace_sub(ComplexRes *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * ComplexRes_div(ComplexRes *self, PyObject *arg) { DIV };
+static PyObject * ComplexRes_inplace_div(ComplexRes *self, PyObject *arg) { INPLACE_DIV };
+
+static PyObject *
+ComplexRes_setFreq(ComplexRes *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->freq);
+	if (isNumber == 1) {
+		self->freq = PyNumber_Float(tmp);
+        self->modebuffer[2] = 0;
+	}
+	else {
+		self->freq = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->freq_stream);
+        self->freq_stream = (Stream *)streamtmp;
+		self->modebuffer[2] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+ComplexRes_setDecay(ComplexRes *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->decay);
+	if (isNumber == 1) {
+		self->decay = PyNumber_Float(tmp);
+        self->modebuffer[3] = 0;
+	}
+	else {
+		self->decay = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->decay, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->decay_stream);
+        self->decay_stream = (Stream *)streamtmp;
+		self->modebuffer[3] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyMemberDef ComplexRes_members[] = {
+{"server", T_OBJECT_EX, offsetof(ComplexRes, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(ComplexRes, stream), 0, "Stream object."},
+{"input", T_OBJECT_EX, offsetof(ComplexRes, input), 0, "Input sound object."},
+{"freq", T_OBJECT_EX, offsetof(ComplexRes, freq), 0, "Center frequency in cycle per second."},
+{"decay", T_OBJECT_EX, offsetof(ComplexRes, decay), 0, "Decaying envelope time in seconds."},
+{"mul", T_OBJECT_EX, offsetof(ComplexRes, mul), 0, "Mul factor."},
+{"add", T_OBJECT_EX, offsetof(ComplexRes, add), 0, "Add factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyMethodDef ComplexRes_methods[] = {
+{"getServer", (PyCFunction)ComplexRes_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)ComplexRes_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)ComplexRes_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"out", (PyCFunction)ComplexRes_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+{"stop", (PyCFunction)ComplexRes_stop, METH_NOARGS, "Stops computing."},
+{"setFreq", (PyCFunction)ComplexRes_setFreq, METH_O, "Sets filter center frequency in cycle per second."},
+{"setDecay", (PyCFunction)ComplexRes_setDecay, METH_O, "Sets filter decaying envelope time."},
+{"setMul", (PyCFunction)ComplexRes_setMul, METH_O, "Sets oscillator mul factor."},
+{"setAdd", (PyCFunction)ComplexRes_setAdd, METH_O, "Sets oscillator add factor."},
+{"setSub", (PyCFunction)ComplexRes_setSub, METH_O, "Sets inverse add factor."},
+{"setDiv", (PyCFunction)ComplexRes_setDiv, METH_O, "Sets inverse mul factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyNumberMethods ComplexRes_as_number = {
+(binaryfunc)ComplexRes_add,                         /*nb_add*/
+(binaryfunc)ComplexRes_sub,                         /*nb_subtract*/
+(binaryfunc)ComplexRes_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)ComplexRes_inplace_add,                 /*inplace_add*/
+(binaryfunc)ComplexRes_inplace_sub,                 /*inplace_subtract*/
+(binaryfunc)ComplexRes_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)ComplexRes_div,                       /*nb_true_divide*/
+0,                                              /*nb_inplace_floor_divide*/
+(binaryfunc)ComplexRes_inplace_div,                       /*nb_inplace_true_divide*/
+0,                                              /* nb_index */
+};
+
+PyTypeObject ComplexResType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.ComplexRes_base",                                   /*tp_name*/
+sizeof(ComplexRes),                                 /*tp_basicsize*/
+0,                                              /*tp_itemsize*/
+(destructor)ComplexRes_dealloc,                     /*tp_dealloc*/
+0,                                              /*tp_print*/
+0,                                              /*tp_getattr*/
+0,                                              /*tp_setattr*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
+0,                                              /*tp_repr*/
+&ComplexRes_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*/
+"ComplexRes objects. Second order allpass filter.",           /* tp_doc */
+(traverseproc)ComplexRes_traverse,                  /* tp_traverse */
+(inquiry)ComplexRes_clear,                          /* tp_clear */
+0,                                              /* tp_richcompare */
+0,                                              /* tp_weaklistoffset */
+0,                                              /* tp_iter */
+0,                                              /* tp_iternext */
+ComplexRes_methods,                                 /* tp_methods */
+ComplexRes_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 */
+ComplexRes_new,                                     /* tp_new */
+};
+
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *input;
+    Stream *input_stream;
+    PyObject *freq;
+    Stream *freq_stream;
+    PyObject *res;
+    Stream *res_stream;
+    int modebuffer[4]; // need at least 2 slots for mul & add
+    MYFLT nyquist;
+    MYFLT last_freq;
+    MYFLT last_res;
+    // sample memories
+    MYFLT y1;
+    MYFLT y2;
+    MYFLT y3;
+    MYFLT y4;
+    MYFLT oldX;
+    MYFLT oldY1;
+    MYFLT oldY2;
+    MYFLT oldY3;
+    MYFLT oneOverSr;
+    // coefficients
+    MYFLT r;
+    MYFLT p;
+    MYFLT k;
+} MoogLP;
+
+static void
+MoogLP_compute_coeffs(MoogLP *self, MYFLT freq, MYFLT res)
+{
+    MYFLT f, fi, t, t2;
+
+    if (freq < 0.1)
+        freq = 0.1;
+    else if (freq > self->nyquist)
+        freq = self->nyquist;
+    if (res < 0.0)
+        res = 0.0;
+    else if (res > 10.0)
+        res = 10.0;
+
+    f = (freq + freq) * self->oneOverSr;
+    fi = 1.0 - f;
+    self->p = f * (1.8 - 0.8 * f);
+    self->k = 2.0 * MYSIN(f * PI * 0.5) - 1.0;
+    t = (1.0 - self->p) * 1.386249;
+    t2 = 12.0 + t * t;
+    self->r = res * 0.5 * (t2 + 6.0 * t) / (t2 - 6.0 * t);
+    /* Resonance compensation according to normalized frequency. */
+    self->r *= fi * fi * fi * 0.9 + 0.1;
+}
+
+static void
+MoogLP_filters_ii(MoogLP *self) {
+    MYFLT x, fr, res;
+    int i;
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+    fr = PyFloat_AS_DOUBLE(self->freq);
+    res = PyFloat_AS_DOUBLE(self->res);
+
+    if (fr != self->last_freq || res != self->last_res) {
+        self->last_freq = fr;
+        self->last_res = res;
+        MoogLP_compute_coeffs(self, fr, res);
+    }
+
+    for (i=0; i<self->bufsize; i++) {
+        x = in[i] - self->r * self->y4;
+        self->y1 = (x + self->oldX) * self->p - self->k * self->y1;
+        self->y2 = (self->y1 + self->oldY1) * self->p - self->k * self->y2;
+        self->y3 = (self->y2 + self->oldY2) * self->p - self->k * self->y3;
+        self->y4 = (self->y3 + self->oldY3) * self->p - self->k * self->y4;
+        self->y4 -= (self->y4*self->y4*self->y4) * 0.16666666666666666;
+        self->oldX = x; self->oldY1 = self->y1; self->oldY2 = self->y2; self->oldY3 = self->y3;
+        self->data[i] = self->y4;
+    }
+}
+
+static void
+MoogLP_filters_ai(MoogLP *self) {
+    MYFLT x, fr, res;
+    int i;
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+    MYFLT *freq = Stream_getData((Stream *)self->freq_stream);
+    res = PyFloat_AS_DOUBLE(self->res);
+
+    for (i=0; i<self->bufsize; i++) {
+        fr = freq[i];
+        if (fr != self->last_freq || res != self->last_res) {
+            self->last_freq = fr;
+            self->last_res = res;
+            MoogLP_compute_coeffs(self, fr, res);
+        }
+        x = in[i] - self->r * self->y4;
+        self->y1 = (x + self->oldX) * self->p - self->k * self->y1;
+        self->y2 = (self->y1 + self->oldY1) * self->p - self->k * self->y2;
+        self->y3 = (self->y2 + self->oldY2) * self->p - self->k * self->y3;
+        self->y4 = (self->y3 + self->oldY3) * self->p - self->k * self->y4;
+        self->y4 -= (self->y4*self->y4*self->y4) * 0.16666666666666666;
+        self->oldX = x; self->oldY1 = self->y1; self->oldY2 = self->y2; self->oldY3 = self->y3;
+        self->data[i] = self->y4;
+    }
+}
+
+static void
+MoogLP_filters_ia(MoogLP *self) {
+    MYFLT x, fr, res;
+    int i;
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+    fr = PyFloat_AS_DOUBLE(self->freq);
+    MYFLT *rz = Stream_getData((Stream *)self->res_stream);
+
+    for (i=0; i<self->bufsize; i++) {
+        res = rz[i];
+        if (fr != self->last_freq || res != self->last_res) {
+            self->last_freq = fr;
+            self->last_res = res;
+            MoogLP_compute_coeffs(self, fr, res);
+        }
+        x = in[i] - self->r * self->y4;
+        self->y1 = (x + self->oldX) * self->p - self->k * self->y1;
+        self->y2 = (self->y1 + self->oldY1) * self->p - self->k * self->y2;
+        self->y3 = (self->y2 + self->oldY2) * self->p - self->k * self->y3;
+        self->y4 = (self->y3 + self->oldY3) * self->p - self->k * self->y4;
+        self->y4 -= (self->y4*self->y4*self->y4) * 0.16666666666666666;
+        self->oldX = x; self->oldY1 = self->y1; self->oldY2 = self->y2; self->oldY3 = self->y3;
+        self->data[i] = self->y4;
+    }
+}
+
+static void
+MoogLP_filters_aa(MoogLP *self) {
+    MYFLT x, fr, res;
+    int i;
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+    MYFLT *freq = Stream_getData((Stream *)self->freq_stream);
+    MYFLT *rz = Stream_getData((Stream *)self->res_stream);
+
+    for (i=0; i<self->bufsize; i++) {
+        fr = freq[i];
+        res = rz[i];
+        if (fr != self->last_freq || res != self->last_res) {
+            self->last_freq = fr;
+            self->last_res = res;
+            MoogLP_compute_coeffs(self, fr, res);
+        }
+        x = in[i] - self->r * self->y4;
+        self->y1 = (x + self->oldX) * self->p - self->k * self->y1;
+        self->y2 = (self->y1 + self->oldY1) * self->p - self->k * self->y2;
+        self->y3 = (self->y2 + self->oldY2) * self->p - self->k * self->y3;
+        self->y4 = (self->y3 + self->oldY3) * self->p - self->k * self->y4;
+        self->y4 -= (self->y4*self->y4*self->y4) * 0.16666666666666666;
+        self->oldX = x; self->oldY1 = self->y1; self->oldY2 = self->y2; self->oldY3 = self->y3;
+        self->data[i] = self->y4;
+    }
+}
+
+static void MoogLP_postprocessing_ii(MoogLP *self) { POST_PROCESSING_II };
+static void MoogLP_postprocessing_ai(MoogLP *self) { POST_PROCESSING_AI };
+static void MoogLP_postprocessing_ia(MoogLP *self) { POST_PROCESSING_IA };
+static void MoogLP_postprocessing_aa(MoogLP *self) { POST_PROCESSING_AA };
+static void MoogLP_postprocessing_ireva(MoogLP *self) { POST_PROCESSING_IREVA };
+static void MoogLP_postprocessing_areva(MoogLP *self) { POST_PROCESSING_AREVA };
+static void MoogLP_postprocessing_revai(MoogLP *self) { POST_PROCESSING_REVAI };
+static void MoogLP_postprocessing_revaa(MoogLP *self) { POST_PROCESSING_REVAA };
+static void MoogLP_postprocessing_revareva(MoogLP *self) { POST_PROCESSING_REVAREVA };
+
+static void
+MoogLP_setProcMode(MoogLP *self)
+{
+    int procmode, muladdmode;
+    procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+	switch (procmode) {
+        case 0:
+            self->proc_func_ptr = MoogLP_filters_ii;
+            break;
+        case 1:
+            self->proc_func_ptr = MoogLP_filters_ai;
+            break;
+        case 10:
+            self->proc_func_ptr = MoogLP_filters_ia;
+            break;
+        case 11:
+            self->proc_func_ptr = MoogLP_filters_aa;
+            break;
+    }
+	switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = MoogLP_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = MoogLP_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = MoogLP_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = MoogLP_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = MoogLP_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = MoogLP_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = MoogLP_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = MoogLP_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = MoogLP_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+MoogLP_compute_next_data_frame(MoogLP *self)
+{
+    (*self->proc_func_ptr)(self);
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+MoogLP_traverse(MoogLP *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->input);
+    Py_VISIT(self->input_stream);
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->res);
+    Py_VISIT(self->res_stream);
+    return 0;
+}
+
+static int
+MoogLP_clear(MoogLP *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->input);
+    Py_CLEAR(self->input_stream);
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->res);
+    Py_CLEAR(self->res_stream);
+    return 0;
+}
+
+static void
+MoogLP_dealloc(MoogLP* self)
+{
+    pyo_DEALLOC
+    MoogLP_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+MoogLP_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *inputtmp, *input_streamtmp, *freqtmp=NULL, *restmp=NULL, *multmp=NULL, *addtmp=NULL;
+    MoogLP *self;
+    self = (MoogLP *)type->tp_alloc(type, 0);
+
+    self->freq = PyFloat_FromDouble(1000);
+    self->res = PyFloat_FromDouble(1);
+    self->last_freq = self->last_res = -1.0;
+    self->y1 = self->y2 = self->y3 = self->y4 = self->oldX = self->oldY1 = self->oldY2 = self->oldY3 - 0.0;
+	self->modebuffer[0] = 0;
+	self->modebuffer[1] = 0;
+	self->modebuffer[2] = 0;
+	self->modebuffer[3] = 0;
+
+    INIT_OBJECT_COMMON
+
+    self->nyquist = (MYFLT)self->sr * 0.49;
+    self->oneOverSr = 1.0 / (MYFLT)self->sr;
+
+    Stream_setFunctionPtr(self->stream, MoogLP_compute_next_data_frame);
+    self->mode_func_ptr = MoogLP_setProcMode;
+
+    static char *kwlist[] = {"input", "freq", "res", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &freqtmp, &restmp, &multmp, &addtmp))
+        Py_RETURN_NONE;
+
+    INIT_INPUT_STREAM
+
+    if (freqtmp) {
+        PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
+    }
+
+    if (restmp) {
+        PyObject_CallMethod((PyObject *)self, "setRes", "O", restmp);
+    }
+
+    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 * MoogLP_getServer(MoogLP* self) { GET_SERVER };
+static PyObject * MoogLP_getStream(MoogLP* self) { GET_STREAM };
+static PyObject * MoogLP_setMul(MoogLP *self, PyObject *arg) { SET_MUL };
+static PyObject * MoogLP_setAdd(MoogLP *self, PyObject *arg) { SET_ADD };
+static PyObject * MoogLP_setSub(MoogLP *self, PyObject *arg) { SET_SUB };
+static PyObject * MoogLP_setDiv(MoogLP *self, PyObject *arg) { SET_DIV };
+
+static PyObject * MoogLP_play(MoogLP *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * MoogLP_out(MoogLP *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * MoogLP_stop(MoogLP *self) { STOP };
+
+static PyObject * MoogLP_multiply(MoogLP *self, PyObject *arg) { MULTIPLY };
+static PyObject * MoogLP_inplace_multiply(MoogLP *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * MoogLP_add(MoogLP *self, PyObject *arg) { ADD };
+static PyObject * MoogLP_inplace_add(MoogLP *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * MoogLP_sub(MoogLP *self, PyObject *arg) { SUB };
+static PyObject * MoogLP_inplace_sub(MoogLP *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * MoogLP_div(MoogLP *self, PyObject *arg) { DIV };
+static PyObject * MoogLP_inplace_div(MoogLP *self, PyObject *arg) { INPLACE_DIV };
+
+static PyObject *
+MoogLP_setFreq(MoogLP *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->freq);
+	if (isNumber == 1) {
+		self->freq = PyNumber_Float(tmp);
+        self->modebuffer[2] = 0;
+	}
+	else {
+		self->freq = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->freq_stream);
+        self->freq_stream = (Stream *)streamtmp;
+		self->modebuffer[2] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+MoogLP_setRes(MoogLP *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->res);
+	if (isNumber == 1) {
+		self->res = PyNumber_Float(tmp);
+        self->modebuffer[3] = 0;
+	}
+	else {
+		self->res = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->res, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->res_stream);
+        self->res_stream = (Stream *)streamtmp;
+		self->modebuffer[3] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyMemberDef MoogLP_members[] = {
+    {"server", T_OBJECT_EX, offsetof(MoogLP, server), 0, "Pyo server."},
+    {"stream", T_OBJECT_EX, offsetof(MoogLP, stream), 0, "Stream object."},
+    {"input", T_OBJECT_EX, offsetof(MoogLP, input), 0, "Input sound object."},
+    {"freq", T_OBJECT_EX, offsetof(MoogLP, freq), 0, "Cutoff frequency in cycle per second."},
+    {"res", T_OBJECT_EX, offsetof(MoogLP, res), 0, "Resonance factor."},
+    {"mul", T_OBJECT_EX, offsetof(MoogLP, mul), 0, "Mul factor."},
+    {"add", T_OBJECT_EX, offsetof(MoogLP, add), 0, "Add factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef MoogLP_methods[] = {
+    {"getServer", (PyCFunction)MoogLP_getServer, METH_NOARGS, "Returns server object."},
+    {"_getStream", (PyCFunction)MoogLP_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)MoogLP_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+    {"out", (PyCFunction)MoogLP_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+    {"stop", (PyCFunction)MoogLP_stop, METH_NOARGS, "Stops computing."},
+	{"setFreq", (PyCFunction)MoogLP_setFreq, METH_O, "Sets filter cutoff frequency in cycle per second."},
+    {"setRes", (PyCFunction)MoogLP_setRes, METH_O, "Sets filter's resonance."},
+	{"setMul", (PyCFunction)MoogLP_setMul, METH_O, "Sets oscillator mul factor."},
+	{"setAdd", (PyCFunction)MoogLP_setAdd, METH_O, "Sets oscillator add factor."},
+    {"setSub", (PyCFunction)MoogLP_setSub, METH_O, "Sets inverse add factor."},
+    {"setDiv", (PyCFunction)MoogLP_setDiv, METH_O, "Sets inverse mul factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyNumberMethods MoogLP_as_number = {
+    (binaryfunc)MoogLP_add,                         /*nb_add*/
+    (binaryfunc)MoogLP_sub,                         /*nb_subtract*/
+    (binaryfunc)MoogLP_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)MoogLP_inplace_add,                 /*inplace_add*/
+    (binaryfunc)MoogLP_inplace_sub,                 /*inplace_subtract*/
+    (binaryfunc)MoogLP_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)MoogLP_div,                       /*nb_true_divide*/
+    0,                                              /*nb_inplace_floor_divide*/
+    (binaryfunc)MoogLP_inplace_div,                       /*nb_inplace_true_divide*/
+    0,                                              /* nb_index */
+};
+
+PyTypeObject MoogLPType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.MoogLP_base",                                   /*tp_name*/
+    sizeof(MoogLP),                                 /*tp_basicsize*/
+    0,                                              /*tp_itemsize*/
+    (destructor)MoogLP_dealloc,                     /*tp_dealloc*/
+    0,                                              /*tp_print*/
+    0,                                              /*tp_getattr*/
+    0,                                              /*tp_setattr*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
+    0,                                              /*tp_repr*/
+    &MoogLP_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*/
+    "MoogLP objects. Second-order resonant bandpass filter.",           /* tp_doc */
+    (traverseproc)MoogLP_traverse,                  /* tp_traverse */
+    (inquiry)MoogLP_clear,                          /* tp_clear */
+    0,                                              /* tp_richcompare */
+    0,                                              /* tp_weaklistoffset */
+    0,                                              /* tp_iter */
+    0,                                              /* tp_iternext */
+    MoogLP_methods,                                 /* tp_methods */
+    MoogLP_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 */
+    MoogLP_new,                                     /* tp_new */
+};
diff --git a/src/objects/freeverbmodule.c b/src/objects/freeverbmodule.c
index 8ba510b..895efee 100644
--- a/src/objects/freeverbmodule.c
+++ b/src/objects/freeverbmodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
@@ -31,26 +32,26 @@
 #define NUM_ALLPASS      4
 
 static const MYFLT comb_delays[NUM_COMB] = {
-1116.0 / DEFAULT_SRATE, 
-1188.0 / DEFAULT_SRATE, 
-1277.0 / DEFAULT_SRATE, 
+1116.0 / DEFAULT_SRATE,
+1188.0 / DEFAULT_SRATE,
+1277.0 / DEFAULT_SRATE,
 1356.0 / DEFAULT_SRATE,
-1422.0 / DEFAULT_SRATE, 
-1491.0 / DEFAULT_SRATE, 
-1557.0 / DEFAULT_SRATE, 
+1422.0 / DEFAULT_SRATE,
+1491.0 / DEFAULT_SRATE,
+1557.0 / DEFAULT_SRATE,
 1617.0 / DEFAULT_SRATE
 };
 
 static const MYFLT allpass_delays[NUM_ALLPASS] = {
-556.0 / DEFAULT_SRATE, 
-441.0 / DEFAULT_SRATE, 
-341.0 / DEFAULT_SRATE, 
+556.0 / DEFAULT_SRATE,
+441.0 / DEFAULT_SRATE,
+341.0 / DEFAULT_SRATE,
 225.0 / DEFAULT_SRATE
 };
 
 static const MYFLT fixedGain   = 0.015;
 static const MYFLT scaleDamp   = 0.5;
-static const MYFLT scaleRoom   = 0.28;
+static const MYFLT scaleRoom   = 0.29;
 static const MYFLT offsetRoom  = 0.7;
 static const MYFLT allPassFeedBack = 0.5;
 
@@ -86,7 +87,7 @@ _clip(MYFLT x)
         return x;
 }
 
-static int 
+static int
 Freeverb_calc_nsamples(Freeverb *self, MYFLT delTime)
 {
     return (int)(delTime * self->sr + 0.5);
@@ -108,10 +109,10 @@ Freeverb_transform_iii(Freeverb *self) {
 
     mix1 = MYSQRT(mix);
     mix2 = MYSQRT(1.0 - mix);
-    
+
     MYFLT tmp[self->bufsize];
     memset(&tmp, 0, sizeof(tmp));
-    
+
     for (j=0; j<self->bufsize; j++) {
         for (i=0; i<NUM_COMB; i++) {
             x = self->comb_buf[i][self->comb_bufPos[i]];
@@ -124,7 +125,7 @@ Freeverb_transform_iii(Freeverb *self) {
                 self->comb_bufPos[i] = 0;
         }
     }
-    
+
     for (i=0; i<NUM_ALLPASS; i++) {
         for (j=0; j<self->bufsize; j++) {
             x = self->allpass_buf[i][self->allpass_bufPos[i]] - tmp[j];
@@ -134,33 +135,33 @@ Freeverb_transform_iii(Freeverb *self) {
             if (self->allpass_bufPos[i] >= self->allpass_nSamples[i])
                 self->allpass_bufPos[i] = 0;
             tmp[j] = x;
-        }    
+        }
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = (tmp[i] * fixedGain * mix1) + (in[i] * mix2);
-    }    
+    }
 }
 
 static void
 Freeverb_transform_aii(Freeverb *self) {
     MYFLT x, feedback, damp1, damp2, mix1, mix2;
     int i, j;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *siz = Stream_getData((Stream *)self->size_stream);
     MYFLT dam = _clip(PyFloat_AS_DOUBLE(self->damp));
     MYFLT mix = _clip(PyFloat_AS_DOUBLE(self->mix));
-    
+
     damp1 = dam * scaleDamp;
     damp2 = 1.0 - damp1;
-    
+
     mix1 = MYSQRT(mix);
     mix2 = MYSQRT(1.0 - mix);
-    
+
     MYFLT tmp[self->bufsize];
     memset(&tmp, 0, sizeof(tmp));
-    
+
     for (j=0; j<self->bufsize; j++) {
         feedback = _clip(siz[j]) * scaleRoom + offsetRoom;
         for (i=0; i<NUM_COMB; i++) {
@@ -174,7 +175,7 @@ Freeverb_transform_aii(Freeverb *self) {
                 self->comb_bufPos[i] = 0;
         }
     }
-    
+
     for (i=0; i<NUM_ALLPASS; i++) {
         for (j=0; j<self->bufsize; j++) {
             x = self->allpass_buf[i][self->allpass_bufPos[i]] - tmp[j];
@@ -184,32 +185,32 @@ Freeverb_transform_aii(Freeverb *self) {
             if (self->allpass_bufPos[i] >= self->allpass_nSamples[i])
                 self->allpass_bufPos[i] = 0;
             tmp[j] = x;
-        }    
+        }
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = (tmp[i] * fixedGain * mix1) + (in[i] * mix2);
-    }    
+    }
 }
 
 static void
 Freeverb_transform_iai(Freeverb *self) {
     MYFLT x, feedback, damp1, damp2, mix1, mix2;
     int i, j;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT siz = _clip(PyFloat_AS_DOUBLE(self->size));
     MYFLT *dam = Stream_getData((Stream *)self->damp_stream);
     MYFLT mix = _clip(PyFloat_AS_DOUBLE(self->mix));
-    
+
     feedback = siz * scaleRoom + offsetRoom;
-    
+
     mix1 = MYSQRT(mix);
     mix2 = MYSQRT(1.0 - mix);
-    
+
     MYFLT tmp[self->bufsize];
     memset(&tmp, 0, sizeof(tmp));
-    
+
     for (j=0; j<self->bufsize; j++) {
         damp1 = _clip(dam[j]) * scaleDamp;
         damp2 = 1.0 - damp1;
@@ -224,7 +225,7 @@ Freeverb_transform_iai(Freeverb *self) {
                 self->comb_bufPos[i] = 0;
         }
     }
-    
+
     for (i=0; i<NUM_ALLPASS; i++) {
         for (j=0; j<self->bufsize; j++) {
             x = self->allpass_buf[i][self->allpass_bufPos[i]] - tmp[j];
@@ -234,19 +235,19 @@ Freeverb_transform_iai(Freeverb *self) {
             if (self->allpass_bufPos[i] >= self->allpass_nSamples[i])
                 self->allpass_bufPos[i] = 0;
             tmp[j] = x;
-        }    
+        }
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = (tmp[i] * fixedGain * mix1) + (in[i] * mix2);
-    }    
+    }
 }
 
 static void
 Freeverb_transform_aai(Freeverb *self) {
     MYFLT x, feedback, damp1, damp2, mix1, mix2;
     int i, j;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *siz = Stream_getData((Stream *)self->size_stream);
     MYFLT *dam = Stream_getData((Stream *)self->damp_stream);
@@ -257,7 +258,7 @@ Freeverb_transform_aai(Freeverb *self) {
 
     MYFLT tmp[self->bufsize];
     memset(&tmp, 0, sizeof(tmp));
-    
+
     for (j=0; j<self->bufsize; j++) {
         feedback = _clip(siz[j]) * scaleRoom + offsetRoom;
         damp1 = _clip(dam[j]) * scaleDamp;
@@ -273,7 +274,7 @@ Freeverb_transform_aai(Freeverb *self) {
                 self->comb_bufPos[i] = 0;
         }
     }
-    
+
     for (i=0; i<NUM_ALLPASS; i++) {
         for (j=0; j<self->bufsize; j++) {
             x = self->allpass_buf[i][self->allpass_bufPos[i]] - tmp[j];
@@ -283,31 +284,31 @@ Freeverb_transform_aai(Freeverb *self) {
             if (self->allpass_bufPos[i] >= self->allpass_nSamples[i])
                 self->allpass_bufPos[i] = 0;
             tmp[j] = x;
-        }    
+        }
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = (tmp[i] * fixedGain * mix1) + (in[i] * mix2);
-    }    
+    }
 }
 
 static void
 Freeverb_transform_iia(Freeverb *self) {
     MYFLT x, feedback, damp1, damp2, mix1, mix2, mixtmp;
     int i, j;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT siz = _clip(PyFloat_AS_DOUBLE(self->size));
     MYFLT dam = _clip(PyFloat_AS_DOUBLE(self->damp));
     MYFLT *mix = Stream_getData((Stream *)self->mix_stream);
-    
+
     feedback = siz * scaleRoom + offsetRoom;
     damp1 = dam * scaleDamp;
     damp2 = 1.0 - damp1;
 
     MYFLT tmp[self->bufsize];
     memset(&tmp, 0, sizeof(tmp));
-    
+
     for (j=0; j<self->bufsize; j++) {
         for (i=0; i<NUM_COMB; i++) {
             x = self->comb_buf[i][self->comb_bufPos[i]];
@@ -320,7 +321,7 @@ Freeverb_transform_iia(Freeverb *self) {
                 self->comb_bufPos[i] = 0;
         }
     }
-    
+
     for (i=0; i<NUM_ALLPASS; i++) {
         for (j=0; j<self->bufsize; j++) {
             x = self->allpass_buf[i][self->allpass_bufPos[i]] - tmp[j];
@@ -330,33 +331,33 @@ Freeverb_transform_iia(Freeverb *self) {
             if (self->allpass_bufPos[i] >= self->allpass_nSamples[i])
                 self->allpass_bufPos[i] = 0;
             tmp[j] = x;
-        }    
+        }
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         mixtmp = _clip(mix[i]);
         mix1 = MYSQRT(mixtmp);
         mix2 = MYSQRT(1.0 - mixtmp);
         self->data[i] = (tmp[i] * fixedGain * mix1) + (in[i] * mix2);
-    }    
+    }
 }
 
 static void
 Freeverb_transform_aia(Freeverb *self) {
     MYFLT x, feedback, damp1, damp2, mix1, mix2, mixtmp;
     int i, j;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *siz = Stream_getData((Stream *)self->size_stream);
     MYFLT dam = _clip(PyFloat_AS_DOUBLE(self->damp));
     MYFLT *mix = Stream_getData((Stream *)self->mix_stream);
-    
+
     damp1 = dam * scaleDamp;
     damp2 = 1.0 - damp1;
-    
+
     MYFLT tmp[self->bufsize];
     memset(&tmp, 0, sizeof(tmp));
-    
+
     for (j=0; j<self->bufsize; j++) {
         feedback = _clip(siz[j]) * scaleRoom + offsetRoom;
         for (i=0; i<NUM_COMB; i++) {
@@ -370,7 +371,7 @@ Freeverb_transform_aia(Freeverb *self) {
                 self->comb_bufPos[i] = 0;
         }
     }
-    
+
     for (i=0; i<NUM_ALLPASS; i++) {
         for (j=0; j<self->bufsize; j++) {
             x = self->allpass_buf[i][self->allpass_bufPos[i]] - tmp[j];
@@ -380,32 +381,32 @@ Freeverb_transform_aia(Freeverb *self) {
             if (self->allpass_bufPos[i] >= self->allpass_nSamples[i])
                 self->allpass_bufPos[i] = 0;
             tmp[j] = x;
-        }    
+        }
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         mixtmp = _clip(mix[i]);
         mix1 = MYSQRT(mixtmp);
         mix2 = MYSQRT(1.0 - mixtmp);
         self->data[i] = (tmp[i] * fixedGain * mix1) + (in[i] * mix2);
-    }    
+    }
 }
 
 static void
 Freeverb_transform_iaa(Freeverb *self) {
     MYFLT x, feedback, damp1, damp2, mix1, mix2, mixtmp;
     int i, j;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT siz = _clip(PyFloat_AS_DOUBLE(self->size));
     MYFLT *dam = Stream_getData((Stream *)self->damp_stream);
     MYFLT *mix = Stream_getData((Stream *)self->mix_stream);
-    
+
     feedback = siz * scaleRoom + offsetRoom;
-    
+
     MYFLT tmp[self->bufsize];
     memset(&tmp, 0, sizeof(tmp));
-    
+
     for (j=0; j<self->bufsize; j++) {
         damp1 = _clip(dam[j]) * scaleDamp;
         damp2 = 1.0 - damp1;
@@ -420,7 +421,7 @@ Freeverb_transform_iaa(Freeverb *self) {
                 self->comb_bufPos[i] = 0;
         }
     }
-    
+
     for (i=0; i<NUM_ALLPASS; i++) {
         for (j=0; j<self->bufsize; j++) {
             x = self->allpass_buf[i][self->allpass_bufPos[i]] - tmp[j];
@@ -430,30 +431,30 @@ Freeverb_transform_iaa(Freeverb *self) {
             if (self->allpass_bufPos[i] >= self->allpass_nSamples[i])
                 self->allpass_bufPos[i] = 0;
             tmp[j] = x;
-        }    
+        }
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         mixtmp = _clip(mix[i]);
         mix1 = MYSQRT(mixtmp);
         mix2 = MYSQRT(1.0 - mixtmp);
         self->data[i] = (tmp[i] * fixedGain * mix1) + (in[i] * mix2);
-    }    
+    }
 }
 
 static void
 Freeverb_transform_aaa(Freeverb *self) {
     MYFLT x, feedback, damp1, damp2, mix1, mix2, mixtmp;
     int i, j;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *siz = Stream_getData((Stream *)self->size_stream);
     MYFLT *dam = Stream_getData((Stream *)self->damp_stream);
     MYFLT *mix = Stream_getData((Stream *)self->mix_stream);
-        
+
     MYFLT tmp[self->bufsize];
     memset(&tmp, 0, sizeof(tmp));
-    
+
     for (j=0; j<self->bufsize; j++) {
         feedback = _clip(siz[j]) * scaleRoom + offsetRoom;
         damp1 = _clip(dam[j]) * scaleDamp;
@@ -469,7 +470,7 @@ Freeverb_transform_aaa(Freeverb *self) {
                 self->comb_bufPos[i] = 0;
         }
     }
-    
+
     for (i=0; i<NUM_ALLPASS; i++) {
         for (j=0; j<self->bufsize; j++) {
             x = self->allpass_buf[i][self->allpass_bufPos[i]] - tmp[j];
@@ -479,15 +480,15 @@ Freeverb_transform_aaa(Freeverb *self) {
             if (self->allpass_bufPos[i] >= self->allpass_nSamples[i])
                 self->allpass_bufPos[i] = 0;
             tmp[j] = x;
-        }    
+        }
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         mixtmp = _clip(mix[i]);
         mix1 = MYSQRT(mixtmp);
         mix2 = MYSQRT(1.0 - mixtmp);
         self->data[i] = (tmp[i] * fixedGain * mix1) + (in[i] * mix2);
-    }    
+    }
 }
 
 static void Freeverb_postprocessing_ii(Freeverb *self) { POST_PROCESSING_II };
@@ -508,66 +509,66 @@ Freeverb_setProcMode(Freeverb *self)
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Freeverb_transform_iii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Freeverb_transform_aii;
             break;
-        case 10:        
+        case 10:
             self->proc_func_ptr = Freeverb_transform_iai;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Freeverb_transform_aai;
             break;
-        case 100:        
+        case 100:
             self->proc_func_ptr = Freeverb_transform_iia;
             break;
-        case 101:    
+        case 101:
             self->proc_func_ptr = Freeverb_transform_aia;
             break;
-        case 110:        
+        case 110:
             self->proc_func_ptr = Freeverb_transform_iaa;
             break;
-        case 111:    
+        case 111:
             self->proc_func_ptr = Freeverb_transform_aaa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Freeverb_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Freeverb_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Freeverb_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Freeverb_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Freeverb_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Freeverb_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Freeverb_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Freeverb_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Freeverb_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Freeverb_compute_next_data_frame(Freeverb *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -576,28 +577,28 @@ Freeverb_traverse(Freeverb *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->input);
-    Py_VISIT(self->input_stream);    
-    Py_VISIT(self->size);    
-    Py_VISIT(self->size_stream);    
-    Py_VISIT(self->damp);    
-    Py_VISIT(self->damp_stream);    
-    Py_VISIT(self->mix);    
-    Py_VISIT(self->mix_stream);    
+    Py_VISIT(self->input_stream);
+    Py_VISIT(self->size);
+    Py_VISIT(self->size_stream);
+    Py_VISIT(self->damp);
+    Py_VISIT(self->damp_stream);
+    Py_VISIT(self->mix);
+    Py_VISIT(self->mix_stream);
     return 0;
 }
 
-static int 
+static int
 Freeverb_clear(Freeverb *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->size);    
-    Py_CLEAR(self->size_stream);    
-    Py_CLEAR(self->damp);    
-    Py_CLEAR(self->damp_stream);    
-    Py_CLEAR(self->mix);    
-    Py_CLEAR(self->mix_stream);    
+    Py_CLEAR(self->size);
+    Py_CLEAR(self->size_stream);
+    Py_CLEAR(self->damp);
+    Py_CLEAR(self->damp_stream);
+    Py_CLEAR(self->mix);
+    Py_CLEAR(self->mix_stream);
     return 0;
 }
 
@@ -611,9 +612,9 @@ Freeverb_dealloc(Freeverb* self)
     }
     for(i=0; i<NUM_ALLPASS; i++) {
         free(self->allpass_buf[i]);
-    }    
+    }
     Freeverb_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -633,7 +634,7 @@ Freeverb_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
 	self->modebuffer[4] = 0;
-    
+
     self->srFactor = pow((DEFAULT_SRATE/self->sr), 0.8);
 
     INIT_OBJECT_COMMON
@@ -658,7 +659,7 @@ Freeverb_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (mixtmp) {
         PyObject_CallMethod((PyObject *)self, "setMix", "O", mixtmp);
     }
-    
+
     if (multmp) {
         PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
     }
@@ -666,14 +667,14 @@ Freeverb_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (addtmp) {
         PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
     }
-            
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     (*self->mode_func_ptr)(self);
 
     Server_generateSeed((Server *)self->server, FREEVERB_ID);
-    
-    rndSamps = (rand()/(MYFLT)(RAND_MAX) * 20 + 10) / DEFAULT_SRATE;
+
+    rndSamps = (RANDOM_UNIFORM * 20 + 10) / DEFAULT_SRATE;
     for(i=0; i<NUM_COMB; i++) {
         nsamps = Freeverb_calc_nsamples((Freeverb *)self, comb_delays[i] + rndSamps);
         self->comb_buf[i] = (MYFLT *)realloc(self->comb_buf[i], (nsamps+1) * sizeof(MYFLT));
@@ -683,26 +684,26 @@ Freeverb_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         for(j=0; j<nsamps; j++) {
             self->comb_buf[i][j] = 0.0;
         }
-    }    
-        for(i=0; i<NUM_ALLPASS; i++) {
-            nsamps = Freeverb_calc_nsamples((Freeverb *)self, allpass_delays[i] + rndSamps);
-            self->allpass_buf[i] = (MYFLT *)realloc(self->allpass_buf[i], (nsamps+1) * sizeof(MYFLT));
-            self->allpass_nSamples[i] = nsamps;
-            self->allpass_bufPos[i] = 0;
-            for(j=0; j<nsamps; j++) {
-                self->allpass_buf[i][j] = 0.0;
-            }
-    }
-    
+    }
+    for(i=0; i<NUM_ALLPASS; i++) {
+        nsamps = Freeverb_calc_nsamples((Freeverb *)self, allpass_delays[i] + rndSamps);
+        self->allpass_buf[i] = (MYFLT *)realloc(self->allpass_buf[i], (nsamps+1) * sizeof(MYFLT));
+        self->allpass_nSamples[i] = nsamps;
+        self->allpass_bufPos[i] = 0;
+        for(j=0; j<nsamps; j++) {
+            self->allpass_buf[i][j] = 0.0;
+        }
+    }
+
     return (PyObject *)self;
 }
 
 static PyObject * Freeverb_getServer(Freeverb* self) { GET_SERVER };
 static PyObject * Freeverb_getStream(Freeverb* self) { GET_STREAM };
-static PyObject * Freeverb_setMul(Freeverb *self, PyObject *arg) { SET_MUL };	
-static PyObject * Freeverb_setAdd(Freeverb *self, PyObject *arg) { SET_ADD };	
-static PyObject * Freeverb_setSub(Freeverb *self, PyObject *arg) { SET_SUB };	
-static PyObject * Freeverb_setDiv(Freeverb *self, PyObject *arg) { SET_DIV };	
+static PyObject * Freeverb_setMul(Freeverb *self, PyObject *arg) { SET_MUL };
+static PyObject * Freeverb_setAdd(Freeverb *self, PyObject *arg) { SET_ADD };
+static PyObject * Freeverb_setSub(Freeverb *self, PyObject *arg) { SET_SUB };
+static PyObject * Freeverb_setDiv(Freeverb *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Freeverb_play(Freeverb *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Freeverb_out(Freeverb *self, PyObject *args, PyObject *kwds) { OUT };
@@ -718,17 +719,34 @@ static PyObject * Freeverb_div(Freeverb *self, PyObject *arg) { DIV };
 static PyObject * Freeverb_inplace_div(Freeverb *self, PyObject *arg) { INPLACE_DIV };
 
 static PyObject *
+Freeverb_reset(Freeverb *self)
+{
+    int i, j;
+    for(i=0; i<NUM_COMB; i++) {
+        self->comb_bufPos[i] = 0;
+        self->comb_filterState[i] = 0.0;
+        for(j=0; j<self->comb_nSamples[i]; j++) {
+            self->comb_buf[i][j] = 0.0;
+        }
+    }
+    for(i=0; i<NUM_ALLPASS; i++) {
+        self->allpass_bufPos[i] = 0;
+        for(j=0; j<self->allpass_nSamples[i]; j++) {
+            self->allpass_buf[i][j] = 0.0;
+        }
+    }
+	Py_RETURN_NONE;
+}
+
+static PyObject *
 Freeverb_setSize(Freeverb *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->size);
@@ -744,25 +762,22 @@ Freeverb_setSize(Freeverb *self, PyObject *arg)
         self->size_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Freeverb_setDamp(Freeverb *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->damp);
@@ -778,25 +793,22 @@ Freeverb_setDamp(Freeverb *self, PyObject *arg)
         self->damp_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Freeverb_setMix(Freeverb *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->mix);
@@ -812,9 +824,9 @@ Freeverb_setMix(Freeverb *self, PyObject *arg)
         self->mix_stream = (Stream *)streamtmp;
 		self->modebuffer[4] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -836,6 +848,7 @@ static PyMethodDef Freeverb_methods[] = {
     {"play", (PyCFunction)Freeverb_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
     {"out", (PyCFunction)Freeverb_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
     {"stop", (PyCFunction)Freeverb_stop, METH_NOARGS, "Stops computing."},
+    {"reset", (PyCFunction)Freeverb_reset, METH_NOARGS, "Reset the delay lines."},
 	{"setSize", (PyCFunction)Freeverb_setSize, METH_O, "Sets distortion size factor (0 -> 1)."},
     {"setDamp", (PyCFunction)Freeverb_setDamp, METH_O, "Sets lowpass filter damp factor."},
     {"setMix", (PyCFunction)Freeverb_setMix, METH_O, "Sets the mix factor."},
@@ -850,7 +863,7 @@ static PyNumberMethods Freeverb_as_number = {
     (binaryfunc)Freeverb_add,                      /*nb_add*/
     (binaryfunc)Freeverb_sub,                 /*nb_subtract*/
     (binaryfunc)Freeverb_multiply,                 /*nb_multiply*/
-    (binaryfunc)Freeverb_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -864,16 +877,16 @@ static PyNumberMethods Freeverb_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)Freeverb_inplace_add,              /*inplace_add*/
     (binaryfunc)Freeverb_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)Freeverb_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)Freeverb_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -882,15 +895,14 @@ static PyNumberMethods Freeverb_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)Freeverb_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)Freeverb_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject FreeverbType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Freeverb_base",         /*tp_name*/
     sizeof(Freeverb),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -898,7 +910,7 @@ PyTypeObject FreeverbType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &Freeverb_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -928,5 +940,4 @@ PyTypeObject FreeverbType = {
     0,      /* tp_init */
     0,                         /* tp_alloc */
     Freeverb_new,                 /* tp_new */
-};
-
+};
\ No newline at end of file
diff --git a/src/objects/granulatormodule.c b/src/objects/granulatormodule.c
index 44eaf46..78db68b 100644
--- a/src/objects/granulatormodule.c
+++ b/src/objects/granulatormodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
@@ -56,23 +57,23 @@ static void
 Granulator_transform_iii(Granulator *self) {
     MYFLT val, x, x1, inc, index, fpart, amp, ppos;
     int i, j, ipart;
-    
+
     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 pit = PyFloat_AS_DOUBLE(self->pitch);
     MYFLT pos = PyFloat_AS_DOUBLE(self->pos);
     MYFLT dur = PyFloat_AS_DOUBLE(self->dur);
-    
+
     inc = pit * (1.0 / self->basedur) / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = 0.0;
         self->pointerPos += inc;
-        
+
         for (j=0; j<self->ngrains; j++) {
             ppos = self->pointerPos + self->gphase[j];
             if (ppos >= 1.0) {
@@ -85,13 +86,13 @@ Granulator_transform_iii(Granulator *self) {
             x = envlist[ipart];
             x1 = envlist[ipart+1];
             amp = x + (x1 - x) * fpart;
-            
+
             if (ppos < self->lastppos[j]) {
                 self->startPos[j] = pos;
                 self->gsize[j] = dur * self->sr;
             }
             self->lastppos[j] = ppos;
-            
+
             // compute sampling
             index = ppos * self->gsize[j] + self->startPos[j];
             if (index >= 0 && index < size) {
@@ -103,39 +104,39 @@ Granulator_transform_iii(Granulator *self) {
             }
             else
                 val = 0.0;
-            
+
             self->data[i] += (val * amp);
         }
-        
+
         if (self->pointerPos < 0)
             self->pointerPos += 1.0;
         else if (self->pointerPos >= 1)
             self->pointerPos -= 1.0;
-    }    
+    }
 }
 
 static void
 Granulator_transform_aii(Granulator *self) {
     MYFLT val, x, x1, inc, index, fpart, amp, ppos, frtosamps;
     int i, j, ipart;
-    
+
     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 *pit = Stream_getData((Stream *)self->pitch_stream);
     MYFLT pos = PyFloat_AS_DOUBLE(self->pos);
     MYFLT dur = PyFloat_AS_DOUBLE(self->dur);
-    
+
     frtosamps = (1.0 / self->basedur) / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = 0.0;
         inc = pit[i] * frtosamps;
         self->pointerPos += inc;
-        
+
         for (j=0; j<self->ngrains; j++) {
             ppos = self->pointerPos + self->gphase[j];
             if (ppos >= 1.0) {
@@ -148,13 +149,13 @@ Granulator_transform_aii(Granulator *self) {
             x = envlist[ipart];
             x1 = envlist[ipart+1];
             amp = x + (x1 - x) * fpart;
-            
+
             if (ppos < self->lastppos[j]) {
                 self->startPos[j] = pos;
                 self->gsize[j] = dur * self->sr;
             }
             self->lastppos[j] = ppos;
-            
+
             // compute sampling
             index = ppos * self->gsize[j] + self->startPos[j];
             if (index >= 0 && index < size) {
@@ -166,15 +167,15 @@ Granulator_transform_aii(Granulator *self) {
             }
             else
                 val = 0.0;
-            
+
             self->data[i] += (val * amp);
         }
-        
+
         if (self->pointerPos < 0)
             self->pointerPos += 1.0;
         else if (self->pointerPos >= 1)
             self->pointerPos -= 1.0;
-    }    
+    }
 }
 
 static void
@@ -193,9 +194,9 @@ Granulator_transform_iai(Granulator *self) {
     MYFLT dur = PyFloat_AS_DOUBLE(self->dur);
 
     inc = pit * (1.0 / self->basedur) / self->sr;
-    
+
     MYFLT gsize = dur * self->sr;
-    
+
     for (j=0; j<self->ngrains; j++) {
         self->gsize[j] = gsize;
     }
@@ -203,7 +204,7 @@ Granulator_transform_iai(Granulator *self) {
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = 0.0;
         self->pointerPos += inc;
-        
+
         for (j=0; j<self->ngrains; j++) {
             ppos = self->pointerPos + self->gphase[j];
             if (ppos >= 1.0) {
@@ -221,7 +222,7 @@ Granulator_transform_iai(Granulator *self) {
                 self->startPos[j] = pos[i];
             }
             self->lastppos[j] = ppos;
-            
+
             // compute sampling
             index = ppos * self->gsize[j] + self->startPos[j];
             if (index >= 0 && index < size) {
@@ -236,36 +237,36 @@ Granulator_transform_iai(Granulator *self) {
 
             self->data[i] += (val * amp);
         }
-        
+
         if (self->pointerPos < 0)
             self->pointerPos += 1.0;
         else if (self->pointerPos >= 1)
             self->pointerPos -= 1.0;
-    }    
+    }
 }
 
 static void
 Granulator_transform_aai(Granulator *self) {
     MYFLT val, x, x1, inc, index, fpart, amp, ppos, frtosamps;
     int i, j, ipart;
-    
+
     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 *pit = Stream_getData((Stream *)self->pitch_stream);
     MYFLT *pos = Stream_getData((Stream *)self->pos_stream);
     MYFLT dur = PyFloat_AS_DOUBLE(self->dur);
-    
+
     frtosamps = (1.0 / self->basedur) / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = 0.0;
         inc = pit[i] * frtosamps;
         self->pointerPos += inc;
-        
+
         for (j=0; j<self->ngrains; j++) {
             ppos = self->pointerPos + self->gphase[j];
             if (ppos >= 1.0) {
@@ -278,13 +279,13 @@ Granulator_transform_aai(Granulator *self) {
             x = envlist[ipart];
             x1 = envlist[ipart+1];
             amp = x + (x1 - x) * fpart;
-            
+
             if (ppos < self->lastppos[j]) {
                 self->startPos[j] = pos[i];
                 self->gsize[j] = dur * self->sr;
             }
             self->lastppos[j] = ppos;
-            
+
             // compute sampling
             index = ppos * self->gsize[j] + self->startPos[j];
             if (index >= 0 && index < size) {
@@ -296,38 +297,38 @@ Granulator_transform_aai(Granulator *self) {
             }
             else
                 val = 0.0;
-            
+
             self->data[i] += (val * amp);
         }
-        
+
         if (self->pointerPos < 0)
             self->pointerPos += 1.0;
         else if (self->pointerPos >= 1)
             self->pointerPos -= 1.0;
     }
-} 
+}
 
 static void
 Granulator_transform_iia(Granulator *self) {
     MYFLT val, x, x1, inc, index, fpart, amp, ppos;
     int i, j, ipart;
-    
+
     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 pit = PyFloat_AS_DOUBLE(self->pitch);
     MYFLT pos = PyFloat_AS_DOUBLE(self->pos);
     MYFLT *dur = Stream_getData((Stream *)self->dur_stream);
-    
+
     inc = pit * (1.0 / self->basedur) / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = 0.0;
         self->pointerPos += inc;
-        
+
         for (j=0; j<self->ngrains; j++) {
             ppos = self->pointerPos + self->gphase[j];
             if (ppos >= 1.0) {
@@ -340,13 +341,13 @@ Granulator_transform_iia(Granulator *self) {
             x = envlist[ipart];
             x1 = envlist[ipart+1];
             amp = x + (x1 - x) * fpart;
-            
+
             if (ppos < self->lastppos[j]) {
                 self->startPos[j] = pos;
                 self->gsize[j] = dur[i] * self->sr;
             }
             self->lastppos[j] = ppos;
-            
+
             // compute sampling
             index = ppos * self->gsize[j] + self->startPos[j];
             if (index >= 0 && index < size) {
@@ -358,39 +359,39 @@ Granulator_transform_iia(Granulator *self) {
             }
             else
                 val = 0.0;
-            
+
             self->data[i] += (val * amp);
         }
-        
+
         if (self->pointerPos < 0)
             self->pointerPos += 1.0;
         else if (self->pointerPos >= 1)
             self->pointerPos -= 1.0;
-    }     
+    }
 }
 
 static void
 Granulator_transform_aia(Granulator *self) {
     MYFLT val, x, x1, inc, index, fpart, amp, ppos, frtosamps;
     int i, j, ipart;
-    
+
     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 *pit = Stream_getData((Stream *)self->pitch_stream);
     MYFLT pos = PyFloat_AS_DOUBLE(self->pos);
     MYFLT *dur = Stream_getData((Stream *)self->dur_stream);
-    
+
     frtosamps = (1.0 / self->basedur) / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = 0.0;
         inc = pit[i] * frtosamps;
         self->pointerPos += inc;
-        
+
         for (j=0; j<self->ngrains; j++) {
             ppos = self->pointerPos + self->gphase[j];
             if (ppos >= 1.0) {
@@ -403,13 +404,13 @@ Granulator_transform_aia(Granulator *self) {
             x = envlist[ipart];
             x1 = envlist[ipart+1];
             amp = x + (x1 - x) * fpart;
-            
+
             if (ppos < self->lastppos[j]) {
                 self->startPos[j] = pos;
                 self->gsize[j] = dur[i] * self->sr;
             }
             self->lastppos[j] = ppos;
-            
+
             // compute sampling
             index = ppos * self->gsize[j] + self->startPos[j];
             if (index >= 0 && index < size) {
@@ -421,38 +422,38 @@ Granulator_transform_aia(Granulator *self) {
             }
             else
                 val = 0.0;
-            
+
             self->data[i] += (val * amp);
         }
-        
+
         if (self->pointerPos < 0)
             self->pointerPos += 1.0;
         else if (self->pointerPos >= 1)
             self->pointerPos -= 1.0;
-    } 
+    }
 }
 
 static void
 Granulator_transform_iaa(Granulator *self) {
     MYFLT val, x, x1, inc, index, fpart, amp, ppos;
     int i, j, ipart;
-    
+
     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 pit = PyFloat_AS_DOUBLE(self->pitch);
     MYFLT *pos = Stream_getData((Stream *)self->pos_stream);
     MYFLT *dur = Stream_getData((Stream *)self->dur_stream);
-    
+
     inc = pit * (1.0 / self->basedur) / self->sr;
 
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = 0.0;
         self->pointerPos += inc;
-        
+
         for (j=0; j<self->ngrains; j++) {
             ppos = self->pointerPos + self->gphase[j];
             if (ppos >= 1.0) {
@@ -465,13 +466,13 @@ Granulator_transform_iaa(Granulator *self) {
             x = envlist[ipart];
             x1 = envlist[ipart+1];
             amp = x + (x1 - x) * fpart;
-            
+
             if (ppos < self->lastppos[j]) {
                 self->startPos[j] = pos[i];
                 self->gsize[j] = dur[i] * self->sr;
             }
             self->lastppos[j] = ppos;
-            
+
             // compute sampling
             index = ppos * self->gsize[j] + self->startPos[j];
             if (index >= 0 && index < size) {
@@ -483,39 +484,39 @@ Granulator_transform_iaa(Granulator *self) {
             }
             else
                 val = 0.0;
-            
+
             self->data[i] += (val * amp);
         }
-        
+
         if (self->pointerPos < 0)
             self->pointerPos += 1.0;
         else if (self->pointerPos >= 1)
             self->pointerPos -= 1.0;
-    }    
+    }
 }
 
 static void
-Granulator_transform_aaa(Granulator *self) { 
+Granulator_transform_aaa(Granulator *self) {
     MYFLT val, x, x1, inc, index, fpart, amp, ppos, frtosamps;
     int i, j, ipart;
-    
+
     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 *pit = Stream_getData((Stream *)self->pitch_stream);
     MYFLT *pos = Stream_getData((Stream *)self->pos_stream);
     MYFLT *dur = Stream_getData((Stream *)self->dur_stream);
-    
+
     frtosamps = (1.0 / self->basedur) / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = 0.0;
         inc = pit[i] * frtosamps;
         self->pointerPos += inc;
-        
+
         for (j=0; j<self->ngrains; j++) {
             ppos = self->pointerPos + self->gphase[j];
             if (ppos >= 1.0) {
@@ -528,13 +529,13 @@ Granulator_transform_aaa(Granulator *self) {
             x = envlist[ipart];
             x1 = envlist[ipart+1];
             amp = x + (x1 - x) * fpart;
-            
+
             if (ppos < self->lastppos[j]) {
                 self->startPos[j] = pos[i];
                 self->gsize[j] = dur[i] * self->sr;
             }
             self->lastppos[j] = ppos;
-            
+
             // compute sampling
             index = ppos * self->gsize[j] + self->startPos[j];
             if (index >= 0 && index < size) {
@@ -546,15 +547,15 @@ Granulator_transform_aaa(Granulator *self) {
             }
             else
                 val = 0.0;
-            
+
             self->data[i] += (val * amp);
         }
-        
+
         if (self->pointerPos < 0)
             self->pointerPos += 1.0;
         else if (self->pointerPos >= 1)
             self->pointerPos -= 1.0;
-    } 
+    }
 }
 
 static void Granulator_postprocessing_ii(Granulator *self) { POST_PROCESSING_II };
@@ -575,66 +576,66 @@ Granulator_setProcMode(Granulator *self)
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Granulator_transform_iii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Granulator_transform_aii;
             break;
-        case 10:        
+        case 10:
             self->proc_func_ptr = Granulator_transform_iai;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Granulator_transform_aai;
             break;
-        case 100:        
+        case 100:
             self->proc_func_ptr = Granulator_transform_iia;
             break;
-        case 101:    
+        case 101:
             self->proc_func_ptr = Granulator_transform_aia;
             break;
-        case 110:        
+        case 110:
             self->proc_func_ptr = Granulator_transform_iaa;
             break;
-        case 111:    
+        case 111:
             self->proc_func_ptr = Granulator_transform_aaa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Granulator_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Granulator_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Granulator_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Granulator_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Granulator_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Granulator_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Granulator_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Granulator_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Granulator_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Granulator_compute_next_data_frame(Granulator *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -644,27 +645,27 @@ Granulator_traverse(Granulator *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->table);
     Py_VISIT(self->env);
-    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->pitch);
+    Py_VISIT(self->pitch_stream);
+    Py_VISIT(self->pos);
+    Py_VISIT(self->pos_stream);
+    Py_VISIT(self->dur);
+    Py_VISIT(self->dur_stream);
     return 0;
 }
 
-static int 
+static int
 Granulator_clear(Granulator *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->table);
     Py_CLEAR(self->env);
-    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->pitch);
+    Py_CLEAR(self->pitch_stream);
+    Py_CLEAR(self->pos);
+    Py_CLEAR(self->pos_stream);
+    Py_CLEAR(self->dur);
+    Py_CLEAR(self->dur_stream);
     return 0;
 }
 
@@ -672,12 +673,12 @@ static void
 Granulator_dealloc(Granulator* self)
 {
     pyo_DEALLOC
-    free(self->startPos);   
+    free(self->startPos);
     free(self->gphase);
     free(self->gsize);
     free(self->lastppos);
     Granulator_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -711,25 +712,19 @@ Granulator_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         Py_RETURN_NONE;
 
     if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
-        PySys_WriteStderr("TypeError: \"table\" argument of Granulator must be a PyoTableObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"table\" argument of Granulator must be a PyoTableObject.\n");
+        Py_RETURN_NONE;
     }
     Py_XDECREF(self->table);
     self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", "");
 
     if ( PyObject_HasAttrString((PyObject *)envtmp, "getTableStream") == 0 ) {
-        PySys_WriteStderr("TypeError: \"env\" argument of Granulator must be a PyoTableObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"env\" argument of Granulator must be a PyoTableObject.\n");
+        Py_RETURN_NONE;
     }
     Py_XDECREF(self->env);
     self->env = PyObject_CallMethod((PyObject *)envtmp, "getTableStream", "");
-    
+
     if (pitchtmp) {
         PyObject_CallMethod((PyObject *)self, "setPitch", "O", pitchtmp);
     }
@@ -741,7 +736,7 @@ Granulator_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (durtmp) {
         PyObject_CallMethod((PyObject *)self, "setDur", "O", durtmp);
     }
-    
+
     if (multmp) {
         PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
     }
@@ -749,7 +744,7 @@ Granulator_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (addtmp) {
         PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
     }
- 
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     self->startPos = (MYFLT *)realloc(self->startPos, self->ngrains * sizeof(MYFLT));
@@ -758,9 +753,9 @@ Granulator_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->lastppos = (MYFLT *)realloc(self->lastppos, self->ngrains * sizeof(MYFLT));
 
     Server_generateSeed((Server *)self->server, GRANULATOR_ID);
-    
+
     for (i=0; i<self->ngrains; i++) {
-        phase = ((MYFLT)i/self->ngrains) * (1.0 + ((rand()/((MYFLT)(RAND_MAX)+1)*2.0-1.0) * 0.01));
+        phase = ((MYFLT)i/self->ngrains) * (1.0 + ((RANDOM_UNIFORM * 2.0 - 1.0) * 0.01));
         if (phase < 0.0)
             phase = 0.0;
         else if (phase >= 1.0)
@@ -769,18 +764,18 @@ Granulator_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         self->startPos[i] = self->gsize[i] = 0.0;
         self->lastppos[i] = 1.0;
     }
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * Granulator_getServer(Granulator* self) { GET_SERVER };
 static PyObject * Granulator_getStream(Granulator* self) { GET_STREAM };
-static PyObject * Granulator_setMul(Granulator *self, PyObject *arg) { SET_MUL };	
-static PyObject * Granulator_setAdd(Granulator *self, PyObject *arg) { SET_ADD };	
-static PyObject * Granulator_setSub(Granulator *self, PyObject *arg) { SET_SUB };	
-static PyObject * Granulator_setDiv(Granulator *self, PyObject *arg) { SET_DIV };	
+static PyObject * Granulator_setMul(Granulator *self, PyObject *arg) { SET_MUL };
+static PyObject * Granulator_setAdd(Granulator *self, PyObject *arg) { SET_ADD };
+static PyObject * Granulator_setSub(Granulator *self, PyObject *arg) { SET_SUB };
+static PyObject * Granulator_setDiv(Granulator *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Granulator_play(Granulator *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Granulator_out(Granulator *self, PyObject *args, PyObject *kwds) { OUT };
@@ -799,14 +794,11 @@ static PyObject *
 Granulator_setPitch(Granulator *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->pitch);
@@ -822,25 +814,22 @@ Granulator_setPitch(Granulator *self, PyObject *arg)
         self->pitch_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Granulator_setPos(Granulator *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->pos);
@@ -856,25 +845,22 @@ Granulator_setPos(Granulator *self, PyObject *arg)
         self->pos_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Granulator_setDur(Granulator *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->dur);
@@ -890,9 +876,9 @@ Granulator_setDur(Granulator *self, PyObject *arg)
         self->dur_stream = (Stream *)streamtmp;
 		self->modebuffer[4] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -908,19 +894,16 @@ static PyObject *
 Granulator_setTable(Granulator *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    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 *
 Granulator_getEnv(Granulator* self)
@@ -933,33 +916,30 @@ static PyObject *
 Granulator_setEnv(Granulator *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    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 PyObject *
 Granulator_setBaseDur(Granulator *self, PyObject *arg)
-{	
+{
 	if (arg != NULL)
-        self->basedur = PyFloat_AS_DOUBLE(PyNumber_Float(arg));
-        
+        self->basedur = PyFloat_AsDouble(arg);
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Granulator_setGrains(Granulator *self, PyObject *arg)
-{	
+{
     int i;
     MYFLT phase;
 	if (PyLong_Check(arg) || PyInt_Check(arg)) {
@@ -968,9 +948,9 @@ Granulator_setGrains(Granulator *self, PyObject *arg)
         self->gsize = (MYFLT *)realloc(self->gsize, self->ngrains * sizeof(MYFLT));
         self->gphase = (MYFLT *)realloc(self->gphase, self->ngrains * sizeof(MYFLT));
         self->lastppos = (MYFLT *)realloc(self->lastppos, self->ngrains * sizeof(MYFLT));
-        
+
         for (i=0; i<self->ngrains; i++) {
-            phase = ((MYFLT)i/self->ngrains) * (1.0 + ((rand()/((MYFLT)(RAND_MAX)+1)*2.0-1.0) * 0.01));
+            phase = ((MYFLT)i/self->ngrains) * (1.0 + ((RANDOM_UNIFORM * 2.0 - 1.0) * 0.01));
             if (phase < 0.0)
                 phase = 0.0;
             else if (phase >= 1.0)
@@ -978,12 +958,12 @@ Granulator_setGrains(Granulator *self, PyObject *arg)
             self->gphase[i] = phase;
             self->startPos[i] = self->gsize[i] = 0.0;
             self->lastppos[i] = 1.0;
-        }  
-    }    
-    
+        }
+    }
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Granulator_members[] = {
     {"server", T_OBJECT_EX, offsetof(Granulator, server), 0, "Pyo server."},
@@ -1024,7 +1004,7 @@ static PyNumberMethods Granulator_as_number = {
     (binaryfunc)Granulator_add,                      /*nb_add*/
     (binaryfunc)Granulator_sub,                 /*nb_subtract*/
     (binaryfunc)Granulator_multiply,                 /*nb_multiply*/
-    (binaryfunc)Granulator_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -1038,16 +1018,16 @@ static PyNumberMethods Granulator_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)Granulator_inplace_add,              /*inplace_add*/
     (binaryfunc)Granulator_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)Granulator_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)Granulator_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -1056,15 +1036,14 @@ static PyNumberMethods Granulator_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)Granulator_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)Granulator_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject GranulatorType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_pitch*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Granulator_base",         /*tp_name*/
     sizeof(Granulator),         /*tp_basicpitch*/
     0,                         /*tp_itempitch*/
@@ -1072,7 +1051,7 @@ PyTypeObject GranulatorType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &Granulator_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -1115,12 +1094,18 @@ typedef struct {
     Stream *dur_stream;
     PyObject *xfade;
     Stream *xfade_stream;
+    MYFLT *trigsBuffer;
+    TriggerStream *trig_stream;
+    MYFLT *time_buffer;
     int xfadeshape;
     int startfromloop;
     int init;
-    int mode; /* 0 = no loop, 1 = forward, 2 = backward, 3 = back-and-forth */
+    int mode[2]; /* 0 = no loop, 1 = forward, 2 = backward, 3 = back-and-forth */
     int tmpmode;
+    int direction[2];
     double pointerPos[2];
+    double loopDuration;
+    int current;
     int active[2];
     long loopstart[2];
     long loopend[2];
@@ -1133,17 +1118,45 @@ typedef struct {
     MYFLT (*interp_func_ptr)(MYFLT *, int, MYFLT, int);
     int modebuffer[6];
     int autosmooth;
+    int appendfade;
+    int fadeinseconds;
     MYFLT lastpitch;
     // sample memories
     MYFLT y1;
     MYFLT y2;
     // variables
     MYFLT c1;
-    MYFLT c2;
-    
 } Looper;
 
 static void
+Looper_endloop(Looper *self) {
+    int which = self->current;
+    switch (self->mode[which]) {
+        case 0:
+            self->maxfadepoint[which] = self->pointerPos[which];
+            self->loopend[which] = self->maxfadepoint[which] + self->crossfadedur[which];
+            break;
+        case 1:
+            self->maxfadepoint[which] = self->pointerPos[which];
+            self->loopend[which] = self->maxfadepoint[which] + self->crossfadedur[which];
+            break;
+        case 2:
+            self->maxfadepoint[which] = self->pointerPos[which];
+            self->loopend[which] = self->maxfadepoint[which] - self->crossfadedur[which];
+            break;
+        case 3:
+            if (self->direction[which] == 0) {
+                self->maxfadepoint[which] = self->pointerPos[which];
+                self->loopend[which] = self->maxfadepoint[which] + self->crossfadedur[which];
+            } else {
+                self->maxfadepoint[which] = self->pointerPos[which];
+                self->loopend[which] = self->maxfadepoint[which] - self->crossfadedur[which];
+            }
+            break;
+    }
+}
+
+static void
 Looper_reset(Looper *self, int x, int which, int init) {
     MYFLT start, dur, xfade;
 
@@ -1162,13 +1175,17 @@ Looper_reset(Looper *self, int x, int which, int init) {
         xfade = PyFloat_AS_DOUBLE(self->xfade);
     else
         xfade = Stream_getData((Stream *)self->xfade_stream)[x];
-    
+
     if (start < 0.0)
         start = 0.0;
     else if (start > (size/tableSr))
         start = (MYFLT)(size/tableSr);
     if (dur < 0.001)
         dur = 0.001;
+        
+    if (self->fadeinseconds == 1)
+        xfade = xfade / dur * 100.0;
+
     if (xfade < 0.0)
         xfade = 0.0;
     else if (xfade > 50.0)
@@ -1182,19 +1199,25 @@ Looper_reset(Looper *self, int x, int which, int init) {
         self->fader = LOOPER_SIGMOID_FADE;
     else
         self->fader = LOOPER_LINEAR_FADE;
-    
-    if (self->tmpmode != self->mode) {
-        self->mode = self->tmpmode;
-        self->active[0] = self->active[1] = 0;
-        which = 0;
-    }
-    
-    switch (self->mode) {
+
+    self->current = which;
+
+    if (self->tmpmode != self->mode[which])
+        self->mode[which] = self->tmpmode;
+
+    if (init == 0)
+        self->trigsBuffer[x] = 1.0;
+
+    switch (self->mode[which]) {
         case 0:
             self->loopstart[which] = 0;
             self->loopend[which] = (long)size;
-                self->crossfadedur[which] = 5;
+            self->crossfadedur[which] = (long)((self->loopend[which] - self->loopstart[which]) * xfade * 0.01);
+            if (self->crossfadedur[which] < 1)
+                self->crossfadedur[which] = 1;
             self->crossfadescaling[which] = 1.0 / self->crossfadedur[which] * 512.0;
+            if (self->appendfade == 1)
+                self->loopend[which] += self->crossfadedur[which];
             if (init == 1 && self->startfromloop == 0) {
                 self->minfadepoint[which] = self->crossfadedur[which];
                 self->maxfadepoint[which] = self->loopend[which] - self->crossfadedur[which];
@@ -1203,16 +1226,19 @@ Looper_reset(Looper *self, int x, int which, int init) {
             else {
                 self->minfadepoint[which] = self->loopstart[which] + self->crossfadedur[which];
                 self->maxfadepoint[which] = self->loopend[which] - self->crossfadedur[which];
-                self->pointerPos[which] = self->loopstart[which];        
-            }            
+                self->pointerPos[which] = self->loopstart[which];
+            }
+            self->loopDuration = self->maxfadepoint[which] - self->loopstart[which];
             break;
         case 1:
             self->loopstart[which] = (long)(start * tableSr);
             self->loopend[which] = (long)((start + dur) * tableSr);
             self->crossfadedur[which] = (long)((self->loopend[which] - self->loopstart[which]) * xfade * 0.01);
-            if (self->crossfadedur[which] < 5)
-                self->crossfadedur[which] = 5;
+            if (self->crossfadedur[which] < 1)
+                self->crossfadedur[which] = 1;
             self->crossfadescaling[which] = 1.0 / self->crossfadedur[which] * 512.0;
+            if (self->appendfade == 1)
+                self->loopend[which] += self->crossfadedur[which];
             if (init == 1 && self->startfromloop == 0) {
                 self->minfadepoint[which] = self->crossfadedur[which];
                 self->maxfadepoint[which] = self->loopend[which] - self->crossfadedur[which];
@@ -1221,16 +1247,19 @@ Looper_reset(Looper *self, int x, int which, int init) {
             else {
                 self->minfadepoint[which] = self->loopstart[which] + self->crossfadedur[which];
                 self->maxfadepoint[which] = self->loopend[which] - self->crossfadedur[which];
-                self->pointerPos[which] = self->loopstart[which];        
-            }            
+                self->pointerPos[which] = self->loopstart[which];
+            }
+            self->loopDuration = self->maxfadepoint[which] - self->loopstart[which];
             break;
         case 2:
             self->loopstart[which] = (long)((start + dur) * tableSr);
-            self->loopend[which] = (long)((start) * tableSr);
+            self->loopend[which] = (long)(start * tableSr);
             self->crossfadedur[which] = (long)((self->loopstart[which] - self->loopend[which]) * xfade * 0.01);
-            if (self->crossfadedur[which] < 5)
-                self->crossfadedur[which] = 5;
+            if (self->crossfadedur[which] < 1)
+                self->crossfadedur[which] = 1;
             self->crossfadescaling[which] = 1.0 / self->crossfadedur[which] * 512.0;
+            if (self->appendfade == 1)
+                self->loopend[which] -= self->crossfadedur[which];
             if (init == 1 && self->startfromloop == 0) {
                 self->minfadepoint[which] = size - self->crossfadedur[which];
                 self->maxfadepoint[which] = self->loopend[which] + self->crossfadedur[which];
@@ -1239,17 +1268,36 @@ Looper_reset(Looper *self, int x, int which, int init) {
             else {
                 self->minfadepoint[which] = self->loopstart[which] - self->crossfadedur[which];
                 self->maxfadepoint[which] = self->loopend[which] + self->crossfadedur[which];
-                self->pointerPos[which] = self->loopstart[which];        
-            }            
+                self->pointerPos[which] = self->loopstart[which];
+            }
+            self->loopDuration = self->loopstart[which] - self->maxfadepoint[which];
             break;
         case 3:
-            if (which == 0) {
+            if (self->direction[1-which] == 0 && init == 0) {
+                self->direction[which] = 1;
+                self->loopstart[which] = (long)((start + dur) * tableSr);
+                self->loopend[which] = (long)(start * tableSr);
+                self->crossfadedur[which] = (long)((self->loopstart[which] - self->loopend[which]) * xfade * 0.01);
+                if (self->crossfadedur[which] < 1)
+                    self->crossfadedur[which] = 1;
+                self->crossfadescaling[which] = 1.0 / self->crossfadedur[which] * 512.0;
+                if (self->appendfade == 1)
+                    self->loopend[which] -= self->crossfadedur[which];
+                self->minfadepoint[which] = self->loopstart[which] - self->crossfadedur[which];
+                self->maxfadepoint[which] = self->loopend[which] + self->crossfadedur[which];
+                self->pointerPos[which] = self->loopstart[which];
+                self->loopDuration = self->loopstart[which] - self->maxfadepoint[which];
+            }
+            else {
+                self->direction[which] = 0;
                 self->loopstart[which] = (long)(start * tableSr);
                 self->loopend[which] = (long)((start + dur) * tableSr);
                 self->crossfadedur[which] = (long)((self->loopend[which] - self->loopstart[which]) * xfade * 0.01);
-                if (self->crossfadedur[which] < 5)
-                    self->crossfadedur[which] = 5;
+                if (self->crossfadedur[which] < 1)
+                    self->crossfadedur[which] = 1;
                 self->crossfadescaling[which] = 1.0 / self->crossfadedur[which] * 512.0;
+                if (self->appendfade == 1)
+                    self->loopend[which] += self->crossfadedur[which];
                 if (init == 1 && self->startfromloop == 0) {
                     self->minfadepoint[which] = self->crossfadedur[which];
                     self->maxfadepoint[which] = self->loopend[which] - self->crossfadedur[which];
@@ -1258,32 +1306,27 @@ Looper_reset(Looper *self, int x, int which, int init) {
                 else {
                     self->minfadepoint[which] = self->loopstart[which] + self->crossfadedur[which];
                     self->maxfadepoint[which] = self->loopend[which] - self->crossfadedur[which];
-                    self->pointerPos[which] = self->loopstart[which];        
+                    self->pointerPos[which] = self->loopstart[which];
                 }
-            }
-            else {
-                self->loopstart[which] = (long)((start + dur) * tableSr);
-                self->loopend[which] = (long)(start * tableSr);
-                self->crossfadedur[which] = (long)((self->loopstart[which] - self->loopend[which]) * xfade * 0.01);
-                if (self->crossfadedur[which] < 5)
-                    self->crossfadedur[which] = 5;
-                self->crossfadescaling[which] = 1.0 / self->crossfadedur[which] * 512.0;
-                self->minfadepoint[which] = self->loopstart[which] - self->crossfadedur[which];
-                self->maxfadepoint[which] = self->loopend[which] + self->crossfadedur[which];
-                self->pointerPos[which] = self->loopstart[which];
+                self->loopDuration = self->maxfadepoint[which] - self->loopstart[which];
             }
             break;
     }
-
     self->active[which] = 1;
 }
 
+static MYFLT
+Looper_get_amp(Looper *self, MYFLT pos) {
+    int ipart = (int)pos;
+    return self->fader[ipart] + (self->fader[ipart+1] - self->fader[ipart]) * (pos - ipart);
+}
+
 static void
 Looper_transform_i(Looper *self) {
-    MYFLT fpart, amp, fr, b;
+    MYFLT fpart, amp, fr;
     double pit;
-    int i, j, ipart;
-    
+    int i, j, k, ipart;
+
     MYFLT *tablelist = TableStream_getData(self->table);
     int size = TableStream_getSize(self->table);
     double tableSr = TableStream_getSamplingRate(self->table);
@@ -1291,68 +1334,65 @@ Looper_transform_i(Looper *self) {
     MYFLT pitval = PyFloat_AS_DOUBLE(self->pitch);
     if (pitval < 0.0)
         pitval = 0.0;
-    
+
     pit = pitval * tableSr / self->sr;
-    
+
+    for (i=0; i<self->bufsize; i++) {
+        self->trigsBuffer[i] = 0.0;
+    }
+
     if (self->active[0] == 0 && self->active[1] == 0) {
         Looper_reset(self, 0, 0, 1);
     }
-    
-    switch (self->mode) {
-        case 0:            
-            for (i=0; i<self->bufsize; i++) {
-                self->data[i] = 0.0;
-                if (self->active[0] == 1) {
-                    if (self->pointerPos[0] > size)
-                        self->data[i] += 0.0;
-                    else {
-                        if (self->pointerPos[0] < self->minfadepoint[0]) {
-                            fpart = (self->pointerPos[0] - self->loopstart[0]) * self->crossfadescaling[0];
-                            ipart = (int)fpart;
-                            fpart = fpart - ipart;
-                            amp = self->fader[ipart] + (self->fader[ipart+1] - self->fader[ipart]) * fpart;
+
+    for (i=0; i<self->bufsize; i++) {
+        self->data[i] = 0.0;
+        for (j=0; j<2; j++) {
+            if (self->active[j] == 1) {
+                switch (self->mode[j]) {
+                    case 0:
+                        if (self->pointerPos[j] >= 0 && self->pointerPos[j] < size) {
+                            if (self->pointerPos[j] < self->minfadepoint[j]) {
+                                fpart = (self->pointerPos[j] - self->loopstart[j]) * self->crossfadescaling[j];
+                                amp = Looper_get_amp(self, fpart);
+                            }
+                            else if (self->pointerPos[j] > self->maxfadepoint[j]) {
+                                fpart = (self->loopend[j] - self->pointerPos[j]) * self->crossfadescaling[j];
+                                amp = Looper_get_amp(self, fpart);
+                            }
+                            else
+                                amp = 1.0;
+                            ipart = (int)self->pointerPos[j];
+                            fpart = self->pointerPos[j] - ipart;
+                            self->data[i] += (*self->interp_func_ptr)(tablelist, ipart, fpart, size) * amp;
                         }
-                        else if (self->pointerPos[0] > self->maxfadepoint[0]) {
-                            fpart = (self->loopend[0] - self->pointerPos[0]) * self->crossfadescaling[0];
-                            ipart = (int)fpart;
-                            fpart = fpart - ipart;
-                            amp = self->fader[ipart] + (self->fader[ipart+1] - self->fader[ipart]) * fpart;
+                        self->pointerPos[j] += pit;
+                        if (self->pointerPos[j] < 0.0) {
+                            self->pointerPos[j] = self->time_buffer[i] = 0.0;
+                        }
+                        else if (self->pointerPos[j] <= self->maxfadepoint[j]) {
+                            self->time_buffer[i] = (self->pointerPos[j] - self->loopstart[j]) / self->loopDuration;
+                        }
+                        else if (self->pointerPos[j] >= self->loopend[j]) {
+                            self->active[j] = 0;
+                            for (k=0; k < self->bufsize; k++) {
+                                self->time_buffer[k] = 0.0;
+                            }
+                            PyObject_CallMethod((PyObject *)self, "stop", NULL);
                         }
-                        else
-                            amp = 1.0;
-                        ipart = (int)self->pointerPos[0];
-                        fpart = self->pointerPos[0] - ipart;
-                        self->data[i] += (*self->interp_func_ptr)(tablelist, ipart, fpart, size) * amp;
-                    }
-                    self->pointerPos[0] += pit;
-                    if (self->pointerPos[0] < 0)
-                        self->pointerPos[0] = 0.0;
-                    else if (self->pointerPos[0] >= self->loopend[0]) {
-                        self->active[0] = 0;
-                        PyObject_CallMethod((PyObject *)self, "stop", NULL);
-                    }
-                }
-            }
-            break;
-        case 1:
-            for (i=0; i<self->bufsize; i++) {
-                self->data[i] = 0.0;
-                for (j=0; j<2; j++) {
-                    if (self->active[j] == 1) {
-                        if (self->pointerPos[j] > size)
-                            self->data[i] += 0.0;
                         else {
+                            self->time_buffer[i] = 1.0;
+                        }
+                        break;
+                    case 1:
+                        if (self->pointerPos[j] >= 0 && self->pointerPos[j] < size) {
                             if (self->pointerPos[j] < self->minfadepoint[j]) {
                                 fpart = (self->pointerPos[j] - self->loopstart[j]) * self->crossfadescaling[j];
-                                ipart = (int)fpart;
-                                fpart = fpart - ipart;
-                                amp = self->fader[ipart] + (self->fader[ipart+1] - self->fader[ipart]) * fpart;
+                                amp = Looper_get_amp(self, fpart);
                             }
                             else if (self->pointerPos[j] > self->maxfadepoint[j]) {
                                 fpart = (self->loopend[j] - self->pointerPos[j]) * self->crossfadescaling[j];
-                                ipart = (int)fpart;
-                                fpart = fpart - ipart;
-                                amp = self->fader[ipart] + (self->fader[ipart+1] - self->fader[ipart]) * fpart;
+                                amp = Looper_get_amp(self, fpart);
                             }
                             else
                                 amp = 1.0;
@@ -1361,35 +1401,26 @@ Looper_transform_i(Looper *self) {
                             self->data[i] += (*self->interp_func_ptr)(tablelist, ipart, fpart, size) * amp;
                         }
                         self->pointerPos[j] += pit;
-                        if (self->pointerPos[j] < 0)
-                            self->pointerPos[j] = 0.0;
+                        if (self->pointerPos[j] < 0.0) {
+                            self->pointerPos[j] = self->time_buffer[i] = 0.0;
+                        }
+                        else if (self->pointerPos[j] <= self->maxfadepoint[j]) {
+                            self->time_buffer[i] = (self->pointerPos[j] - self->loopstart[j]) / self->loopDuration;
+                        }
                         else if (self->pointerPos[j] > self->maxfadepoint[j] && self->active[1-j] == 0)
-                            Looper_reset(self, i, 1-j, 0);                    
-                        else if (self->pointerPos[j] >= self->loopend[j])
+                            Looper_reset(self, i, 1-j, 0);
+                        if (self->pointerPos[j] >= self->loopend[j])
                             self->active[j] = 0;
-                    }
-                }
-            }
-            break;
-        case 2:
-            for (i=0; i<self->bufsize; i++) {
-                self->data[i] = 0.0;
-                for (j=0; j<2; j++) {
-                    if (self->active[j] == 1) {
-                        if (self->pointerPos[j] < 0.0)
-                            self->data[i] += 0.0;
-                        else {
+                        break;
+                    case 2:
+                        if (self->pointerPos[j] >= 0 && self->pointerPos[j] < size) {
                             if (self->pointerPos[j] > self->minfadepoint[j]) {
                                 fpart = (self->loopstart[j] - self->pointerPos[j]) * self->crossfadescaling[j];
-                                ipart = (int)fpart;
-                                fpart = fpart - ipart;
-                                amp = self->fader[ipart] + (self->fader[ipart+1] - self->fader[ipart]) * fpart;
+                                amp = Looper_get_amp(self, fpart);
                             }
                             else if (self->pointerPos[j] < self->maxfadepoint[j]) {
                                 fpart = (self->pointerPos[j] - self->loopend[j]) * self->crossfadescaling[j];
-                                ipart = (int)fpart;
-                                fpart = fpart - ipart;
-                                amp = self->fader[ipart] + (self->fader[ipart+1] - self->fader[ipart]) * fpart;
+                                amp = Looper_get_amp(self, fpart);
                             }
                             else
                                 amp = 1.0;
@@ -1398,95 +1429,94 @@ Looper_transform_i(Looper *self) {
                             self->data[i] += (*self->interp_func_ptr)(tablelist, ipart, fpart, size) * amp;
                         }
                         self->pointerPos[j] -= pit;
-                        if (self->pointerPos[j] >= size)
+                        if (self->pointerPos[j] >= size) {
                             self->pointerPos[j] = size-1;
+                            self->time_buffer[i] = 0.0;
+                        }
+                        else if (self->pointerPos[j] >= self->maxfadepoint[j]) {
+                            self->time_buffer[i] = (self->loopstart[j] - self->pointerPos[j]) / self->loopDuration;
+                        }
                         else if (self->pointerPos[j] < self->maxfadepoint[j] && self->active[1-j] == 0)
-                            Looper_reset(self, i, 1-j, 0);                    
-                        else if (self->pointerPos[j] <= self->loopend[j])
+                            Looper_reset(self, i, 1-j, 0);
+                        if (self->pointerPos[j] <= self->loopend[j])
                             self->active[j] = 0;
-                    }
-                }
-            }
-            break;
-        case 3:
-            for (i=0; i<self->bufsize; i++) {
-                self->data[i] = 0.0;
-                if (self->active[0] == 1) {
-                    if (self->pointerPos[0] > size)
-                        self->data[i] += 0.0;
-                    else {
-                        if (self->pointerPos[0] < self->minfadepoint[0]) {
-                            fpart = (self->pointerPos[0] - self->loopstart[0]) * self->crossfadescaling[0];
-                            ipart = (int)fpart;
-                            fpart = fpart - ipart;
-                            amp = self->fader[ipart] + (self->fader[ipart+1] - self->fader[ipart]) * fpart;
-                        }
-                        else if (self->pointerPos[0] > self->maxfadepoint[0]) {
-                            fpart = (self->loopend[0] - self->pointerPos[0]) * self->crossfadescaling[0];
-                            ipart = (int)fpart;
-                            fpart = fpart - ipart;
-                            amp = self->fader[ipart] + (self->fader[ipart+1] - self->fader[ipart]) * fpart;
-                        }
-                        else
-                            amp = 1.0;
-                        ipart = (int)self->pointerPos[0];
-                        fpart = self->pointerPos[0] - ipart;
-                        self->data[i] += (*self->interp_func_ptr)(tablelist, ipart, fpart, size) * amp;
-                    }
-                    self->pointerPos[0] += pit;
-                    if (self->pointerPos[0] < 0)
-                        self->pointerPos[0] = 0.0;
-                    else if (self->pointerPos[0] > self->maxfadepoint[0] && self->active[1] == 0)
-                        Looper_reset(self, i, 1, 0);                    
-                    else if (self->pointerPos[0] >= self->loopend[0])
-                        self->active[0] = 0;
-                } 
-                if (self->active[1] == 1) {
-                    if (self->pointerPos[1] < 0.0)
-                        self->data[i] += 0.0;
-                    else {
-                        if (self->pointerPos[1] > self->minfadepoint[1]) {
-                            fpart = (self->loopstart[1] - self->pointerPos[1]) * self->crossfadescaling[1];
-                            ipart = (int)fpart;
-                            fpart = fpart - ipart;
-                            amp = self->fader[ipart] + (self->fader[ipart+1] - self->fader[ipart]) * fpart;
+                        break;
+                    case 3:
+                        if (self->direction[j] == 0) {
+                            if (self->pointerPos[j] >= 0 && self->pointerPos[j] < size) {
+                                if (self->pointerPos[j] < self->minfadepoint[j]) {
+                                    fpart = (self->pointerPos[j] - self->loopstart[j]) * self->crossfadescaling[j];
+                                    amp = Looper_get_amp(self, fpart);
+                                }
+                                else if (self->pointerPos[j] > self->maxfadepoint[j]) {
+                                    fpart = (self->loopend[j] - self->pointerPos[j]) * self->crossfadescaling[j];
+                                    amp = Looper_get_amp(self, fpart);
+                                }
+                                else
+                                    amp = 1.0;
+                                ipart = (int)self->pointerPos[j];
+                                fpart = self->pointerPos[j] - ipart;
+                                self->data[i] += (*self->interp_func_ptr)(tablelist, ipart, fpart, size) * amp;
+                            }
+                            self->pointerPos[j] += pit;
+                            if (self->pointerPos[j] < 0.0) {
+                                self->pointerPos[j] = self->time_buffer[i] = 0.0;
+                            }
+                            else if (self->pointerPos[j] <= self->maxfadepoint[j]) {
+                                self->time_buffer[i] = (self->pointerPos[j] - self->loopstart[j]) / self->loopDuration;
+                            }
+                            else if (self->pointerPos[j] > self->maxfadepoint[j] && self->active[1-j] == 0)
+                                Looper_reset(self, i, 1-j, 0);
+                            if (self->pointerPos[j] >= self->loopend[j])
+                                self->active[j] = 0;
                         }
-                        else if (self->pointerPos[1] < self->maxfadepoint[1]) {
-                            fpart = (self->pointerPos[1] - self->loopend[1]) * self->crossfadescaling[1];
-                            ipart = (int)fpart;
-                            fpart = fpart - ipart;
-                            amp = self->fader[ipart] + (self->fader[ipart+1] - self->fader[ipart]) * fpart;
+                        else {
+                            if (self->pointerPos[j] >= 0 && self->pointerPos[j] < size) {
+                                if (self->pointerPos[j] > self->minfadepoint[j]) {
+                                    fpart = (self->loopstart[j] - self->pointerPos[j]) * self->crossfadescaling[j];
+                                    amp = Looper_get_amp(self, fpart);
+                                }
+                                else if (self->pointerPos[j] < self->maxfadepoint[j]) {
+                                    fpart = (self->pointerPos[j] - self->loopend[j]) * self->crossfadescaling[j];
+                                    amp = Looper_get_amp(self, fpart);
+                                }
+                                else
+                                    amp = 1.0;
+                                ipart = (int)self->pointerPos[j];
+                                fpart = self->pointerPos[j] - ipart;
+                                self->data[i] += (*self->interp_func_ptr)(tablelist, ipart, fpart, size) * amp;
+                            }
+                            self->pointerPos[j] -= pit;
+                            if (self->pointerPos[j] >= size) {
+                                self->pointerPos[j] = size-1;
+                                self->time_buffer[i] = 0.0;
+                            }
+                            else if (self->pointerPos[j] >= self->maxfadepoint[j]) {
+                                self->time_buffer[i] = (self->loopstart[j] - self->pointerPos[j]) / self->loopDuration;
+                            }
+                            else if (self->pointerPos[j] < self->maxfadepoint[j] && self->active[1-j] == 0)
+                                Looper_reset(self, i, 1-j, 0);
+                            if (self->pointerPos[j] <= self->loopend[j])
+                                self->active[j] = 0;
                         }
-                        else
-                            amp = 1.0;
-                        ipart = (int)self->pointerPos[1];
-                        fpart = self->pointerPos[1] - ipart;
-                        self->data[i] += (*self->interp_func_ptr)(tablelist, ipart, fpart, size) * amp;
-                    }
-                    self->pointerPos[1] -= pit;
-                    if (self->pointerPos[1] >= size)
-                        self->pointerPos[1] = size-1;
-                    else if (self->pointerPos[1] < self->maxfadepoint[1] && self->active[0] == 0)
-                        Looper_reset(self, i, 0, 0);                    
-                    else if (self->pointerPos[1] <= self->loopend[1])
-                        self->active[1] = 0;
-                }
+                        break;
+                } // end of switch
             }
-            break;
+        }
     }
 
     /* Automatic smoothering of low transposition */
-    if (self->autosmooth == 1 && pitval < 1.0 && pit > 0.0) {
+    if (self->autosmooth == 1 && pitval < 1.0) {
         if (self->lastpitch != pitval) {
             self->lastpitch = pitval;
-            fr = pitval * tableSr * 0.45;
-            b = 2.0 - MYCOS(TWOPI * fr / self->sr);
-            self->c2 = (b - MYSQRT(b * b - 1.0));
-            self->c1 = 1.0 - self->c2;
+            if (pitval < 0.001)
+                pitval = 0.001;
+            fr = pitval * self->sr * 0.45;
+            self->c1 = MYEXP(-TWOPI * fr / self->sr);
         }
         for (i=0; i<self->bufsize; i++) {
-            self->y1 = self->c1 * self->data[i] + self->c2 * self->y1;
-            self->y2 = self->c1 * self->y1 + self->c2 * self->y2;
+            self->y1 = self->data[i] + (self->y1 - self->data[i]) * self->c1;
+            self->y2 = self->y1 + (self->y2 - self->y1) * self->c1;
             self->data[i] = self->y2;
         }
     }
@@ -1494,84 +1524,75 @@ Looper_transform_i(Looper *self) {
 
 static void
 Looper_transform_a(Looper *self) {
-    MYFLT fpart, amp, fr, b;
-    double pit;
-    int i, j, ipart;
-    
+    MYFLT fpart, amp, fr, pitval;
+    double pit, srFactor;
+    int i, j, k, ipart;
+
     MYFLT *tablelist = TableStream_getData(self->table);
     int size = TableStream_getSize(self->table);
     double tableSr = TableStream_getSamplingRate(self->table);
-    double ratio = tableSr / self->sr;
-    
+
     MYFLT *pitch = Stream_getData((Stream *)self->pitch_stream);
-    
+
+    srFactor = tableSr / self->sr;
+
     if (self->active[0] == 0 && self->active[1] == 0) {
         Looper_reset(self, 0, 0, 1);
     }
-    
-    switch (self->mode) {
-        case 0:            
-            for (i=0; i<self->bufsize; i++) {
-                self->data[i] = 0.0;
-                pit = pitch[i];
-                if (pit < 0.0)
-                    pit = 0.0;    
-                pit = pit * ratio;
-                if (self->active[0] == 1) {
-                    if (self->pointerPos[0] > size)
-                        self->data[i] += 0.0;
-                    else {
-                        if (self->pointerPos[0] < self->minfadepoint[0]) {
-                            fpart = (self->pointerPos[0] - self->loopstart[0]) * self->crossfadescaling[0];
-                            ipart = (int)fpart;
-                            fpart = fpart - ipart;
-                            amp = self->fader[ipart] + (self->fader[ipart+1] - self->fader[ipart]) * fpart;
+
+    for (i=0; i<self->bufsize; i++) {
+        self->trigsBuffer[i] = 0.0;
+    }
+
+    for (i=0; i<self->bufsize; i++) {
+        self->data[i] = 0.0;
+        pitval = pitch[i];
+        if (pitval < 0.0)
+            pitval = 0.0;
+        pit = pitval * srFactor;
+        for (j=0; j<2; j++) {
+            if (self->active[j] == 1) {
+                switch (self->mode[j]) {
+                    case 0:
+                        if (self->pointerPos[j] >= 0 && self->pointerPos[j] < size) {
+                            if (self->pointerPos[j] < self->minfadepoint[j]) {
+                                fpart = (self->pointerPos[j] - self->loopstart[j]) * self->crossfadescaling[j];
+                                amp = Looper_get_amp(self, fpart);
+                            }
+                            else if (self->pointerPos[j] > self->maxfadepoint[j]) {
+                                fpart = (self->loopend[j] - self->pointerPos[j]) * self->crossfadescaling[j];
+                                amp = Looper_get_amp(self, fpart);
+                            }
+                            else
+                                amp = 1.0;
+                            ipart = (int)self->pointerPos[j];
+                            fpart = self->pointerPos[j] - ipart;
+                            self->data[i] += (*self->interp_func_ptr)(tablelist, ipart, fpart, size) * amp;
                         }
-                        else if (self->pointerPos[0] > self->maxfadepoint[0]) {
-                            fpart = (self->loopend[0] - self->pointerPos[0]) * self->crossfadescaling[0];
-                            ipart = (int)fpart;
-                            fpart = fpart - ipart;
-                            amp = self->fader[ipart] + (self->fader[ipart+1] - self->fader[ipart]) * fpart;
+                        self->pointerPos[j] += pit;
+                        if (self->pointerPos[j] < 0.0) {
+                            self->pointerPos[j] = self->time_buffer[i] = 0.0;
                         }
-                        else
-                            amp = 1.0;
-                        ipart = (int)self->pointerPos[0];
-                        fpart = self->pointerPos[0] - ipart;
-                        self->data[i] += (*self->interp_func_ptr)(tablelist, ipart, fpart, size) * amp;
-                    }
-                    self->pointerPos[0] += pit;
-                    if (self->pointerPos[0] < 0)
-                        self->pointerPos[0] = 0.0;
-                    else if (self->pointerPos[0] >= self->loopend[0]) {
-                        self->active[0] = 0;
-                        PyObject_CallMethod((PyObject *)self, "stop", NULL);
-                    }
-                }
-            }
-            break;
-        case 1:
-            for (i=0; i<self->bufsize; i++) {
-                self->data[i] = 0.0;
-                pit = pitch[i];
-                if (pit < 0.0)
-                    pit = 0.0;    
-                pit = pit * ratio;
-                for (j=0; j<2; j++) {
-                    if (self->active[j] == 1) {
-                        if (self->pointerPos[j] > size)
-                            self->data[i] += 0.0;
-                        else {
+                        else if (self->pointerPos[j] <= self->maxfadepoint[j]) {
+                            self->time_buffer[i] = (self->pointerPos[j] - self->loopstart[j]) / self->loopDuration;
+                        }
+                        else if (self->pointerPos[j] >= self->loopend[j]) {
+                            self->active[j] = 0;
+                            for (k=0; k < self->bufsize; k++) {
+                                self->time_buffer[k] = 0.0;
+                            }
+                            PyObject_CallMethod((PyObject *)self, "stop", NULL);
+                        }
+                        break;
+                    case 1:
+                        if (self->pointerPos[j] >= 0 && self->pointerPos[j] < size) {
                             if (self->pointerPos[j] < self->minfadepoint[j]) {
                                 fpart = (self->pointerPos[j] - self->loopstart[j]) * self->crossfadescaling[j];
-                                ipart = (int)fpart;
-                                fpart = fpart - ipart;
-                                amp = self->fader[ipart] + (self->fader[ipart+1] - self->fader[ipart]) * fpart;
+                                amp = Looper_get_amp(self, fpart);
                             }
                             else if (self->pointerPos[j] > self->maxfadepoint[j]) {
                                 fpart = (self->loopend[j] - self->pointerPos[j]) * self->crossfadescaling[j];
-                                ipart = (int)fpart;
-                                fpart = fpart - ipart;
-                                amp = self->fader[ipart] + (self->fader[ipart+1] - self->fader[ipart]) * fpart;
+                                amp = Looper_get_amp(self, fpart);
                             }
                             else
                                 amp = 1.0;
@@ -1580,39 +1601,26 @@ Looper_transform_a(Looper *self) {
                             self->data[i] += (*self->interp_func_ptr)(tablelist, ipart, fpart, size) * amp;
                         }
                         self->pointerPos[j] += pit;
-                        if (self->pointerPos[j] < 0)
-                            self->pointerPos[j] = 0.0;
+                        if (self->pointerPos[j] < 0.0) {
+                            self->pointerPos[j] = self->time_buffer[i] = 0.0;
+                        }
+                        else if (self->pointerPos[j] <= self->maxfadepoint[j]) {
+                            self->time_buffer[i] = (self->pointerPos[j] - self->loopstart[j]) / self->loopDuration;
+                        }
                         else if (self->pointerPos[j] > self->maxfadepoint[j] && self->active[1-j] == 0)
-                            Looper_reset(self, i, 1-j, 0);                    
-                        else if (self->pointerPos[j] >= self->loopend[j])
+                            Looper_reset(self, i, 1-j, 0);
+                        if (self->pointerPos[j] >= self->loopend[j])
                             self->active[j] = 0;
-                    }
-                }
-            }
-            break;
-        case 2:
-            for (i=0; i<self->bufsize; i++) {
-                self->data[i] = 0.0;
-                pit = pitch[i];
-                if (pit < 0.0)
-                    pit = 0.0;    
-                pit = pit * ratio;
-                for (j=0; j<2; j++) {
-                    if (self->active[j] == 1) {
-                        if (self->pointerPos[j] < 0.0)
-                            self->data[i] += 0.0;
-                        else {
+                        break;
+                    case 2:
+                        if (self->pointerPos[j] >= 0 && self->pointerPos[j] < size) {
                             if (self->pointerPos[j] > self->minfadepoint[j]) {
                                 fpart = (self->loopstart[j] - self->pointerPos[j]) * self->crossfadescaling[j];
-                                ipart = (int)fpart;
-                                fpart = fpart - ipart;
-                                amp = self->fader[ipart] + (self->fader[ipart+1] - self->fader[ipart]) * fpart;
+                                amp = Looper_get_amp(self, fpart);
                             }
                             else if (self->pointerPos[j] < self->maxfadepoint[j]) {
                                 fpart = (self->pointerPos[j] - self->loopend[j]) * self->crossfadescaling[j];
-                                ipart = (int)fpart;
-                                fpart = fpart - ipart;
-                                amp = self->fader[ipart] + (self->fader[ipart+1] - self->fader[ipart]) * fpart;
+                                amp = Looper_get_amp(self, fpart);
                             }
                             else
                                 amp = 1.0;
@@ -1621,105 +1629,97 @@ Looper_transform_a(Looper *self) {
                             self->data[i] += (*self->interp_func_ptr)(tablelist, ipart, fpart, size) * amp;
                         }
                         self->pointerPos[j] -= pit;
-                        if (self->pointerPos[j] >= size)
+                        if (self->pointerPos[j] >= size) {
                             self->pointerPos[j] = size-1;
-                        else if (self->pointerPos[j] < self->maxfadepoint[j] && self->active[1-j] == 0)
-                            Looper_reset(self, i, 1-j, 0);                    
-                        else if (self->pointerPos[j] <= self->loopend[j])
-                            self->active[j] = 0;
-                    }
-                }
-            }
-            break;
-        case 3:
-            for (i=0; i<self->bufsize; i++) {
-                self->data[i] = 0.0;
-                pit = pitch[i];
-                if (pit < 0.0)
-                    pit = 0.0;    
-                pit = pit * ratio;
-                if (self->active[0] == 1) {
-                    if (self->pointerPos[0] > size)
-                        self->data[i] += 0.0;
-                    else {
-                        if (self->pointerPos[0] < self->minfadepoint[0]) {
-                            fpart = (self->pointerPos[0] - self->loopstart[0]) * self->crossfadescaling[0];
-                            ipart = (int)fpart;
-                            fpart = fpart - ipart;
-                            amp = self->fader[ipart] + (self->fader[ipart+1] - self->fader[ipart]) * fpart;
+                            self->time_buffer[i] = 0.0;
                         }
-                        else if (self->pointerPos[0] > self->maxfadepoint[0]) {
-                            fpart = (self->loopend[0] - self->pointerPos[0]) * self->crossfadescaling[0];
-                            ipart = (int)fpart;
-                            fpart = fpart - ipart;
-                            amp = self->fader[ipart] + (self->fader[ipart+1] - self->fader[ipart]) * fpart;
+                        else if (self->pointerPos[j] >= self->maxfadepoint[j]) {
+                            self->time_buffer[i] = (self->loopstart[j] - self->pointerPos[j]) / self->loopDuration;
                         }
-                        else
-                            amp = 1.0;
-                        ipart = (int)self->pointerPos[0];
-                        fpart = self->pointerPos[0] - ipart;
-                        self->data[i] += (*self->interp_func_ptr)(tablelist, ipart, fpart, size) * amp;
-                    }
-                    self->pointerPos[0] += pit;
-                    if (self->pointerPos[0] < 0)
-                        self->pointerPos[0] = 0.0;
-                    else if (self->pointerPos[0] > self->maxfadepoint[0] && self->active[1] == 0)
-                        Looper_reset(self, i, 1, 0);                    
-                    else if (self->pointerPos[0] >= self->loopend[0])
-                        self->active[0] = 0;
-                } 
-                if (self->active[1] == 1) {
-                    if (self->pointerPos[1] < 0.0)
-                        self->data[i] += 0.0;
-                    else {
-                        if (self->pointerPos[1] > self->minfadepoint[1]) {
-                            fpart = (self->loopstart[1] - self->pointerPos[1]) * self->crossfadescaling[1];
-                            ipart = (int)fpart;
-                            fpart = fpart - ipart;
-                            amp = self->fader[ipart] + (self->fader[ipart+1] - self->fader[ipart]) * fpart;
+                        else if (self->pointerPos[j] < self->maxfadepoint[j] && self->active[1-j] == 0)
+                            Looper_reset(self, i, 1-j, 0);
+                        if (self->pointerPos[j] <= self->loopend[j])
+                            self->active[j] = 0;
+                        break;
+                    case 3:
+                        if (self->direction[j] == 0) {
+                            if (self->pointerPos[j] >= 0 && self->pointerPos[j] < size) {
+                                if (self->pointerPos[j] < self->minfadepoint[j]) {
+                                    fpart = (self->pointerPos[j] - self->loopstart[j]) * self->crossfadescaling[j];
+                                    amp = Looper_get_amp(self, fpart);
+                                }
+                                else if (self->pointerPos[j] > self->maxfadepoint[j]) {
+                                    fpart = (self->loopend[j] - self->pointerPos[j]) * self->crossfadescaling[j];
+                                    amp = Looper_get_amp(self, fpart);
+                                }
+                                else
+                                    amp = 1.0;
+                                ipart = (int)self->pointerPos[j];
+                                fpart = self->pointerPos[j] - ipart;
+                                self->data[i] += (*self->interp_func_ptr)(tablelist, ipart, fpart, size) * amp;
+                            }
+                            self->pointerPos[j] += pit;
+                            if (self->pointerPos[j] < 0.0) {
+                                self->pointerPos[j] = self->time_buffer[i] = 0.0;
+                            }
+                            else if (self->pointerPos[j] <= self->maxfadepoint[j]) {
+                                self->time_buffer[i] = (self->pointerPos[j] - self->loopstart[j]) / self->loopDuration;
+                            }
+                            else if (self->pointerPos[j] > self->maxfadepoint[j] && self->active[1-j] == 0)
+                                Looper_reset(self, i, 1-j, 0);
+                            if (self->pointerPos[j] >= self->loopend[j])
+                                self->active[j] = 0;
                         }
-                        else if (self->pointerPos[1] < self->maxfadepoint[1]) {
-                            fpart = (self->pointerPos[1] - self->loopend[1]) * self->crossfadescaling[1];
-                            ipart = (int)fpart;
-                            fpart = fpart - ipart;
-                            amp = self->fader[ipart] + (self->fader[ipart+1] - self->fader[ipart]) * fpart;
+                        else {
+                            if (self->pointerPos[j] >= 0 && self->pointerPos[j] < size) {
+                                if (self->pointerPos[j] > self->minfadepoint[j]) {
+                                    fpart = (self->loopstart[j] - self->pointerPos[j]) * self->crossfadescaling[j];
+                                    amp = Looper_get_amp(self, fpart);
+                                }
+                                else if (self->pointerPos[j] < self->maxfadepoint[j]) {
+                                    fpart = (self->pointerPos[j] - self->loopend[j]) * self->crossfadescaling[j];
+                                    amp = Looper_get_amp(self, fpart);
+                                }
+                                else
+                                    amp = 1.0;
+                                ipart = (int)self->pointerPos[j];
+                                fpart = self->pointerPos[j] - ipart;
+                                self->data[i] += (*self->interp_func_ptr)(tablelist, ipart, fpart, size) * amp;
+                            }
+                            self->pointerPos[j] -= pit;
+                            if (self->pointerPos[j] >= size) {
+                                self->pointerPos[j] = size-1;
+                                self->time_buffer[i] = 0.0;
+                            }
+                            else if (self->pointerPos[j] >= self->maxfadepoint[j]) {
+                                self->time_buffer[i] = (self->loopstart[j] - self->pointerPos[j]) / self->loopDuration;
+                            }
+                            else if (self->pointerPos[j] < self->maxfadepoint[j] && self->active[1-j] == 0)
+                                Looper_reset(self, i, 1-j, 0);
+                            if (self->pointerPos[j] <= self->loopend[j])
+                                self->active[j] = 0;
                         }
-                        else
-                            amp = 1.0;
-                        ipart = (int)self->pointerPos[1];
-                        fpart = self->pointerPos[1] - ipart;
-                        self->data[i] += (*self->interp_func_ptr)(tablelist, ipart, fpart, size) * amp;
-                    }
-                    self->pointerPos[1] -= pit;
-                    if (self->pointerPos[1] >= size)
-                        self->pointerPos[1] = size-1;
-                    else if (self->pointerPos[1] < self->maxfadepoint[1] && self->active[0] == 0)
-                        Looper_reset(self, i, 0, 0);                    
-                    else if (self->pointerPos[1] <= self->loopend[1])
-                        self->active[1] = 0;
-                }
+                        break;
+                } // end of switch
             }
-            break;
+        }
     }
+
     /* Automatic smoothering of low transposition */
     if (self->autosmooth == 1) {
         for (i=0; i<self->bufsize; i++) {
-            pit = pitch[i];
-            if (pit < 0.0)
-                pit = 0.0;    
-            if (pit < 1.0 && pit > 0.0) {
-                if (self->lastpitch != pit) {
-                    self->lastpitch = pit;
-                    fr = pit * tableSr * 0.45;
-                    b = 2.0 - MYCOS(TWOPI * fr / self->sr);
-                    self->c2 = (b - MYSQRT(b * b - 1.0));
-                    self->c1 = 1.0 - self->c2;
-                }
-                for (i=0; i<self->bufsize; i++) {
-                    self->y1 = self->c1 * self->data[i] + self->c2 * self->y1;
-                    self->y2 = self->c1 * self->y1 + self->c2 * self->y2;
-                    self->data[i] = self->y2;
+            pitval = pitch[i];
+            if (pitval < 0.001)
+                pitval = 0.001;
+            if (pitval < 1.0) {
+                if (self->lastpitch != pitval) {
+                    self->lastpitch = pitval;
+                    fr = pitval * self->sr * 0.45;
+                    self->c1 = MYEXP(-TWOPI * fr / self->sr);
                 }
+                self->y1 = self->data[i] + (self->y1 - self->data[i]) * self->c1;
+                self->y2 = self->y1 + (self->y2 - self->y1) * self->c1;
+                self->data[i] = self->y2;
             }
         }
     }
@@ -1741,82 +1741,89 @@ Looper_setProcMode(Looper *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2];
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Looper_transform_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Looper_transform_a;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Looper_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Looper_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Looper_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Looper_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Looper_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Looper_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Looper_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Looper_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Looper_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Looper_compute_next_data_frame(Looper *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
+static MYFLT *
+Looper_getTimeBuffer(Looper *self) {
+    return self->time_buffer;
+}
+
 static int
 Looper_traverse(Looper *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->table);
-    Py_VISIT(self->pitch);    
-    Py_VISIT(self->pitch_stream);    
-    Py_VISIT(self->start);    
-    Py_VISIT(self->start_stream);    
-    Py_VISIT(self->dur);    
-    Py_VISIT(self->dur_stream);    
-    Py_VISIT(self->xfade);    
-    Py_VISIT(self->xfade_stream);    
+    Py_VISIT(self->pitch);
+    Py_VISIT(self->pitch_stream);
+    Py_VISIT(self->start);
+    Py_VISIT(self->start_stream);
+    Py_VISIT(self->dur);
+    Py_VISIT(self->dur_stream);
+    Py_VISIT(self->xfade);
+    Py_VISIT(self->xfade_stream);
+    Py_VISIT(self->trig_stream);
     return 0;
 }
 
-static int 
+static int
 Looper_clear(Looper *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->table);
-    Py_CLEAR(self->pitch);    
-    Py_CLEAR(self->pitch_stream);    
-    Py_CLEAR(self->start);    
-    Py_CLEAR(self->start_stream);    
-    Py_CLEAR(self->dur);    
-    Py_CLEAR(self->dur_stream);    
-    Py_CLEAR(self->xfade);    
-    Py_CLEAR(self->xfade_stream);    
+    Py_CLEAR(self->pitch);
+    Py_CLEAR(self->pitch_stream);
+    Py_CLEAR(self->start);
+    Py_CLEAR(self->start_stream);
+    Py_CLEAR(self->dur);
+    Py_CLEAR(self->dur_stream);
+    Py_CLEAR(self->xfade);
+    Py_CLEAR(self->xfade_stream);
+    Py_CLEAR(self->trig_stream);
     return 0;
 }
 
@@ -1824,8 +1831,10 @@ static void
 Looper_dealloc(Looper* self)
 {
     pyo_DEALLOC
+    free(self->trigsBuffer);
+    free(self->time_buffer);
     Looper_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1835,42 +1844,42 @@ Looper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *tabletmp, *pitchtmp=NULL, *starttmp=NULL, *durtmp=NULL, *xfadetmp=NULL, *multmp=NULL, *addtmp=NULL;
     Looper *self;
     self = (Looper *)type->tp_alloc(type, 0);
-    
+
     self->pitch = PyFloat_FromDouble(1.0);
     self->start = PyFloat_FromDouble(0.0);
     self->dur = PyFloat_FromDouble(1.0);
     self->xfade = PyFloat_FromDouble(20.0);
     self->lastpitch = -1.0;
     self->autosmooth = 0;
-    self->y1 = self->y2 = 0.0;
+    self->y1 = self->y2 = self->c1 = 0.0;
     self->xfadeshape = 0;
     self->startfromloop = 0;
     self->interp = 2;
     self->init = 1;
-    self->mode = self->tmpmode = 1;
+    self->appendfade = self->fadeinseconds = 0;
+    self->mode[0] = self->mode[1] = self->tmpmode = 1;
+    self->direction[0] = self->direction[1] = 0;
     self->pointerPos[0] = self->pointerPos[1] = 0.0;
-    self->active[0] = self->active[1] = 0;
+    self->loopDuration = 0.0;
+    self->active[0] = self->active[1] = self->current = 0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
 	self->modebuffer[4] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Looper_compute_next_data_frame);
     self->mode_func_ptr = Looper_setProcMode;
 
     static char *kwlist[] = {"table", "pitch", "start", "dur", "xfade", "mode", "xfadeshape", "startfromloop", "interp", "autosmooth", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOOiiiiiOO", kwlist, &tabletmp, &pitchtmp, &starttmp, &durtmp, &xfadetmp, &self->tmpmode, &self->xfadeshape, &self->startfromloop, &self->interp, &self->autosmooth, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
-        PySys_WriteStderr("TypeError: \"table\" argument of Looper must be a PyoTableObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"table\" argument of Looper must be a PyoTableObject.\n");
+        Py_RETURN_NONE;
     }
     Py_XDECREF(self->table);
     self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", "");
@@ -1878,11 +1887,11 @@ Looper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (pitchtmp) {
         PyObject_CallMethod((PyObject *)self, "setPitch", "O", pitchtmp);
     }
-    
+
     if (starttmp) {
         PyObject_CallMethod((PyObject *)self, "setStart", "O", starttmp);
     }
-    
+
     if (durtmp) {
         PyObject_CallMethod((PyObject *)self, "setDur", "O", durtmp);
     }
@@ -1890,35 +1899,46 @@ Looper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (xfadetmp) {
         PyObject_CallMethod((PyObject *)self, "setXfade", "O", xfadetmp);
     }
-    
+
     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);
-    
+
+    self->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT));
+    self->time_buffer = (MYFLT *)realloc(self->time_buffer, self->bufsize * sizeof(MYFLT));
+
+    for (i=0; i<self->bufsize; i++) {
+        self->trigsBuffer[i] = self->time_buffer[i] = 0.0;
+    }
+
+    MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL);
+    TriggerStream_setData(self->trig_stream, self->trigsBuffer);
+
     if (self->tmpmode >= 0 && self->tmpmode < 4)
-        self->mode = self->tmpmode;
+        self->mode[0] = self->mode[1] = self->tmpmode;
     else
-        self->mode = self->tmpmode = 1;
+        self->mode[0] = self->mode[1] = self->tmpmode = 1;
 
     SET_INTERP_POINTER
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * Looper_getServer(Looper* self) { GET_SERVER };
 static PyObject * Looper_getStream(Looper* self) { GET_STREAM };
-static PyObject * Looper_setMul(Looper *self, PyObject *arg) { SET_MUL };	
-static PyObject * Looper_setAdd(Looper *self, PyObject *arg) { SET_ADD };	
-static PyObject * Looper_setSub(Looper *self, PyObject *arg) { SET_SUB };	
-static PyObject * Looper_setDiv(Looper *self, PyObject *arg) { SET_DIV };	
+static PyObject * Looper_getTriggerStream(Looper* self) { GET_TRIGGER_STREAM };
+static PyObject * Looper_setMul(Looper *self, PyObject *arg) { SET_MUL };
+static PyObject * Looper_setAdd(Looper *self, PyObject *arg) { SET_ADD };
+static PyObject * Looper_setSub(Looper *self, PyObject *arg) { SET_SUB };
+static PyObject * Looper_setDiv(Looper *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Looper_play(Looper *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Looper_out(Looper *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1937,14 +1957,11 @@ static PyObject *
 Looper_setPitch(Looper *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->pitch);
@@ -1960,25 +1977,22 @@ Looper_setPitch(Looper *self, PyObject *arg)
         self->pitch_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Looper_setStart(Looper *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->start);
@@ -1997,20 +2011,17 @@ Looper_setStart(Looper *self, PyObject *arg)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Looper_setDur(Looper *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->dur);
@@ -2035,14 +2046,11 @@ static PyObject *
 Looper_setXfade(Looper *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->xfade);
@@ -2074,34 +2082,28 @@ static PyObject *
 Looper_setTable(Looper *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    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 *
 Looper_setStartFromLoop(Looper *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
     int isInt = PyInt_Check(arg);
-    
+
 	if (isInt == 1) {
 		self->startfromloop = PyInt_AsLong(arg);
-    }  
-    
+    }
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -2109,16 +2111,13 @@ Looper_setStartFromLoop(Looper *self, PyObject *arg)
 static PyObject *
 Looper_setXfadeShape(Looper *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
     int isInt = PyInt_Check(arg);
-    
+
 	if (isInt == 1) {
 		self->xfadeshape = PyInt_AsLong(arg);
-    }  
+    }
 
     Py_INCREF(Py_None);
     return Py_None;
@@ -2128,19 +2127,17 @@ static PyObject *
 Looper_setMode(Looper *self, PyObject *arg)
 {
     int tmp;
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
     int isInt = PyInt_Check(arg);
-    
+
 	if (isInt == 1) {
 		tmp = PyInt_AsLong(arg);
         if (tmp >= 0 && tmp < 4)
             self->tmpmode = tmp;
-    }  
-    
+    }
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -2148,19 +2145,16 @@ Looper_setMode(Looper *self, PyObject *arg)
 static PyObject *
 Looper_setInterp(Looper *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
     int isNumber = PyNumber_Check(arg);
-    
+
 	if (isNumber == 1) {
 		self->interp = PyInt_AsLong(PyNumber_Int(arg));
-    }  
-    
+    }
+
     SET_INTERP_POINTER
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -2168,17 +2162,59 @@ Looper_setInterp(Looper *self, PyObject *arg)
 static PyObject *
 Looper_setAutoSmooth(Looper *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
     int isInt = PyInt_Check(arg);
-    
+
 	if (isInt == 1) {
 		self->autosmooth = PyInt_AsLong(arg);
-    }  
-    
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *
+Looper_on_reset(Looper *self) {
+    self->pointerPos[0] = self->pointerPos[1] = 0.0;
+    self->active[0] = self->active[1] = 0;
+    Py_INCREF(Py_None);
+    return Py_None;
+};
+
+static PyObject *
+Looper_loopnow(Looper *self) {
+    Looper_endloop(self);
+    Py_INCREF(Py_None);
+    return Py_None;
+};
+
+static PyObject *
+Looper_appendFadeTime(Looper *self, PyObject *arg)
+{
+    ASSERT_ARG_NOT_NULL
+
+    int isInt = PyInt_Check(arg);
+
+	if (isInt == 1) {
+		self->appendfade = PyInt_AsLong(arg) == 0 ? 0 : 1;
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *
+Looper_fadeInSeconds(Looper *self, PyObject *arg)
+{
+    ASSERT_ARG_NOT_NULL
+
+    int isInt = PyInt_Check(arg);
+
+	if (isInt == 1) {
+		self->fadeinseconds = PyInt_AsLong(arg) == 0 ? 0 : 1;
+    }
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -2186,6 +2222,7 @@ Looper_setAutoSmooth(Looper *self, PyObject *arg)
 static PyMemberDef Looper_members[] = {
     {"server", T_OBJECT_EX, offsetof(Looper, server), 0, "Pyo server."},
     {"stream", T_OBJECT_EX, offsetof(Looper, stream), 0, "Stream object."},
+    {"trig_stream", T_OBJECT_EX, offsetof(Looper, trig_stream), 0, "Trigger Stream object."},
     {"table", T_OBJECT_EX, offsetof(Looper, table), 0, "Sound table."},
     {"pitch", T_OBJECT_EX, offsetof(Looper, pitch), 0, "Speed of the reading pointer."},
     {"start", T_OBJECT_EX, offsetof(Looper, start), 0, "Position in the sound table."},
@@ -2201,6 +2238,7 @@ static PyMethodDef Looper_methods[] = {
     {"setTable", (PyCFunction)Looper_setTable, METH_O, "Sets sound table."},
     {"getServer", (PyCFunction)Looper_getServer, METH_NOARGS, "Returns server object."},
     {"_getStream", (PyCFunction)Looper_getStream, METH_NOARGS, "Returns stream object."},
+    {"_getTriggerStream", (PyCFunction)Looper_getTriggerStream, METH_NOARGS, "Returns trigger stream object."},
     {"play", (PyCFunction)Looper_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
     {"out", (PyCFunction)Looper_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
     {"stop", (PyCFunction)Looper_stop, METH_NOARGS, "Stops computing."},
@@ -2213,6 +2251,10 @@ static PyMethodDef Looper_methods[] = {
     {"setStartFromLoop", (PyCFunction)Looper_setStartFromLoop, METH_O, "Sets init pointer position."},
     {"setInterp", (PyCFunction)Looper_setInterp, METH_O, "Sets oscillator interpolation mode."},
     {"setAutoSmooth", (PyCFunction)Looper_setAutoSmooth, METH_O, "Activate lowpass filter for transposition below 1."},
+    {"appendFadeTime", (PyCFunction)Looper_appendFadeTime, METH_O, "If positive, fade time is added to loop duration."},
+    {"fadeInSeconds", (PyCFunction)Looper_fadeInSeconds, METH_O, "If positive, fade time is set in seconds instead of percentage."},
+    {"reset", (PyCFunction)Looper_on_reset, METH_NOARGS, "Resets internal counters."},
+    {"loopnow", (PyCFunction)Looper_loopnow, METH_NOARGS, "Satrts a new loop immediately."},
 	{"setMul", (PyCFunction)Looper_setMul, METH_O, "Sets granulator mul factor."},
 	{"setAdd", (PyCFunction)Looper_setAdd, METH_O, "Sets granulator add factor."},
     {"setSub", (PyCFunction)Looper_setSub, METH_O, "Sets inverse add factor."},
@@ -2224,7 +2266,7 @@ static PyNumberMethods Looper_as_number = {
     (binaryfunc)Looper_add,                      /*nb_add*/
     (binaryfunc)Looper_sub,                 /*nb_subtract*/
     (binaryfunc)Looper_multiply,                 /*nb_multiply*/
-    (binaryfunc)Looper_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -2238,16 +2280,16 @@ static PyNumberMethods Looper_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)Looper_inplace_add,              /*inplace_add*/
     (binaryfunc)Looper_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)Looper_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)Looper_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -2256,15 +2298,14 @@ static PyNumberMethods Looper_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)Looper_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)Looper_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject LooperType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_pitch*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Looper_base",         /*tp_name*/
     sizeof(Looper),         /*tp_basicpitch*/
     0,                         /*tp_itempitch*/
@@ -2272,7 +2313,7 @@ PyTypeObject LooperType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &Looper_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -2304,60 +2345,310 @@ PyTypeObject LooperType = {
     Looper_new,                 /* tp_new */
 };
 
-static const MYFLT Granule_MAX_GRAINS = 1024; 
 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;
-    MYFLT *gpos;
-    MYFLT *glen;
-    MYFLT *inc;
-    MYFLT *phase;
-    int *flags;
-    int num;
-    double timer;
-    MYFLT oneOnSr;
-    int modebuffer[6];
-} Granule;
+    Looper *mainPlayer;
+    int modebuffer[2];
+} LooperTimeStream;
+
+static void LooperTimeStream_postprocessing_ii(LooperTimeStream *self) { POST_PROCESSING_II };
+static void LooperTimeStream_postprocessing_ai(LooperTimeStream *self) { POST_PROCESSING_AI };
+static void LooperTimeStream_postprocessing_ia(LooperTimeStream *self) { POST_PROCESSING_IA };
+static void LooperTimeStream_postprocessing_aa(LooperTimeStream *self) { POST_PROCESSING_AA };
+static void LooperTimeStream_postprocessing_ireva(LooperTimeStream *self) { POST_PROCESSING_IREVA };
+static void LooperTimeStream_postprocessing_areva(LooperTimeStream *self) { POST_PROCESSING_AREVA };
+static void LooperTimeStream_postprocessing_revai(LooperTimeStream *self) { POST_PROCESSING_REVAI };
+static void LooperTimeStream_postprocessing_revaa(LooperTimeStream *self) { POST_PROCESSING_REVAA };
+static void LooperTimeStream_postprocessing_revareva(LooperTimeStream *self) { POST_PROCESSING_REVAREVA };
 
 static void
-Granule_transform_i(Granule *self) {
-    MYFLT dens, inc, index, amp, phase;
-    int i, j, ipart;
-    int flag = 0; 
-    MYFLT pit = 0, pos = 0, dur = 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 = -dens;
-    
-    inc = dens * self->oneOnSr;
-    
-    for (i=0; i<self->bufsize; i++) {
-        self->data[i] = 0.0;
+LooperTimeStream_setProcMode(LooperTimeStream *self) {
+    int muladdmode;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
-        /* clocker */
-        self->timer += inc;
-        if (self->timer >= 1.0) {
-            self->timer -= 1.0;
-            flag = 1;
-        }
+    switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = LooperTimeStream_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = LooperTimeStream_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = LooperTimeStream_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = LooperTimeStream_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = LooperTimeStream_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = LooperTimeStream_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = LooperTimeStream_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = LooperTimeStream_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = LooperTimeStream_postprocessing_revareva;
+            break;
+    }
+}
 
-        /* need to start a new grain */
+static void
+LooperTimeStream_compute_next_data_frame(LooperTimeStream *self)
+{
+    int i;
+    MYFLT *tmp;
+    tmp = Looper_getTimeBuffer((Looper *)self->mainPlayer);
+    for (i=0; i<self->bufsize; i++) {
+        self->data[i] = tmp[i];
+    }
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+LooperTimeStream_traverse(LooperTimeStream *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->mainPlayer);
+    return 0;
+}
+
+static int
+LooperTimeStream_clear(LooperTimeStream *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->mainPlayer);
+    return 0;
+}
+
+static void
+LooperTimeStream_dealloc(LooperTimeStream* self)
+{
+    pyo_DEALLOC
+    LooperTimeStream_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+LooperTimeStream_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *maintmp=NULL;
+    LooperTimeStream *self;
+    self = (LooperTimeStream *)type->tp_alloc(type, 0);
+
+    self->modebuffer[0] = 0;
+    self->modebuffer[1] = 0;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, LooperTimeStream_compute_next_data_frame);
+    self->mode_func_ptr = LooperTimeStream_setProcMode;
+
+    static char *kwlist[] = {"mainPlayer", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &maintmp))
+        Py_RETURN_NONE;
+
+    Py_XDECREF(self->mainPlayer);
+    Py_INCREF(maintmp);
+    self->mainPlayer = (Looper *)maintmp;
+
+    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
+
+    (*self->mode_func_ptr)(self);
+
+    return (PyObject *)self;
+}
+
+static PyObject * LooperTimeStream_getServer(LooperTimeStream* self) { GET_SERVER };
+static PyObject * LooperTimeStream_getStream(LooperTimeStream* self) { GET_STREAM };
+static PyObject * LooperTimeStream_setMul(LooperTimeStream *self, PyObject *arg) { SET_MUL };
+static PyObject * LooperTimeStream_setAdd(LooperTimeStream *self, PyObject *arg) { SET_ADD };
+static PyObject * LooperTimeStream_setSub(LooperTimeStream *self, PyObject *arg) { SET_SUB };
+static PyObject * LooperTimeStream_setDiv(LooperTimeStream *self, PyObject *arg) { SET_DIV };
+
+static PyObject * LooperTimeStream_play(LooperTimeStream *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * LooperTimeStream_out(LooperTimeStream *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * LooperTimeStream_stop(LooperTimeStream *self) { STOP };
+
+static PyObject * LooperTimeStream_multiply(LooperTimeStream *self, PyObject *arg) { MULTIPLY };
+static PyObject * LooperTimeStream_inplace_multiply(LooperTimeStream *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * LooperTimeStream_add(LooperTimeStream *self, PyObject *arg) { ADD };
+static PyObject * LooperTimeStream_inplace_add(LooperTimeStream *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * LooperTimeStream_sub(LooperTimeStream *self, PyObject *arg) { SUB };
+static PyObject * LooperTimeStream_inplace_sub(LooperTimeStream *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * LooperTimeStream_div(LooperTimeStream *self, PyObject *arg) { DIV };
+static PyObject * LooperTimeStream_inplace_div(LooperTimeStream *self, PyObject *arg) { INPLACE_DIV };
+
+static PyMemberDef LooperTimeStream_members[] = {
+    {"server", T_OBJECT_EX, offsetof(LooperTimeStream, server), 0, "Pyo server."},
+    {"stream", T_OBJECT_EX, offsetof(LooperTimeStream, stream), 0, "Stream object."},
+    {"mul", T_OBJECT_EX, offsetof(LooperTimeStream, mul), 0, "Mul factor."},
+    {"add", T_OBJECT_EX, offsetof(LooperTimeStream, add), 0, "Add factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef LooperTimeStream_methods[] = {
+    {"getServer", (PyCFunction)LooperTimeStream_getServer, METH_NOARGS, "Returns server object."},
+    {"_getStream", (PyCFunction)LooperTimeStream_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)LooperTimeStream_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+    {"out", (PyCFunction)LooperTimeStream_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+    {"stop", (PyCFunction)LooperTimeStream_stop, METH_NOARGS, "Stops computing."},
+    {"setMul", (PyCFunction)LooperTimeStream_setMul, METH_O, "Sets oscillator mul factor."},
+    {"setAdd", (PyCFunction)LooperTimeStream_setAdd, METH_O, "Sets oscillator add factor."},
+    {"setSub", (PyCFunction)LooperTimeStream_setSub, METH_O, "Sets inverse add factor."},
+    {"setDiv", (PyCFunction)LooperTimeStream_setDiv, METH_O, "Sets inverse mul factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyNumberMethods LooperTimeStream_as_number = {
+    (binaryfunc)LooperTimeStream_add,                         /*nb_add*/
+    (binaryfunc)LooperTimeStream_sub,                         /*nb_subtract*/
+    (binaryfunc)LooperTimeStream_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)LooperTimeStream_inplace_add,                 /*inplace_add*/
+    (binaryfunc)LooperTimeStream_inplace_sub,                 /*inplace_subtract*/
+    (binaryfunc)LooperTimeStream_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)LooperTimeStream_div,                       /*nb_true_divide*/
+    0,                                              /*nb_inplace_floor_divide*/
+    (binaryfunc)LooperTimeStream_inplace_div,                       /*nb_inplace_true_divide*/
+    0,                                              /* nb_index */
+};
+
+PyTypeObject LooperTimeStreamType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.LooperTimeStream_base",         /*tp_name*/
+    sizeof(LooperTimeStream),         /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)LooperTimeStream_dealloc, /*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
+    0,                         /*tp_repr*/
+    &LooperTimeStream_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*/
+    "LooperTimeStream objects. Returns the current recording time, in samples, of a Looper object.",           /* tp_doc */
+    (traverseproc)LooperTimeStream_traverse,   /* tp_traverse */
+    (inquiry)LooperTimeStream_clear,           /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    LooperTimeStream_methods,             /* tp_methods */
+    LooperTimeStream_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 */
+    LooperTimeStream_new,                 /* tp_new */
+};
+
+static const MYFLT Granule_MAX_GRAINS = 4096;
+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;
+    MYFLT *gpos;
+    MYFLT *glen;
+    MYFLT *inc;
+    MYFLT *phase;
+    int *flags;
+    int num;
+    int sync;
+    double timer;
+    MYFLT oneOnSr;
+    MYFLT srOnRandMax;
+    int modebuffer[6];
+} Granule;
+
+static void
+Granule_transform_i(Granule *self) {
+    MYFLT dens, inc, index, amp, phase;
+    int i, j, ipart, flag = 0;
+    MYFLT pit = 0, pos = 0, dur = 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;
+
+    for (i=0; i<self->bufsize; i++) {
+        self->data[i] = 0.0;
+
+        if (self->sync == 1) {
+            /* synchronous */
+            self->timer += inc;
+            if (self->timer >= 1.0) {
+                self->timer -= 1.0;
+                flag = 1;
+            }
+        } else {
+            /* asynchronous */
+            if ((pyorand() * self->srOnRandMax) < dens)
+                flag = 1;
+        }
+
+        /* need to start a new grain */
         if (flag) {
             for (j=0; j<Granule_MAX_GRAINS; j++) {
                 if (self->flags[j] == 0) {
@@ -2376,10 +2667,14 @@ Granule_transform_i(Granule *self) {
                         dur = PyFloat_AS_DOUBLE(self->dur);
                     else
                         dur = Stream_getData((Stream *)self->dur_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;
                     self->gpos[j] = pos;
                     self->glen[j] = dur * self->sr * pit;
                     if ((pos + self->glen[j]) >= size || (pos + self->glen[j]) < 0)
@@ -2395,39 +2690,34 @@ Granule_transform_i(Granule *self) {
         for (j=0; j<self->num; j++) {
             if (self->flags[j]) {
                 phase = self->phase[j];
-                if (phase >= 0.0 && phase < 1.0) {
-                    // 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;
-                    self->data[i] += (tablelist[ipart] + (tablelist[ipart+1] - tablelist[ipart]) * (index - ipart)) * amp;
-
-                    phase += self->inc[j];
-                    if (phase >= 1.0)
-                        self->flags[j] = 0;
-                    else
-                        self->phase[j] = phase;
-                }
+                /* 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;
+                self->data[i] += (tablelist[ipart] + (tablelist[ipart+1] - tablelist[ipart]) * (index - ipart)) * amp;
+                phase += self->inc[j];
+                if (phase >= 1.0)
+                    self->flags[j] = 0;
+                else
+                    self->phase[j] = phase;
             }
         }
         flag = 0;
-    }    
+    }
 }
 
 static void
 Granule_transform_a(Granule *self) {
     MYFLT index, amp, phase;
-    int i, j, ipart;
-    int flag = 0;
-    MYFLT pit = 0, pos = 0, dur = 0; 
-    
+    int i, j, ipart, flag = 0;
+    MYFLT pit = 0, pos = 0, dur = 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);
 
@@ -2436,11 +2726,17 @@ Granule_transform_a(Granule *self) {
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = 0.0;
 
-        /* clocker */
-        self->timer += density[i] * self->oneOnSr;
-        if (self->timer >= 1.0) {
-            self->timer -= 1.0;
-            flag = 1;
+        if (self->sync == 1) {
+            /* synchronous */
+            self->timer += density[i] * self->oneOnSr;
+            if (self->timer >= 1.0) {
+                self->timer -= 1.0;
+                flag = 1;
+            }
+        } else {
+            /* asynchronous */
+            if ((pyorand() * self->srOnRandMax) < density[i])
+                flag = 1;
         }
 
         /* need to start a new grain */
@@ -2462,10 +2758,14 @@ Granule_transform_a(Granule *self) {
                         dur = PyFloat_AS_DOUBLE(self->dur);
                     else
                         dur = Stream_getData((Stream *)self->dur_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;
                     self->gpos[j] = pos;
                     self->glen[j] = dur * self->sr * pit;
                     if ((pos + self->glen[j]) >= size || (pos + self->glen[j]) < 0)
@@ -2481,27 +2781,23 @@ Granule_transform_a(Granule *self) {
         for (j=0; j<self->num; j++) {
             if (self->flags[j]) {
                 phase = self->phase[j];
-                if (phase >= 0.0 && phase < 1.0) {
-                    // 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;
-                    self->data[i] += (tablelist[ipart] + (tablelist[ipart+1] - tablelist[ipart]) * (index - ipart)) * amp;
-
-                    phase += self->inc[j];
-                    if (phase >= 1.0)
-                        self->flags[j] = 0;
-                    else
-                        self->phase[j] = phase;
-                }
+                // 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;
+                self->data[i] += (tablelist[ipart] + (tablelist[ipart+1] - tablelist[ipart]) * (index - ipart)) * amp;
+                phase += self->inc[j];
+                if (phase >= 1.0)
+                    self->flags[j] = 0;
+                else
+                    self->phase[j] = phase;
             }
         }
         flag = 0;
-    }    
+    }
 }
 
 static void Granule_postprocessing_ii(Granule *self) { POST_PROCESSING_II };
@@ -2522,48 +2818,48 @@ Granule_setProcMode(Granule *self)
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Granule_transform_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Granule_transform_a;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Granule_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Granule_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Granule_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Granule_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Granule_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Granule_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Granule_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Granule_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Granule_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Granule_compute_next_data_frame(Granule *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -2573,31 +2869,31 @@ Granule_traverse(Granule *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->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);
     return 0;
 }
 
-static int 
+static int
 Granule_clear(Granule *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->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);
     return 0;
 }
 
@@ -2605,13 +2901,13 @@ static void
 Granule_dealloc(Granule* self)
 {
     pyo_DEALLOC
-    free(self->gpos);   
+    free(self->gpos);
     free(self->glen);
     free(self->inc);
     free(self->flags);
     free(self->phase);
     Granule_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2628,6 +2924,7 @@ Granule_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->dur = PyFloat_FromDouble(0.1);
     self->timer = 1.0;
     self->num = 0;
+    self->sync = 1;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
@@ -2636,8 +2933,9 @@ Granule_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[5] = 0;
 
     INIT_OBJECT_COMMON
-    
+
     self->oneOnSr = 1.0 / self->sr;
+    self->srOnRandMax = self->sr / (MYFLT)PYO_RAND_MAX;
 
     Stream_setFunctionPtr(self->stream, Granule_compute_next_data_frame);
     self->mode_func_ptr = Granule_setProcMode;
@@ -2648,21 +2946,15 @@ Granule_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         Py_RETURN_NONE;
 
     if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
-        PySys_WriteStderr("TypeError: \"table\" argument of Granule must be a PyoTableObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"table\" argument of Granule must be a PyoTableObject.\n");
+        Py_RETURN_NONE;
     }
     Py_XDECREF(self->table);
     self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", "");
 
     if ( PyObject_HasAttrString((PyObject *)envtmp, "getTableStream") == 0 ) {
-        PySys_WriteStderr("TypeError: \"env\" argument of Granule must be a PyoTableObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"env\" argument of Granule must be a PyoTableObject.\n");
+        Py_RETURN_NONE;
     }
     Py_XDECREF(self->env);
     self->env = PyObject_CallMethod((PyObject *)envtmp, "getTableStream", "");
@@ -2670,7 +2962,7 @@ Granule_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (denstmp) {
         PyObject_CallMethod((PyObject *)self, "setDens", "O", denstmp);
     }
-    
+
     if (pitchtmp) {
         PyObject_CallMethod((PyObject *)self, "setPitch", "O", pitchtmp);
     }
@@ -2682,7 +2974,7 @@ Granule_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (durtmp) {
         PyObject_CallMethod((PyObject *)self, "setDur", "O", durtmp);
     }
-    
+
     if (multmp) {
         PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
     }
@@ -2690,7 +2982,7 @@ Granule_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (addtmp) {
         PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
     }
- 
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     self->gpos = (MYFLT *)realloc(self->gpos, Granule_MAX_GRAINS * sizeof(MYFLT));
@@ -2698,23 +2990,25 @@ Granule_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->inc = (MYFLT *)realloc(self->inc, Granule_MAX_GRAINS * sizeof(MYFLT));
     self->phase = (MYFLT *)realloc(self->phase, Granule_MAX_GRAINS * sizeof(MYFLT));
     self->flags = (int *)realloc(self->flags, Granule_MAX_GRAINS * sizeof(int));
-    
+
     for (i=0; i<Granule_MAX_GRAINS; i++) {
         self->gpos[i] = self->glen[i] = self->inc[i] = self->phase[i] = 0.0;
         self->flags[i] = 0;
     }
-    
+
+    Server_generateSeed((Server *)self->server, GRANULE_ID);
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * Granule_getServer(Granule* self) { GET_SERVER };
 static PyObject * Granule_getStream(Granule* self) { GET_STREAM };
-static PyObject * Granule_setMul(Granule *self, PyObject *arg) { SET_MUL };	
-static PyObject * Granule_setAdd(Granule *self, PyObject *arg) { SET_ADD };	
-static PyObject * Granule_setSub(Granule *self, PyObject *arg) { SET_SUB };	
-static PyObject * Granule_setDiv(Granule *self, PyObject *arg) { SET_DIV };	
+static PyObject * Granule_setMul(Granule *self, PyObject *arg) { SET_MUL };
+static PyObject * Granule_setAdd(Granule *self, PyObject *arg) { SET_ADD };
+static PyObject * Granule_setSub(Granule *self, PyObject *arg) { SET_SUB };
+static PyObject * Granule_setDiv(Granule *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Granule_play(Granule *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Granule_out(Granule *self, PyObject *args, PyObject *kwds) { OUT };
@@ -2733,14 +3027,11 @@ static PyObject *
 Granule_setDens(Granule *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->dens);
@@ -2756,25 +3047,22 @@ Granule_setDens(Granule *self, PyObject *arg)
         self->dens_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Granule_setPitch(Granule *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->pitch);
@@ -2793,20 +3081,17 @@ Granule_setPitch(Granule *self, PyObject *arg)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Granule_setPos(Granule *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->pos);
@@ -2825,20 +3110,17 @@ Granule_setPos(Granule *self, PyObject *arg)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Granule_setDur(Granule *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->dur);
@@ -2870,19 +3152,16 @@ static PyObject *
 Granule_setTable(Granule *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    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 *
 Granule_getEnv(Granule* self)
@@ -2895,19 +3174,31 @@ static PyObject *
 Granule_setEnv(Granule *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    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 PyObject *
+Granule_setSync(Granule *self, PyObject *arg)
+{
+	if (PyLong_Check(arg) || PyInt_Check(arg)) {
+        self->sync = PyLong_AsLong(arg);
+        if (self->sync <= 0)
+            self->sync = 0;
+        else
+            self->sync = 1;
+    }
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Granule_members[] = {
     {"server", T_OBJECT_EX, offsetof(Granule, server), 0, "Pyo server."},
@@ -2937,6 +3228,7 @@ static PyMethodDef Granule_methods[] = {
 	{"setPitch", (PyCFunction)Granule_setPitch, METH_O, "Sets global pitch factor."},
     {"setPos", (PyCFunction)Granule_setPos, METH_O, "Sets position in the sound table."},
     {"setDur", (PyCFunction)Granule_setDur, METH_O, "Sets the grain duration."},
+    {"setSync", (PyCFunction)Granule_setSync, METH_O, "Sets the granulator mode: synchronous or asynchronous."},
 	{"setMul", (PyCFunction)Granule_setMul, METH_O, "Sets Granule mul factor."},
 	{"setAdd", (PyCFunction)Granule_setAdd, METH_O, "Sets Granule add factor."},
     {"setSub", (PyCFunction)Granule_setSub, METH_O, "Sets inverse add factor."},
@@ -2948,7 +3240,7 @@ static PyNumberMethods Granule_as_number = {
     (binaryfunc)Granule_add,                      /*nb_add*/
     (binaryfunc)Granule_sub,                 /*nb_subtract*/
     (binaryfunc)Granule_multiply,                 /*nb_multiply*/
-    (binaryfunc)Granule_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -2962,16 +3254,16 @@ static PyNumberMethods Granule_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)Granule_inplace_add,              /*inplace_add*/
     (binaryfunc)Granule_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)Granule_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)Granule_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -2980,15 +3272,14 @@ static PyNumberMethods Granule_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)Granule_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)Granule_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject GranuleType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_pitch*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Granule_base",         /*tp_name*/
     sizeof(Granule),         /*tp_basicpitch*/
     0,                         /*tp_itempitch*/
@@ -2996,7 +3287,7 @@ PyTypeObject GranuleType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &Granule_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -3028,3 +3319,2988 @@ PyTypeObject GranuleType = {
     Granule_new,                 /* tp_new */
 };
 
+static const MYFLT MAINPARTICLE_MAX_GRAINS = 4096;
+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;
+    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 srOnRandMax;
+    MYFLT *buffer_streams;
+    int modebuffer[6];
+} MainParticle;
+
+static void
+MainParticle_transform_mono_i(MainParticle *self) {
+    MYFLT dens, inc, index, amp, phase, val;
+    int i, j, ipart, flag = 0;
+    MYFLT pit = 0, pos = 0, dur = 0, dev = 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 (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;
+                    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;
+                    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)) * amp;
+                self->buffer_streams[i] += val;
+                phase += self->inc[j];
+                if (phase >= 1.0)
+                    self->flags[j] = 0;
+                else
+                    self->phase[j] = phase;
+            }
+        }
+        flag = 0;
+    }
+}
+
+static void
+MainParticle_transform_mono_a(MainParticle *self) {
+    MYFLT dens, index, amp, phase, val;
+    int i, j, ipart, flag = 0;
+    MYFLT pit = 0, pos = 0, dur = 0, dev = 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 (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;
+                    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;
+                    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)) * amp;
+                self->buffer_streams[i] += val;
+                phase += self->inc[j];
+                if (phase >= 1.0)
+                    self->flags[j] = 0;
+                else
+                    self->phase[j] = phase;
+            }
+        }
+        flag = 0;
+    }
+}
+
+static void
+MainParticle_transform_i(MainParticle *self) {
+    MYFLT dens, inc, index, amp, phase, val, min = 0;
+    int i, j, l, l1, ipart, flag = 0;
+    MYFLT pit = 0, pos = 0, dur = 0, dev = 0, pan = 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 (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;
+                    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;
+                            }
+                        }
+                    }
+                    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)) * amp;
+                self->buffer_streams[i+self->k1[j]] += val * self->amp1[j];
+                self->buffer_streams[i+self->k2[j]] += val * self->amp2[j];
+                phase += self->inc[j];
+                if (phase >= 1.0)
+                    self->flags[j] = 0;
+                else
+                    self->phase[j] = phase;
+            }
+        }
+        flag = 0;
+    }
+}
+
+static void
+MainParticle_transform_a(MainParticle *self) {
+    MYFLT dens, index, amp, phase, val, min = 0;
+    int i, j, l, l1, ipart, flag = 0;
+    MYFLT pit = 0, pos = 0, dur = 0, dev = 0, pan = 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 (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;
+                    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;
+                            }
+                        }
+                    }
+                    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)) * amp;
+                self->buffer_streams[i+self->k1[j]] += val * self->amp1[j];
+                self->buffer_streams[i+self->k2[j]] += val * self->amp2[j];
+                phase += self->inc[j];
+                if (phase >= 1.0)
+                    self->flags[j] = 0;
+                else
+                    self->phase[j] = phase;
+            }
+        }
+        flag = 0;
+    }
+}
+
+static void
+MainParticle_setProcMode(MainParticle *self)
+{
+    int procmode = self->modebuffer[0];
+
+	switch (procmode) {
+        case 0:
+            if (self->chnls == 1)
+                self->proc_func_ptr = MainParticle_transform_mono_i;
+            else
+                self->proc_func_ptr = MainParticle_transform_i;
+            break;
+        case 1:
+            if (self->chnls == 1)
+                self->proc_func_ptr = MainParticle_transform_mono_a;
+            else
+                self->proc_func_ptr = MainParticle_transform_a;
+            break;
+    }
+}
+
+static void
+MainParticle_compute_next_data_frame(MainParticle *self)
+{
+    (*self->proc_func_ptr)(self);
+}
+
+static int
+MainParticle_traverse(MainParticle *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);
+    return 0;
+}
+
+static int
+MainParticle_clear(MainParticle *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);
+    return 0;
+}
+
+static void
+MainParticle_dealloc(MainParticle* 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->buffer_streams);
+    MainParticle_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+MYFLT *
+MainParticle_getSamplesBuffer(MainParticle *self)
+{
+    return (MYFLT *)self->buffer_streams;
+}
+
+static PyObject *
+MainParticle_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *tabletmp, *envtmp, *denstmp=NULL, *pitchtmp=NULL, *postmp=NULL, *durtmp=NULL, *devtmp=NULL, *pantmp=NULL;
+    MainParticle *self;
+    self = (MainParticle *)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->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;
+
+    INIT_OBJECT_COMMON
+
+    self->oneOnSr = 1.0 / self->sr;
+    self->srOnRandMax = self->sr / (MYFLT)PYO_RAND_MAX;
+
+    Stream_setFunctionPtr(self->stream, MainParticle_compute_next_data_frame);
+    self->mode_func_ptr = MainParticle_setProcMode;
+
+    static char *kwlist[] = {"table", "env", "dens", "pitch", "pos", "dur", "dev", "pan", "chnls", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOOOOOi", kwlist, &tabletmp, &envtmp, &denstmp, &pitchtmp, &postmp, &durtmp, &devtmp, &pantmp, &self->chnls))
+        Py_RETURN_NONE;
+
+    if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
+        PyErr_SetString(PyExc_TypeError, "\"table\" argument of MainParticle 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 MainParticle 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);
+    }
+
+    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));
+
+    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->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 * MainParticle_getServer(MainParticle* self) { GET_SERVER };
+static PyObject * MainParticle_getStream(MainParticle* self) { GET_STREAM };
+
+static PyObject * MainParticle_play(MainParticle *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * MainParticle_stop(MainParticle *self) { STOP };
+
+static PyObject *
+MainParticle_setDens(MainParticle *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 *
+MainParticle_setPitch(MainParticle *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 *
+MainParticle_setPos(MainParticle *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 *
+MainParticle_setDur(MainParticle *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 *
+MainParticle_setDev(MainParticle *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 *
+MainParticle_setPan(MainParticle *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 *
+MainParticle_getTable(MainParticle* self)
+{
+    Py_INCREF(self->table);
+    return self->table;
+};
+
+static PyObject *
+MainParticle_setTable(MainParticle *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 *
+MainParticle_getEnv(MainParticle* self)
+{
+    Py_INCREF(self->env);
+    return self->env;
+};
+
+static PyObject *
+MainParticle_setEnv(MainParticle *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 MainParticle_members[] = {
+    {"server", T_OBJECT_EX, offsetof(MainParticle, server), 0, "Pyo server."},
+    {"stream", T_OBJECT_EX, offsetof(MainParticle, stream), 0, "Stream object."},
+    {"table", T_OBJECT_EX, offsetof(MainParticle, table), 0, "Sound table."},
+    {"env", T_OBJECT_EX, offsetof(MainParticle, env), 0, "Envelope table."},
+    {"dens", T_OBJECT_EX, offsetof(MainParticle, dens), 0, "Density of grains per second."},
+    {"pitch", T_OBJECT_EX, offsetof(MainParticle, pitch), 0, "Speed of the reading pointer."},
+    {"pos", T_OBJECT_EX, offsetof(MainParticle, pos), 0, "Position in the sound table."},
+    {"dur", T_OBJECT_EX, offsetof(MainParticle, dur), 0, "Duration of each grains."},
+    {"dev", T_OBJECT_EX, offsetof(MainParticle, dev), 0, "Grain start point deviation factor."},
+    {"pan", T_OBJECT_EX, offsetof(MainParticle, pan), 0, "Grain panning factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef MainParticle_methods[] = {
+    {"getTable", (PyCFunction)MainParticle_getTable, METH_NOARGS, "Returns sound table object."},
+    {"setTable", (PyCFunction)MainParticle_setTable, METH_O, "Sets sound table."},
+    {"getEnv", (PyCFunction)MainParticle_getEnv, METH_NOARGS, "Returns envelope table object."},
+    {"setEnv", (PyCFunction)MainParticle_setEnv, METH_O, "Sets envelope table."},
+    {"getServer", (PyCFunction)MainParticle_getServer, METH_NOARGS, "Returns server object."},
+    {"_getStream", (PyCFunction)MainParticle_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)MainParticle_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+    {"stop", (PyCFunction)MainParticle_stop, METH_NOARGS, "Stops computing."},
+	{"setDens", (PyCFunction)MainParticle_setDens, METH_O, "Sets the density of grains per second."},
+	{"setPitch", (PyCFunction)MainParticle_setPitch, METH_O, "Sets global pitch factor."},
+    {"setPos", (PyCFunction)MainParticle_setPos, METH_O, "Sets position in the sound table."},
+    {"setDur", (PyCFunction)MainParticle_setDur, METH_O, "Sets the grain duration."},
+	{"setDev", (PyCFunction)MainParticle_setDev, METH_O, "Sets grain start point deviation factor."},
+	{"setPan", (PyCFunction)MainParticle_setPan, METH_O, "Sets grain panning factor."},
+    {NULL}  /* Sentinel */
+};
+
+PyTypeObject MainParticleType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.MainParticle_base",         /*tp_name*/
+    sizeof(MainParticle),         /*tp_basicpitch*/
+    0,                         /*tp_itempitch*/
+    (destructor)MainParticle_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*/
+    "MainParticle objects. Accumulation of multiples grains of sound.",           /* tp_doc */
+    (traverseproc)MainParticle_traverse,   /* tp_traverse */
+    (inquiry)MainParticle_clear,           /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    MainParticle_methods,             /* tp_methods */
+    MainParticle_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 */
+    MainParticle_new,                 /* tp_new */
+};
+
+typedef struct {
+    pyo_audio_HEAD
+    MainParticle *mainSplitter;
+    int modebuffer[2];
+    int chnl; // panning order
+} Particle;
+
+static void Particle_postprocessing_ii(Particle *self) { POST_PROCESSING_II };
+static void Particle_postprocessing_ai(Particle *self) { POST_PROCESSING_AI };
+static void Particle_postprocessing_ia(Particle *self) { POST_PROCESSING_IA };
+static void Particle_postprocessing_aa(Particle *self) { POST_PROCESSING_AA };
+static void Particle_postprocessing_ireva(Particle *self) { POST_PROCESSING_IREVA };
+static void Particle_postprocessing_areva(Particle *self) { POST_PROCESSING_AREVA };
+static void Particle_postprocessing_revai(Particle *self) { POST_PROCESSING_REVAI };
+static void Particle_postprocessing_revaa(Particle *self) { POST_PROCESSING_REVAA };
+static void Particle_postprocessing_revareva(Particle *self) { POST_PROCESSING_REVAREVA };
+
+static void
+Particle_setProcMode(Particle *self)
+{
+    int muladdmode;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+	switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = Particle_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = Particle_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = Particle_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = Particle_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = Particle_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = Particle_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = Particle_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = Particle_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = Particle_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+Particle_compute_next_data_frame(Particle *self)
+{
+    int i;
+    MYFLT *tmp;
+    int offset = self->chnl * self->bufsize;
+    tmp = MainParticle_getSamplesBuffer((MainParticle *)self->mainSplitter);
+    for (i=0; i<self->bufsize; i++) {
+        self->data[i] = tmp[i + offset];
+    }
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+Particle_traverse(Particle *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->mainSplitter);
+    return 0;
+}
+
+static int
+Particle_clear(Particle *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->mainSplitter);
+    return 0;
+}
+
+static void
+Particle_dealloc(Particle* self)
+{
+    pyo_DEALLOC
+    Particle_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+Particle_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL;
+    Particle *self;
+    self = (Particle *)type->tp_alloc(type, 0);
+
+	self->modebuffer[0] = 0;
+	self->modebuffer[1] = 0;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, Particle_compute_next_data_frame);
+    self->mode_func_ptr = Particle_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 = (MainParticle *)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 * Particle_getServer(Particle* self) { GET_SERVER };
+static PyObject * Particle_getStream(Particle* self) { GET_STREAM };
+static PyObject * Particle_setMul(Particle *self, PyObject *arg) { SET_MUL };
+static PyObject * Particle_setAdd(Particle *self, PyObject *arg) { SET_ADD };
+static PyObject * Particle_setSub(Particle *self, PyObject *arg) { SET_SUB };
+static PyObject * Particle_setDiv(Particle *self, PyObject *arg) { SET_DIV };
+
+static PyObject * Particle_play(Particle *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * Particle_out(Particle *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * Particle_stop(Particle *self) { STOP };
+
+static PyObject * Particle_multiply(Particle *self, PyObject *arg) { MULTIPLY };
+static PyObject * Particle_inplace_multiply(Particle *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * Particle_add(Particle *self, PyObject *arg) { ADD };
+static PyObject * Particle_inplace_add(Particle *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * Particle_sub(Particle *self, PyObject *arg) { SUB };
+static PyObject * Particle_inplace_sub(Particle *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * Particle_div(Particle *self, PyObject *arg) { DIV };
+static PyObject * Particle_inplace_div(Particle *self, PyObject *arg) { INPLACE_DIV };
+
+static PyMemberDef Particle_members[] = {
+{"server", T_OBJECT_EX, offsetof(Particle, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(Particle, stream), 0, "Stream object."},
+{"mul", T_OBJECT_EX, offsetof(Particle, mul), 0, "Mul factor."},
+{"add", T_OBJECT_EX, offsetof(Particle, add), 0, "Add factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyMethodDef Particle_methods[] = {
+{"getServer", (PyCFunction)Particle_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)Particle_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)Particle_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"out", (PyCFunction)Particle_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+{"stop", (PyCFunction)Particle_stop, METH_NOARGS, "Stops computing."},
+{"setMul", (PyCFunction)Particle_setMul, METH_O, "Sets Particle mul factor."},
+{"setAdd", (PyCFunction)Particle_setAdd, METH_O, "Sets Particle add factor."},
+{"setSub", (PyCFunction)Particle_setSub, METH_O, "Sets inverse add factor."},
+{"setDiv", (PyCFunction)Particle_setDiv, METH_O, "Sets inverse mul factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyNumberMethods Particle_as_number = {
+(binaryfunc)Particle_add,                      /*nb_add*/
+(binaryfunc)Particle_sub,                 /*nb_subtract*/
+(binaryfunc)Particle_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)Particle_inplace_add,              /*inplace_add*/
+(binaryfunc)Particle_inplace_sub,         /*inplace_subtract*/
+(binaryfunc)Particle_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)Particle_div,                       /*nb_true_divide*/
+0,     /*nb_inplace_floor_divide*/
+(binaryfunc)Particle_inplace_div,                       /*nb_inplace_true_divide*/
+0,                     /* nb_index */
+};
+
+PyTypeObject ParticleType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.Particle_base",         /*tp_name*/
+sizeof(Particle),         /*tp_basicsize*/
+0,                         /*tp_itemsize*/
+(destructor)Particle_dealloc, /*tp_dealloc*/
+0,                         /*tp_print*/
+0,                         /*tp_getattr*/
+0,                         /*tp_setattr*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
+0,                         /*tp_repr*/
+&Particle_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*/
+"Particle objects. Reads one band from a MainParticle object.",           /* tp_doc */
+(traverseproc)Particle_traverse,   /* tp_traverse */
+(inquiry)Particle_clear,           /* tp_clear */
+0,		               /* tp_richcompare */
+0,		               /* tp_weaklistoffset */
+0,		               /* tp_iter */
+0,		               /* tp_iternext */
+Particle_methods,             /* tp_methods */
+Particle_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 */
+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/harmonizermodule.c b/src/objects/harmonizermodule.c
index 2bc85e4..a9653d8 100644
--- a/src/objects/harmonizermodule.c
+++ b/src/objects/harmonizermodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
@@ -47,7 +48,7 @@ static void
 Harmonizer_transform_ii(Harmonizer *self) {
     MYFLT val, amp, inc, ratio, rate, del, xind, pos, envpos, fpart;
     int i, ipart;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT trans = PyFloat_AS_DOUBLE(self->transpo);
     MYFLT feed = PyFloat_AS_DOUBLE(self->feedback);
@@ -55,11 +56,11 @@ Harmonizer_transform_ii(Harmonizer *self) {
         feed = 0.0;
     else if (feed > 1.0)
         feed = 1.0;
-    
+
     ratio = MYPOW(2.0, trans/12.0);
-	rate = (ratio-1.0) / self->winsize;	
+	rate = (ratio-1.0) / self->winsize;
     inc = -rate / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
 		/* first overlap */
 		pos = self->pointerPos;
@@ -67,7 +68,7 @@ Harmonizer_transform_ii(Harmonizer *self) {
 		ipart = (int)envpos;
 		fpart = envpos - ipart;
 		amp = ENVELOPE[ipart] + (ENVELOPE[ipart+1] - ENVELOPE[ipart]) * fpart;
-        
+
 		del = pos * self->winsize;
         xind = self->in_count - (del * self->sr);
         if (xind < 0)
@@ -85,7 +86,7 @@ Harmonizer_transform_ii(Harmonizer *self) {
 		ipart = (int)envpos;
 		fpart = envpos - ipart;
 		amp = ENVELOPE[ipart] + (ENVELOPE[ipart+1] - ENVELOPE[ipart]) * fpart;
-		
+
 		del = pos * self->winsize;
         xind = self->in_count - (del * self->sr);
         if (xind < 0)
@@ -94,27 +95,27 @@ Harmonizer_transform_ii(Harmonizer *self) {
         fpart = xind - ipart;
         val = self->buffer[ipart] + (self->buffer[ipart+1] - self->buffer[ipart]) * fpart;
         self->data[i] += (val * amp);
-		
+
         self->pointerPos += inc;
         if (self->pointerPos < 0.0)
             self->pointerPos += 1.0;
         else if (self->pointerPos >= 1.0)
             self->pointerPos -= 1.0;
-		
+
 		self->buffer[self->in_count] = in[i]  + (self->data[i] * feed);
         if (self->in_count == 0)
             self->buffer[(int)self->sr] = self->buffer[0];
         self->in_count++;
         if (self->in_count >= self->sr)
             self->in_count = 0;
-    }    
+    }
 }
 
 static void
 Harmonizer_transform_ai(Harmonizer *self) {
     MYFLT val, amp, inc, ratio, rate, del, xind, pos, envpos, fpart;
     int i, ipart;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *trans = Stream_getData((Stream *)self->transpo_stream);
     MYFLT feed = PyFloat_AS_DOUBLE(self->feedback);
@@ -122,21 +123,21 @@ Harmonizer_transform_ai(Harmonizer *self) {
         feed = 0.0;
     else if (feed > 1.0)
         feed = 1.0;
-    
+
 	MYFLT oneOnWinsize = 1.0 / self->winsize;
 	MYFLT oneOnSr = 1.0 / self->sr;
     for (i=0; i<self->bufsize; i++) {
 		ratio = MYPOW(2.0, trans[i]/12.0);
-		rate = (ratio-1.0) * oneOnWinsize;	
+		rate = (ratio-1.0) * oneOnWinsize;
 		inc = -rate * oneOnSr;;
-		
+
 		/* first overlap */
 		pos = self->pointerPos;
 		envpos = pos * 8192.0;
 		ipart = (int)envpos;
 		fpart = envpos - ipart;
 		amp = ENVELOPE[ipart] + (ENVELOPE[ipart+1] - ENVELOPE[ipart]) * fpart;
-		
+
 		del = pos * self->winsize;
         xind = self->in_count - (del * self->sr);
         if (xind < 0)
@@ -145,7 +146,7 @@ Harmonizer_transform_ai(Harmonizer *self) {
         fpart = xind - ipart;
         val = self->buffer[ipart] + (self->buffer[ipart+1] - self->buffer[ipart]) * fpart;
         self->data[i] = val * amp;
-		
+
 		/* second overlap */
 		pos = self->pointerPos + 0.5;
         if (pos >= 1)
@@ -154,7 +155,7 @@ Harmonizer_transform_ai(Harmonizer *self) {
 		ipart = (int)envpos;
 		fpart = envpos - ipart;
 		amp = ENVELOPE[ipart] + (ENVELOPE[ipart+1] - ENVELOPE[ipart]) * fpart;
-		
+
 		del = pos * self->winsize;
         xind = self->in_count - (del * self->sr);
         if (xind < 0)
@@ -163,35 +164,35 @@ Harmonizer_transform_ai(Harmonizer *self) {
         fpart = xind - ipart;
         val = self->buffer[ipart] + (self->buffer[ipart+1] - self->buffer[ipart]) * fpart;
         self->data[i] += (val * amp);
-		
+
         self->pointerPos += inc;
         if (self->pointerPos < 0)
             self->pointerPos += 1.0;
         else if (self->pointerPos >= 1)
             self->pointerPos -= 1.0;
-		
+
 		self->buffer[self->in_count] = in[i]  + (self->data[i] * feed);
         if (self->in_count == 0)
             self->buffer[(int)self->sr] = self->buffer[0];
         self->in_count++;
         if (self->in_count >= self->sr)
             self->in_count = 0;
-    }  
+    }
 }
 
 static void
 Harmonizer_transform_ia(Harmonizer *self) {
     MYFLT val, amp, inc, ratio, rate, del, xind, pos, envpos, fpart, feedback;
     int i, ipart;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT trans = PyFloat_AS_DOUBLE(self->transpo);
     MYFLT *feed = Stream_getData((Stream *)self->feedback_stream);
-	
+
 	ratio = MYPOW(2.0, trans/12.0);
-	rate = (ratio-1.0) / self->winsize;	
+	rate = (ratio-1.0) / self->winsize;
     inc = -rate / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (feed[i] < 0.0)
             feedback = 0.0;
@@ -206,7 +207,7 @@ Harmonizer_transform_ia(Harmonizer *self) {
 		ipart = (int)envpos;
 		fpart = envpos - ipart;
 		amp = ENVELOPE[ipart] + (ENVELOPE[ipart+1] - ENVELOPE[ipart]) * fpart;
-		
+
 		del = pos * self->winsize;
         xind = self->in_count - (del * self->sr);
         if (xind < 0)
@@ -215,7 +216,7 @@ Harmonizer_transform_ia(Harmonizer *self) {
         fpart = xind - ipart;
         val = self->buffer[ipart] + (self->buffer[ipart+1] - self->buffer[ipart]) * fpart;
         self->data[i] = val * amp;
-		
+
 		/* second overlap */
 		pos = self->pointerPos + 0.5;
         if (pos > 1)
@@ -224,7 +225,7 @@ Harmonizer_transform_ia(Harmonizer *self) {
 		ipart = (int)envpos;
 		fpart = envpos - ipart;
 		amp = ENVELOPE[ipart] + (ENVELOPE[ipart+1] - ENVELOPE[ipart]) * fpart;
-		
+
 		del = pos * self->winsize;
         xind = self->in_count - (del * self->sr);
         if (xind < 0)
@@ -233,38 +234,38 @@ Harmonizer_transform_ia(Harmonizer *self) {
         fpart = xind - ipart;
         val = self->buffer[ipart] + (self->buffer[ipart+1] - self->buffer[ipart]) * fpart;
         self->data[i] += (val * amp);
-		
+
         self->pointerPos += inc;
         if (self->pointerPos < 0)
             self->pointerPos += 1.0;
         else if (self->pointerPos >= 1)
             self->pointerPos -= 1.0;
-		
+
 		self->buffer[self->in_count] = in[i]  + (self->data[i] * feedback);
         if (self->in_count == 0)
             self->buffer[(int)self->sr] = self->buffer[0];
         self->in_count++;
         if (self->in_count >= self->sr)
             self->in_count = 0;
-    }  
+    }
 }
 
 static void
 Harmonizer_transform_aa(Harmonizer *self) {
     MYFLT val, amp, inc, ratio, rate, del, xind, pos, envpos, fpart, feedback;
     int i, ipart;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *trans = Stream_getData((Stream *)self->transpo_stream);
     MYFLT *feed = Stream_getData((Stream *)self->feedback_stream);
-	
+
 	MYFLT oneOnWinsize = 1.0 / self->winsize;
 	MYFLT oneOnSr = 1.0 / self->sr;
     for (i=0; i<self->bufsize; i++) {
 		ratio = MYPOW(2.0, trans[i]/12.0);
-		rate = (ratio-1.0) * oneOnWinsize;	
+		rate = (ratio-1.0) * oneOnWinsize;
 		inc = -rate * oneOnSr;;
-		
+
         if (feed[i] < 0.0)
             feedback = 0.0;
         else if (feed[i] > 1.0)
@@ -278,7 +279,7 @@ Harmonizer_transform_aa(Harmonizer *self) {
 		ipart = (int)envpos;
 		fpart = envpos - ipart;
 		amp = ENVELOPE[ipart] + (ENVELOPE[ipart+1] - ENVELOPE[ipart]) * fpart;
-		
+
 		del = pos * self->winsize;
         xind = self->in_count - (del * self->sr);
         if (xind < 0)
@@ -287,7 +288,7 @@ Harmonizer_transform_aa(Harmonizer *self) {
         fpart = xind - ipart;
         val = self->buffer[ipart] + (self->buffer[ipart+1] - self->buffer[ipart]) * fpart;
         self->data[i] = val * amp;
-		
+
 		/* second overlap */
 		pos = self->pointerPos + 0.5;
         if (pos > 1)
@@ -296,7 +297,7 @@ Harmonizer_transform_aa(Harmonizer *self) {
 		ipart = (int)envpos;
 		fpart = envpos - ipart;
 		amp = ENVELOPE[ipart] + (ENVELOPE[ipart+1] - ENVELOPE[ipart]) * fpart;
-		
+
 		del = pos * self->winsize;
         xind = self->in_count - (del * self->sr);
         if (xind < 0)
@@ -305,13 +306,13 @@ Harmonizer_transform_aa(Harmonizer *self) {
         fpart = xind - ipart;
         val = self->buffer[ipart] + (self->buffer[ipart+1] - self->buffer[ipart]) * fpart;
         self->data[i] += (val * amp);
-		
+
         self->pointerPos += inc;
         if (self->pointerPos < 0)
             self->pointerPos += 1.0;
         else if (self->pointerPos >= 1)
             self->pointerPos -= 1.0;
-		
+
 		self->buffer[self->in_count] = in[i]  + (self->data[i] * feedback);
         if (self->in_count == 0)
             self->buffer[(int)self->sr] = self->buffer[0];
@@ -319,7 +320,7 @@ Harmonizer_transform_aa(Harmonizer *self) {
         if (self->in_count >= self->sr)
             self->in_count = 0;
     }
-} 
+}
 
 static void Harmonizer_feedbacktprocessing_ii(Harmonizer *self) { POST_PROCESSING_II };
 static void Harmonizer_feedbacktprocessing_ai(Harmonizer *self) { POST_PROCESSING_AI };
@@ -339,54 +340,54 @@ Harmonizer_setProcMode(Harmonizer *self)
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Harmonizer_transform_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Harmonizer_transform_ai;
             break;
-        case 10:        
+        case 10:
             self->proc_func_ptr = Harmonizer_transform_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Harmonizer_transform_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Harmonizer_feedbacktprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Harmonizer_feedbacktprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Harmonizer_feedbacktprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Harmonizer_feedbacktprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Harmonizer_feedbacktprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Harmonizer_feedbacktprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Harmonizer_feedbacktprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Harmonizer_feedbacktprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Harmonizer_feedbacktprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Harmonizer_compute_next_data_frame(Harmonizer *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -396,23 +397,23 @@ Harmonizer_traverse(Harmonizer *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->transpo);    
-    Py_VISIT(self->transpo_stream);    
-    Py_VISIT(self->feedback);    
-    Py_VISIT(self->feedback_stream);    
+    Py_VISIT(self->transpo);
+    Py_VISIT(self->transpo_stream);
+    Py_VISIT(self->feedback);
+    Py_VISIT(self->feedback_stream);
     return 0;
 }
 
-static int 
+static int
 Harmonizer_clear(Harmonizer *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->transpo);    
-    Py_CLEAR(self->transpo_stream);    
-    Py_CLEAR(self->feedback);    
-    Py_CLEAR(self->feedback_stream);    
+    Py_CLEAR(self->transpo);
+    Py_CLEAR(self->transpo_stream);
+    Py_CLEAR(self->feedback);
+    Py_CLEAR(self->feedback_stream);
     return 0;
 }
 
@@ -422,7 +423,7 @@ Harmonizer_dealloc(Harmonizer* self)
     pyo_DEALLOC
     free(self->buffer);
     Harmonizer_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -470,18 +471,18 @@ Harmonizer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (addtmp) {
         PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
     }
- 
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     self->buffer = (MYFLT *)realloc(self->buffer, (self->sr+1) * sizeof(MYFLT));
     for (i=0; i<(self->sr+1); i++) {
         self->buffer[i] = 0.;
-    }    
-	
+    }
+
     if (wintmp > 0.0 && wintmp <= 1.0)
         self->winsize = wintmp;
     else
-        printf("Harmonizer : winsize lower than 0.0 or larger than 1.0 second, keeping default value.\n");
+        PySys_WriteStdout("Harmonizer : winsize lower than 0.0 or larger than 1.0 second, keeping default value.\n");
 
     (*self->mode_func_ptr)(self);
 
@@ -490,10 +491,10 @@ Harmonizer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Harmonizer_getServer(Harmonizer* self) { GET_SERVER };
 static PyObject * Harmonizer_getStream(Harmonizer* self) { GET_STREAM };
-static PyObject * Harmonizer_setMul(Harmonizer *self, PyObject *arg) { SET_MUL };	
-static PyObject * Harmonizer_setAdd(Harmonizer *self, PyObject *arg) { SET_ADD };	
-static PyObject * Harmonizer_setSub(Harmonizer *self, PyObject *arg) { SET_SUB };	
-static PyObject * Harmonizer_setDiv(Harmonizer *self, PyObject *arg) { SET_DIV };	
+static PyObject * Harmonizer_setMul(Harmonizer *self, PyObject *arg) { SET_MUL };
+static PyObject * Harmonizer_setAdd(Harmonizer *self, PyObject *arg) { SET_ADD };
+static PyObject * Harmonizer_setSub(Harmonizer *self, PyObject *arg) { SET_SUB };
+static PyObject * Harmonizer_setDiv(Harmonizer *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Harmonizer_play(Harmonizer *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Harmonizer_out(Harmonizer *self, PyObject *args, PyObject *kwds) { OUT };
@@ -509,17 +510,24 @@ static PyObject * Harmonizer_div(Harmonizer *self, PyObject *arg) { DIV };
 static PyObject * Harmonizer_inplace_div(Harmonizer *self, PyObject *arg) { INPLACE_DIV };
 
 static PyObject *
+Harmonizer_reset(Harmonizer *self)
+{
+    int i;
+    for (i=0; i<(self->sr+1); i++) {
+        self->buffer[i] = 0.;
+    }
+	Py_RETURN_NONE;
+}
+
+static PyObject *
 Harmonizer_setTranspo(Harmonizer *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->transpo);
@@ -535,25 +543,22 @@ Harmonizer_setTranspo(Harmonizer *self, PyObject *arg)
         self->transpo_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Harmonizer_setFeedback(Harmonizer *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->feedback);
@@ -569,25 +574,30 @@ Harmonizer_setFeedback(Harmonizer *self, PyObject *arg)
         self->feedback_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Harmonizer_setWinsize(Harmonizer *self, PyObject *arg)
 {
 	MYFLT wintmp;
-	if (arg != NULL) {
-        wintmp = PyFloat_AS_DOUBLE(PyNumber_Float(arg));
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	if (isNumber == 1) {
+        wintmp = PyFloat_AsDouble(arg);
         if (wintmp > 0.0 && wintmp <= 1.0)
 			self->winsize = wintmp;
         else
-            printf("winsize lower than 0.0 or larger than 1.0 second!\n");
+            PySys_WriteStdout("Harmonizer: winsize lower than 0.0 or larger than 1.0 second!\n");
 	}
-	
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -609,6 +619,7 @@ static PyMethodDef Harmonizer_methods[] = {
     {"play", (PyCFunction)Harmonizer_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
     {"out", (PyCFunction)Harmonizer_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
     {"stop", (PyCFunction)Harmonizer_stop, METH_NOARGS, "Stops computing."},
+    {"reset", (PyCFunction)Harmonizer_reset, METH_NOARGS, "Reset the delay line."},
 	{"setTranspo", (PyCFunction)Harmonizer_setTranspo, METH_O, "Sets global transpo factor."},
     {"setFeedback", (PyCFunction)Harmonizer_setFeedback, METH_O, "Sets feedback factor."},
     {"setWinsize", (PyCFunction)Harmonizer_setWinsize, METH_O, "Sets the window size."},
@@ -623,7 +634,7 @@ static PyNumberMethods Harmonizer_as_number = {
     (binaryfunc)Harmonizer_add,                      /*nb_add*/
     (binaryfunc)Harmonizer_sub,                 /*nb_subtract*/
     (binaryfunc)Harmonizer_multiply,                 /*nb_multiply*/
-    (binaryfunc)Harmonizer_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -637,16 +648,16 @@ static PyNumberMethods Harmonizer_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)Harmonizer_inplace_add,              /*inplace_add*/
     (binaryfunc)Harmonizer_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)Harmonizer_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)Harmonizer_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -655,15 +666,14 @@ static PyNumberMethods Harmonizer_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)Harmonizer_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)Harmonizer_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject HarmonizerType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_transpo*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Harmonizer_base",         /*tp_name*/
     sizeof(Harmonizer),         /*tp_basictranspo*/
     0,                         /*tp_itemtranspo*/
@@ -671,7 +681,7 @@ PyTypeObject HarmonizerType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &Harmonizer_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -702,4 +712,3 @@ PyTypeObject HarmonizerType = {
     0,                         /* tp_alloc */
     Harmonizer_new,                 /* tp_new */
 };
-
diff --git a/src/objects/hilbertmodule.c b/src/objects/hilbertmodule.c
index 5c860e7..1aae321 100644
--- a/src/objects/hilbertmodule.c
+++ b/src/objects/hilbertmodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
@@ -38,23 +39,23 @@ typedef struct {
 } HilbertMain;
 
 /* 6th order allpass poles */
-static const MYFLT poles[12] = {.3609, 2.7412, 11.1573, 44.7581, 179.6242, 798.4578, 
+static const MYFLT poles[12] = {.3609, 2.7412, 11.1573, 44.7581, 179.6242, 798.4578,
                     1.2524, 5.5671, 22.3423, 89.6271, 364.7914, 2770.1114};
 
 static void
 HilbertMain_compute_variables(HilbertMain *self)
-{    
+{
     int i;
     MYFLT polefreq[12];
     MYFLT rc[12];
     MYFLT alpha[12];
-    
+
     for (i=0; i<12; i++) {
         polefreq[i] = poles[i] * 15.0;
         rc[i] = 1.0 / (TWOPI * polefreq[i]);
         alpha[i] = 1.0 / rc[i];
         self->coefs[i] = - (1.0 - (alpha[i] / (2.0 * self->sr))) / (1.0 + (alpha[i] / (2.0 * self->sr)));
-    }    
+    }
 }
 
 static void
@@ -62,7 +63,7 @@ HilbertMain_filters(HilbertMain *self) {
     MYFLT xn1, xn2, yn1, yn2;
     int j, i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         xn1 = in[i];
         for (j=0; j<6; j++) {
@@ -75,32 +76,32 @@ HilbertMain_filters(HilbertMain *self) {
         xn2 = in[i];
         for (j=6; j<12; j++) {
             yn2 = self->coefs[j] * (xn2 - self->y1[j]) + self->x1[j];
-            self->x1[j] = xn1;
-            self->y1[j] = yn1;
+            self->x1[j] = xn2;
+            self->y1[j] = yn2;
             xn2 = yn2;
         }
         self->buffer_streams[i] = yn1;
         self->buffer_streams[i+self->bufsize] = yn2;
-        
-    }    
+
+    }
 }
 
 MYFLT *
 HilbertMain_getSamplesBuffer(HilbertMain *self)
 {
     return (MYFLT *)self->buffer_streams;
-}    
+}
 
 static void
 HilbertMain_setProcMode(HilbertMain *self)
-{        
-    self->proc_func_ptr = HilbertMain_filters;  
+{
+    self->proc_func_ptr = HilbertMain_filters;
 }
 
 static void
 HilbertMain_compute_next_data_frame(HilbertMain *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -112,7 +113,7 @@ HilbertMain_traverse(HilbertMain *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 HilbertMain_clear(HilbertMain *self)
 {
     pyo_CLEAR
@@ -127,7 +128,7 @@ HilbertMain_dealloc(HilbertMain* self)
     pyo_DEALLOC
     free(self->buffer_streams);
     HilbertMain_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -137,7 +138,7 @@ HilbertMain_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp;
     HilbertMain *self;
     self = (HilbertMain *)type->tp_alloc(type, 0);
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, HilbertMain_compute_next_data_frame);
     self->mode_func_ptr = HilbertMain_setProcMode;
@@ -148,12 +149,12 @@ HilbertMain_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     }
 
     static char *kwlist[] = {"input", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &inputtmp))
         Py_RETURN_NONE;
 
     INIT_INPUT_STREAM
- 
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, 2 * self->bufsize * sizeof(MYFLT));
@@ -187,8 +188,7 @@ static PyMethodDef HilbertMain_methods[] = {
 };
 
 PyTypeObject HilbertMainType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.HilbertMain_base",                                   /*tp_name*/
 sizeof(HilbertMain),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -196,7 +196,7 @@ sizeof(HilbertMain),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 0,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -253,33 +253,33 @@ Hilbert_setProcMode(Hilbert *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Hilbert_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Hilbert_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Hilbert_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Hilbert_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Hilbert_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Hilbert_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Hilbert_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Hilbert_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Hilbert_postprocessing_revareva;
             break;
     }
@@ -294,7 +294,7 @@ Hilbert_compute_next_data_frame(Hilbert *self)
     tmp = HilbertMain_getSamplesBuffer((HilbertMain *)self->mainSplitter);
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = tmp[i + offset];
-    }    
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -306,11 +306,11 @@ Hilbert_traverse(Hilbert *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Hilbert_clear(Hilbert *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->mainSplitter);    
+    Py_CLEAR(self->mainSplitter);
     return 0;
 }
 
@@ -319,7 +319,7 @@ Hilbert_dealloc(Hilbert* self)
 {
     pyo_DEALLOC
     Hilbert_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -329,44 +329,44 @@ Hilbert_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL;
     Hilbert *self;
     self = (Hilbert *)type->tp_alloc(type, 0);
-    
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Hilbert_compute_next_data_frame);
     self->mode_func_ptr = Hilbert_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 = (HilbertMain *)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 * Hilbert_getServer(Hilbert* self) { GET_SERVER };
 static PyObject * Hilbert_getStream(Hilbert* self) { GET_STREAM };
-static PyObject * Hilbert_setMul(Hilbert *self, PyObject *arg) { SET_MUL };	
-static PyObject * Hilbert_setAdd(Hilbert *self, PyObject *arg) { SET_ADD };	
-static PyObject * Hilbert_setSub(Hilbert *self, PyObject *arg) { SET_SUB };	
-static PyObject * Hilbert_setDiv(Hilbert *self, PyObject *arg) { SET_DIV };	
+static PyObject * Hilbert_setMul(Hilbert *self, PyObject *arg) { SET_MUL };
+static PyObject * Hilbert_setAdd(Hilbert *self, PyObject *arg) { SET_ADD };
+static PyObject * Hilbert_setSub(Hilbert *self, PyObject *arg) { SET_SUB };
+static PyObject * Hilbert_setDiv(Hilbert *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Hilbert_play(Hilbert *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Hilbert_out(Hilbert *self, PyObject *args, PyObject *kwds) { OUT };
@@ -406,7 +406,7 @@ static PyNumberMethods Hilbert_as_number = {
 (binaryfunc)Hilbert_add,                      /*nb_add*/
 (binaryfunc)Hilbert_sub,                 /*nb_subtract*/
 (binaryfunc)Hilbert_multiply,                 /*nb_multiply*/
-(binaryfunc)Hilbert_div,                   /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -420,16 +420,16 @@ static PyNumberMethods Hilbert_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
 (binaryfunc)Hilbert_inplace_add,              /*inplace_add*/
 (binaryfunc)Hilbert_inplace_sub,         /*inplace_subtract*/
 (binaryfunc)Hilbert_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)Hilbert_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -438,15 +438,14 @@ static PyNumberMethods Hilbert_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)Hilbert_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)Hilbert_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
 PyTypeObject HilbertType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Hilbert_base",         /*tp_name*/
 sizeof(Hilbert),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -454,7 +453,7 @@ sizeof(Hilbert),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &Hilbert_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -484,4 +483,4 @@ Hilbert_members,             /* tp_members */
 0,      /* tp_init */
 0,                         /* tp_alloc */
 Hilbert_new,                 /* tp_new */
-};
+};
\ No newline at end of file
diff --git a/src/objects/inputmodule.c b/src/objects/inputmodule.c
index 5661103..e9025a2 100644
--- a/src/objects/inputmodule.c
+++ b/src/objects/inputmodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include "pyomodule.h"
 #include "streammodule.h"
@@ -48,46 +49,46 @@ Input_setProcMode(Input *self)
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Input_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Input_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Input_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Input_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Input_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Input_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Input_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Input_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Input_postprocessing_revareva;
             break;
-    } 
+    }
 }
 
 static void
 Input_compute_next_data_frame(Input *self)
-{   
+{
     int i;
     MYFLT *tmp;
     tmp = Server_getInputBuffer((Server *)self->server);
-    for (i=0; i<self->bufsize*self->nchnls; i++) {
-        if ((i % self->nchnls) == self->chnl)
-            self->data[(int)(i/self->nchnls)] = tmp[i];
-    }    
+    for (i=0; i<self->bufsize*self->ichnls; i++) {
+        if ((i % self->ichnls) == self->chnl)
+            self->data[(int)(i/self->ichnls)] = tmp[i];
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -98,7 +99,7 @@ Input_traverse(Input *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Input_clear(Input *self)
 {
     pyo_CLEAR
@@ -110,7 +111,7 @@ Input_dealloc(Input* self)
 {
     pyo_DEALLOC
     Input_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -133,7 +134,7 @@ Input_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|iOO", kwlist, &self->chnl, &multmp, &addtmp))
         Py_RETURN_NONE;
- 
+
     if (multmp) {
         PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
     }
@@ -141,20 +142,20 @@ Input_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     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 * Input_getServer(Input* self) { GET_SERVER };
 static PyObject * Input_getStream(Input* self) { GET_STREAM };
-static PyObject * Input_setMul(Input *self, PyObject *arg) { SET_MUL };	
-static PyObject * Input_setAdd(Input *self, PyObject *arg) { SET_ADD };	
-static PyObject * Input_setSub(Input *self, PyObject *arg) { SET_SUB };	
-static PyObject * Input_setDiv(Input *self, PyObject *arg) { SET_DIV };	
+static PyObject * Input_setMul(Input *self, PyObject *arg) { SET_MUL };
+static PyObject * Input_setAdd(Input *self, PyObject *arg) { SET_ADD };
+static PyObject * Input_setSub(Input *self, PyObject *arg) { SET_SUB };
+static PyObject * Input_setDiv(Input *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Input_play(Input *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Input_out(Input *self, PyObject *args, PyObject *kwds) { OUT };
@@ -194,7 +195,7 @@ static PyNumberMethods Input_as_number = {
     (binaryfunc)Input_add,                      /*nb_add*/
     (binaryfunc)Input_sub,                 /*nb_subtract*/
     (binaryfunc)Input_multiply,                 /*nb_multiply*/
-    (binaryfunc)Input_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -208,16 +209,16 @@ static PyNumberMethods Input_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)Input_inplace_add,              /*inplace_add*/
     (binaryfunc)Input_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)Input_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)Input_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -226,15 +227,14 @@ static PyNumberMethods Input_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)Input_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)Input_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject InputType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Input_base",         /*tp_name*/
     sizeof(Input),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -242,7 +242,7 @@ PyTypeObject InputType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &Input_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -273,4 +273,3 @@ PyTypeObject InputType = {
     0,                         /* tp_alloc */
     Input_new,                 /* tp_new */
 };
-
diff --git a/src/objects/lfomodule.c b/src/objects/lfomodule.c
index b1a2bdb..c67d81c 100644
--- a/src/objects/lfomodule.c
+++ b/src/objects/lfomodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
@@ -32,8 +33,9 @@ typedef struct {
     Stream *freq_stream;
     PyObject *sharp;
     Stream *sharp_stream;
-    int modebuffer[4]; // need at least 2 slots for mul & add 
+    int modebuffer[4]; // need at least 2 slots for mul & add
     int wavetype;
+    MYFLT oneOverSr;
     MYFLT oneOverPiOverTwo;
     MYFLT srOverFour;
     MYFLT srOverEight;
@@ -48,75 +50,79 @@ static void
 LFO_generates_ii(LFO *self) {
     MYFLT val, inc, freq, sharp, pointer, numh;
     MYFLT v1, v2, inc2, fade;
+    MYFLT sharp2 = 0.0;
     int i, maxHarms;
 
     freq = PyFloat_AS_DOUBLE(self->freq);
-    if (freq <= 0) {
-        return;
-    }
+    if (freq < 0.00001)
+        freq = 0.00001;
+    else if (freq > self->srOverFour)
+        freq = self->srOverFour;
+
     sharp = PyFloat_AS_DOUBLE(self->sharp);
     if (sharp < 0.0)
         sharp = 0.0;
     else if (sharp > 1.0)
         sharp = 1.0;
-    inc = freq / self->sr;
+
+    inc = freq * self->oneOverSr;
 
     switch (self->wavetype) {
         case 0: /* Saw up */
             maxHarms = (int)(self->srOverFour/freq);
             numh = sharp * 46.0 + 4.0;
             if (numh > maxHarms)
-                numh = maxHarms;   
-                for (i=0; i<self->bufsize; i++) {
-                    pointer = self->pointerPos * 2.0 - 1.0;
-                    val = pointer - MYTANH(numh * pointer) / MYTANH(numh);
-                    self->data[i] = val;
-                    self->pointerPos += inc;
-                    if (self->pointerPos < 0)
-                        self->pointerPos += 1.0;
-                    else if (self->pointerPos >= 1)
-                        self->pointerPos -= 1.0;        
-                }            
+                numh = maxHarms;
+            for (i=0; i<self->bufsize; i++) {
+                pointer = self->pointerPos * 2.0 - 1.0;
+                val = pointer - MYTANH(numh * pointer) / MYTANH(numh);
+                self->data[i] = val;
+                self->pointerPos += inc;
+                if (self->pointerPos < 0)
+                    self->pointerPos += 1.0;
+                else if (self->pointerPos >= 1)
+                    self->pointerPos -= 1.0;
+            }
             break;
         case 1: /* Saw down */
             maxHarms = (int)(self->srOverFour/freq);
             numh = sharp * 46.0 + 4.0;
             if (numh > maxHarms)
-                numh = maxHarms;   
-                for (i=0; i<self->bufsize; i++) {
-                    pointer = self->pointerPos * 2.0 - 1.0;
-                    val = -(pointer - MYTANH(numh * pointer) / MYTANH(numh));
-                    self->data[i] = val;
-                    self->pointerPos += inc;
-                    if (self->pointerPos < 0)
-                        self->pointerPos += 1.0;
-                    else if (self->pointerPos >= 1)
-                        self->pointerPos -= 1.0;        
-                }            
+                numh = maxHarms;
+            for (i=0; i<self->bufsize; i++) {
+                pointer = self->pointerPos * 2.0 - 1.0;
+                val = -(pointer - MYTANH(numh * pointer) / MYTANH(numh));
+                self->data[i] = val;
+                self->pointerPos += inc;
+                if (self->pointerPos < 0)
+                    self->pointerPos += 1.0;
+                else if (self->pointerPos >= 1)
+                    self->pointerPos -= 1.0;
+            }
             break;
         case 2: /* Square */
             maxHarms = (int)(self->srOverEight/freq);
             numh = sharp * 46.0 + 4.0;
             if (numh > maxHarms)
-                numh = maxHarms;    
-                for (i=0; i<self->bufsize; i++) {
-                    val = MYATAN(numh * MYSIN(TWOPI*self->pointerPos));
-                    self->data[i] = val * self->oneOverPiOverTwo;
-                    self->pointerPos += inc;
-                    if (self->pointerPos < 0)
-                        self->pointerPos += 1.0;
-                    else if (self->pointerPos >= 1)
-                        self->pointerPos -= 1.0;        
-                }            
+                numh = maxHarms;
+            for (i=0; i<self->bufsize; i++) {
+                val = MYATAN(numh * MYSIN(TWOPI*self->pointerPos));
+                self->data[i] = val * self->oneOverPiOverTwo;
+                self->pointerPos += inc;
+                if (self->pointerPos < 0)
+                    self->pointerPos += 1.0;
+                else if (self->pointerPos >= 1)
+                    self->pointerPos -= 1.0;
+            }
             break;
         case 3: /* Triangle */
             maxHarms = (int)(self->srOverFour/freq);
             if ((sharp * 36.0) > maxHarms)
                 numh = (MYFLT)(maxHarms / 36.0);
             else
-                numh = sharp;    
+                numh = sharp;
             for (i=0; i<self->bufsize; i++) {
-                v1 = MYTAN(MYSIN(TWOPI*self->pointerPos));
+                v1 = MYTAN(MYSIN(TWOPI*self->pointerPos)) * self->oneOverPiOverTwo;
                 pointer = self->pointerPos + 0.25;
                 if (pointer > 1.0)
                     pointer -= 1.0;
@@ -127,8 +133,8 @@ LFO_generates_ii(LFO *self) {
                 if (self->pointerPos < 0)
                     self->pointerPos += 1.0;
                 else if (self->pointerPos >= 1)
-                    self->pointerPos -= 1.0;        
-            }            
+                    self->pointerPos -= 1.0;
+            }
             break;
         case 4: /* Pulse */
             maxHarms = (int)(self->srOverEight/freq);
@@ -144,14 +150,14 @@ LFO_generates_ii(LFO *self) {
                 if (self->pointerPos < 0)
                     self->pointerPos += 1.0;
                 else if (self->pointerPos >= 1)
-                    self->pointerPos -= 1.0;        
-            }            
+                    self->pointerPos -= 1.0;
+            }
             break;
         case 5: /* Bi-Pulse */
             maxHarms = (int)(self->srOverEight/freq);
             numh = MYFLOOR(sharp * 46.0 + 4.0);
             if (numh > maxHarms)
-                numh = maxHarms;    
+                numh = maxHarms;
             if (MYFMOD(numh, 2.0) == 0.0)
                 numh += 1.0;
             for (i=0; i<self->bufsize; i++) {
@@ -161,8 +167,8 @@ LFO_generates_ii(LFO *self) {
                 if (self->pointerPos < 0)
                     self->pointerPos += 1.0;
                 else if (self->pointerPos >= 1)
-                    self->pointerPos -= 1.0;        
-            }            
+                    self->pointerPos -= 1.0;
+            }
             break;
         case 6: /* SAH */
             numh = 1.0 - sharp;
@@ -175,7 +181,7 @@ LFO_generates_ii(LFO *self) {
                     self->pointerPos -= 1.0;
                     self->sahPointerPos = 0.0;
                     self->sahLastValue = self->sahCurrentValue;
-                    self->sahCurrentValue = rand()/((MYFLT)(RAND_MAX)*0.5) - 1.0;
+                    self->sahCurrentValue = RANDOM_UNIFORM * 2.0 - 1.0;
                 }
                 if (self->sahPointerPos < 1.0) {
                     fade = 0.5 * MYSIN(PI * (self->sahPointerPos+0.5)) + 0.5;
@@ -186,24 +192,25 @@ LFO_generates_ii(LFO *self) {
                     val = self->sahCurrentValue;
                 }
                 self->data[i] = val;
-            }            
+            }
             break;
         case 7: /* Sine-mod */
-            inc2 = inc * sharp;
+            inc2 = inc * sharp * 0.99;
+            sharp2 = sharp * 0.5;
             for (i=0; i<self->bufsize; i++) {
                 self->modPointerPos += inc2;
                 if (self->modPointerPos < 0)
                     self->modPointerPos += 1.0;
                 else if (self->modPointerPos >= 1)
                     self->modPointerPos -= 1.0;
-                val = (0.5 * MYCOS(TWOPI*self->modPointerPos) + 0.5) * MYSIN(TWOPI*self->pointerPos);
+                val = ((sharp2 * MYCOS(TWOPI*self->modPointerPos) + sharp2) + (1.0 - sharp)) * MYSIN(TWOPI*self->pointerPos);
                 self->data[i] = val;
                 self->pointerPos += inc;
                 if (self->pointerPos < 0)
                     self->pointerPos += 1.0;
                 else if (self->pointerPos >= 1)
                     self->pointerPos -= 1.0;
-            }            
+            }
             break;
         default:
             break;
@@ -214,27 +221,29 @@ static void
 LFO_generates_ai(LFO *self) {
     MYFLT val, inc, freq, sharp, pointer, numh;
     MYFLT v1, v2, inc2, fade;
+    MYFLT sharp2 = 0.0;
     int i, maxHarms;
-    
+
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    if (fr[0] <= 0) {
-        return;
-    }
     sharp = PyFloat_AS_DOUBLE(self->sharp);
     if (sharp < 0.0)
         sharp = 0.0;
     else if (sharp > 1.0)
         sharp = 1.0;
-    
+
     switch (self->wavetype) {
         case 0: /* Saw up */
             for (i=0; i<self->bufsize; i++) {
                 freq = fr[i];
-                inc = freq / self->sr;
+                if (freq < 0.00001)
+                    freq = 0.00001;
+                else if (freq > self->srOverFour)
+                    freq = self->srOverFour;
+                inc = freq * self->oneOverSr;
                 maxHarms = (int)(self->srOverFour/freq);
                 numh = sharp * 46.0 + 4.0;
                 if (numh > maxHarms)
-                    numh = maxHarms;   
+                    numh = maxHarms;
                 pointer = self->pointerPos * 2.0 - 1.0;
                 val = pointer - MYTANH(numh * pointer) / MYTANH(numh);
                 self->data[i] = val;
@@ -242,17 +251,21 @@ LFO_generates_ai(LFO *self) {
                 if (self->pointerPos < 0)
                     self->pointerPos += 1.0;
                 else if (self->pointerPos >= 1)
-                    self->pointerPos -= 1.0;        
-            }            
+                    self->pointerPos -= 1.0;
+            }
             break;
         case 1: /* Saw down */
             for (i=0; i<self->bufsize; i++) {
                 freq = fr[i];
-                inc = freq / self->sr;
+                if (freq < 0.00001)
+                    freq = 0.00001;
+                else if (freq > self->srOverFour)
+                    freq = self->srOverFour;
+                inc = freq * self->oneOverSr;
                 maxHarms = (int)(self->srOverFour/freq);
                 numh = sharp * 46.0 + 4.0;
                 if (numh > maxHarms)
-                    numh = maxHarms;   
+                    numh = maxHarms;
                 pointer = self->pointerPos * 2.0 - 1.0;
                 val = -(pointer - MYTANH(numh * pointer) / MYTANH(numh));
                 self->data[i] = val;
@@ -260,36 +273,44 @@ LFO_generates_ai(LFO *self) {
                 if (self->pointerPos < 0)
                     self->pointerPos += 1.0;
                 else if (self->pointerPos >= 1)
-                    self->pointerPos -= 1.0;        
-            }            
+                    self->pointerPos -= 1.0;
+            }
             break;
         case 2: /* Square */
             for (i=0; i<self->bufsize; i++) {
                 freq = fr[i];
-                inc = freq / self->sr;
+                if (freq < 0.00001)
+                    freq = 0.00001;
+                else if (freq > self->srOverFour)
+                    freq = self->srOverFour;
+                inc = freq * self->oneOverSr;
                 maxHarms = (int)(self->srOverEight/freq);
                 numh = sharp * 46.0 + 4.0;
                 if (numh > maxHarms)
-                    numh = maxHarms;    
+                    numh = maxHarms;
                 val = MYATAN(numh * MYSIN(TWOPI*self->pointerPos));
                 self->data[i] = val * self->oneOverPiOverTwo;
                 self->pointerPos += inc;
                 if (self->pointerPos < 0)
                     self->pointerPos += 1.0;
                 else if (self->pointerPos >= 1)
-                    self->pointerPos -= 1.0;        
-            }            
+                    self->pointerPos -= 1.0;
+            }
             break;
         case 3: /* Triangle */
             for (i=0; i<self->bufsize; i++) {
                 freq = fr[i];
-                inc = freq / self->sr;
+                if (freq < 0.00001)
+                    freq = 0.00001;
+                else if (freq > self->srOverFour)
+                    freq = self->srOverFour;
+                inc = freq * self->oneOverSr;
                 maxHarms = (int)(self->srOverFour/freq);
                 if ((sharp * 36.0) > maxHarms)
                     numh = (MYFLT)(maxHarms / 36.0);
                 else
-                    numh = sharp;    
-                v1 = MYTAN(MYSIN(TWOPI*self->pointerPos));
+                    numh = sharp;
+                v1 = MYTAN(MYSIN(TWOPI*self->pointerPos)) * self->oneOverPiOverTwo;
                 pointer = self->pointerPos + 0.25;
                 if (pointer > 1.0)
                     pointer -= 1.0;
@@ -300,13 +321,17 @@ LFO_generates_ai(LFO *self) {
                 if (self->pointerPos < 0)
                     self->pointerPos += 1.0;
                 else if (self->pointerPos >= 1)
-                    self->pointerPos -= 1.0;        
-            }            
+                    self->pointerPos -= 1.0;
+            }
             break;
         case 4: /* Pulse */
             for (i=0; i<self->bufsize; i++) {
                 freq = fr[i];
-                inc = freq / self->sr;
+                if (freq < 0.00001)
+                    freq = 0.00001;
+                else if (freq > self->srOverFour)
+                    freq = self->srOverFour;
+                inc = freq * self->oneOverSr;
                 maxHarms = (int)(self->srOverEight/freq);
                 numh = MYFLOOR(sharp * 46.0 + 4.0);
                 if (numh > maxHarms)
@@ -319,17 +344,21 @@ LFO_generates_ai(LFO *self) {
                 if (self->pointerPos < 0)
                     self->pointerPos += 1.0;
                 else if (self->pointerPos >= 1)
-                    self->pointerPos -= 1.0;        
-            }            
+                    self->pointerPos -= 1.0;
+            }
             break;
         case 5: /* Bi-Pulse */
             for (i=0; i<self->bufsize; i++) {
                 freq = fr[i];
-                inc = freq / self->sr;
+                if (freq < 0.00001)
+                    freq = 0.00001;
+                else if (freq > self->srOverFour)
+                    freq = self->srOverFour;
+                inc = freq * self->oneOverSr;
                 maxHarms = (int)(self->srOverEight/freq);
                 numh = MYFLOOR(sharp * 46.0 + 4.0);
                 if (numh > maxHarms)
-                    numh = maxHarms;    
+                    numh = maxHarms;
                 if (MYFMOD(numh, 2.0) == 0.0)
                     numh += 1.0;
                 val = MYTAN(MYPOW(MYSIN(TWOPI*self->pointerPos), numh));
@@ -338,14 +367,18 @@ LFO_generates_ai(LFO *self) {
                 if (self->pointerPos < 0)
                     self->pointerPos += 1.0;
                 else if (self->pointerPos >= 1)
-                    self->pointerPos -= 1.0;        
-            }            
+                    self->pointerPos -= 1.0;
+            }
             break;
         case 6: /* SAH */
             numh = 1.0 - sharp;
             for (i=0; i<self->bufsize; i++) {
                 freq = fr[i];
-                inc = freq / self->sr;
+                if (freq < 0.00001)
+                    freq = 0.00001;
+                else if (freq > self->srOverFour)
+                    freq = self->srOverFour;
+                inc = freq * self->oneOverSr;
                 inc2 = 1.0 / (int)(1.0 / inc * numh);
                 self->pointerPos += inc;
                 if (self->pointerPos < 0)
@@ -354,7 +387,7 @@ LFO_generates_ai(LFO *self) {
                     self->pointerPos -= 1.0;
                     self->sahPointerPos = 0.0;
                     self->sahLastValue = self->sahCurrentValue;
-                    self->sahCurrentValue = rand()/((MYFLT)(RAND_MAX)*0.5) - 1.0;
+                    self->sahCurrentValue = RANDOM_UNIFORM * 2.0 - 1.0;
                 }
                 if (self->sahPointerPos < 1.0) {
                     fade = 0.5 * MYSIN(PI * (self->sahPointerPos+0.5)) + 0.5;
@@ -365,45 +398,53 @@ LFO_generates_ai(LFO *self) {
                     val = self->sahCurrentValue;
                 }
                 self->data[i] = val;
-            }            
+            }
             break;
         case 7: /* Sine-mod */
+            sharp2 = sharp * 0.5;
             for (i=0; i<self->bufsize; i++) {
                 freq = fr[i];
-                inc = freq / self->sr;
-                inc2 = inc * sharp;
+                if (freq < 0.00001)
+                    freq = 0.00001;
+                else if (freq > self->srOverFour)
+                    freq = self->srOverFour;
+                inc = freq * self->oneOverSr;
+                inc2 = inc * sharp * 0.99;
                 self->modPointerPos += inc2;
                 if (self->modPointerPos < 0)
                     self->modPointerPos += 1.0;
                 else if (self->modPointerPos >= 1)
                     self->modPointerPos -= 1.0;
-                val = (0.5 * MYCOS(TWOPI*self->modPointerPos) + 0.5) * MYSIN(TWOPI*self->pointerPos);
+                val = ((sharp2 * MYCOS(TWOPI*self->modPointerPos) + sharp2) + (1.0 - sharp)) * MYSIN(TWOPI*self->pointerPos);
                 self->data[i] = val;
                 self->pointerPos += inc;
                 if (self->pointerPos < 0)
                     self->pointerPos += 1.0;
                 else if (self->pointerPos >= 1)
                     self->pointerPos -= 1.0;
-            }            
+            }
             break;
         default:
             break;
-    }    
+    }
 }
 
 static void
 LFO_generates_ia(LFO *self) {
     MYFLT val, inc, freq, sharp, pointer, numh;
     MYFLT v1, v2, inc2, fade;
+    MYFLT sharp2 = 0.0;
     int i, maxHarms;
-    
+
     freq = PyFloat_AS_DOUBLE(self->freq);
-    if (freq <= 0) {
-        return;
-    }
+    if (freq < 0.00001)
+        freq = 0.00001;
+    else if (freq > self->srOverFour)
+        freq = self->srOverFour;
+    inc = freq * self->oneOverSr;
+
     MYFLT *sh = Stream_getData((Stream *)self->sharp_stream);
-    inc = freq / self->sr;
-    
+
     switch (self->wavetype) {
         case 0: /* Saw up */
             maxHarms = (int)(self->srOverFour/freq);
@@ -415,7 +456,7 @@ LFO_generates_ia(LFO *self) {
                     sharp = 1.0;
                 numh = sharp * 46.0 + 4.0;
                 if (numh > maxHarms)
-                    numh = maxHarms;   
+                    numh = maxHarms;
                 pointer = self->pointerPos * 2.0 - 1.0;
                 val = pointer - MYTANH(numh * pointer) / MYTANH(numh);
                 self->data[i] = val;
@@ -423,8 +464,8 @@ LFO_generates_ia(LFO *self) {
                 if (self->pointerPos < 0)
                     self->pointerPos += 1.0;
                 else if (self->pointerPos >= 1)
-                    self->pointerPos -= 1.0;        
-            }            
+                    self->pointerPos -= 1.0;
+            }
             break;
         case 1: /* Saw down */
             maxHarms = (int)(self->srOverFour/freq);
@@ -436,7 +477,7 @@ LFO_generates_ia(LFO *self) {
                     sharp = 1.0;
                 numh = sharp * 46.0 + 4.0;
                 if (numh > maxHarms)
-                    numh = maxHarms;   
+                    numh = maxHarms;
                 pointer = self->pointerPos * 2.0 - 1.0;
                 val = -(pointer - MYTANH(numh * pointer) / MYTANH(numh));
                 self->data[i] = val;
@@ -444,8 +485,8 @@ LFO_generates_ia(LFO *self) {
                 if (self->pointerPos < 0)
                     self->pointerPos += 1.0;
                 else if (self->pointerPos >= 1)
-                    self->pointerPos -= 1.0;        
-            }            
+                    self->pointerPos -= 1.0;
+            }
             break;
         case 2: /* Square */
             maxHarms = (int)(self->srOverEight/freq);
@@ -457,15 +498,15 @@ LFO_generates_ia(LFO *self) {
                     sharp = 1.0;
                 numh = sharp * 46.0 + 4.0;
                 if (numh > maxHarms)
-                    numh = maxHarms;   
+                    numh = maxHarms;
                 val = MYATAN(numh * MYSIN(TWOPI*self->pointerPos));
                 self->data[i] = val * self->oneOverPiOverTwo;
                 self->pointerPos += inc;
                 if (self->pointerPos < 0)
                     self->pointerPos += 1.0;
                 else if (self->pointerPos >= 1)
-                    self->pointerPos -= 1.0;        
-            }            
+                    self->pointerPos -= 1.0;
+            }
             break;
         case 3: /* Triangle */
             maxHarms = (int)(self->srOverFour/freq);
@@ -478,8 +519,8 @@ LFO_generates_ia(LFO *self) {
                 if ((sharp * 36.0) > maxHarms)
                     numh = (MYFLT)(maxHarms / 36.0);
                 else
-                    numh = sharp;    
-                v1 = MYTAN(MYSIN(TWOPI*self->pointerPos));
+                    numh = sharp;
+                v1 = MYTAN(MYSIN(TWOPI*self->pointerPos)) * self->oneOverPiOverTwo;
                 pointer = self->pointerPos + 0.25;
                 if (pointer > 1.0)
                     pointer -= 1.0;
@@ -490,8 +531,8 @@ LFO_generates_ia(LFO *self) {
                 if (self->pointerPos < 0)
                     self->pointerPos += 1.0;
                 else if (self->pointerPos >= 1)
-                    self->pointerPos -= 1.0;        
-            }            
+                    self->pointerPos -= 1.0;
+            }
             break;
         case 4: /* Pulse */
             maxHarms = (int)(self->srOverEight/freq);
@@ -512,8 +553,8 @@ LFO_generates_ia(LFO *self) {
                 if (self->pointerPos < 0)
                     self->pointerPos += 1.0;
                 else if (self->pointerPos >= 1)
-                    self->pointerPos -= 1.0;        
-            }            
+                    self->pointerPos -= 1.0;
+            }
             break;
         case 5: /* Bi-Pulse */
             maxHarms = (int)(self->srOverEight/freq);
@@ -534,8 +575,8 @@ LFO_generates_ia(LFO *self) {
                 if (self->pointerPos < 0)
                     self->pointerPos += 1.0;
                 else if (self->pointerPos >= 1)
-                    self->pointerPos -= 1.0;        
-            }            
+                    self->pointerPos -= 1.0;
+            }
             break;
         case 6: /* SAH */
             for (i=0; i<self->bufsize; i++) {
@@ -553,7 +594,7 @@ LFO_generates_ia(LFO *self) {
                     self->pointerPos -= 1.0;
                     self->sahPointerPos = 0.0;
                     self->sahLastValue = self->sahCurrentValue;
-                    self->sahCurrentValue = rand()/((MYFLT)(RAND_MAX)*0.5) - 1.0;
+                    self->sahCurrentValue = RANDOM_UNIFORM * 2.0 - 1.0;
                 }
                 if (self->sahPointerPos < 1.0) {
                     fade = 0.5 * MYSIN(PI * (self->sahPointerPos+0.5)) + 0.5;
@@ -564,7 +605,7 @@ LFO_generates_ia(LFO *self) {
                     val = self->sahCurrentValue;
                 }
                 self->data[i] = val;
-            }            
+            }
             break;
         case 7: /* Sine-mod */
             for (i=0; i<self->bufsize; i++) {
@@ -573,20 +614,21 @@ LFO_generates_ia(LFO *self) {
                     sharp = 0.0;
                 else if (sharp > 1.0)
                     sharp = 1.0;
-                inc2 = inc * sharp;
+                inc2 = inc * sharp * 0.99;
+                sharp2 = sharp * 0.5;
                 self->modPointerPos += inc2;
                 if (self->modPointerPos < 0)
                     self->modPointerPos += 1.0;
                 else if (self->modPointerPos >= 1)
                     self->modPointerPos -= 1.0;
-                val = (0.5 * MYCOS(TWOPI*self->modPointerPos) + 0.5) * MYSIN(TWOPI*self->pointerPos);
+                val = ((sharp2 * MYCOS(TWOPI*self->modPointerPos) + sharp2) + (1.0 - sharp)) * MYSIN(TWOPI*self->pointerPos);
                 self->data[i] = val;
                 self->pointerPos += inc;
                 if (self->pointerPos < 0)
                     self->pointerPos += 1.0;
                 else if (self->pointerPos >= 1)
                     self->pointerPos -= 1.0;
-            }            
+            }
             break;
         default:
             break;
@@ -597,14 +639,12 @@ static void
 LFO_generates_aa(LFO *self) {
     MYFLT val, inc, freq, sharp, pointer, numh;
     MYFLT v1, v2, inc2, fade;
+    MYFLT sharp2 = 0.0;
     int i, maxHarms;
-    
+
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    if (fr[0] <= 0) {
-        return;
-    }
     MYFLT *sh = Stream_getData((Stream *)self->sharp_stream);
-    
+
     switch (self->wavetype) {
         case 0: /* Saw up */
             for (i=0; i<self->bufsize; i++) {
@@ -614,11 +654,15 @@ LFO_generates_aa(LFO *self) {
                 else if (sharp > 1.0)
                     sharp = 1.0;
                 freq = fr[i];
-                inc = freq / self->sr;
+                if (freq < 0.00001)
+                    freq = 0.00001;
+                else if (freq > self->srOverFour)
+                    freq = self->srOverFour;
+                inc = freq * self->oneOverSr;
                 maxHarms = (int)(self->srOverFour/freq);
                 numh = sharp * 46.0 + 4.0;
                 if (numh > maxHarms)
-                    numh = maxHarms;   
+                    numh = maxHarms;
                 pointer = self->pointerPos * 2.0 - 1.0;
                 val = pointer - MYTANH(numh * pointer) / MYTANH(numh);
                 self->data[i] = val;
@@ -626,8 +670,8 @@ LFO_generates_aa(LFO *self) {
                 if (self->pointerPos < 0)
                     self->pointerPos += 1.0;
                 else if (self->pointerPos >= 1)
-                    self->pointerPos -= 1.0;        
-            }            
+                    self->pointerPos -= 1.0;
+            }
             break;
         case 1: /* Saw down */
             for (i=0; i<self->bufsize; i++) {
@@ -637,11 +681,15 @@ LFO_generates_aa(LFO *self) {
                 else if (sharp > 1.0)
                     sharp = 1.0;
                 freq = fr[i];
-                inc = freq / self->sr;
+                if (freq < 0.00001)
+                    freq = 0.00001;
+                else if (freq > self->srOverFour)
+                    freq = self->srOverFour;
+                inc = freq * self->oneOverSr;
                 maxHarms = (int)(self->srOverFour/freq);
                 numh = sharp * 46.0 + 4.0;
                 if (numh > maxHarms)
-                    numh = maxHarms;   
+                    numh = maxHarms;
                 pointer = self->pointerPos * 2.0 - 1.0;
                 val = -(pointer - MYTANH(numh * pointer) / MYTANH(numh));
                 self->data[i] = val;
@@ -649,8 +697,8 @@ LFO_generates_aa(LFO *self) {
                 if (self->pointerPos < 0)
                     self->pointerPos += 1.0;
                 else if (self->pointerPos >= 1)
-                    self->pointerPos -= 1.0;        
-            }            
+                    self->pointerPos -= 1.0;
+            }
             break;
         case 2: /* Square */
             for (i=0; i<self->bufsize; i++) {
@@ -660,19 +708,23 @@ LFO_generates_aa(LFO *self) {
                 else if (sharp > 1.0)
                     sharp = 1.0;
                 freq = fr[i];
-                inc = freq / self->sr;
+                if (freq < 0.00001)
+                    freq = 0.00001;
+                else if (freq > self->srOverFour)
+                    freq = self->srOverFour;
+                inc = freq * self->oneOverSr;
                 maxHarms = (int)(self->srOverEight/freq);
                 numh = sharp * 46.0 + 4.0;
                 if (numh > maxHarms)
-                    numh = maxHarms;    
+                    numh = maxHarms;
                 val = MYATAN(numh * MYSIN(TWOPI*self->pointerPos));
                 self->data[i] = val * self->oneOverPiOverTwo;
                 self->pointerPos += inc;
                 if (self->pointerPos < 0)
                     self->pointerPos += 1.0;
                 else if (self->pointerPos >= 1)
-                    self->pointerPos -= 1.0;        
-            }            
+                    self->pointerPos -= 1.0;
+            }
             break;
         case 3: /* Triangle */
             for (i=0; i<self->bufsize; i++) {
@@ -682,13 +734,17 @@ LFO_generates_aa(LFO *self) {
                 else if (sharp > 1.0)
                     sharp = 1.0;
                 freq = fr[i];
-                inc = freq / self->sr;
+                if (freq < 0.00001)
+                    freq = 0.00001;
+                else if (freq > self->srOverFour)
+                    freq = self->srOverFour;
+                inc = freq * self->oneOverSr;
                 maxHarms = (int)(self->srOverFour/freq);
                 if ((sharp * 36.0) > maxHarms)
                     numh = (MYFLT)(maxHarms / 36.0);
                 else
-                    numh = sharp;    
-                v1 = MYTAN(MYSIN(TWOPI*self->pointerPos));
+                    numh = sharp;
+                v1 = MYTAN(MYSIN(TWOPI*self->pointerPos)) * self->oneOverPiOverTwo;
                 pointer = self->pointerPos + 0.25;
                 if (pointer > 1.0)
                     pointer -= 1.0;
@@ -699,8 +755,8 @@ LFO_generates_aa(LFO *self) {
                 if (self->pointerPos < 0)
                     self->pointerPos += 1.0;
                 else if (self->pointerPos >= 1)
-                    self->pointerPos -= 1.0;        
-            }            
+                    self->pointerPos -= 1.0;
+            }
             break;
         case 4: /* Pulse */
             for (i=0; i<self->bufsize; i++) {
@@ -710,7 +766,11 @@ LFO_generates_aa(LFO *self) {
                 else if (sharp > 1.0)
                     sharp = 1.0;
                 freq = fr[i];
-                inc = freq / self->sr;
+                if (freq < 0.00001)
+                    freq = 0.00001;
+                else if (freq > self->srOverFour)
+                    freq = self->srOverFour;
+                inc = freq * self->oneOverSr;
                 maxHarms = (int)(self->srOverEight/freq);
                 numh = MYFLOOR(sharp * 46.0 + 4.0);
                 if (numh > maxHarms)
@@ -723,8 +783,8 @@ LFO_generates_aa(LFO *self) {
                 if (self->pointerPos < 0)
                     self->pointerPos += 1.0;
                 else if (self->pointerPos >= 1)
-                    self->pointerPos -= 1.0;        
-            }            
+                    self->pointerPos -= 1.0;
+            }
             break;
         case 5: /* Bi-Pulse */
             for (i=0; i<self->bufsize; i++) {
@@ -734,11 +794,15 @@ LFO_generates_aa(LFO *self) {
                 else if (sharp > 1.0)
                     sharp = 1.0;
                 freq = fr[i];
-                inc = freq / self->sr;
+                if (freq < 0.00001)
+                    freq = 0.00001;
+                else if (freq > self->srOverFour)
+                    freq = self->srOverFour;
+                inc = freq * self->oneOverSr;
                 maxHarms = (int)(self->srOverEight/freq);
                 numh = MYFLOOR(sharp * 46.0 + 4.0);
                 if (numh > maxHarms)
-                    numh = maxHarms;    
+                    numh = maxHarms;
                 if (MYFMOD(numh, 2.0) == 0.0)
                     numh += 1.0;
                 val = MYTAN(MYPOW(MYSIN(TWOPI*self->pointerPos), numh));
@@ -747,8 +811,8 @@ LFO_generates_aa(LFO *self) {
                 if (self->pointerPos < 0)
                     self->pointerPos += 1.0;
                 else if (self->pointerPos >= 1)
-                    self->pointerPos -= 1.0;        
-            }            
+                    self->pointerPos -= 1.0;
+            }
             break;
         case 6: /* SAH */
             for (i=0; i<self->bufsize; i++) {
@@ -759,7 +823,11 @@ LFO_generates_aa(LFO *self) {
                     sharp = 1.0;
                 numh = 1.0 - sharp;
                 freq = fr[i];
-                inc = freq / self->sr;
+                if (freq < 0.00001)
+                    freq = 0.00001;
+                else if (freq > self->srOverFour)
+                    freq = self->srOverFour;
+                inc = freq * self->oneOverSr;
                 inc2 = 1.0 / (int)(1.0 / inc * numh);
                 self->pointerPos += inc;
                 if (self->pointerPos < 0)
@@ -768,7 +836,7 @@ LFO_generates_aa(LFO *self) {
                     self->pointerPos -= 1.0;
                     self->sahPointerPos = 0.0;
                     self->sahLastValue = self->sahCurrentValue;
-                    self->sahCurrentValue = rand()/((MYFLT)(RAND_MAX)*0.5) - 1.0;
+                    self->sahCurrentValue = RANDOM_UNIFORM * 2.0 - 1.0;
                 }
                 if (self->sahPointerPos < 1.0) {
                     fade = 0.5 * MYSIN(PI * (self->sahPointerPos+0.5)) + 0.5;
@@ -779,7 +847,7 @@ LFO_generates_aa(LFO *self) {
                     val = self->sahCurrentValue;
                 }
                 self->data[i] = val;
-            }            
+            }
             break;
         case 7: /* Sine-mod */
             for (i=0; i<self->bufsize; i++) {
@@ -789,21 +857,26 @@ LFO_generates_aa(LFO *self) {
                 else if (sharp > 1.0)
                     sharp = 1.0;
                 freq = fr[i];
-                inc = freq / self->sr;
-                inc2 = inc * sharp;
+                if (freq < 0.00001)
+                    freq = 0.00001;
+                else if (freq > self->srOverFour)
+                    freq = self->srOverFour;
+                inc = freq * self->oneOverSr;
+                inc2 = inc * sharp * 0.99;
+                sharp2 = sharp * 0.5;
                 self->modPointerPos += inc2;
                 if (self->modPointerPos < 0)
                     self->modPointerPos += 1.0;
                 else if (self->modPointerPos >= 1)
                     self->modPointerPos -= 1.0;
-                val = (0.5 * MYCOS(TWOPI*self->modPointerPos) + 0.5) * MYSIN(TWOPI*self->pointerPos);
+                val = ((sharp2 * MYCOS(TWOPI*self->modPointerPos) + sharp2) + (1.0 - sharp)) * MYSIN(TWOPI*self->pointerPos);
                 self->data[i] = val;
                 self->pointerPos += inc;
                 if (self->pointerPos < 0)
                     self->pointerPos += 1.0;
                 else if (self->pointerPos >= 1)
                     self->pointerPos -= 1.0;
-            }            
+            }
             break;
         default:
             break;
@@ -826,56 +899,56 @@ LFO_setProcMode(LFO *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = LFO_generates_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = LFO_generates_ai;
             break;
-        case 10:        
+        case 10:
             self->proc_func_ptr = LFO_generates_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = LFO_generates_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = LFO_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = LFO_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = LFO_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = LFO_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = LFO_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = LFO_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = LFO_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = LFO_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = LFO_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 LFO_compute_next_data_frame(LFO *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -883,21 +956,21 @@ static int
 LFO_traverse(LFO *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
-    Py_VISIT(self->sharp);    
-    Py_VISIT(self->sharp_stream);    
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->sharp);
+    Py_VISIT(self->sharp_stream);
     return 0;
 }
 
-static int 
+static int
 LFO_clear(LFO *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
-    Py_CLEAR(self->sharp);    
-    Py_CLEAR(self->sharp_stream);    
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->sharp);
+    Py_CLEAR(self->sharp_stream);
     return 0;
 }
 
@@ -906,7 +979,7 @@ LFO_dealloc(LFO* self)
 {
     pyo_DEALLOC
     LFO_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -916,7 +989,7 @@ LFO_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *freqtmp=NULL, *sharptmp=NULL, *multmp=NULL, *addtmp=NULL;
     LFO *self;
     self = (LFO *)type->tp_alloc(type, 0);
-        
+
     self->freq = PyFloat_FromDouble(100);
     self->sharp = PyFloat_FromDouble(0.5);
     self->oneOverPiOverTwo = 1.0 / (PI / 2.0);
@@ -930,7 +1003,8 @@ LFO_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[3] = 0;
 
     INIT_OBJECT_COMMON
-    
+
+    self->oneOverSr = 1.0 / (MYFLT)self->sr;
     self->srOverFour = (MYFLT)self->sr * 0.25;
     self->srOverEight = (MYFLT)self->sr * 0.125;
     Stream_setFunctionPtr(self->stream, LFO_compute_next_data_frame);
@@ -948,7 +1022,7 @@ LFO_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (sharptmp) {
         PyObject_CallMethod((PyObject *)self, "setSharp", "O", sharptmp);
     }
-    
+
     if (multmp) {
         PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
     }
@@ -956,13 +1030,13 @@ LFO_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (addtmp) {
         PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
     }
-            
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     Server_generateSeed((Server *)self->server, LFO_ID);
 
-    self->sahCurrentValue = self->sahLastValue = rand()/((MYFLT)(RAND_MAX)*0.5) - 1.0;
-    
+    self->sahCurrentValue = self->sahLastValue = RANDOM_UNIFORM * 2.0 - 1.0;
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
@@ -970,10 +1044,10 @@ LFO_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * LFO_getServer(LFO* self) { GET_SERVER };
 static PyObject * LFO_getStream(LFO* self) { GET_STREAM };
-static PyObject * LFO_setMul(LFO *self, PyObject *arg) { SET_MUL };	
-static PyObject * LFO_setAdd(LFO *self, PyObject *arg) { SET_ADD };	
-static PyObject * LFO_setSub(LFO *self, PyObject *arg) { SET_SUB };	
-static PyObject * LFO_setDiv(LFO *self, PyObject *arg) { SET_DIV };	
+static PyObject * LFO_setMul(LFO *self, PyObject *arg) { SET_MUL };
+static PyObject * LFO_setAdd(LFO *self, PyObject *arg) { SET_ADD };
+static PyObject * LFO_setSub(LFO *self, PyObject *arg) { SET_SUB };
+static PyObject * LFO_setDiv(LFO *self, PyObject *arg) { SET_DIV };
 
 static PyObject * LFO_play(LFO *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * LFO_out(LFO *self, PyObject *args, PyObject *kwds) { OUT };
@@ -992,14 +1066,11 @@ static PyObject *
 LFO_setFreq(LFO *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -1015,25 +1086,22 @@ LFO_setFreq(LFO *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 LFO_setSharp(LFO *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->sharp);
@@ -1049,25 +1117,22 @@ LFO_setSharp(LFO *self, PyObject *arg)
         self->sharp_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 LFO_setType(LFO *self, PyObject *arg)
 {
     int tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	
+
+    ASSERT_ARG_NOT_NULL
+
 	int isInt = PyInt_Check(arg);
-    
+
 	if (isInt == 1) {
 		tmp = PyInt_AsLong(arg);
         if (tmp >= 0 && tmp < 8)
@@ -1075,13 +1140,13 @@ LFO_setType(LFO *self, PyObject *arg)
 	}
 
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
-static PyObject * 
-LFO_reset(LFO *self) 
+static PyObject *
+LFO_reset(LFO *self)
 {
     self->pointerPos = 0.0;
     self->sahPointerPos = 0.0;
@@ -1121,7 +1186,7 @@ static PyNumberMethods LFO_as_number = {
     (binaryfunc)LFO_add,                         /*nb_add*/
     (binaryfunc)LFO_sub,                         /*nb_subtract*/
     (binaryfunc)LFO_multiply,                    /*nb_multiply*/
-    (binaryfunc)LFO_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -1135,16 +1200,16 @@ static PyNumberMethods LFO_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)LFO_inplace_add,                 /*inplace_add*/
     (binaryfunc)LFO_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)LFO_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)LFO_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -1153,15 +1218,14 @@ static PyNumberMethods LFO_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)LFO_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)LFO_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject LFOType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.LFO_base",                                   /*tp_name*/
     sizeof(LFO),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -1169,7 +1233,7 @@ PyTypeObject LFOType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &LFO_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -1199,4 +1263,4 @@ PyTypeObject LFOType = {
     0,                          /* tp_init */
     0,                                              /* tp_alloc */
     LFO_new,                                     /* tp_new */
-};
+};
\ No newline at end of file
diff --git a/src/objects/matrixmodule.c b/src/objects/matrixmodule.c
index dc1a8d6..e4fd2d6 100644
--- a/src/objects/matrixmodule.c
+++ b/src/objects/matrixmodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include "pyomodule.h"
 #include "servermodule.h"
@@ -35,7 +36,7 @@
 static void
 MatrixStream_dealloc(MatrixStream* self)
 {
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -72,7 +73,7 @@ MatrixStream_getInterpPointFromPos(MatrixStream *self, MYFLT x, MYFLT y)
         while (xpos >= self->width) {
             xpos -= self->width;
         }
-    }    
+    }
 
     ypos = y * self->height;
     if (ypos < 0)
@@ -81,11 +82,11 @@ MatrixStream_getInterpPointFromPos(MatrixStream *self, MYFLT x, MYFLT y)
         while (ypos >= self->height) {
             ypos -= self->height;
         }
-    }    
+    }
 
     xipart = (int)xpos;
     xfpart = xpos - xipart;
-        
+
     yipart = (int)ypos;
     yfpart = ypos - yipart;
 
@@ -93,37 +94,36 @@ MatrixStream_getInterpPointFromPos(MatrixStream *self, MYFLT x, MYFLT y)
     x2 = self->data[yipart+1][xipart]; // (0, 1)
     x3 = self->data[yipart][xipart+1]; // (1, 0)
     x4 = self->data[yipart+1][xipart+1]; // (1, 1)
-        
+
     return (x1*(1-yfpart)*(1-xfpart) + x2*yfpart*(1-xfpart) + x3*(1-yfpart)*xfpart + x4*yfpart*xfpart);
 }
 
-MYFLT 
+MYFLT
 MatrixStream_getPointFromPos(MatrixStream *self, long x, long y)
 {
     return self->data[y][x];
-}    
+}
 
 void
 MatrixStream_setData(MatrixStream *self, MYFLT **data)
 {
     self->data = data;
-}    
+}
 
 void
 MatrixStream_setWidth(MatrixStream *self, int size)
 {
     self->width = size;
-}    
+}
 
 void
 MatrixStream_setHeight(MatrixStream *self, int size)
 {
     self->height = size;
-}    
+}
 
 PyTypeObject MatrixStreamType = {
-PyObject_HEAD_INIT(NULL)
-0, /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.MatrixStream", /*tp_name*/
 sizeof(MatrixStream), /*tp_basicsize*/
 0, /*tp_itemsize*/
@@ -131,7 +131,7 @@ sizeof(MatrixStream), /*tp_basicsize*/
 0, /*tp_print*/
 0, /*tp_getattr*/
 0, /*tp_setattr*/
-0, /*tp_compare*/
+0, /*tp_as_async (tp_compare in Python 2)*/
 0, /*tp_repr*/
 0, /*tp_as_number*/
 0, /*tp_as_sequence*/
@@ -172,7 +172,7 @@ typedef struct {
     int y_pointer;
 } NewMatrix;
 
-MYFLT 
+MYFLT
 NewMatrix_clip(MYFLT val, MYFLT min, MYFLT max) {
     if (val < min) return min;
     else if (val > max) return max;
@@ -191,7 +191,7 @@ NewMatrix_recordChunkAllRow(NewMatrix *self, MYFLT *data, long datasize)
             self->y_pointer++;
             if (self->y_pointer >= self->height)
                 self->y_pointer = 0;
-        }    
+        }
     }
     Py_INCREF(Py_None);
     return Py_None;
@@ -204,7 +204,7 @@ NewMatrix_traverse(NewMatrix *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 NewMatrix_clear(NewMatrix *self)
 {
     pyo_matrix_CLEAR
@@ -217,10 +217,10 @@ NewMatrix_dealloc(NewMatrix* self)
     int i;
     for (i=0; i<(self->height+1); i++) {
         free(self->data[i]);
-    }    
+    }
     free(self->data);
     NewMatrix_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -229,41 +229,41 @@ NewMatrix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     int i, j;
     PyObject *inittmp=NULL;
     NewMatrix *self;
-    
+
     self = (NewMatrix *)type->tp_alloc(type, 0);
-    
+
     self->server = PyServer_get_server();
-    
+
     self->x_pointer = self->y_pointer = 0;
-    
+
     MAKE_NEW_MATRIXSTREAM(self->matrixstream, &MatrixStreamType, NULL);
 
     static char *kwlist[] = {"width", "height", "init", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "ii|O", kwlist, &self->width, &self->height, &inittmp))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     self->data = (MYFLT **)realloc(self->data, (self->height + 1) * sizeof(MYFLT *));
-    
+
     for (i=0; i<(self->height+1); i++) {
         self->data[i] = (MYFLT *)malloc((self->width + 1) * sizeof(MYFLT));
     }
-    
+
     for(i=0; i<(self->height+1); i++) {
         for (j=0; j<(self->width+1); j++) {
             self->data[i][j] = 0.0;
-        }    
+        }
     }
-    
+
     MatrixStream_setWidth(self->matrixstream, self->width);
     MatrixStream_setHeight(self->matrixstream, self->height);
-    
+
     if (inittmp) {
         PyObject_CallMethod((PyObject *)self, "setMatrix", "O", inittmp);
     }
-    
+
     MatrixStream_setData(self->matrixstream, self->data);
-    
+
     return (PyObject *)self;
 }
 
@@ -275,6 +275,7 @@ static PyObject * NewMatrix_blur(NewMatrix *self) { MATRIX_BLUR };
 static PyObject * NewMatrix_boost(NewMatrix *self, PyObject *args, PyObject *kwds) { MATRIX_BOOST };
 static PyObject * NewMatrix_put(NewMatrix *self, PyObject *args, PyObject *kwds) { MATRIX_PUT };
 static PyObject * NewMatrix_get(NewMatrix *self, PyObject *args, PyObject *kwds) { MATRIX_GET };
+static PyObject * NewMatrix_getInterpolated(NewMatrix *self, PyObject *args, PyObject *kwds) { MATRIX_GET_INTERPOLATED };
 
 static PyObject *
 NewMatrix_getSize(NewMatrix *self)
@@ -306,16 +307,16 @@ NewMatrix_getData(NewMatrix *self)
 {
     int i, j;
     PyObject *matrix, *samples;
-    
+
     matrix = PyList_New(self->height);
     for(i=0; i<self->height; i++) {
         samples = PyList_New(self->width);
         for (j=0; j<self->width; j++) {
             PyList_SetItem(samples, j, PyFloat_FromDouble(self->data[i][j]));
-        }    
+        }
         PyList_SetItem(matrix, i, samples);
     }
-    
+
     return matrix;
 };
 
@@ -324,18 +325,37 @@ NewMatrix_getViewData(NewMatrix *self)
 {
     int i, j;
     PyObject *matrix;
-    
+
     matrix = PyList_New(self->width*self->height);
     for(i=0; i<self->height; i++) {
         for (j=0; j<self->width; j++) {
             PyList_SET_ITEM(matrix, i*self->width+j, PyFloat_FromDouble(self->data[i][j]*128+128));
-        }    
+        }
     }
-    
+
     return matrix;
 };
 
 static PyObject *
+NewMatrix_getImageData(NewMatrix *self)
+{
+    int i, j, w3, index;
+    char value;
+    char matrix[self->width*self->height*3];
+
+    w3 = self->width * 3;
+    for(i=0; i<self->height; i++) {
+        for (j=0; j<self->width; j++) {
+            value = (char)(self->data[i][j]*128+128);
+            index = i * w3 + j * 3;
+            matrix[index] = matrix[index+1] = matrix[index+2] = value;
+        }
+    }
+
+    return PyByteArray_FromStringAndSize(matrix, self->width*self->height*3);
+};
+
+static PyObject *
 NewMatrix_setMatrix(NewMatrix *self, PyObject *value)
 {
     int i, j;
@@ -345,7 +365,7 @@ NewMatrix_setMatrix(NewMatrix *self, PyObject *value)
         PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyList_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The matrix value value must be a list.");
         return PyInt_FromLong(-1);
@@ -357,16 +377,16 @@ NewMatrix_setMatrix(NewMatrix *self, PyObject *value)
         PyErr_SetString(PyExc_TypeError, "New matrix must be of the same size as actual matrix.");
         return PyInt_FromLong(-1);
     }
-    
+
     for(i=0; i<self->height; i++) {
         innerlist = PyList_GetItem(value, i);
         for (j=0; j<self->width; j++) {
-            self->data[i][j] = PyFloat_AS_DOUBLE(PyNumber_Float(PyList_GET_ITEM(innerlist, j)));
-        }    
+            self->data[i][j] = PyFloat_AsDouble(PyList_GET_ITEM(innerlist, j));
+        }
     }
 
     Py_INCREF(Py_None);
-    return Py_None;    
+    return Py_None;
 }
 
 static PyObject *
@@ -377,10 +397,10 @@ NewMatrix_genSineTerrain(NewMatrix *self, PyObject *args, PyObject *kwds)
     MYFLT freq = 1;
     MYFLT phase = 0.0625;
     static char *kwlist[] = {"freq", "phase", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__FF, kwlist, &freq, &phase))
         return PyInt_FromLong(-1);
-    
+
     xfreq = TWOPI * freq;
     xsize = 1.0 / self->width;
     for (i=0; i<self->height; i++) {
@@ -390,7 +410,7 @@ NewMatrix_genSineTerrain(NewMatrix *self, PyObject *args, PyObject *kwds)
         }
     }
     Py_INCREF(Py_None);
-    return Py_None;    
+    return Py_None;
 }
 
 static PyMemberDef NewMatrix_members[] = {
@@ -403,6 +423,7 @@ static PyMethodDef NewMatrix_methods[] = {
 {"getServer", (PyCFunction)NewMatrix_getServer, METH_NOARGS, "Returns server object."},
 {"getData", (PyCFunction)NewMatrix_getData, METH_NOARGS, "Returns a list of matrix samples."},
 {"getViewData", (PyCFunction)NewMatrix_getViewData, METH_NOARGS, "Returns a list of matrix samples normalized between 0 and 256 ."},
+{"getImageData", (PyCFunction)NewMatrix_getImageData, METH_NOARGS, "Returns a list of matrix samples in tuple of 3 ints normalized between 0 and 256 ."},
 {"getMatrixStream", (PyCFunction)NewMatrix_getMatrixStream, METH_NOARGS, "Returns matrixstream object created by this matrix."},
 {"setMatrix", (PyCFunction)NewMatrix_setMatrix, METH_O, "Sets the matrix from a list of list of floats (must be the same size as the object size)."},
 {"setData", (PyCFunction)NewMatrix_setData, METH_O, "Sets the matrix from a list of list of floats (resizes the matrix)."},
@@ -412,14 +433,14 @@ static PyMethodDef NewMatrix_methods[] = {
 {"boost", (PyCFunction)NewMatrix_boost, METH_VARARGS|METH_KEYWORDS, "Boost the contrast of the matrix."},
 {"put", (PyCFunction)NewMatrix_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the matrix."},
 {"get", (PyCFunction)NewMatrix_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the matrix."},
+{"getInterpolated", (PyCFunction)NewMatrix_getInterpolated, METH_VARARGS|METH_KEYWORDS, "Gets the value at normalized position in the matrix."},
 {"getSize", (PyCFunction)NewMatrix_getSize, METH_NOARGS, "Return the size of the matrix in samples."},
 {"getRate", (PyCFunction)NewMatrix_getRate, METH_NOARGS, "Return the frequency (in cps) that reads the sound without pitch transposition."},
 {NULL}  /* Sentinel */
 };
 
 PyTypeObject NewMatrixType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.NewMatrix_base",         /*tp_name*/
 sizeof(NewMatrix),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -427,7 +448,7 @@ sizeof(NewMatrix),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 0,                         /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -485,9 +506,9 @@ MatrixRec_compute_next_data_frame(MatrixRec *self)
     int width = NewMatrix_getWidth((NewMatrix *)self->matrix);
     int height = NewMatrix_getHeight((NewMatrix *)self->matrix);
     int size = width * height;
-   
+
     int off = self->delay - self->delayCount;
- 
+
     for (i=0; i<self->bufsize; i++) {
         self->trigsBuffer[i] = 0.0;
     }
@@ -502,12 +523,12 @@ MatrixRec_compute_next_data_frame(MatrixRec *self)
             else
                 self->trigsBuffer[num-1] = 1.0;
             self->active = 0;
-        }    
+        }
     }
-    
-    if (self->pointer < size) {   
+
+    if (self->pointer < size) {
         upBound = size - self->fadeInSample;
-       
+
         if (off == 0)
             num2 = num;
         else if ((num-off) <= 0)
@@ -518,7 +539,7 @@ MatrixRec_compute_next_data_frame(MatrixRec *self)
         MYFLT buffer[num2];
         memset(&buffer, 0, sizeof(buffer));
         MYFLT *in = Stream_getData((Stream *)self->input_stream);
-        
+
         for (i=0; i<num; i++) {
             if (self->delayCount < self->delay) {
                 self->delayCount++;
@@ -535,7 +556,7 @@ MatrixRec_compute_next_data_frame(MatrixRec *self)
             }
         }
         NewMatrix_recordChunkAllRow((NewMatrix *)self->matrix, buffer, num2);
-    }    
+    }
 }
 
 static int
@@ -545,18 +566,18 @@ MatrixRec_traverse(MatrixRec *self, visitproc visit, void *arg)
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
     Py_VISIT(self->matrix);
-    Py_VISIT(self->trig_stream);    
+    Py_VISIT(self->trig_stream);
     return 0;
 }
 
-static int 
+static int
 MatrixRec_clear(MatrixRec *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
     Py_CLEAR(self->matrix);
-    Py_CLEAR(self->trig_stream);    
+    Py_CLEAR(self->trig_stream);
     return 0;
 }
 
@@ -566,7 +587,7 @@ MatrixRec_dealloc(MatrixRec* self)
     pyo_DEALLOC
     free(self->trigsBuffer);
     MatrixRec_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -576,35 +597,35 @@ MatrixRec_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *matrixtmp;
     MatrixRec *self;
     self = (MatrixRec *)type->tp_alloc(type, 0);
-    
+
     self->pointer = 0;
     self->active = 1;
     self->fadetime = 0.;
     self->delay = self->delayCount = 0;
-    
+
     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};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_OO_FI, kwlist, &inputtmp, &matrixtmp, &self->fadetime, &self->delay))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     INIT_INPUT_STREAM
 
     Py_XDECREF(self->matrix);
+    Py_INCREF(matrixtmp);
     self->matrix = (NewMatrix *)matrixtmp;
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     self->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT));
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->trigsBuffer[i] = 0.0;
-    }    
-    
+    }
+
     MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL);
     TriggerStream_setData(self->trig_stream, self->trigsBuffer);
 
@@ -614,7 +635,7 @@ MatrixRec_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if ((self->fadetime * self->sr) > (size * 0.5))
         self->fadetime = size * 0.5 / self->sr;
     self->fadeInSample = roundf(self->fadetime * self->sr + 0.5);
-    
+
     return (PyObject *)self;
 }
 
@@ -622,12 +643,12 @@ static PyObject * MatrixRec_getServer(MatrixRec* self) { GET_SERVER };
 static PyObject * MatrixRec_getStream(MatrixRec* self) { GET_STREAM };
 static PyObject * MatrixRec_getTriggerStream(MatrixRec* self) { GET_TRIGGER_STREAM };
 
-static PyObject * MatrixRec_play(MatrixRec *self, PyObject *args, PyObject *kwds) 
-{ 
+static PyObject * MatrixRec_play(MatrixRec *self, PyObject *args, PyObject *kwds)
+{
     self->pointer = 0;
     self->active = 1;
     self->delayCount = 0;
-    PLAY 
+    PLAY
 };
 
 static PyObject * MatrixRec_stop(MatrixRec *self) { STOP };
@@ -636,20 +657,17 @@ static PyObject *
 MatrixRec_setMatrix(MatrixRec *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	tmp = arg;
     Py_INCREF(tmp);
 	Py_DECREF(self->matrix);
     self->matrix = (NewMatrix *)tmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef MatrixRec_members[] = {
     {"server", T_OBJECT_EX, offsetof(MatrixRec, server), 0, "Pyo server."},
@@ -671,8 +689,7 @@ static PyMethodDef MatrixRec_methods[] = {
 };
 
 PyTypeObject MatrixRecType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.MatrixRec_base",         /*tp_name*/
     sizeof(MatrixRec),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -680,7 +697,7 @@ PyTypeObject MatrixRecType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     0,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -736,7 +753,7 @@ MatrixRecLoop_compute_next_data_frame(MatrixRecLoop *self)
     MYFLT buffer[self->bufsize];
     memset(&buffer, 0, sizeof(buffer));
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-        
+
     for (i=0; i<self->bufsize; i++) {
         self->trigsBuffer[i] = 0.0;
         buffer[i] = in[i];
@@ -755,18 +772,18 @@ MatrixRecLoop_traverse(MatrixRecLoop *self, visitproc visit, void *arg)
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
     Py_VISIT(self->matrix);
-    Py_VISIT(self->trig_stream);    
+    Py_VISIT(self->trig_stream);
     return 0;
 }
 
-static int 
+static int
 MatrixRecLoop_clear(MatrixRecLoop *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
     Py_CLEAR(self->matrix);
-    Py_CLEAR(self->trig_stream);    
+    Py_CLEAR(self->trig_stream);
     return 0;
 }
 
@@ -776,7 +793,7 @@ MatrixRecLoop_dealloc(MatrixRecLoop* self)
     pyo_DEALLOC
     free(self->trigsBuffer);
     MatrixRecLoop_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -786,31 +803,32 @@ MatrixRecLoop_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *matrixtmp;
     MatrixRecLoop *self;
     self = (MatrixRecLoop *)type->tp_alloc(type, 0);
-    
+
     self->pointer = 0;
-    
+
     INIT_OBJECT_COMMON
-    
+
     Stream_setFunctionPtr(self->stream, MatrixRecLoop_compute_next_data_frame);
-    
+
     static char *kwlist[] = {"input", "matrix", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &inputtmp, &matrixtmp))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     INIT_INPUT_STREAM
 
     Py_XDECREF(self->matrix);
+    Py_INCREF(matrixtmp);
     self->matrix = (NewMatrix *)matrixtmp;
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     self->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT));
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->trigsBuffer[i] = 0.0;
-    }    
-    
+    }
+
     MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL);
     TriggerStream_setData(self->trig_stream, self->trigsBuffer);
 
@@ -828,20 +846,17 @@ static PyObject *
 MatrixRecLoop_setMatrix(MatrixRecLoop *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	tmp = arg;
     Py_INCREF(tmp);
 	Py_DECREF(self->matrix);
     self->matrix = (NewMatrix *)tmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef MatrixRecLoop_members[] = {
     {"server", T_OBJECT_EX, offsetof(MatrixRecLoop, server), 0, "Pyo server."},
@@ -863,8 +878,7 @@ static PyMethodDef MatrixRecLoop_methods[] = {
 };
 
 PyTypeObject MatrixRecLoopType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.MatrixRecLoop_base",         /*tp_name*/
     sizeof(MatrixRecLoop),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -872,7 +886,7 @@ PyTypeObject MatrixRecLoopType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     0,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -932,32 +946,32 @@ MatrixMorph_compute_next_data_frame(MatrixMorph *self)
     int x, y;
     long i, j, width, height, numsamps, index;
     MYFLT input, interp, interp1;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     width = NewMatrix_getWidth((NewMatrix *)self->matrix);
     height = NewMatrix_getHeight((NewMatrix *)self->matrix);
     numsamps = width * height;
     int len = PyList_Size(self->sources);
-    
+
     input = MatrixMorph_clip(in[0]);
-    
+
     interp = input * (len - 1);
-    x = (int)(interp);   
+    x = (int)(interp);
     y = x + 1;
-    
+
     MatrixStream *tab1 = (MatrixStream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->sources, x), "getMatrixStream", "");
     MatrixStream *tab2 = (MatrixStream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->sources, y), "getMatrixStream", "");
-    
+
     interp = MYFMOD(interp, 1.0);
     interp1 = 1. - interp;
-    
+
     for (i=0; i<height; i++) {
         for (j=0; j<width; j++) {
             index = i*width+j;
             self->buffer[index] = MatrixStream_getPointFromPos(tab1, j, i) * interp1 + MatrixStream_getPointFromPos(tab2, j, i) * interp;
-        }    
-    }    
-    
+        }
+    }
+
     NewMatrix_recordChunkAllRow((NewMatrix *)self->matrix, self->buffer, numsamps);
 }
 
@@ -972,7 +986,7 @@ MatrixMorph_traverse(MatrixMorph *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 MatrixMorph_clear(MatrixMorph *self)
 {
     pyo_CLEAR
@@ -989,7 +1003,7 @@ MatrixMorph_dealloc(MatrixMorph* self)
     pyo_DEALLOC
     free(self->buffer);
     MatrixMorph_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1000,19 +1014,20 @@ MatrixMorph_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *matrixtmp, *sourcestmp;
     MatrixMorph *self;
     self = (MatrixMorph *)type->tp_alloc(type, 0);
-    
+
     INIT_OBJECT_COMMON
-    
+
     Stream_setFunctionPtr(self->stream, MatrixMorph_compute_next_data_frame);
 
     static char *kwlist[] = {"input", "matrix", "sources", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OOO", kwlist, &inputtmp, &matrixtmp, &sourcestmp))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     INIT_INPUT_STREAM
 
     Py_XDECREF(self->matrix);
+    Py_INCREF(matrixtmp);
     self->matrix = (PyObject *)matrixtmp;
 
     width = NewMatrix_getWidth((NewMatrix *)self->matrix);
@@ -1021,10 +1036,11 @@ MatrixMorph_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->buffer = (MYFLT *)realloc(self->buffer, (numsamps) * sizeof(MYFLT));
 
     Py_XDECREF(self->sources);
+    Py_INCREF(sourcestmp);
     self->sources = (PyObject *)sourcestmp;
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     return (PyObject *)self;
 }
 
@@ -1038,38 +1054,32 @@ static PyObject *
 MatrixMorph_setMatrix(MatrixMorph *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	tmp = arg;
     Py_INCREF(tmp);
 	Py_DECREF(self->matrix);
     self->matrix = (PyObject *)tmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
 
 static PyObject *
 MatrixMorph_setSources(MatrixMorph *self, PyObject *arg)
-{	
-    if (arg == NULL) {
-        PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute.");
-        return PyInt_FromLong(-1);
-    }
-    
+{
+    ASSERT_ARG_NOT_NULL
+
     if (! PyList_Check(arg)) {
         PyErr_SetString(PyExc_TypeError, "The amplitude list attribute value must be a list.");
         return PyInt_FromLong(-1);
     }
-    
+
     Py_INCREF(arg);
     Py_DECREF(self->sources);
     self->sources = arg;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -1094,8 +1104,7 @@ static PyMethodDef MatrixMorph_methods[] = {
 };
 
 PyTypeObject MatrixMorphType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.MatrixMorph_base",         /*tp_name*/
     sizeof(MatrixMorph),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -1103,7 +1112,7 @@ PyTypeObject MatrixMorphType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     0,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -1134,4 +1143,3 @@ PyTypeObject MatrixMorphType = {
     0,                         /* tp_alloc */
     MatrixMorph_new,                 /* tp_new */
 };
-
diff --git a/src/objects/matrixprocessmodule.c b/src/objects/matrixprocessmodule.c
index 19a5018..058d48b 100644
--- a/src/objects/matrixprocessmodule.c
+++ b/src/objects/matrixprocessmodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include "pyomodule.h"
 #include "streammodule.h"
@@ -70,40 +71,40 @@ MatrixPointer_setProcMode(MatrixPointer *self)
     self->proc_func_ptr = MatrixPointer_readframes;
 
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = MatrixPointer_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = MatrixPointer_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = MatrixPointer_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = MatrixPointer_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = MatrixPointer_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = MatrixPointer_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = MatrixPointer_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = MatrixPointer_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = MatrixPointer_postprocessing_revareva;
             break;
-    } 
+    }
 }
 
 static void
 MatrixPointer_compute_next_data_frame(MatrixPointer *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -112,22 +113,22 @@ MatrixPointer_traverse(MatrixPointer *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->matrix);
-    Py_VISIT(self->x);    
-    Py_VISIT(self->x_stream);    
-    Py_VISIT(self->y);    
-    Py_VISIT(self->y_stream);    
+    Py_VISIT(self->x);
+    Py_VISIT(self->x_stream);
+    Py_VISIT(self->y);
+    Py_VISIT(self->y_stream);
     return 0;
 }
 
-static int 
+static int
 MatrixPointer_clear(MatrixPointer *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->matrix);
-    Py_CLEAR(self->x);    
-    Py_CLEAR(self->x_stream);    
-    Py_CLEAR(self->y);    
-    Py_CLEAR(self->y_stream);    
+    Py_CLEAR(self->x);
+    Py_CLEAR(self->x_stream);
+    Py_CLEAR(self->y);
+    Py_CLEAR(self->y_stream);
     return 0;
 }
 
@@ -136,7 +137,7 @@ MatrixPointer_dealloc(MatrixPointer* self)
 {
     pyo_DEALLOC
     MatrixPointer_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -146,22 +147,26 @@ MatrixPointer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *matrixtmp, *xtmp, *ytmp, *multmp=NULL, *addtmp=NULL;
     MatrixPointer *self;
     self = (MatrixPointer *)type->tp_alloc(type, 0);
-    
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, MatrixPointer_compute_next_data_frame);
     self->mode_func_ptr = MatrixPointer_setProcMode;
 
     static char *kwlist[] = {"matrix", "x", "y", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OOO|OO", kwlist, &matrixtmp, &xtmp, &ytmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
+    if ( PyObject_HasAttrString((PyObject *)matrixtmp, "getMatrixStream") == 0 ) {
+        PyErr_SetString(PyExc_TypeError, "\"matrix\" argument of MatrixPointer must be a PyoMatrixObject.\n");
+        Py_RETURN_NONE;
+    }
     Py_XDECREF(self->matrix);
     self->matrix = PyObject_CallMethod((PyObject *)matrixtmp, "getMatrixStream", "");
-    
+
     if (xtmp) {
         PyObject_CallMethod((PyObject *)self, "setX", "O", xtmp);
     }
@@ -169,26 +174,26 @@ MatrixPointer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (ytmp) {
         PyObject_CallMethod((PyObject *)self, "setY", "O", ytmp);
     }
-    
+
     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);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * MatrixPointer_getServer(MatrixPointer* self) { GET_SERVER };
 static PyObject * MatrixPointer_getStream(MatrixPointer* self) { GET_STREAM };
-static PyObject * MatrixPointer_setMul(MatrixPointer *self, PyObject *arg) { SET_MUL };	
-static PyObject * MatrixPointer_setAdd(MatrixPointer *self, PyObject *arg) { SET_ADD };	
-static PyObject * MatrixPointer_setSub(MatrixPointer *self, PyObject *arg) { SET_SUB };	
-static PyObject * MatrixPointer_setDiv(MatrixPointer *self, PyObject *arg) { SET_DIV };	
+static PyObject * MatrixPointer_setMul(MatrixPointer *self, PyObject *arg) { SET_MUL };
+static PyObject * MatrixPointer_setAdd(MatrixPointer *self, PyObject *arg) { SET_ADD };
+static PyObject * MatrixPointer_setSub(MatrixPointer *self, PyObject *arg) { SET_SUB };
+static PyObject * MatrixPointer_setDiv(MatrixPointer *self, PyObject *arg) { SET_DIV };
 
 static PyObject * MatrixPointer_play(MatrixPointer *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * MatrixPointer_out(MatrixPointer *self, PyObject *args, PyObject *kwds) { OUT };
@@ -214,40 +219,36 @@ static PyObject *
 MatrixPointer_setMatrix(MatrixPointer *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	tmp = arg;
+    if ( PyObject_HasAttrString((PyObject *)tmp, "getMatrixStream") == 0 ) {
+        PyErr_SetString(PyExc_TypeError, "\"matrix\" argument of MatrixPointer must be a PyoMatrixObject.\n");
+        Py_RETURN_NONE;
+    }
+
 	Py_DECREF(self->matrix);
     self->matrix = PyObject_CallMethod((PyObject *)tmp, "getMatrixStream", "");
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 MatrixPointer_setX(MatrixPointer *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	int isNumber = PyNumber_Check(arg);
-	if (isNumber == 1) {
-		PySys_WriteStderr("MatrixPointer x attributes must be a PyoObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
-	}
-	
+
+    ASSERT_ARG_NOT_NULL
+
 	tmp = arg;
+
+	if (PyObject_HasAttrString((PyObject *)tmp, "server") == 0) {
+        PyErr_SetString(PyExc_TypeError, "\"x\" attribute of MatrixPointer must be a PyoObject.\n");
+        Py_RETURN_NONE;
+	}
+
 	Py_INCREF(tmp);
 	Py_XDECREF(self->x);
 
@@ -256,43 +257,37 @@ MatrixPointer_setX(MatrixPointer *self, PyObject *arg)
     Py_INCREF(streamtmp);
     Py_XDECREF(self->x_stream);
     self->x_stream = (Stream *)streamtmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 MatrixPointer_setY(MatrixPointer *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	int isNumber = PyNumber_Check(arg);
-	if (isNumber == 1) {
-		PySys_WriteStderr("MatrixPointer y attributes must be a PyoObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
-	}
-	
+
+    ASSERT_ARG_NOT_NULL
+
 	tmp = arg;
+
+	if (PyObject_HasAttrString((PyObject *)tmp, "server") == 0) {
+        PyErr_SetString(PyExc_TypeError, "\"y\" attribute of MatrixPointer must be a PyoObject.\n");
+        Py_RETURN_NONE;
+	}
+
 	Py_INCREF(tmp);
 	Py_XDECREF(self->y);
-    
+
     self->y = tmp;
     streamtmp = PyObject_CallMethod((PyObject *)self->y, "_getStream", NULL);
     Py_INCREF(streamtmp);
     Py_XDECREF(self->y_stream);
     self->y_stream = (Stream *)streamtmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef MatrixPointer_members[] = {
 {"server", T_OBJECT_EX, offsetof(MatrixPointer, server), 0, "Pyo server."},
@@ -326,7 +321,7 @@ static PyNumberMethods MatrixPointer_as_number = {
 (binaryfunc)MatrixPointer_add,                      /*nb_add*/
 (binaryfunc)MatrixPointer_sub,                 /*nb_subtract*/
 (binaryfunc)MatrixPointer_multiply,                 /*nb_multiply*/
-(binaryfunc)MatrixPointer_div,                   /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -340,16 +335,16 @@ static PyNumberMethods MatrixPointer_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
 (binaryfunc)MatrixPointer_inplace_add,              /*inplace_add*/
 (binaryfunc)MatrixPointer_inplace_sub,         /*inplace_subtract*/
 (binaryfunc)MatrixPointer_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)MatrixPointer_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -358,15 +353,14 @@ static PyNumberMethods MatrixPointer_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)MatrixPointer_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)MatrixPointer_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_x */
 };
 
 PyTypeObject MatrixPointerType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.MatrixPointer_base",         /*tp_name*/
 sizeof(MatrixPointer),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -374,7 +368,7 @@ sizeof(MatrixPointer),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &MatrixPointer_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -404,4 +398,4 @@ MatrixPointer_members,             /* tp_members */
 0,      /* tp_init */
 0,                         /* tp_alloc */
 MatrixPointer_new,                 /* tp_new */
-};
+};
\ No newline at end of file
diff --git a/src/objects/metromodule.c b/src/objects/metromodule.c
index 2279b70..998e2b8 100644
--- a/src/objects/metromodule.c
+++ b/src/objects/metromodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include "pyomodule.h"
 #include "streammodule.h"
@@ -44,23 +45,23 @@ Metro_generate_i(Metro *self) {
     MYFLT val;
     double tm, off;
     int i;
-    
+
     tm = PyFloat_AS_DOUBLE(self->time);
     off = tm * self->offset;
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (self->currentTime >= tm) {
             val = 0;
             self->currentTime -= tm;
             self->flag = 1;
-        }    
+        }
         else if (self->currentTime >= off && self->flag == 1) {
             val = 1;
             self->flag = 0;
-        }    
+        }
         else
             val = 0;
-        
+
         self->data[i] = val;
         self->currentTime += self->sampleToSec;
     }
@@ -71,9 +72,9 @@ Metro_generate_a(Metro *self) {
     MYFLT val;
     double off, tmd;
     int i;
-    
+
     MYFLT *tm = Stream_getData((Stream *)self->time_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         tmd = (double)tm[i];
         off = tmd * self->offset;
@@ -85,10 +86,10 @@ Metro_generate_a(Metro *self) {
         else if (self->currentTime >= off && self->flag == 1) {
             val = 1;
             self->flag = 0;
-        }    
+        }
         else
             val = 0;
-        
+
         self->data[i] = val;
         self->currentTime += self->sampleToSec;
     }
@@ -112,48 +113,48 @@ Metro_setProcMode(Metro *self)
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
     switch (procmode) {
-        case 0:        
+        case 0:
             self->proc_func_ptr = Metro_generate_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Metro_generate_a;
             break;
     }
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Metro_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Metro_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Metro_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Metro_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Metro_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Metro_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Metro_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Metro_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Metro_postprocessing_revareva;
             break;
-    } 
+    }
 }
 
 static void
 Metro_compute_next_data_frame(Metro *self)
 {
-    (*self->proc_func_ptr)(self);    
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -161,16 +162,16 @@ static int
 Metro_traverse(Metro *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->time);    
-    Py_VISIT(self->time_stream);    
+    Py_VISIT(self->time);
+    Py_VISIT(self->time_stream);
     return 0;
 }
 
-static int 
+static int
 Metro_clear(Metro *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->time);    
+    Py_CLEAR(self->time);
     Py_CLEAR(self->time_stream);
     return 0;
 }
@@ -180,7 +181,7 @@ Metro_dealloc(Metro* self)
 {
     pyo_DEALLOC
     Metro_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -190,7 +191,7 @@ Metro_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *timetmp=NULL;
     Metro *self;
     self = (Metro *)type->tp_alloc(type, 0);
-    
+
     self->time = PyFloat_FromDouble(1.);
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
@@ -207,27 +208,27 @@ Metro_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->currentTime = 0.;
 
     static char *kwlist[] = {"time", "offset", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|Od", kwlist, &timetmp, &self->offset))
         Py_RETURN_NONE;
 
     if (timetmp) {
         PyObject_CallMethod((PyObject *)self, "setTime", "O", timetmp);
     }
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * Metro_getServer(Metro* self) { GET_SERVER };
 static PyObject * Metro_getStream(Metro* self) { GET_STREAM };
-static PyObject * Metro_setMul(Metro *self, PyObject *arg) { SET_MUL };	
-static PyObject * Metro_setAdd(Metro *self, PyObject *arg) { SET_ADD };	
-static PyObject * Metro_setSub(Metro *self, PyObject *arg) { SET_SUB };	
-static PyObject * Metro_setDiv(Metro *self, PyObject *arg) { SET_DIV };	
+static PyObject * Metro_setMul(Metro *self, PyObject *arg) { SET_MUL };
+static PyObject * Metro_setAdd(Metro *self, PyObject *arg) { SET_ADD };
+static PyObject * Metro_setSub(Metro *self, PyObject *arg) { SET_SUB };
+static PyObject * Metro_setDiv(Metro *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Metro_play(Metro *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Metro_stop(Metro *self) { STOP };
@@ -245,14 +246,11 @@ static PyObject *
 Metro_setTime(Metro *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->time);
@@ -268,12 +266,12 @@ Metro_setTime(Metro *self, PyObject *arg)
         self->time_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Metro_members[] = {
 {"server", T_OBJECT_EX, offsetof(Metro, server), 0, "Pyo server."},
@@ -290,7 +288,7 @@ static PyMethodDef Metro_methods[] = {
 {"play", (PyCFunction)Metro_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
 {"stop", (PyCFunction)Metro_stop, METH_NOARGS, "Stops computing."},
 {"setTime", (PyCFunction)Metro_setTime, METH_O, "Sets time factor."},
-{"setMul", (PyCFunction)Metro_setMul, METH_O, "Sets oscillator mul factor."}, 
+{"setMul", (PyCFunction)Metro_setMul, METH_O, "Sets oscillator mul factor."},
 {"setAdd", (PyCFunction)Metro_setAdd, METH_O, "Sets oscillator add factor."},
 {"setSub", (PyCFunction)Metro_setSub, METH_O, "Sets inverse add factor."},
 {"setDiv", (PyCFunction)Metro_setDiv, METH_O, "Sets inverse mul factor."},
@@ -301,7 +299,7 @@ static PyNumberMethods Metro_as_number = {
     (binaryfunc)Metro_add,                         /*nb_add*/
     (binaryfunc)Metro_sub,                         /*nb_subtract*/
     (binaryfunc)Metro_multiply,                    /*nb_multiply*/
-    (binaryfunc)Metro_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -315,16 +313,16 @@ static PyNumberMethods Metro_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Metro_inplace_add,                 /*inplace_add*/
     (binaryfunc)Metro_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Metro_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Metro_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -333,15 +331,14 @@ static PyNumberMethods Metro_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Metro_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Metro_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject MetroType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Metro_base",         /*tp_name*/
 sizeof(Metro),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -349,7 +346,7 @@ sizeof(Metro),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &Metro_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -388,107 +385,197 @@ typedef struct {
     pyo_audio_HEAD
     PyObject *time;
     Stream *time_stream;
+    PyObject *speed;
+    Stream *speed_stream;
     PyObject *tmp;
-    int modebuffer[1];
+    int modebuffer[2];
     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
 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;
 }
 
 static void
-Seqer_generate_i(Seqer *self) {
-    double tm;
+Seqer_generate_ii(Seqer *self) {
+    double tm, sp;
     int i;
-    
+
     tm = PyFloat_AS_DOUBLE(self->time);
+    sp = PyFloat_AS_DOUBLE(self->speed);
 
-    if (self->currentTime == -1.0) {
-        self->currentTime = tm;
-    }    
-    
     for (i=0; i<(self->poly*self->bufsize); i++) {
         self->buffer_streams[i] = 0.0;
     }
-        
-    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->to_stop) {
+        PyObject_CallMethod((PyObject *)self, "stop", NULL);
+        self->to_stop = 0;
+        return;
+    }
+
+    for (i=0; i<self->bufsize; i++) {
+        self->currentTime += (self->sampleToSec * sp);
+        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;
+                }
+            }
+        }
+    }
+}
+
+static void
+Seqer_generate_ai(Seqer *self) {
+    int i;
+    double sp;
+
+    MYFLT *time = Stream_getData((Stream *)self->time_stream);
+    sp = PyFloat_AS_DOUBLE(self->speed);
+
+    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 * sp);
+        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;
+                }
+            }
+        }
     }
 }
 
 static void
-Seqer_generate_a(Seqer *self) {
+Seqer_generate_ia(Seqer *self) {
     double tm;
     int i;
-    
+
+    tm = PyFloat_AS_DOUBLE(self->time);
+    MYFLT *speed = Stream_getData((Stream *)self->speed_stream);
+
+    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 * (double)speed[i]);
+        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;
+                }
+            }
+        }
+    }
+}
+
+static void
+Seqer_generate_aa(Seqer *self) {
+    int i;
+
     MYFLT *time = Stream_getData((Stream *)self->time_stream);
-    
-    if (self->currentTime == -1.0) {
-        self->currentTime = time[0];
-    }    
-    
+    MYFLT *speed = Stream_getData((Stream *)self->speed_stream);
+
     for (i=0; i<(self->poly*self->bufsize); i++) {
         self->buffer_streams[i] = 0.0;
     }
-    
-    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->to_stop) {
+        PyObject_CallMethod((PyObject *)self, "stop", NULL);
+        self->to_stop = 0;
+        return;
+    }
+
+    for (i=0; i<self->bufsize; i++) {
+        self->currentTime += (self->sampleToSec * (double)speed[i]);
+        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;
+                }
+            }
+        }
     }
 }
 
@@ -496,18 +583,24 @@ MYFLT *
 Seqer_getSamplesBuffer(Seqer *self)
 {
     return (MYFLT *)self->buffer_streams;
-}    
+}
 
 static void
 Seqer_setProcMode(Seqer *self)
 {
-    int procmode = self->modebuffer[0];
+    int procmode = self->modebuffer[0] + self->modebuffer[1] * 10;
     switch (procmode) {
-        case 0:        
-            self->proc_func_ptr = Seqer_generate_i;
+        case 0:
+            self->proc_func_ptr = Seqer_generate_ii;
+            break;
+        case 1:
+            self->proc_func_ptr = Seqer_generate_ai;
             break;
-        case 1:    
-            self->proc_func_ptr = Seqer_generate_a;
+        case 10:
+            self->proc_func_ptr = Seqer_generate_ia;
+            break;
+        case 11:
+            self->proc_func_ptr = Seqer_generate_aa;
             break;
     }
 }
@@ -515,25 +608,29 @@ Seqer_setProcMode(Seqer *self)
 static void
 Seqer_compute_next_data_frame(Seqer *self)
 {
-    (*self->proc_func_ptr)(self);    
+    (*self->proc_func_ptr)(self);
 }
 
 static int
 Seqer_traverse(Seqer *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->time);    
-    Py_VISIT(self->time_stream);  
+    Py_VISIT(self->time);
+    Py_VISIT(self->time_stream);
+    Py_VISIT(self->speed);
+    Py_VISIT(self->speed_stream);
     Py_VISIT(self->tmp);
     return 0;
 }
 
-static int 
+static int
 Seqer_clear(Seqer *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->time);    
+    Py_CLEAR(self->time);
     Py_CLEAR(self->time_stream);
+    Py_CLEAR(self->speed);
+    Py_CLEAR(self->speed_stream);
     Py_CLEAR(self->tmp);
     return 0;
 }
@@ -542,81 +639,91 @@ static void
 Seqer_dealloc(Seqer* self)
 {
     pyo_DEALLOC
+    free(self->seq);
     free(self->buffer_streams);
     Seqer_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
 Seqer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
-    PyObject *timetmp=NULL, *seqtmp=NULL;
+    PyObject *timetmp=NULL, *speedtmp=NULL, *seqtmp=NULL;
     Seqer *self;
     self = (Seqer *)type->tp_alloc(type, 0);
-    
+
     self->time = PyFloat_FromDouble(1.);
-    self->flag = 1;
+    self->speed = PyFloat_FromDouble(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;
-    
+	self->modebuffer[1] = 0;
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Seqer_compute_next_data_frame);
     self->mode_func_ptr = Seqer_setProcMode;
-    
+
     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", "onlyonce", "speed", NULL};
 
-    static char *kwlist[] = {"time", "seq", "poly", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOi", kwlist, &timetmp, &seqtmp, &self->poly))
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOiiO", kwlist, &timetmp, &seqtmp, &self->poly, &self->onlyonce, &speedtmp))
         Py_RETURN_NONE;
-    
+
     if (timetmp) {
         PyObject_CallMethod((PyObject *)self, "setTime", "O", timetmp);
     }
 
+    if (speedtmp) {
+        PyObject_CallMethod((PyObject *)self, "setSpeed", "O", speedtmp);
+    }
+
     if (seqtmp) {
         PyObject_CallMethod((PyObject *)self, "setSeq", "O", seqtmp);
     }
-    
+    Seqer_reset(self);
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, self->poly * self->bufsize * sizeof(MYFLT));
 
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 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 *
 Seqer_setTime(Seqer *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->time);
@@ -632,25 +739,53 @@ Seqer_setTime(Seqer *self, PyObject *arg)
         self->time_stream = (Stream *)streamtmp;
 		self->modebuffer[0] = 1;
 	}
-    
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+Seqer_setSpeed(Seqer *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->speed);
+	if (isNumber == 1) {
+		self->speed = PyNumber_Float(tmp);
+        self->modebuffer[1] = 0;
+	}
+	else {
+		self->speed = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->speed, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->speed_stream);
+        self->speed_stream = (Stream *)streamtmp;
+		self->modebuffer[1] = 1;
+	}
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Seqer_setSeq(Seqer *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isList = PyList_Check(arg);
-	
+
 	if (isList == 1) {
         tmp = arg;
         Py_INCREF(tmp);
@@ -658,15 +793,31 @@ Seqer_setSeq(Seqer *self, PyObject *arg)
         self->tmp = tmp;
         self->newseq = 1;
     }
-    
+
+	Py_INCREF(Py_None);
+	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."},
     {"time", T_OBJECT_EX, offsetof(Seqer, time), 0, "Seqer time factor."},
+    {"speed", T_OBJECT_EX, offsetof(Seqer, speed), 0, "Seqer speed factor."},
     {NULL}  /* Sentinel */
 };
 
@@ -676,13 +827,14 @@ static PyMethodDef Seqer_methods[] = {
     {"play", (PyCFunction)Seqer_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
     {"stop", (PyCFunction)Seqer_stop, METH_NOARGS, "Stops computing."},
     {"setTime", (PyCFunction)Seqer_setTime, METH_O, "Sets time factor."},
+    {"setSpeed", (PyCFunction)Seqer_setSpeed, METH_O, "Sets speed factor."},
     {"setSeq", (PyCFunction)Seqer_setSeq, METH_O, "Sets duration sequence."},
+    {"setOnlyonce", (PyCFunction)Seqer_setOnlyonce, METH_O, "Sets onlyonce attribute."},
     {NULL}  /* Sentinel */
 };
 
 PyTypeObject SeqerType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Seqer_base",         /*tp_name*/
     sizeof(Seqer),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -690,7 +842,7 @@ PyTypeObject SeqerType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     0,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -728,7 +880,7 @@ PyTypeObject SeqerType = {
 typedef struct {
     pyo_audio_HEAD
     Seqer *mainPlayer;
-    int chnl; 
+    int chnl;
     int modebuffer[2];
 } Seq;
 
@@ -746,36 +898,36 @@ static void
 Seq_setProcMode(Seq *self) {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Seq_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Seq_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Seq_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Seq_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Seq_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Seq_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Seq_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Seq_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Seq_postprocessing_revareva;
             break;
-    }      
+    }
 }
 
 static void
@@ -787,7 +939,7 @@ Seq_compute_next_data_frame(Seq *self)
     tmp = Seqer_getSamplesBuffer((Seqer *)self->mainPlayer);
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = tmp[i + offset];
-    }    
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -799,11 +951,11 @@ Seq_traverse(Seq *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Seq_clear(Seq *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->mainPlayer);    
+    Py_CLEAR(self->mainPlayer);
     return 0;
 }
 
@@ -812,7 +964,7 @@ Seq_dealloc(Seq* self)
 {
     pyo_DEALLOC
     Seq_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -822,37 +974,37 @@ Seq_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *maintmp=NULL;
     Seq *self;
     self = (Seq *)type->tp_alloc(type, 0);
-    
+
     self->chnl = 0;
     self->modebuffer[0] = 0;
     self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Seq_compute_next_data_frame);
     self->mode_func_ptr = Seq_setProcMode;
 
     static char *kwlist[] = {"mainPlayer", "chnl", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &maintmp, &self->chnl))
         Py_RETURN_NONE;
-    
+
     Py_XDECREF(self->mainPlayer);
     Py_INCREF(maintmp);
     self->mainPlayer = (Seqer *)maintmp;
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * Seq_getServer(Seq* self) { GET_SERVER };
 static PyObject * Seq_getStream(Seq* self) { GET_STREAM };
-static PyObject * Seq_setMul(Seq *self, PyObject *arg) { SET_MUL };	
-static PyObject * Seq_setAdd(Seq *self, PyObject *arg) { SET_ADD };	
-static PyObject * Seq_setSub(Seq *self, PyObject *arg) { SET_SUB };	
-static PyObject * Seq_setDiv(Seq *self, PyObject *arg) { SET_DIV };	
+static PyObject * Seq_setMul(Seq *self, PyObject *arg) { SET_MUL };
+static PyObject * Seq_setAdd(Seq *self, PyObject *arg) { SET_ADD };
+static PyObject * Seq_setSub(Seq *self, PyObject *arg) { SET_SUB };
+static PyObject * Seq_setDiv(Seq *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Seq_play(Seq *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Seq_out(Seq *self, PyObject *args, PyObject *kwds) { OUT };
@@ -884,7 +1036,7 @@ static PyMethodDef Seq_methods[] = {
     {"setMul", (PyCFunction)Seq_setMul, METH_O, "Sets oscillator mul factor."},
     {"setAdd", (PyCFunction)Seq_setAdd, METH_O, "Sets oscillator add factor."},
     {"setSub", (PyCFunction)Seq_setSub, METH_O, "Sets inverse add factor."},
-    {"setDiv", (PyCFunction)Seq_setDiv, METH_O, "Sets inverse mul factor."},    
+    {"setDiv", (PyCFunction)Seq_setDiv, METH_O, "Sets inverse mul factor."},
     {NULL}  /* Sentinel */
 };
 
@@ -892,7 +1044,7 @@ static PyNumberMethods Seq_as_number = {
     (binaryfunc)Seq_add,                         /*nb_add*/
     (binaryfunc)Seq_sub,                         /*nb_subtract*/
     (binaryfunc)Seq_multiply,                    /*nb_multiply*/
-    (binaryfunc)Seq_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -906,16 +1058,16 @@ static PyNumberMethods Seq_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Seq_inplace_add,                 /*inplace_add*/
     (binaryfunc)Seq_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Seq_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Seq_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -924,15 +1076,14 @@ static PyNumberMethods Seq_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Seq_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Seq_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject SeqType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Seq_base",         /*tp_name*/
     sizeof(Seq),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -940,7 +1091,7 @@ PyTypeObject SeqType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &Seq_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -987,7 +1138,8 @@ typedef struct {
 
 static void
 Clouder_generate_i(Clouder *self) {
-    int i, rnd;
+    int i;
+    MYFLT rnd;
 
     MYFLT dens = PyFloat_AS_DOUBLE(self->density);
     if (dens <= 0.0)
@@ -998,43 +1150,44 @@ Clouder_generate_i(Clouder *self) {
     for (i=0; i<(self->poly*self->bufsize); i++) {
         self->buffer_streams[i] = 0.0;
     }
-    
+
     dens *= 0.5;
     for (i=0; i<self->bufsize; i++) {
-        rnd = (int)(rand() / (MYFLT)RAND_MAX * self->sr);
+        rnd = RANDOM_UNIFORM * self->sr;
         if (rnd < dens) {
             self->buffer_streams[i + self->voiceCount++ * self->bufsize] = 1.0;
             if (self->voiceCount == self->poly)
                 self->voiceCount = 0;
-        }        
+        }
     }
 }
 
 static void
 Clouder_generate_a(Clouder *self) {
     MYFLT dens;
-    int i, rnd;
-    
+    int i;
+    MYFLT rnd;
+
     MYFLT *density = Stream_getData((Stream *)self->density_stream);
 
     for (i=0; i<(self->poly*self->bufsize); i++) {
         self->buffer_streams[i] = 0.0;
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         dens = density[i];
         if (dens <= 0.0)
             dens = 0.0;
         else if (dens > self->sr)
             dens = self->sr;
-        
+
         dens *= 0.5;
-        rnd = (int)(rand() / (MYFLT)RAND_MAX * self->sr);
+        rnd = RANDOM_UNIFORM * self->sr;
         if (rnd < dens) {
             self->buffer_streams[i + self->voiceCount++ * self->bufsize] = 1.0;
             if (self->voiceCount == self->poly)
                 self->voiceCount = 0;
-        } 
+        }
     }
 }
 
@@ -1042,17 +1195,17 @@ MYFLT *
 Clouder_getSamplesBuffer(Clouder *self)
 {
     return (MYFLT *)self->buffer_streams;
-}    
+}
 
 static void
 Clouder_setProcMode(Clouder *self)
 {
     int procmode = self->modebuffer[0];
     switch (procmode) {
-        case 0:        
+        case 0:
             self->proc_func_ptr = Clouder_generate_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Clouder_generate_a;
             break;
     }
@@ -1061,23 +1214,23 @@ Clouder_setProcMode(Clouder *self)
 static void
 Clouder_compute_next_data_frame(Clouder *self)
 {
-    (*self->proc_func_ptr)(self);    
+    (*self->proc_func_ptr)(self);
 }
 
 static int
 Clouder_traverse(Clouder *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->density);    
-    Py_VISIT(self->density_stream);    
+    Py_VISIT(self->density);
+    Py_VISIT(self->density_stream);
     return 0;
 }
 
-static int 
+static int
 Clouder_clear(Clouder *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->density);    
+    Py_CLEAR(self->density);
     Py_CLEAR(self->density_stream);
     return 0;
 }
@@ -1088,7 +1241,7 @@ Clouder_dealloc(Clouder* self)
     pyo_DEALLOC
     free(self->buffer_streams);
     Clouder_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1098,35 +1251,35 @@ Clouder_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *densitytmp=NULL;
     Clouder *self;
     self = (Clouder *)type->tp_alloc(type, 0);
-    
+
     self->density = PyFloat_FromDouble(10.0);
     self->poly = 1;
     self->voiceCount = 0;
 	self->modebuffer[0] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Clouder_compute_next_data_frame);
     self->mode_func_ptr = Clouder_setProcMode;
-    
+
     Stream_setStreamActive(self->stream, 0);
 
     static char *kwlist[] = {"density", "poly", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|Oi", kwlist, &densitytmp, &self->poly))
         Py_RETURN_NONE;
-    
+
     if (densitytmp) {
         PyObject_CallMethod((PyObject *)self, "setDensity", "O", densitytmp);
     }
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     (*self->mode_func_ptr)(self);
 
     Server_generateSeed((Server *)self->server, CLOUD_ID);
 
     self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, self->poly * self->bufsize * sizeof(MYFLT));
-    
+
     return (PyObject *)self;
 }
 
@@ -1140,14 +1293,11 @@ static PyObject *
 Clouder_setDensity(Clouder *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->density);
@@ -1163,12 +1313,12 @@ Clouder_setDensity(Clouder *self, PyObject *arg)
         self->density_stream = (Stream *)streamtmp;
 		self->modebuffer[0] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Clouder_members[] = {
 {"server", T_OBJECT_EX, offsetof(Clouder, server), 0, "Pyo server."},
@@ -1187,8 +1337,7 @@ static PyMethodDef Clouder_methods[] = {
 };
 
 PyTypeObject ClouderType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Clouder_base",         /*tp_name*/
 sizeof(Clouder),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -1196,7 +1345,7 @@ sizeof(Clouder),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 0,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -1234,7 +1383,7 @@ Clouder_new,                 /* tp_new */
 typedef struct {
     pyo_audio_HEAD
     Clouder *mainPlayer;
-    int chnl; 
+    int chnl;
     int modebuffer[2];
 } Cloud;
 
@@ -1252,36 +1401,36 @@ static void
 Cloud_setProcMode(Cloud *self) {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Cloud_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Cloud_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Cloud_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Cloud_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Cloud_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Cloud_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Cloud_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Cloud_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Cloud_postprocessing_revareva;
             break;
-    }      
+    }
 }
 
 static void
@@ -1293,7 +1442,7 @@ Cloud_compute_next_data_frame(Cloud *self)
     tmp = Clouder_getSamplesBuffer((Clouder *)self->mainPlayer);
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = tmp[i + offset];
-    }    
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1305,11 +1454,11 @@ Cloud_traverse(Cloud *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Cloud_clear(Cloud *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->mainPlayer);    
+    Py_CLEAR(self->mainPlayer);
     return 0;
 }
 
@@ -1318,7 +1467,7 @@ Cloud_dealloc(Cloud* self)
 {
     pyo_DEALLOC
     Cloud_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1328,37 +1477,37 @@ Cloud_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *maintmp=NULL;
     Cloud *self;
     self = (Cloud *)type->tp_alloc(type, 0);
-    
+
     self->chnl = 0;
     self->modebuffer[0] = 0;
     self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Cloud_compute_next_data_frame);
     self->mode_func_ptr = Cloud_setProcMode;
 
     static char *kwlist[] = {"mainPlayer", "chnl", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &maintmp, &self->chnl))
         Py_RETURN_NONE;
-    
+
     Py_XDECREF(self->mainPlayer);
     Py_INCREF(maintmp);
     self->mainPlayer = (Clouder *)maintmp;
 
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * Cloud_getServer(Cloud* self) { GET_SERVER };
 static PyObject * Cloud_getStream(Cloud* self) { GET_STREAM };
-static PyObject * Cloud_setMul(Cloud *self, PyObject *arg) { SET_MUL };	
-static PyObject * Cloud_setAdd(Cloud *self, PyObject *arg) { SET_ADD };	
-static PyObject * Cloud_setSub(Cloud *self, PyObject *arg) { SET_SUB };	
-static PyObject * Cloud_setDiv(Cloud *self, PyObject *arg) { SET_DIV };	
+static PyObject * Cloud_setMul(Cloud *self, PyObject *arg) { SET_MUL };
+static PyObject * Cloud_setAdd(Cloud *self, PyObject *arg) { SET_ADD };
+static PyObject * Cloud_setSub(Cloud *self, PyObject *arg) { SET_SUB };
+static PyObject * Cloud_setDiv(Cloud *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Cloud_play(Cloud *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Cloud_out(Cloud *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1390,7 +1539,7 @@ static PyMethodDef Cloud_methods[] = {
 {"setMul", (PyCFunction)Cloud_setMul, METH_O, "Sets oscillator mul factor."},
 {"setAdd", (PyCFunction)Cloud_setAdd, METH_O, "Sets oscillator add factor."},
 {"setSub", (PyCFunction)Cloud_setSub, METH_O, "Sets inverse add factor."},
-{"setDiv", (PyCFunction)Cloud_setDiv, METH_O, "Sets inverse mul factor."},    
+{"setDiv", (PyCFunction)Cloud_setDiv, METH_O, "Sets inverse mul factor."},
 {NULL}  /* Sentinel */
 };
 
@@ -1398,7 +1547,7 @@ static PyNumberMethods Cloud_as_number = {
     (binaryfunc)Cloud_add,                         /*nb_add*/
     (binaryfunc)Cloud_sub,                         /*nb_subtract*/
     (binaryfunc)Cloud_multiply,                    /*nb_multiply*/
-    (binaryfunc)Cloud_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -1412,16 +1561,16 @@ static PyNumberMethods Cloud_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Cloud_inplace_add,                 /*inplace_add*/
     (binaryfunc)Cloud_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Cloud_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Cloud_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -1430,15 +1579,14 @@ static PyNumberMethods Cloud_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Cloud_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Cloud_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject CloudType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Cloud_base",         /*tp_name*/
 sizeof(Cloud),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -1446,7 +1594,7 @@ sizeof(Cloud),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &Cloud_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -1502,36 +1650,36 @@ Trig_setProcMode(Trig *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Trig_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Trig_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Trig_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Trig_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Trig_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Trig_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Trig_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Trig_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Trig_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
@@ -1540,7 +1688,7 @@ Trig_compute_next_data_frame(Trig *self)
     if (self->flag == 1) {
         self->data[0] = 1.0;
         self->flag = 0;
-    }    
+    }
     else
         self->data[0] = 0.0;
     (*self->muladd_func_ptr)(self);
@@ -1553,7 +1701,7 @@ Trig_traverse(Trig *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Trig_clear(Trig *self)
 {
     pyo_CLEAR
@@ -1565,7 +1713,7 @@ Trig_dealloc(Trig* self)
 {
     pyo_DEALLOC
     Trig_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1574,38 +1722,38 @@ Trig_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     int i;
     Trig *self;
     self = (Trig *)type->tp_alloc(type, 0);
-    
+
     self->flag = 1;
     self->modebuffer[0] = 0;
     self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Trig_compute_next_data_frame);
     self->mode_func_ptr = Trig_setProcMode;
 
     static char *kwlist[] = {NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "", kwlist))
         Py_RETURN_NONE;
 
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * Trig_getServer(Trig* self) { GET_SERVER };
 static PyObject * Trig_getStream(Trig* self) { GET_STREAM };
-static PyObject * Trig_setMul(Trig *self, PyObject *arg) { SET_MUL };	
-static PyObject * Trig_setAdd(Trig *self, PyObject *arg) { SET_ADD };	
-static PyObject * Trig_setSub(Trig *self, PyObject *arg) { SET_SUB };	
-static PyObject * Trig_setDiv(Trig *self, PyObject *arg) { SET_DIV };	
+static PyObject * Trig_setMul(Trig *self, PyObject *arg) { SET_MUL };
+static PyObject * Trig_setAdd(Trig *self, PyObject *arg) { SET_ADD };
+static PyObject * Trig_setSub(Trig *self, PyObject *arg) { SET_SUB };
+static PyObject * Trig_setDiv(Trig *self, PyObject *arg) { SET_DIV };
 
-static PyObject * Trig_play(Trig *self, PyObject *args, PyObject *kwds) 
-{ 
+static PyObject * Trig_play(Trig *self, PyObject *args, PyObject *kwds)
+{
     self->flag = 1;
-    PLAY 
+    PLAY
 };
 
 static PyObject * Trig_stop(Trig *self) { STOP };
@@ -1643,7 +1791,7 @@ static PyNumberMethods Trig_as_number = {
     (binaryfunc)Trig_add,                         /*nb_add*/
     (binaryfunc)Trig_sub,                         /*nb_subtract*/
     (binaryfunc)Trig_multiply,                    /*nb_multiply*/
-    (binaryfunc)Trig_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -1657,16 +1805,16 @@ static PyNumberMethods Trig_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Trig_inplace_add,                 /*inplace_add*/
     (binaryfunc)Trig_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Trig_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Trig_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -1675,15 +1823,14 @@ static PyNumberMethods Trig_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Trig_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Trig_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject TrigType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Trig_base",         /*tp_name*/
 sizeof(Trig),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -1691,7 +1838,7 @@ sizeof(Trig),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &Trig_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -1760,6 +1907,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;
@@ -1771,16 +1920,16 @@ typedef struct {
 static MYFLT
 Beater_defineAccent(int n) {
 	if (n == 1)
-		return (MYFLT)((rand() % 15) + 112) / 127.; // 112 -> 127
+		return (MYFLT)((pyorand() % 15) + 112) / 127.; // 112 -> 127
 	else if (n == 2)
-		return (MYFLT)((rand() % 20) + 70) / 127.; // 70 -> 90
+		return (MYFLT)((pyorand() % 20) + 70) / 127.; // 70 -> 90
 	else if (n == 3)
-		return (MYFLT)((rand() % 20) + 40) / 127.; // 40 -> 60
+		return (MYFLT)((pyorand() % 20) + 40) / 127.; // 40 -> 60
     else
         return 0.5;
 }
 
-static void 
+static void
 Beater_restore(Beater *self) {
     int i;
     self->fillEnd = 0;
@@ -1789,9 +1938,9 @@ Beater_restore(Beater *self) {
         self->sequence[i] = self->tmp_sequence[i];
         self->durations[i] = self->tmp_durations[i];
     }
-}    
-    
-static void 
+}
+
+static void
 Beater_makeTable(Beater *self, int fill) {
 	short i;
 	short len;
@@ -1813,25 +1962,25 @@ Beater_makeTable(Beater *self, int fill) {
             self->tmp_accentTable[i] = self->accentTable[i];
             self->tmp_sequence[i] = self->sequence[i];
             self->tmp_durations[i] = self->durations[i];
-        }    
+        }
     }
-    
+
 	if ((self->taps % 7) == 0) {
 		len = 7;
 		for (i=0; i < self->taps; i++) {
             if ((i % len) == 4  || (i % len) == 2) {
                 self->tapProb[i] = w2;
                 self->accentTable[i] = Beater_defineAccent(2);
-            }	
+            }
             else if ((i % len) == 0) {
                 self->tapProb[i] = w1;
                 self->accentTable[i] = Beater_defineAccent(1);
-            }	
+            }
             else {
                 self->tapProb[i] = w3;
                 self->accentTable[i] = Beater_defineAccent(3);
-            }	
-		}	
+            }
+		}
 	}
 	else if ((self->taps % 6) == 0) {
 		len = 6;
@@ -1839,7 +1988,7 @@ Beater_makeTable(Beater *self, int fill) {
             if ((i % len) == 3) {
                 self->tapProb[i] = w2;
                 self->accentTable[i] = Beater_defineAccent(2);
-            }	
+            }
             else if ((i % len) == 0) {
                 self->tapProb[i] = w1;
                 self->accentTable[i] = Beater_defineAccent(1);
@@ -1847,8 +1996,8 @@ Beater_makeTable(Beater *self, int fill) {
             else {
                 self->tapProb[i] = w3;
                 self->accentTable[i] = Beater_defineAccent(3);
-            }		
-		}	
+            }
+		}
 	}
 	else if ((self->taps % 5) == 0) {
 		len = 5;
@@ -1856,7 +2005,7 @@ Beater_makeTable(Beater *self, int fill) {
             if ((i % len) == 3) {
                 self->tapProb[i] = w2;
                 self->accentTable[i] = Beater_defineAccent(2);
-            }	
+            }
             else if ((i % len) == 0) {
                 self->tapProb[i] = w1;
                 self->accentTable[i] = Beater_defineAccent(1);
@@ -1864,25 +2013,25 @@ Beater_makeTable(Beater *self, int fill) {
             else {
                 self->tapProb[i] = w3;
                 self->accentTable[i] = Beater_defineAccent(3);
-            }		
-		}	
+            }
+		}
 	}
 	else if ((self->taps % 4) == 0) {
 		len = 4;
-		for (i=0; i < self->taps; i++) {	
+		for (i=0; i < self->taps; i++) {
             if ((i % len) == 2) {
                 self->tapProb[i] = w2;
                 self->accentTable[i] = Beater_defineAccent(2);
-            }	
+            }
             else if ((i % len) == 0) {
                 self->tapProb[i] = w1;
                 self->accentTable[i] = Beater_defineAccent(1);
-            }	
+            }
             else {
                 self->tapProb[i] = w3;
                 self->accentTable[i] = Beater_defineAccent(3);
-            }	
-		}	
+            }
+		}
 	}
 	else if ((self->taps % 3) == 0) {
 		len = 3;
@@ -1894,8 +2043,8 @@ Beater_makeTable(Beater *self, int fill) {
             else {
                 self->tapProb[i] = w3;
                 self->accentTable[i] = Beater_defineAccent(3);
-            }	
-		}	
+            }
+		}
 	}
 	else if ((self->taps % 2) == 0) {
 		len = 2;
@@ -1907,22 +2056,22 @@ Beater_makeTable(Beater *self, int fill) {
             else {
                 self->tapProb[i] = w3;
                 self->accentTable[i] = Beater_defineAccent(3);
-            }	
-		}	
-	}		
+            }
+		}
+	}
 }
 
-static void 
+static void
 Beater_makeSequence(Beater *self) {
 	short i, j;
-    
+
 	j = 0;
 	for (i=0; i < self->taps; i++) {
-		if ((rand() % 100) < self->tapProb[i]) {
+		if ((int)(pyorand() % 100) < self->tapProb[i]) {
 			self->sequence[i] = 1;
 			self->tapList[j++] = i;
-		}	
-		else	
+		}
+		else
 			self->sequence[i] = 0;
 	}
 
@@ -1932,7 +2081,7 @@ Beater_makeSequence(Beater *self) {
 static void
 Beater_calculateDurations(Beater *self) {
     int i;
-    
+
     for (i=0; i < (self->tapLength-1); i++) {
 		self->durations[self->tapList[i]] = (self->tapList[i+1] - self->tapList[i]) * self->tapDur - 0.005;
 	}
@@ -1940,24 +2089,24 @@ Beater_calculateDurations(Beater *self) {
 }
 
 static void
-Beater_makePresetActive(Beater *self, int n) 
+Beater_makePresetActive(Beater *self, int n)
 {
     int i, j, len;
-    
+
     self->preCall = -1;
     len = self->preset[n][0];
     if (len != self->taps) {
         self->taps = len;
         Beater_makeTable(self, 0);
     }
-    
+
     j = 0;
     for (i=0; i<self->taps; i++) {
         self->sequence[i] = self->preset[n][i+1];
         if (self->sequence[i] == 1)
             self->tapList[j++] = i;
     }
-    
+
     self->tapLength = j;
 }
 
@@ -1965,20 +2114,26 @@ static void
 Beater_generate_i(Beater *self) {
     int i, j;
     double tm;
-    
+
     tm = PyFloat_AS_DOUBLE(self->time);
-    
+
     self->tapDur = (MYFLT)tm;
     Beater_calculateDurations(self);
 
     if (self->currentTime == -1.0) {
         self->currentTime = tm;
-    }    
-    
+    }
+
     for (i=0; i<(self->poly*self->bufsize); i++) {
         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++) {
@@ -1987,8 +2142,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-1))
+            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];
@@ -2007,11 +2163,11 @@ Beater_generate_i(Beater *self) {
                     Beater_restore(self);
                     Beater_makeTable(self, 0);
                     Beater_makeSequence(self);
-                }    
+                }
                 else if (self->fillEnd == 1 && self->preCall != -1) {
                     Beater_restore(self);
                     Beater_makePresetActive(self, self->preCall);
-                }    
+                }
                 else if (self->fillEnd == 1) {
                     Beater_restore(self);
                 }
@@ -2023,7 +2179,11 @@ Beater_generate_i(Beater *self) {
                     self->newFlag == 1) {
                     Beater_makeTable(self, 0);
                     Beater_makeSequence(self);
-                }    
+                }
+                if (self->onlyonce) {
+                    self->to_stop = 1;
+                    return;
+                }
             }
         }
         self->currentTime += self->sampleToSec;
@@ -2034,7 +2194,7 @@ static void
 Beater_generate_a(Beater *self) {
     double tm;
     int i, j;
-    
+
     MYFLT *time = Stream_getData((Stream *)self->time_stream);
 
     self->tapDur = time[0];
@@ -2042,12 +2202,18 @@ Beater_generate_a(Beater *self) {
 
     if (self->currentTime == -1.0) {
         self->currentTime = (double)time[0];
-    }    
-    
+    }
+
     for (i=0; i<(self->poly*self->bufsize); i++) {
         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;
@@ -2057,7 +2223,7 @@ Beater_generate_a(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-1))
+            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;
@@ -2081,7 +2247,7 @@ Beater_generate_a(Beater *self) {
                 else if (self->fillEnd == 1 && self->preCall != -1) {
                     Beater_restore(self);
                     Beater_makePresetActive(self, self->preCall);
-                }    
+                }
                 else if (self->fillEnd == 1) {
                     Beater_restore(self);
                 }
@@ -2094,7 +2260,11 @@ Beater_generate_a(Beater *self) {
                     self->tapDur = time[i];
                     Beater_makeTable(self, 0);
                     Beater_makeSequence(self);
-                }    
+                }
+                if (self->onlyonce) {
+                    self->to_stop = 1;
+                    return;
+                }
             }
         }
         self->currentTime += self->sampleToSec;
@@ -2105,41 +2275,41 @@ MYFLT *
 Beater_getSamplesBuffer(Beater *self)
 {
     return (MYFLT *)self->buffer_streams;
-}    
+}
 
 MYFLT *
 Beater_getTapBuffer(Beater *self)
 {
     return (MYFLT *)self->tap_buffer_streams;
-}    
+}
 
 MYFLT *
 Beater_getAmpBuffer(Beater *self)
 {
     return (MYFLT *)self->amp_buffer_streams;
-}    
+}
 
 MYFLT *
 Beater_getDurBuffer(Beater *self)
 {
     return (MYFLT *)self->dur_buffer_streams;
-}    
+}
 
 MYFLT *
 Beater_getEndBuffer(Beater *self)
 {
     return (MYFLT *)self->end_buffer_streams;
-}    
+}
 
 static void
 Beater_setProcMode(Beater *self)
 {
     int procmode = self->modebuffer[0];
     switch (procmode) {
-        case 0:        
+        case 0:
             self->proc_func_ptr = Beater_generate_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Beater_generate_a;
             break;
     }
@@ -2148,23 +2318,23 @@ Beater_setProcMode(Beater *self)
 static void
 Beater_compute_next_data_frame(Beater *self)
 {
-    (*self->proc_func_ptr)(self);    
+    (*self->proc_func_ptr)(self);
 }
 
 static int
 Beater_traverse(Beater *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->time);    
-    Py_VISIT(self->time_stream);    
+    Py_VISIT(self->time);
+    Py_VISIT(self->time_stream);
     return 0;
 }
 
-static int 
+static int
 Beater_clear(Beater *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->time);    
+    Py_CLEAR(self->time);
     Py_CLEAR(self->time_stream);
     return 0;
 }
@@ -2180,7 +2350,7 @@ Beater_dealloc(Beater* self)
     free(self->end_buffer_streams);
     free(self->amplitudes);
     Beater_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2190,20 +2360,22 @@ Beater_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *timetmp=NULL;
     Beater *self;
     self = (Beater *)type->tp_alloc(type, 0);
-    
+
     for (i=0; i<32; i++) {
         for (j=0; j<64; j++) {
             self->preset[i][j] = 0;
         }
     }
-    
+
     self->preCall = -1;
     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;
-    
+
     self->taps = 16;
     self->tapCount = 0;
     self->currentTap = 0;
@@ -2213,31 +2385,31 @@ Beater_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->last_taps = self->last_weight1 = self->last_weight2 = self->last_weight3 = -1;
     self->newFlag = self->fillStart = self->fillEnd = 0;
     self->tapLength = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Beater_compute_next_data_frame);
     self->mode_func_ptr = Beater_setProcMode;
-    
+
     self->sampleToSec = 1. / self->sr;
     self->currentTime = -1.0;
 
     Stream_setStreamActive(self->stream, 0);
 
-    static char *kwlist[] = {"time", "taps", "weight1", "weight2", "weight3", "poly", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|Oiiiii", kwlist, &timetmp, &self->taps, &self->weight1, &self->weight2, &self->weight3, &self->poly))
+    static char *kwlist[] = {"time", "taps", "weight1", "weight2", "weight3", "poly", "onlyonce", NULL};
+
+    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) {
         PyObject_CallMethod((PyObject *)self, "setTime", "O", timetmp);
     }
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     Server_generateSeed((Server *)self->server, BEATER_ID);
-    
+
     self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, self->poly * self->bufsize * sizeof(MYFLT));
     self->tap_buffer_streams = (MYFLT *)realloc(self->tap_buffer_streams, self->poly * self->bufsize * sizeof(MYFLT));
     self->amp_buffer_streams = (MYFLT *)realloc(self->amp_buffer_streams, self->poly * self->bufsize * sizeof(MYFLT));
@@ -2247,34 +2419,38 @@ Beater_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         self->buffer_streams[i] = self->tap_buffer_streams[i] = self->amp_buffer_streams[i] = self->dur_buffer_streams[i] = self->end_buffer_streams[i] = 0.0;
     }
     self->amplitudes = (MYFLT *)realloc(self->amplitudes, self->poly * sizeof(MYFLT));
-    for (i=0; i<self->poly; i++) { 
+    for (i=0; i<self->poly; i++) {
         self->amplitudes[i] = 0.0;
     }
-        
+
     Beater_makeTable(self, 0);
     Beater_makeSequence(self);
-    
+
     return (PyObject *)self;
 }
 
 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 *
 Beater_setTime(Beater *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->time);
@@ -2293,35 +2469,46 @@ Beater_setTime(Beater *self, PyObject *arg)
         MYFLT *time = Stream_getData((Stream *)self->time_stream);
         self->tapDur = time[0];
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+Beater_reset(Beater *self)
+{
+    self->voiceCount = 0;
+    self->tapCount = 0;
+    self->currentTap = 0;
+    self->currentTime = -1.0;
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Beater_setTaps(Beater *self, PyObject *arg)
-{    
+{
 	if (PyInt_Check(arg))
         self->taps = PyInt_AS_LONG(arg);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Beater_setWeights(Beater *self, PyObject *args, PyObject *kwds)
-{    
+{
     PyObject *w1=NULL, *w2=NULL, *w3=NULL;
-    
+
     static char *kwlist[] = {"weight1", "weight2", "weight3", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOO", kwlist, &w1, &w2, &w3)) {
         Py_INCREF(Py_None);
         return Py_None;
-    }    
-    
+    }
+
 	if (PyInt_Check(w1))
         self->weight1 = PyInt_AS_LONG(w1);
 
@@ -2333,19 +2520,27 @@ Beater_setWeights(Beater *self, PyObject *args, PyObject *kwds)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
-Beater_newPattern(Beater *self)
-{    
-    self->newFlag = 1;
+Beater_newPattern(Beater *self, PyObject *arg)
+{
+    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;
 }
 
 static PyObject *
 Beater_fillPattern(Beater *self)
-{    
+{
     self->fillStart = 1;
 	Py_INCREF(Py_None);
 	return Py_None;
@@ -2355,17 +2550,17 @@ static PyObject *
 Beater_storePreset(Beater *self, PyObject *arg)
 {
     int i, n;
-    
+
     if (PyInt_Check(arg)) {
         n = PyInt_AS_LONG(arg);
         self->preset[n][0] = self->taps;
         for (i=0; i<self->taps; i++) {
             self->preset[n][i+1] = self->sequence[i];
-        }    
+        }
     }
 
 	Py_INCREF(Py_None);
-	return Py_None;    
+	return Py_None;
 }
 
 static PyObject *
@@ -2377,32 +2572,32 @@ Beater_recallPreset(Beater *self, PyObject *arg)
         if (x >= 0 && x < 32)
             self->preCall = x;
     }
-    
+
     if (Stream_getStreamActive(self->stream) == 0)
         Beater_makePresetActive(self, self->preCall);
-    
+
     Py_INCREF(Py_None);
-    return Py_None;    
+    return Py_None;
 
-}        
+}
 
 static PyObject *
 Beater_getPresets(Beater *self) {
     int i, j;
     PyObject *list, *tmp;
-    
+
     list = PyList_New(0);
     for (i=0; i<32; i++) {
         if (self->preset[i][0] != 0) {
             tmp = PyList_New(0);
-            PyList_Append(tmp, PyInt_FromLong(self->preset[i][0])); 
+            PyList_Append(tmp, PyInt_FromLong(self->preset[i][0]));
             for (j=0; j<self->preset[i][0]; j++) {
                 PyList_Append(tmp, PyInt_FromLong(self->preset[i][j+1]));
             }
             PyList_Append(list, tmp);
         }
     }
-    
+
     return list;
 }
 
@@ -2418,14 +2613,29 @@ Beater_setPresets(Beater *self, PyObject *arg) {
             if (PyList_Check(tmp)) {
                 len2 = PyInt_AsLong(PyList_GetItem(tmp, 0));
                 self->preset[i][0] = len2;
-                for (j=0; j<len2; j++) {                    
+                for (j=0; j<len2; j++) {
                     self->preset[i][j+1] = PyInt_AsLong(PyList_GetItem(tmp, j+1));
                 }
             }
         }
-    }    
+    }
     Py_INCREF(Py_None);
-    return Py_None;    
+    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[] = {
@@ -2443,18 +2653,19 @@ 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 */
 };
 
 PyTypeObject BeaterType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Beater_base",         /*tp_name*/
     sizeof(Beater),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -2462,7 +2673,7 @@ PyTypeObject BeaterType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     0,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -2500,7 +2711,7 @@ PyTypeObject BeaterType = {
 typedef struct {
     pyo_audio_HEAD
     Beater *mainPlayer;
-    int chnl; 
+    int chnl;
     int modebuffer[2];
 } Beat;
 
@@ -2518,36 +2729,36 @@ static void
 Beat_setProcMode(Beat *self) {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Beat_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Beat_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Beat_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Beat_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Beat_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Beat_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Beat_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Beat_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Beat_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
@@ -2559,7 +2770,7 @@ Beat_compute_next_data_frame(Beat *self)
     tmp = Beater_getSamplesBuffer((Beater *)self->mainPlayer);
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = tmp[i + offset];
-    }    
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -2571,11 +2782,11 @@ Beat_traverse(Beat *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Beat_clear(Beat *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->mainPlayer);    
+    Py_CLEAR(self->mainPlayer);
     return 0;
 }
 
@@ -2584,7 +2795,7 @@ Beat_dealloc(Beat* self)
 {
     pyo_DEALLOC
     Beat_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2594,37 +2805,37 @@ Beat_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *maintmp=NULL;
     Beat *self;
     self = (Beat *)type->tp_alloc(type, 0);
-    
+
     self->chnl = 0;
     self->modebuffer[0] = 0;
     self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Beat_compute_next_data_frame);
     self->mode_func_ptr = Beat_setProcMode;
 
     static char *kwlist[] = {"mainPlayer", "chnl", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &maintmp, &self->chnl))
         Py_RETURN_NONE;
-    
+
     Py_XDECREF(self->mainPlayer);
     Py_INCREF(maintmp);
     self->mainPlayer = (Beater *)maintmp;
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * Beat_getServer(Beat* self) { GET_SERVER };
 static PyObject * Beat_getStream(Beat* self) { GET_STREAM };
-static PyObject * Beat_setMul(Beat *self, PyObject *arg) { SET_MUL };	
-static PyObject * Beat_setAdd(Beat *self, PyObject *arg) { SET_ADD };	
-static PyObject * Beat_setSub(Beat *self, PyObject *arg) { SET_SUB };	
-static PyObject * Beat_setDiv(Beat *self, PyObject *arg) { SET_DIV };	
+static PyObject * Beat_setMul(Beat *self, PyObject *arg) { SET_MUL };
+static PyObject * Beat_setAdd(Beat *self, PyObject *arg) { SET_ADD };
+static PyObject * Beat_setSub(Beat *self, PyObject *arg) { SET_SUB };
+static PyObject * Beat_setDiv(Beat *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Beat_play(Beat *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Beat_out(Beat *self, PyObject *args, PyObject *kwds) { OUT };
@@ -2664,7 +2875,7 @@ static PyNumberMethods Beat_as_number = {
     (binaryfunc)Beat_add,                         /*nb_add*/
     (binaryfunc)Beat_sub,                         /*nb_subtract*/
     (binaryfunc)Beat_multiply,                    /*nb_multiply*/
-    (binaryfunc)Beat_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -2678,16 +2889,16 @@ static PyNumberMethods Beat_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Beat_inplace_add,                 /*inplace_add*/
     (binaryfunc)Beat_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Beat_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Beat_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -2696,15 +2907,14 @@ static PyNumberMethods Beat_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Beat_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Beat_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject BeatType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Beat_base",         /*tp_name*/
     sizeof(Beat),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -2712,7 +2922,7 @@ PyTypeObject BeatType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &Beat_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -2750,7 +2960,7 @@ PyTypeObject BeatType = {
 typedef struct {
     pyo_audio_HEAD
     Beater *mainPlayer;
-    int chnl; 
+    int chnl;
     int modebuffer[2];
 } BeatTapStream;
 
@@ -2768,36 +2978,36 @@ static void
 BeatTapStream_setProcMode(BeatTapStream *self) {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = BeatTapStream_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = BeatTapStream_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = BeatTapStream_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = BeatTapStream_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = BeatTapStream_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = BeatTapStream_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = BeatTapStream_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = BeatTapStream_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = BeatTapStream_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
@@ -2809,7 +3019,7 @@ BeatTapStream_compute_next_data_frame(BeatTapStream *self)
     tmp = Beater_getTapBuffer((Beater *)self->mainPlayer);
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = tmp[i + offset];
-    }    
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -2821,11 +3031,11 @@ BeatTapStream_traverse(BeatTapStream *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 BeatTapStream_clear(BeatTapStream *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->mainPlayer);    
+    Py_CLEAR(self->mainPlayer);
     return 0;
 }
 
@@ -2834,7 +3044,7 @@ BeatTapStream_dealloc(BeatTapStream* self)
 {
     pyo_DEALLOC
     BeatTapStream_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2844,37 +3054,37 @@ BeatTapStream_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *maintmp=NULL;
     BeatTapStream *self;
     self = (BeatTapStream *)type->tp_alloc(type, 0);
-    
+
     self->chnl = 0;
     self->modebuffer[0] = 0;
     self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, BeatTapStream_compute_next_data_frame);
     self->mode_func_ptr = BeatTapStream_setProcMode;
 
     static char *kwlist[] = {"mainPlayer", "chnl", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &maintmp, &self->chnl))
         Py_RETURN_NONE;
-    
+
     Py_XDECREF(self->mainPlayer);
     Py_INCREF(maintmp);
     self->mainPlayer = (Beater *)maintmp;
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * BeatTapStream_getServer(BeatTapStream* self) { GET_SERVER };
 static PyObject * BeatTapStream_getStream(BeatTapStream* self) { GET_STREAM };
-static PyObject * BeatTapStream_setMul(BeatTapStream *self, PyObject *arg) { SET_MUL };	
-static PyObject * BeatTapStream_setAdd(BeatTapStream *self, PyObject *arg) { SET_ADD };	
-static PyObject * BeatTapStream_setSub(BeatTapStream *self, PyObject *arg) { SET_SUB };	
-static PyObject * BeatTapStream_setDiv(BeatTapStream *self, PyObject *arg) { SET_DIV };	
+static PyObject * BeatTapStream_setMul(BeatTapStream *self, PyObject *arg) { SET_MUL };
+static PyObject * BeatTapStream_setAdd(BeatTapStream *self, PyObject *arg) { SET_ADD };
+static PyObject * BeatTapStream_setSub(BeatTapStream *self, PyObject *arg) { SET_SUB };
+static PyObject * BeatTapStream_setDiv(BeatTapStream *self, PyObject *arg) { SET_DIV };
 
 static PyObject * BeatTapStream_play(BeatTapStream *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * BeatTapStream_out(BeatTapStream *self, PyObject *args, PyObject *kwds) { OUT };
@@ -2906,7 +3116,7 @@ static PyMethodDef BeatTapStream_methods[] = {
     {"setMul", (PyCFunction)BeatTapStream_setMul, METH_O, "Sets oscillator mul factor."},
     {"setAdd", (PyCFunction)BeatTapStream_setAdd, METH_O, "Sets oscillator add factor."},
     {"setSub", (PyCFunction)BeatTapStream_setSub, METH_O, "Sets inverse add factor."},
-    {"setDiv", (PyCFunction)BeatTapStream_setDiv, METH_O, "Sets inverse mul factor."},    
+    {"setDiv", (PyCFunction)BeatTapStream_setDiv, METH_O, "Sets inverse mul factor."},
     {NULL}  /* Sentinel */
 };
 
@@ -2914,7 +3124,7 @@ static PyNumberMethods BeatTapStream_as_number = {
     (binaryfunc)BeatTapStream_add,                         /*nb_add*/
     (binaryfunc)BeatTapStream_sub,                         /*nb_subtract*/
     (binaryfunc)BeatTapStream_multiply,                    /*nb_multiply*/
-    (binaryfunc)BeatTapStream_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -2928,16 +3138,16 @@ static PyNumberMethods BeatTapStream_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)BeatTapStream_inplace_add,                 /*inplace_add*/
     (binaryfunc)BeatTapStream_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)BeatTapStream_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)BeatTapStream_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -2946,15 +3156,14 @@ static PyNumberMethods BeatTapStream_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)BeatTapStream_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)BeatTapStream_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject BeatTapStreamType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.BeatTapStream_base",         /*tp_name*/
     sizeof(BeatTapStream),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -2962,7 +3171,7 @@ PyTypeObject BeatTapStreamType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &BeatTapStream_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -3000,7 +3209,7 @@ PyTypeObject BeatTapStreamType = {
 typedef struct {
     pyo_audio_HEAD
     Beater *mainPlayer;
-    int chnl; 
+    int chnl;
     int modebuffer[2];
 } BeatAmpStream;
 
@@ -3018,36 +3227,36 @@ static void
 BeatAmpStream_setProcMode(BeatAmpStream *self) {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = BeatAmpStream_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = BeatAmpStream_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = BeatAmpStream_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = BeatAmpStream_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = BeatAmpStream_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = BeatAmpStream_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = BeatAmpStream_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = BeatAmpStream_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = BeatAmpStream_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
@@ -3059,7 +3268,7 @@ BeatAmpStream_compute_next_data_frame(BeatAmpStream *self)
     tmp = Beater_getAmpBuffer((Beater *)self->mainPlayer);
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = tmp[i + offset];
-    }    
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -3071,11 +3280,11 @@ BeatAmpStream_traverse(BeatAmpStream *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 BeatAmpStream_clear(BeatAmpStream *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->mainPlayer);    
+    Py_CLEAR(self->mainPlayer);
     return 0;
 }
 
@@ -3084,7 +3293,7 @@ BeatAmpStream_dealloc(BeatAmpStream* self)
 {
     pyo_DEALLOC
     BeatAmpStream_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -3094,37 +3303,37 @@ BeatAmpStream_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *maintmp=NULL;
     BeatAmpStream *self;
     self = (BeatAmpStream *)type->tp_alloc(type, 0);
-    
+
     self->chnl = 0;
     self->modebuffer[0] = 0;
     self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, BeatAmpStream_compute_next_data_frame);
     self->mode_func_ptr = BeatAmpStream_setProcMode;
 
     static char *kwlist[] = {"mainPlayer", "chnl", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &maintmp, &self->chnl))
         Py_RETURN_NONE;
-    
+
     Py_XDECREF(self->mainPlayer);
     Py_INCREF(maintmp);
     self->mainPlayer = (Beater *)maintmp;
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * BeatAmpStream_getServer(BeatAmpStream* self) { GET_SERVER };
 static PyObject * BeatAmpStream_getStream(BeatAmpStream* self) { GET_STREAM };
-static PyObject * BeatAmpStream_setMul(BeatAmpStream *self, PyObject *arg) { SET_MUL };	
-static PyObject * BeatAmpStream_setAdd(BeatAmpStream *self, PyObject *arg) { SET_ADD };	
-static PyObject * BeatAmpStream_setSub(BeatAmpStream *self, PyObject *arg) { SET_SUB };	
-static PyObject * BeatAmpStream_setDiv(BeatAmpStream *self, PyObject *arg) { SET_DIV };	
+static PyObject * BeatAmpStream_setMul(BeatAmpStream *self, PyObject *arg) { SET_MUL };
+static PyObject * BeatAmpStream_setAdd(BeatAmpStream *self, PyObject *arg) { SET_ADD };
+static PyObject * BeatAmpStream_setSub(BeatAmpStream *self, PyObject *arg) { SET_SUB };
+static PyObject * BeatAmpStream_setDiv(BeatAmpStream *self, PyObject *arg) { SET_DIV };
 
 static PyObject * BeatAmpStream_play(BeatAmpStream *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * BeatAmpStream_out(BeatAmpStream *self, PyObject *args, PyObject *kwds) { OUT };
@@ -3156,7 +3365,7 @@ static PyMethodDef BeatAmpStream_methods[] = {
     {"setMul", (PyCFunction)BeatAmpStream_setMul, METH_O, "Sets oscillator mul factor."},
     {"setAdd", (PyCFunction)BeatAmpStream_setAdd, METH_O, "Sets oscillator add factor."},
     {"setSub", (PyCFunction)BeatAmpStream_setSub, METH_O, "Sets inverse add factor."},
-    {"setDiv", (PyCFunction)BeatAmpStream_setDiv, METH_O, "Sets inverse mul factor."},    
+    {"setDiv", (PyCFunction)BeatAmpStream_setDiv, METH_O, "Sets inverse mul factor."},
     {NULL}  /* Sentinel */
 };
 
@@ -3164,7 +3373,7 @@ static PyNumberMethods BeatAmpStream_as_number = {
     (binaryfunc)BeatAmpStream_add,                         /*nb_add*/
     (binaryfunc)BeatAmpStream_sub,                         /*nb_subtract*/
     (binaryfunc)BeatAmpStream_multiply,                    /*nb_multiply*/
-    (binaryfunc)BeatAmpStream_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -3178,16 +3387,16 @@ static PyNumberMethods BeatAmpStream_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)BeatAmpStream_inplace_add,                 /*inplace_add*/
     (binaryfunc)BeatAmpStream_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)BeatAmpStream_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)BeatAmpStream_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -3196,15 +3405,14 @@ static PyNumberMethods BeatAmpStream_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)BeatAmpStream_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)BeatAmpStream_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject BeatAmpStreamType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.BeatAmpStream_base",         /*tp_name*/
     sizeof(BeatAmpStream),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -3212,7 +3420,7 @@ PyTypeObject BeatAmpStreamType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &BeatAmpStream_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -3250,7 +3458,7 @@ PyTypeObject BeatAmpStreamType = {
 typedef struct {
     pyo_audio_HEAD
     Beater *mainPlayer;
-    int chnl; 
+    int chnl;
     int modebuffer[2];
 } BeatDurStream;
 
@@ -3268,36 +3476,36 @@ static void
 BeatDurStream_setProcMode(BeatDurStream *self) {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = BeatDurStream_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = BeatDurStream_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = BeatDurStream_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = BeatDurStream_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = BeatDurStream_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = BeatDurStream_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = BeatDurStream_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = BeatDurStream_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = BeatDurStream_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
@@ -3309,7 +3517,7 @@ BeatDurStream_compute_next_data_frame(BeatDurStream *self)
     tmp = Beater_getDurBuffer((Beater *)self->mainPlayer);
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = tmp[i + offset];
-    }    
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -3321,11 +3529,11 @@ BeatDurStream_traverse(BeatDurStream *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 BeatDurStream_clear(BeatDurStream *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->mainPlayer);    
+    Py_CLEAR(self->mainPlayer);
     return 0;
 }
 
@@ -3334,7 +3542,7 @@ BeatDurStream_dealloc(BeatDurStream* self)
 {
     pyo_DEALLOC
     BeatDurStream_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -3344,37 +3552,37 @@ BeatDurStream_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *maintmp=NULL;
     BeatDurStream *self;
     self = (BeatDurStream *)type->tp_alloc(type, 0);
-    
+
     self->chnl = 0;
     self->modebuffer[0] = 0;
     self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, BeatDurStream_compute_next_data_frame);
     self->mode_func_ptr = BeatDurStream_setProcMode;
 
     static char *kwlist[] = {"mainPlayer", "chnl", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &maintmp, &self->chnl))
         Py_RETURN_NONE;
-    
+
     Py_XDECREF(self->mainPlayer);
     Py_INCREF(maintmp);
     self->mainPlayer = (Beater *)maintmp;
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * BeatDurStream_getServer(BeatDurStream* self) { GET_SERVER };
 static PyObject * BeatDurStream_getStream(BeatDurStream* self) { GET_STREAM };
-static PyObject * BeatDurStream_setMul(BeatDurStream *self, PyObject *arg) { SET_MUL };	
-static PyObject * BeatDurStream_setAdd(BeatDurStream *self, PyObject *arg) { SET_ADD };	
-static PyObject * BeatDurStream_setSub(BeatDurStream *self, PyObject *arg) { SET_SUB };	
-static PyObject * BeatDurStream_setDiv(BeatDurStream *self, PyObject *arg) { SET_DIV };	
+static PyObject * BeatDurStream_setMul(BeatDurStream *self, PyObject *arg) { SET_MUL };
+static PyObject * BeatDurStream_setAdd(BeatDurStream *self, PyObject *arg) { SET_ADD };
+static PyObject * BeatDurStream_setSub(BeatDurStream *self, PyObject *arg) { SET_SUB };
+static PyObject * BeatDurStream_setDiv(BeatDurStream *self, PyObject *arg) { SET_DIV };
 
 static PyObject * BeatDurStream_play(BeatDurStream *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * BeatDurStream_out(BeatDurStream *self, PyObject *args, PyObject *kwds) { OUT };
@@ -3414,7 +3622,7 @@ static PyNumberMethods BeatDurStream_as_number = {
     (binaryfunc)BeatDurStream_add,                         /*nb_add*/
     (binaryfunc)BeatDurStream_sub,                         /*nb_subtract*/
     (binaryfunc)BeatDurStream_multiply,                    /*nb_multiply*/
-    (binaryfunc)BeatDurStream_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -3428,16 +3636,16 @@ static PyNumberMethods BeatDurStream_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)BeatDurStream_inplace_add,                 /*inplace_add*/
     (binaryfunc)BeatDurStream_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)BeatDurStream_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)BeatDurStream_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -3446,15 +3654,14 @@ static PyNumberMethods BeatDurStream_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)BeatDurStream_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)BeatDurStream_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject BeatDurStreamType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.BeatDurStream_base",         /*tp_name*/
     sizeof(BeatDurStream),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -3462,7 +3669,7 @@ PyTypeObject BeatDurStreamType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &BeatDurStream_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -3500,7 +3707,7 @@ PyTypeObject BeatDurStreamType = {
 typedef struct {
     pyo_audio_HEAD
     Beater *mainPlayer;
-    int chnl; 
+    int chnl;
     int modebuffer[2];
 } BeatEndStream;
 
@@ -3518,36 +3725,36 @@ static void
 BeatEndStream_setProcMode(BeatEndStream *self) {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = BeatEndStream_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = BeatEndStream_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = BeatEndStream_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = BeatEndStream_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = BeatEndStream_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = BeatEndStream_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = BeatEndStream_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = BeatEndStream_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = BeatEndStream_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
@@ -3559,7 +3766,7 @@ BeatEndStream_compute_next_data_frame(BeatEndStream *self)
     tmp = Beater_getEndBuffer((Beater *)self->mainPlayer);
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = tmp[i + offset];
-    }    
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -3571,11 +3778,11 @@ BeatEndStream_traverse(BeatEndStream *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 BeatEndStream_clear(BeatEndStream *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->mainPlayer);    
+    Py_CLEAR(self->mainPlayer);
     return 0;
 }
 
@@ -3584,7 +3791,7 @@ BeatEndStream_dealloc(BeatEndStream* self)
 {
     pyo_DEALLOC
     BeatEndStream_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -3594,37 +3801,37 @@ BeatEndStream_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *maintmp=NULL;
     BeatEndStream *self;
     self = (BeatEndStream *)type->tp_alloc(type, 0);
-    
+
     self->chnl = 0;
     self->modebuffer[0] = 0;
     self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, BeatEndStream_compute_next_data_frame);
     self->mode_func_ptr = BeatEndStream_setProcMode;
 
     static char *kwlist[] = {"mainPlayer", "chnl", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &maintmp, &self->chnl))
         Py_RETURN_NONE;
-    
+
     Py_XDECREF(self->mainPlayer);
     Py_INCREF(maintmp);
     self->mainPlayer = (Beater *)maintmp;
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * BeatEndStream_getServer(BeatEndStream* self) { GET_SERVER };
 static PyObject * BeatEndStream_getStream(BeatEndStream* self) { GET_STREAM };
-static PyObject * BeatEndStream_setMul(BeatEndStream *self, PyObject *arg) { SET_MUL };	
-static PyObject * BeatEndStream_setAdd(BeatEndStream *self, PyObject *arg) { SET_ADD };	
-static PyObject * BeatEndStream_setSub(BeatEndStream *self, PyObject *arg) { SET_SUB };	
-static PyObject * BeatEndStream_setDiv(BeatEndStream *self, PyObject *arg) { SET_DIV };	
+static PyObject * BeatEndStream_setMul(BeatEndStream *self, PyObject *arg) { SET_MUL };
+static PyObject * BeatEndStream_setAdd(BeatEndStream *self, PyObject *arg) { SET_ADD };
+static PyObject * BeatEndStream_setSub(BeatEndStream *self, PyObject *arg) { SET_SUB };
+static PyObject * BeatEndStream_setDiv(BeatEndStream *self, PyObject *arg) { SET_DIV };
 
 static PyObject * BeatEndStream_play(BeatEndStream *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * BeatEndStream_out(BeatEndStream *self, PyObject *args, PyObject *kwds) { OUT };
@@ -3656,7 +3863,7 @@ static PyMethodDef BeatEndStream_methods[] = {
     {"setMul", (PyCFunction)BeatEndStream_setMul, METH_O, "Sets oscillator mul factor."},
     {"setAdd", (PyCFunction)BeatEndStream_setAdd, METH_O, "Sets oscillator add factor."},
     {"setSub", (PyCFunction)BeatEndStream_setSub, METH_O, "Sets inverse add factor."},
-    {"setDiv", (PyCFunction)BeatEndStream_setDiv, METH_O, "Sets inverse mul factor."},    
+    {"setDiv", (PyCFunction)BeatEndStream_setDiv, METH_O, "Sets inverse mul factor."},
     {NULL}  /* Sentinel */
 };
 
@@ -3664,7 +3871,7 @@ static PyNumberMethods BeatEndStream_as_number = {
     (binaryfunc)BeatEndStream_add,                         /*nb_add*/
     (binaryfunc)BeatEndStream_sub,                         /*nb_subtract*/
     (binaryfunc)BeatEndStream_multiply,                    /*nb_multiply*/
-    (binaryfunc)BeatEndStream_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -3678,16 +3885,16 @@ static PyNumberMethods BeatEndStream_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)BeatEndStream_inplace_add,                 /*inplace_add*/
     (binaryfunc)BeatEndStream_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)BeatEndStream_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)BeatEndStream_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -3696,15 +3903,14 @@ static PyNumberMethods BeatEndStream_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)BeatEndStream_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)BeatEndStream_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject BeatEndStreamType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.BeatEndStream_base",         /*tp_name*/
     sizeof(BeatEndStream),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -3712,7 +3918,7 @@ PyTypeObject BeatEndStreamType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &BeatEndStream_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -3743,3 +3949,1576 @@ PyTypeObject BeatEndStreamType = {
     0,                         /* tp_alloc */
     BeatEndStream_new,                 /* tp_new */
 };
+
+/****************/
+/**** TrigBurster *****/
+/****************/
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *input;
+    Stream *input_stream;
+    int modebuffer[1];
+    int poly;
+    int voiceCount;
+    MYFLT time;
+    MYFLT a_time;
+    int count;
+    int a_count;
+    MYFLT expand;
+    MYFLT a_expand;
+    MYFLT ampfade;
+    MYFLT a_ampfade;
+    int flag;
+    double sampleToSec;
+    double currentTime;
+    double targetTime;
+    int currentCount;
+    int *currentTap;
+    MYFLT *currentAmp;
+    MYFLT *currentDur;
+    MYFLT *buffer_streams;
+    MYFLT *tap_buffer_streams;
+    MYFLT *amp_buffer_streams;
+    MYFLT *dur_buffer_streams;
+    MYFLT *end_buffer_streams;
+} TrigBurster;
+
+static void
+TrigBurster_generate_i(TrigBurster *self) {
+    int i, j;
+
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+
+    for (i=0; i<(self->poly*self->bufsize); i++) {
+        self->buffer_streams[i] = self->end_buffer_streams[i] = 0.0;
+    }
+
+    for (i=0; i<self->bufsize; i++) {
+        if (in[i] == 1.0) {
+            self->flag = 1;
+            self->currentCount = 0;
+            self->a_time = self->targetTime = self->currentTime = self->time;
+            self->a_count = self->count;
+            self->a_expand = self->expand;
+            self->a_ampfade = self->ampfade;
+        }
+        if (self->flag == 1) {
+            if (self->currentTime >= self->targetTime) {
+                self->currentTime -= self->targetTime;
+                self->targetTime = self->a_time * MYPOW(self->a_expand, self->currentCount);
+                self->currentTap[self->voiceCount] = self->currentCount;
+                self->currentAmp[self->voiceCount] = MYPOW(self->a_ampfade, self->currentCount);
+                self->currentDur[self->voiceCount] = self->targetTime;
+                self->buffer_streams[i + self->voiceCount * self->bufsize] = 1.0;
+                self->currentCount++;
+                if (self->currentCount == (self->a_count - 1))
+                    self->end_buffer_streams[i + self->voiceCount * self->bufsize] = 1.0;
+                if (self->currentCount == self->a_count)
+                    self->flag = 0;
+                self->voiceCount++;
+                if (self->voiceCount == self->poly)
+                    self->voiceCount = 0;
+            }
+            self->currentTime += self->sampleToSec;
+        }
+        for (j=0; j<self->poly; j++) {
+            self->tap_buffer_streams[i + j * self->bufsize] = (MYFLT)self->currentTap[j];
+            self->amp_buffer_streams[i + j * self->bufsize] = self->currentAmp[j];
+            self->dur_buffer_streams[i + j * self->bufsize] = self->currentDur[j];
+        }
+    }
+}
+
+MYFLT *
+TrigBurster_getSamplesBuffer(TrigBurster *self)
+{
+    return (MYFLT *)self->buffer_streams;
+}
+
+MYFLT *
+TrigBurster_getTapBuffer(TrigBurster *self)
+{
+    return (MYFLT *)self->tap_buffer_streams;
+}
+
+MYFLT *
+TrigBurster_getAmpBuffer(TrigBurster *self)
+{
+    return (MYFLT *)self->amp_buffer_streams;
+}
+
+MYFLT *
+TrigBurster_getDurBuffer(TrigBurster *self)
+{
+    return (MYFLT *)self->dur_buffer_streams;
+}
+
+MYFLT *
+TrigBurster_getEndBuffer(TrigBurster *self)
+{
+    return (MYFLT *)self->end_buffer_streams;
+}
+
+static void
+TrigBurster_setProcMode(TrigBurster *self)
+{
+    self->proc_func_ptr = TrigBurster_generate_i;
+}
+
+static void
+TrigBurster_compute_next_data_frame(TrigBurster *self)
+{
+    (*self->proc_func_ptr)(self);
+}
+
+static int
+TrigBurster_traverse(TrigBurster *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->input);
+    Py_VISIT(self->input_stream);
+    return 0;
+}
+
+static int
+TrigBurster_clear(TrigBurster *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->input);
+    Py_CLEAR(self->input_stream);
+    return 0;
+}
+
+static void
+TrigBurster_dealloc(TrigBurster* self)
+{
+    pyo_DEALLOC
+    free(self->buffer_streams);
+    free(self->tap_buffer_streams);
+    free(self->amp_buffer_streams);
+    free(self->dur_buffer_streams);
+    free(self->end_buffer_streams);
+    free(self->currentTap);
+    free(self->currentAmp);
+    free(self->currentDur);
+    TrigBurster_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+TrigBurster_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *inputtmp, *input_streamtmp;
+    TrigBurster *self;
+    self = (TrigBurster *)type->tp_alloc(type, 0);
+
+
+    self->poly = 1;
+    self->voiceCount = 0;
+    self->time = self->a_time = 0.25;
+    self->count = self->a_count = 10;
+    self->expand = self->a_expand = 1.0;
+    self->ampfade = self->a_ampfade = 1.0;
+    self->currentCount = 0;
+    self->targetTime = 0.0;
+    self->currentTime = -1.0;
+    self->flag = 0;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, TrigBurster_compute_next_data_frame);
+    self->mode_func_ptr = TrigBurster_setProcMode;
+
+    self->sampleToSec = 1. / self->sr;
+
+    Stream_setStreamActive(self->stream, 1);
+
+    static char *kwlist[] = {"input", "time", "count", "expand", "ampfade", "poly", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_FIFFI, kwlist, &inputtmp, &self->time, &self->count, &self->expand, &self->ampfade, &self->poly))
+        Py_RETURN_NONE;
+
+    INIT_INPUT_STREAM
+
+    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
+
+    (*self->mode_func_ptr)(self);
+
+    self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, self->poly * self->bufsize * sizeof(MYFLT));
+    self->tap_buffer_streams = (MYFLT *)realloc(self->tap_buffer_streams, self->poly * self->bufsize * sizeof(MYFLT));
+    self->amp_buffer_streams = (MYFLT *)realloc(self->amp_buffer_streams, self->poly * self->bufsize * sizeof(MYFLT));
+    self->dur_buffer_streams = (MYFLT *)realloc(self->dur_buffer_streams, self->poly * self->bufsize * sizeof(MYFLT));
+    self->end_buffer_streams = (MYFLT *)realloc(self->end_buffer_streams, self->poly * self->bufsize * sizeof(MYFLT));
+    for (i=0; i<(self->poly*self->bufsize); i++) {
+        self->buffer_streams[i] = self->tap_buffer_streams[i] = self->amp_buffer_streams[i] = self->dur_buffer_streams[i] = self->end_buffer_streams[i] = 0.0;
+    }
+
+    self->currentTap = (int *)realloc(self->currentTap, self->poly * sizeof(int));
+    self->currentAmp = (MYFLT *)realloc(self->currentAmp, self->poly * sizeof(MYFLT));
+    self->currentDur = (MYFLT *)realloc(self->currentDur, self->poly * sizeof(MYFLT));
+    for (i=0; i<(self->poly); i++) {
+        self->currentTap[i] = 0;
+        self->currentAmp[i] = self->currentDur[i] = 0.0;
+    }
+
+    return (PyObject *)self;
+}
+
+static PyObject * TrigBurster_getServer(TrigBurster* self) { GET_SERVER };
+static PyObject * TrigBurster_getStream(TrigBurster* self) { GET_STREAM };
+
+static PyObject * TrigBurster_play(TrigBurster *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * TrigBurster_stop(TrigBurster *self) { STOP };
+
+static PyObject *
+TrigBurster_setTime(TrigBurster *self, PyObject *arg)
+{
+	if (PyNumber_Check(arg))
+        self->time = PyFloat_AsDouble(arg);
+        if (self->time <= 0.01)
+            self->time = 0.01;
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+TrigBurster_setCount(TrigBurster *self, PyObject *arg)
+{
+	if (PyInt_Check(arg))
+        self->count = PyInt_AS_LONG(arg);
+        if (self->count < 1)
+            self->count = 1;
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+TrigBurster_setExpand(TrigBurster *self, PyObject *arg)
+{
+	if (PyNumber_Check(arg))
+        self->expand = PyFloat_AsDouble(arg);
+        if (self->expand <= 0.1)
+            self->expand = 0.1;
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+TrigBurster_setAmpfade(TrigBurster *self, PyObject *arg)
+{
+	if (PyNumber_Check(arg))
+        self->ampfade = PyFloat_AsDouble(arg);
+        if (self->ampfade <= 0.1)
+            self->ampfade = 0.1;
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyMemberDef TrigBurster_members[] = {
+    {"server", T_OBJECT_EX, offsetof(TrigBurster, server), 0, "Pyo server."},
+    {"stream", T_OBJECT_EX, offsetof(TrigBurster, stream), 0, "Stream object."},
+    {"input", T_OBJECT_EX, offsetof(TrigBurster, input), 0, "Input sound object."},
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef TrigBurster_methods[] = {
+    {"getServer", (PyCFunction)TrigBurster_getServer, METH_NOARGS, "Returns server object."},
+    {"_getStream", (PyCFunction)TrigBurster_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)TrigBurster_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+    {"stop", (PyCFunction)TrigBurster_stop, METH_NOARGS, "Stops computing."},
+    {"setTime", (PyCFunction)TrigBurster_setTime, METH_O, "Sets the base time of the serie."},
+    {"setCount", (PyCFunction)TrigBurster_setCount, METH_O, "Sets the number of trigs in the serie."},
+    {"setExpand", (PyCFunction)TrigBurster_setExpand, METH_O, "Sets the time's expansion factor of the serie."},
+    {"setAmpfade", (PyCFunction)TrigBurster_setAmpfade, METH_O, "Sets the amplitude's expansion factor of the serie."},
+    {NULL}  /* Sentinel */
+};
+
+PyTypeObject TrigBursterType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.TrigBurster_base",         /*tp_name*/
+    sizeof(TrigBurster),         /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)TrigBurster_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*/
+    "TrigBurster objects. Create an algorithmic beat sequence.",           /* tp_doc */
+    (traverseproc)TrigBurster_traverse,   /* tp_traverse */
+    (inquiry)TrigBurster_clear,           /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    TrigBurster_methods,             /* tp_methods */
+    TrigBurster_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 */
+    TrigBurster_new,                 /* tp_new */
+};
+
+/************************************************************************************************/
+/* TrigBurst streamer object per channel */
+/************************************************************************************************/
+typedef struct {
+    pyo_audio_HEAD
+    TrigBurster *mainPlayer;
+    int chnl;
+    int modebuffer[2];
+} TrigBurst;
+
+static void TrigBurst_postprocessing_ii(TrigBurst *self) { POST_PROCESSING_II };
+static void TrigBurst_postprocessing_ai(TrigBurst *self) { POST_PROCESSING_AI };
+static void TrigBurst_postprocessing_ia(TrigBurst *self) { POST_PROCESSING_IA };
+static void TrigBurst_postprocessing_aa(TrigBurst *self) { POST_PROCESSING_AA };
+static void TrigBurst_postprocessing_ireva(TrigBurst *self) { POST_PROCESSING_IREVA };
+static void TrigBurst_postprocessing_areva(TrigBurst *self) { POST_PROCESSING_AREVA };
+static void TrigBurst_postprocessing_revai(TrigBurst *self) { POST_PROCESSING_REVAI };
+static void TrigBurst_postprocessing_revaa(TrigBurst *self) { POST_PROCESSING_REVAA };
+static void TrigBurst_postprocessing_revareva(TrigBurst *self) { POST_PROCESSING_REVAREVA };
+
+static void
+TrigBurst_setProcMode(TrigBurst *self) {
+    int muladdmode;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+    switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = TrigBurst_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = TrigBurst_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = TrigBurst_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = TrigBurst_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = TrigBurst_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = TrigBurst_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = TrigBurst_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = TrigBurst_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = TrigBurst_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+TrigBurst_compute_next_data_frame(TrigBurst *self)
+{
+    int i;
+    MYFLT *tmp;
+    int offset = self->chnl * self->bufsize;
+    tmp = TrigBurster_getSamplesBuffer((TrigBurster *)self->mainPlayer);
+    for (i=0; i<self->bufsize; i++) {
+        self->data[i] = tmp[i + offset];
+    }
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+TrigBurst_traverse(TrigBurst *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->mainPlayer);
+    return 0;
+}
+
+static int
+TrigBurst_clear(TrigBurst *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->mainPlayer);
+    return 0;
+}
+
+static void
+TrigBurst_dealloc(TrigBurst* self)
+{
+    pyo_DEALLOC
+    TrigBurst_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+TrigBurst_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *maintmp=NULL;
+    TrigBurst *self;
+    self = (TrigBurst *)type->tp_alloc(type, 0);
+
+    self->chnl = 0;
+    self->modebuffer[0] = 0;
+    self->modebuffer[1] = 0;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, TrigBurst_compute_next_data_frame);
+    self->mode_func_ptr = TrigBurst_setProcMode;
+
+    static char *kwlist[] = {"mainPlayer", "chnl", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &maintmp, &self->chnl))
+        Py_RETURN_NONE;
+
+    Py_XDECREF(self->mainPlayer);
+    Py_INCREF(maintmp);
+    self->mainPlayer = (TrigBurster *)maintmp;
+
+    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
+
+    (*self->mode_func_ptr)(self);
+
+    return (PyObject *)self;
+}
+
+static PyObject * TrigBurst_getServer(TrigBurst* self) { GET_SERVER };
+static PyObject * TrigBurst_getStream(TrigBurst* self) { GET_STREAM };
+static PyObject * TrigBurst_setMul(TrigBurst *self, PyObject *arg) { SET_MUL };
+static PyObject * TrigBurst_setAdd(TrigBurst *self, PyObject *arg) { SET_ADD };
+static PyObject * TrigBurst_setSub(TrigBurst *self, PyObject *arg) { SET_SUB };
+static PyObject * TrigBurst_setDiv(TrigBurst *self, PyObject *arg) { SET_DIV };
+
+static PyObject * TrigBurst_play(TrigBurst *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * TrigBurst_out(TrigBurst *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * TrigBurst_stop(TrigBurst *self) { STOP };
+
+static PyObject * TrigBurst_multiply(TrigBurst *self, PyObject *arg) { MULTIPLY };
+static PyObject * TrigBurst_inplace_multiply(TrigBurst *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * TrigBurst_add(TrigBurst *self, PyObject *arg) { ADD };
+static PyObject * TrigBurst_inplace_add(TrigBurst *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * TrigBurst_sub(TrigBurst *self, PyObject *arg) { SUB };
+static PyObject * TrigBurst_inplace_sub(TrigBurst *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * TrigBurst_div(TrigBurst *self, PyObject *arg) { DIV };
+static PyObject * TrigBurst_inplace_div(TrigBurst *self, PyObject *arg) { INPLACE_DIV };
+
+static PyMemberDef TrigBurst_members[] = {
+    {"server", T_OBJECT_EX, offsetof(TrigBurst, server), 0, "Pyo server."},
+    {"stream", T_OBJECT_EX, offsetof(TrigBurst, stream), 0, "Stream object."},
+    {"mul", T_OBJECT_EX, offsetof(TrigBurst, mul), 0, "Mul factor."},
+    {"add", T_OBJECT_EX, offsetof(TrigBurst, add), 0, "Add factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef TrigBurst_methods[] = {
+    {"getServer", (PyCFunction)TrigBurst_getServer, METH_NOARGS, "Returns server object."},
+    {"_getStream", (PyCFunction)TrigBurst_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)TrigBurst_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+    {"out", (PyCFunction)TrigBurst_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+    {"stop", (PyCFunction)TrigBurst_stop, METH_NOARGS, "Stops computing."},
+    {"setMul", (PyCFunction)TrigBurst_setMul, METH_O, "Sets oscillator mul factor."},
+    {"setAdd", (PyCFunction)TrigBurst_setAdd, METH_O, "Sets oscillator add factor."},
+    {"setSub", (PyCFunction)TrigBurst_setSub, METH_O, "Sets inverse add factor."},
+    {"setDiv", (PyCFunction)TrigBurst_setDiv, METH_O, "Sets inverse mul factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyNumberMethods TrigBurst_as_number = {
+    (binaryfunc)TrigBurst_add,                         /*nb_add*/
+    (binaryfunc)TrigBurst_sub,                         /*nb_subtract*/
+    (binaryfunc)TrigBurst_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)TrigBurst_inplace_add,                 /*inplace_add*/
+    (binaryfunc)TrigBurst_inplace_sub,                 /*inplace_subtract*/
+    (binaryfunc)TrigBurst_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)TrigBurst_div,                       /*nb_true_divide*/
+    0,                                              /*nb_inplace_floor_divide*/
+    (binaryfunc)TrigBurst_inplace_div,                       /*nb_inplace_true_divide*/
+    0,                                              /* nb_index */
+};
+
+PyTypeObject TrigBurstType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.TrigBurst_base",         /*tp_name*/
+    sizeof(TrigBurst),         /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)TrigBurst_dealloc, /*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
+    0,                         /*tp_repr*/
+    &TrigBurst_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*/
+    "TrigBurst objects. Reads a channel from a TrigBurster.",           /* tp_doc */
+    (traverseproc)TrigBurst_traverse,   /* tp_traverse */
+    (inquiry)TrigBurst_clear,           /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    TrigBurst_methods,             /* tp_methods */
+    TrigBurst_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 */
+    TrigBurst_new,                 /* tp_new */
+};
+
+/************************************************************************************************/
+/* TrigBurstTapStream object per channel */
+/************************************************************************************************/
+typedef struct {
+    pyo_audio_HEAD
+    TrigBurster *mainPlayer;
+    int chnl;
+    int modebuffer[2];
+} TrigBurstTapStream;
+
+static void TrigBurstTapStream_postprocessing_ii(TrigBurstTapStream *self) { POST_PROCESSING_II };
+static void TrigBurstTapStream_postprocessing_ai(TrigBurstTapStream *self) { POST_PROCESSING_AI };
+static void TrigBurstTapStream_postprocessing_ia(TrigBurstTapStream *self) { POST_PROCESSING_IA };
+static void TrigBurstTapStream_postprocessing_aa(TrigBurstTapStream *self) { POST_PROCESSING_AA };
+static void TrigBurstTapStream_postprocessing_ireva(TrigBurstTapStream *self) { POST_PROCESSING_IREVA };
+static void TrigBurstTapStream_postprocessing_areva(TrigBurstTapStream *self) { POST_PROCESSING_AREVA };
+static void TrigBurstTapStream_postprocessing_revai(TrigBurstTapStream *self) { POST_PROCESSING_REVAI };
+static void TrigBurstTapStream_postprocessing_revaa(TrigBurstTapStream *self) { POST_PROCESSING_REVAA };
+static void TrigBurstTapStream_postprocessing_revareva(TrigBurstTapStream *self) { POST_PROCESSING_REVAREVA };
+
+static void
+TrigBurstTapStream_setProcMode(TrigBurstTapStream *self) {
+    int muladdmode;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+    switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = TrigBurstTapStream_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = TrigBurstTapStream_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = TrigBurstTapStream_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = TrigBurstTapStream_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = TrigBurstTapStream_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = TrigBurstTapStream_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = TrigBurstTapStream_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = TrigBurstTapStream_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = TrigBurstTapStream_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+TrigBurstTapStream_compute_next_data_frame(TrigBurstTapStream *self)
+{
+    int i;
+    MYFLT *tmp;
+    int offset = self->chnl * self->bufsize;
+    tmp = TrigBurster_getTapBuffer((TrigBurster *)self->mainPlayer);
+    for (i=0; i<self->bufsize; i++) {
+        self->data[i] = tmp[i + offset];
+    }
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+TrigBurstTapStream_traverse(TrigBurstTapStream *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->mainPlayer);
+    return 0;
+}
+
+static int
+TrigBurstTapStream_clear(TrigBurstTapStream *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->mainPlayer);
+    return 0;
+}
+
+static void
+TrigBurstTapStream_dealloc(TrigBurstTapStream* self)
+{
+    pyo_DEALLOC
+    TrigBurstTapStream_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+TrigBurstTapStream_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *maintmp=NULL;
+    TrigBurstTapStream *self;
+    self = (TrigBurstTapStream *)type->tp_alloc(type, 0);
+
+    self->chnl = 0;
+    self->modebuffer[0] = 0;
+    self->modebuffer[1] = 0;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, TrigBurstTapStream_compute_next_data_frame);
+    self->mode_func_ptr = TrigBurstTapStream_setProcMode;
+
+    static char *kwlist[] = {"mainPlayer", "chnl", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &maintmp, &self->chnl))
+        Py_RETURN_NONE;
+
+    Py_XDECREF(self->mainPlayer);
+    Py_INCREF(maintmp);
+    self->mainPlayer = (TrigBurster *)maintmp;
+
+    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
+
+    (*self->mode_func_ptr)(self);
+
+    return (PyObject *)self;
+}
+
+static PyObject * TrigBurstTapStream_getServer(TrigBurstTapStream* self) { GET_SERVER };
+static PyObject * TrigBurstTapStream_getStream(TrigBurstTapStream* self) { GET_STREAM };
+static PyObject * TrigBurstTapStream_setMul(TrigBurstTapStream *self, PyObject *arg) { SET_MUL };
+static PyObject * TrigBurstTapStream_setAdd(TrigBurstTapStream *self, PyObject *arg) { SET_ADD };
+static PyObject * TrigBurstTapStream_setSub(TrigBurstTapStream *self, PyObject *arg) { SET_SUB };
+static PyObject * TrigBurstTapStream_setDiv(TrigBurstTapStream *self, PyObject *arg) { SET_DIV };
+
+static PyObject * TrigBurstTapStream_play(TrigBurstTapStream *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * TrigBurstTapStream_out(TrigBurstTapStream *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * TrigBurstTapStream_stop(TrigBurstTapStream *self) { STOP };
+
+static PyObject * TrigBurstTapStream_multiply(TrigBurstTapStream *self, PyObject *arg) { MULTIPLY };
+static PyObject * TrigBurstTapStream_inplace_multiply(TrigBurstTapStream *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * TrigBurstTapStream_add(TrigBurstTapStream *self, PyObject *arg) { ADD };
+static PyObject * TrigBurstTapStream_inplace_add(TrigBurstTapStream *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * TrigBurstTapStream_sub(TrigBurstTapStream *self, PyObject *arg) { SUB };
+static PyObject * TrigBurstTapStream_inplace_sub(TrigBurstTapStream *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * TrigBurstTapStream_div(TrigBurstTapStream *self, PyObject *arg) { DIV };
+static PyObject * TrigBurstTapStream_inplace_div(TrigBurstTapStream *self, PyObject *arg) { INPLACE_DIV };
+
+static PyMemberDef TrigBurstTapStream_members[] = {
+    {"server", T_OBJECT_EX, offsetof(TrigBurstTapStream, server), 0, "Pyo server."},
+    {"stream", T_OBJECT_EX, offsetof(TrigBurstTapStream, stream), 0, "Stream object."},
+    {"mul", T_OBJECT_EX, offsetof(TrigBurstTapStream, mul), 0, "Mul factor."},
+    {"add", T_OBJECT_EX, offsetof(TrigBurstTapStream, add), 0, "Add factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef TrigBurstTapStream_methods[] = {
+    {"getServer", (PyCFunction)TrigBurstTapStream_getServer, METH_NOARGS, "Returns server object."},
+    {"_getStream", (PyCFunction)TrigBurstTapStream_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)TrigBurstTapStream_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+    {"out", (PyCFunction)TrigBurstTapStream_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+    {"stop", (PyCFunction)TrigBurstTapStream_stop, METH_NOARGS, "Stops computing."},
+    {"setMul", (PyCFunction)TrigBurstTapStream_setMul, METH_O, "Sets oscillator mul factor."},
+    {"setAdd", (PyCFunction)TrigBurstTapStream_setAdd, METH_O, "Sets oscillator add factor."},
+    {"setSub", (PyCFunction)TrigBurstTapStream_setSub, METH_O, "Sets inverse add factor."},
+    {"setDiv", (PyCFunction)TrigBurstTapStream_setDiv, METH_O, "Sets inverse mul factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyNumberMethods TrigBurstTapStream_as_number = {
+    (binaryfunc)TrigBurstTapStream_add,                         /*nb_add*/
+    (binaryfunc)TrigBurstTapStream_sub,                         /*nb_subtract*/
+    (binaryfunc)TrigBurstTapStream_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)TrigBurstTapStream_inplace_add,                 /*inplace_add*/
+    (binaryfunc)TrigBurstTapStream_inplace_sub,                 /*inplace_subtract*/
+    (binaryfunc)TrigBurstTapStream_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)TrigBurstTapStream_div,                       /*nb_true_divide*/
+    0,                                              /*nb_inplace_floor_divide*/
+    (binaryfunc)TrigBurstTapStream_inplace_div,                       /*nb_inplace_true_divide*/
+    0,                                              /* nb_index */
+};
+
+PyTypeObject TrigBurstTapStreamType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.TrigBurstTapStream_base",         /*tp_name*/
+    sizeof(TrigBurstTapStream),         /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)TrigBurstTapStream_dealloc, /*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
+    0,                         /*tp_repr*/
+    &TrigBurstTapStream_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*/
+    "TrigBurstTapStream objects. Reads the current tap from a TrigBurster object.",           /* tp_doc */
+    (traverseproc)TrigBurstTapStream_traverse,   /* tp_traverse */
+    (inquiry)TrigBurstTapStream_clear,           /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    TrigBurstTapStream_methods,             /* tp_methods */
+    TrigBurstTapStream_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 */
+    TrigBurstTapStream_new,                 /* tp_new */
+};
+
+/************************************************************************************************/
+/* TrigBurstAmpStream object per channel */
+/************************************************************************************************/
+typedef struct {
+    pyo_audio_HEAD
+    TrigBurster *mainPlayer;
+    int chnl;
+    int modebuffer[2];
+} TrigBurstAmpStream;
+
+static void TrigBurstAmpStream_postprocessing_ii(TrigBurstAmpStream *self) { POST_PROCESSING_II };
+static void TrigBurstAmpStream_postprocessing_ai(TrigBurstAmpStream *self) { POST_PROCESSING_AI };
+static void TrigBurstAmpStream_postprocessing_ia(TrigBurstAmpStream *self) { POST_PROCESSING_IA };
+static void TrigBurstAmpStream_postprocessing_aa(TrigBurstAmpStream *self) { POST_PROCESSING_AA };
+static void TrigBurstAmpStream_postprocessing_ireva(TrigBurstAmpStream *self) { POST_PROCESSING_IREVA };
+static void TrigBurstAmpStream_postprocessing_areva(TrigBurstAmpStream *self) { POST_PROCESSING_AREVA };
+static void TrigBurstAmpStream_postprocessing_revai(TrigBurstAmpStream *self) { POST_PROCESSING_REVAI };
+static void TrigBurstAmpStream_postprocessing_revaa(TrigBurstAmpStream *self) { POST_PROCESSING_REVAA };
+static void TrigBurstAmpStream_postprocessing_revareva(TrigBurstAmpStream *self) { POST_PROCESSING_REVAREVA };
+
+static void
+TrigBurstAmpStream_setProcMode(TrigBurstAmpStream *self) {
+    int muladdmode;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+    switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = TrigBurstAmpStream_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = TrigBurstAmpStream_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = TrigBurstAmpStream_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = TrigBurstAmpStream_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = TrigBurstAmpStream_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = TrigBurstAmpStream_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = TrigBurstAmpStream_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = TrigBurstAmpStream_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = TrigBurstAmpStream_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+TrigBurstAmpStream_compute_next_data_frame(TrigBurstAmpStream *self)
+{
+    int i;
+    MYFLT *tmp;
+    int offset = self->chnl * self->bufsize;
+    tmp = TrigBurster_getAmpBuffer((TrigBurster *)self->mainPlayer);
+    for (i=0; i<self->bufsize; i++) {
+        self->data[i] = tmp[i + offset];
+    }
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+TrigBurstAmpStream_traverse(TrigBurstAmpStream *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->mainPlayer);
+    return 0;
+}
+
+static int
+TrigBurstAmpStream_clear(TrigBurstAmpStream *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->mainPlayer);
+    return 0;
+}
+
+static void
+TrigBurstAmpStream_dealloc(TrigBurstAmpStream* self)
+{
+    pyo_DEALLOC
+    TrigBurstAmpStream_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+TrigBurstAmpStream_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *maintmp=NULL;
+    TrigBurstAmpStream *self;
+    self = (TrigBurstAmpStream *)type->tp_alloc(type, 0);
+
+    self->chnl = 0;
+    self->modebuffer[0] = 0;
+    self->modebuffer[1] = 0;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, TrigBurstAmpStream_compute_next_data_frame);
+    self->mode_func_ptr = TrigBurstAmpStream_setProcMode;
+
+    static char *kwlist[] = {"mainPlayer", "chnl", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &maintmp, &self->chnl))
+        Py_RETURN_NONE;
+
+    Py_XDECREF(self->mainPlayer);
+    Py_INCREF(maintmp);
+    self->mainPlayer = (TrigBurster *)maintmp;
+
+    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
+
+    (*self->mode_func_ptr)(self);
+
+    return (PyObject *)self;
+}
+
+static PyObject * TrigBurstAmpStream_getServer(TrigBurstAmpStream* self) { GET_SERVER };
+static PyObject * TrigBurstAmpStream_getStream(TrigBurstAmpStream* self) { GET_STREAM };
+static PyObject * TrigBurstAmpStream_setMul(TrigBurstAmpStream *self, PyObject *arg) { SET_MUL };
+static PyObject * TrigBurstAmpStream_setAdd(TrigBurstAmpStream *self, PyObject *arg) { SET_ADD };
+static PyObject * TrigBurstAmpStream_setSub(TrigBurstAmpStream *self, PyObject *arg) { SET_SUB };
+static PyObject * TrigBurstAmpStream_setDiv(TrigBurstAmpStream *self, PyObject *arg) { SET_DIV };
+
+static PyObject * TrigBurstAmpStream_play(TrigBurstAmpStream *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * TrigBurstAmpStream_out(TrigBurstAmpStream *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * TrigBurstAmpStream_stop(TrigBurstAmpStream *self) { STOP };
+
+static PyObject * TrigBurstAmpStream_multiply(TrigBurstAmpStream *self, PyObject *arg) { MULTIPLY };
+static PyObject * TrigBurstAmpStream_inplace_multiply(TrigBurstAmpStream *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * TrigBurstAmpStream_add(TrigBurstAmpStream *self, PyObject *arg) { ADD };
+static PyObject * TrigBurstAmpStream_inplace_add(TrigBurstAmpStream *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * TrigBurstAmpStream_sub(TrigBurstAmpStream *self, PyObject *arg) { SUB };
+static PyObject * TrigBurstAmpStream_inplace_sub(TrigBurstAmpStream *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * TrigBurstAmpStream_div(TrigBurstAmpStream *self, PyObject *arg) { DIV };
+static PyObject * TrigBurstAmpStream_inplace_div(TrigBurstAmpStream *self, PyObject *arg) { INPLACE_DIV };
+
+static PyMemberDef TrigBurstAmpStream_members[] = {
+    {"server", T_OBJECT_EX, offsetof(TrigBurstAmpStream, server), 0, "Pyo server."},
+    {"stream", T_OBJECT_EX, offsetof(TrigBurstAmpStream, stream), 0, "Stream object."},
+    {"mul", T_OBJECT_EX, offsetof(TrigBurstAmpStream, mul), 0, "Mul factor."},
+    {"add", T_OBJECT_EX, offsetof(TrigBurstAmpStream, add), 0, "Add factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef TrigBurstAmpStream_methods[] = {
+    {"getServer", (PyCFunction)TrigBurstAmpStream_getServer, METH_NOARGS, "Returns server object."},
+    {"_getStream", (PyCFunction)TrigBurstAmpStream_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)TrigBurstAmpStream_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+    {"out", (PyCFunction)TrigBurstAmpStream_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+    {"stop", (PyCFunction)TrigBurstAmpStream_stop, METH_NOARGS, "Stops computing."},
+    {"setMul", (PyCFunction)TrigBurstAmpStream_setMul, METH_O, "Sets oscillator mul factor."},
+    {"setAdd", (PyCFunction)TrigBurstAmpStream_setAdd, METH_O, "Sets oscillator add factor."},
+    {"setSub", (PyCFunction)TrigBurstAmpStream_setSub, METH_O, "Sets inverse add factor."},
+    {"setDiv", (PyCFunction)TrigBurstAmpStream_setDiv, METH_O, "Sets inverse mul factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyNumberMethods TrigBurstAmpStream_as_number = {
+    (binaryfunc)TrigBurstAmpStream_add,                         /*nb_add*/
+    (binaryfunc)TrigBurstAmpStream_sub,                         /*nb_subtract*/
+    (binaryfunc)TrigBurstAmpStream_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)TrigBurstAmpStream_inplace_add,                 /*inplace_add*/
+    (binaryfunc)TrigBurstAmpStream_inplace_sub,                 /*inplace_subtract*/
+    (binaryfunc)TrigBurstAmpStream_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)TrigBurstAmpStream_div,                       /*nb_true_divide*/
+    0,                                              /*nb_inplace_floor_divide*/
+    (binaryfunc)TrigBurstAmpStream_inplace_div,                       /*nb_inplace_true_divide*/
+    0,                                              /* nb_index */
+};
+
+PyTypeObject TrigBurstAmpStreamType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.TrigBurstAmpStream_base",         /*tp_name*/
+    sizeof(TrigBurstAmpStream),         /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)TrigBurstAmpStream_dealloc, /*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
+    0,                         /*tp_repr*/
+    &TrigBurstAmpStream_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*/
+    "TrigBurstAmpStream objects. Reads a amplitude channel from a TrigBurster object.",           /* tp_doc */
+    (traverseproc)TrigBurstAmpStream_traverse,   /* tp_traverse */
+    (inquiry)TrigBurstAmpStream_clear,           /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    TrigBurstAmpStream_methods,             /* tp_methods */
+    TrigBurstAmpStream_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 */
+    TrigBurstAmpStream_new,                 /* tp_new */
+};
+
+/************************************************************************************************/
+/* TrigBurstDurStream object per channel */
+/************************************************************************************************/
+typedef struct {
+    pyo_audio_HEAD
+    TrigBurster *mainPlayer;
+    int chnl;
+    int modebuffer[2];
+} TrigBurstDurStream;
+
+static void TrigBurstDurStream_postprocessing_ii(TrigBurstDurStream *self) { POST_PROCESSING_II };
+static void TrigBurstDurStream_postprocessing_ai(TrigBurstDurStream *self) { POST_PROCESSING_AI };
+static void TrigBurstDurStream_postprocessing_ia(TrigBurstDurStream *self) { POST_PROCESSING_IA };
+static void TrigBurstDurStream_postprocessing_aa(TrigBurstDurStream *self) { POST_PROCESSING_AA };
+static void TrigBurstDurStream_postprocessing_ireva(TrigBurstDurStream *self) { POST_PROCESSING_IREVA };
+static void TrigBurstDurStream_postprocessing_areva(TrigBurstDurStream *self) { POST_PROCESSING_AREVA };
+static void TrigBurstDurStream_postprocessing_revai(TrigBurstDurStream *self) { POST_PROCESSING_REVAI };
+static void TrigBurstDurStream_postprocessing_revaa(TrigBurstDurStream *self) { POST_PROCESSING_REVAA };
+static void TrigBurstDurStream_postprocessing_revareva(TrigBurstDurStream *self) { POST_PROCESSING_REVAREVA };
+
+static void
+TrigBurstDurStream_setProcMode(TrigBurstDurStream *self) {
+    int muladdmode;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+    switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = TrigBurstDurStream_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = TrigBurstDurStream_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = TrigBurstDurStream_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = TrigBurstDurStream_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = TrigBurstDurStream_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = TrigBurstDurStream_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = TrigBurstDurStream_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = TrigBurstDurStream_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = TrigBurstDurStream_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+TrigBurstDurStream_compute_next_data_frame(TrigBurstDurStream *self)
+{
+    int i;
+    MYFLT *tmp;
+    int offset = self->chnl * self->bufsize;
+    tmp = TrigBurster_getDurBuffer((TrigBurster *)self->mainPlayer);
+    for (i=0; i<self->bufsize; i++) {
+        self->data[i] = tmp[i + offset];
+    }
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+TrigBurstDurStream_traverse(TrigBurstDurStream *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->mainPlayer);
+    return 0;
+}
+
+static int
+TrigBurstDurStream_clear(TrigBurstDurStream *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->mainPlayer);
+    return 0;
+}
+
+static void
+TrigBurstDurStream_dealloc(TrigBurstDurStream* self)
+{
+    pyo_DEALLOC
+    TrigBurstDurStream_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+TrigBurstDurStream_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *maintmp=NULL;
+    TrigBurstDurStream *self;
+    self = (TrigBurstDurStream *)type->tp_alloc(type, 0);
+
+    self->chnl = 0;
+    self->modebuffer[0] = 0;
+    self->modebuffer[1] = 0;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, TrigBurstDurStream_compute_next_data_frame);
+    self->mode_func_ptr = TrigBurstDurStream_setProcMode;
+
+    static char *kwlist[] = {"mainPlayer", "chnl", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &maintmp, &self->chnl))
+        Py_RETURN_NONE;
+
+    Py_XDECREF(self->mainPlayer);
+    Py_INCREF(maintmp);
+    self->mainPlayer = (TrigBurster *)maintmp;
+
+    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
+
+    (*self->mode_func_ptr)(self);
+
+    return (PyObject *)self;
+}
+
+static PyObject * TrigBurstDurStream_getServer(TrigBurstDurStream* self) { GET_SERVER };
+static PyObject * TrigBurstDurStream_getStream(TrigBurstDurStream* self) { GET_STREAM };
+static PyObject * TrigBurstDurStream_setMul(TrigBurstDurStream *self, PyObject *arg) { SET_MUL };
+static PyObject * TrigBurstDurStream_setAdd(TrigBurstDurStream *self, PyObject *arg) { SET_ADD };
+static PyObject * TrigBurstDurStream_setSub(TrigBurstDurStream *self, PyObject *arg) { SET_SUB };
+static PyObject * TrigBurstDurStream_setDiv(TrigBurstDurStream *self, PyObject *arg) { SET_DIV };
+
+static PyObject * TrigBurstDurStream_play(TrigBurstDurStream *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * TrigBurstDurStream_out(TrigBurstDurStream *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * TrigBurstDurStream_stop(TrigBurstDurStream *self) { STOP };
+
+static PyObject * TrigBurstDurStream_multiply(TrigBurstDurStream *self, PyObject *arg) { MULTIPLY };
+static PyObject * TrigBurstDurStream_inplace_multiply(TrigBurstDurStream *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * TrigBurstDurStream_add(TrigBurstDurStream *self, PyObject *arg) { ADD };
+static PyObject * TrigBurstDurStream_inplace_add(TrigBurstDurStream *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * TrigBurstDurStream_sub(TrigBurstDurStream *self, PyObject *arg) { SUB };
+static PyObject * TrigBurstDurStream_inplace_sub(TrigBurstDurStream *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * TrigBurstDurStream_div(TrigBurstDurStream *self, PyObject *arg) { DIV };
+static PyObject * TrigBurstDurStream_inplace_div(TrigBurstDurStream *self, PyObject *arg) { INPLACE_DIV };
+
+static PyMemberDef TrigBurstDurStream_members[] = {
+    {"server", T_OBJECT_EX, offsetof(TrigBurstDurStream, server), 0, "Pyo server."},
+    {"stream", T_OBJECT_EX, offsetof(TrigBurstDurStream, stream), 0, "Stream object."},
+    {"mul", T_OBJECT_EX, offsetof(TrigBurstDurStream, mul), 0, "Mul factor."},
+    {"add", T_OBJECT_EX, offsetof(TrigBurstDurStream, add), 0, "Add factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef TrigBurstDurStream_methods[] = {
+    {"getServer", (PyCFunction)TrigBurstDurStream_getServer, METH_NOARGS, "Returns server object."},
+    {"_getStream", (PyCFunction)TrigBurstDurStream_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)TrigBurstDurStream_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+    {"out", (PyCFunction)TrigBurstDurStream_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+    {"stop", (PyCFunction)TrigBurstDurStream_stop, METH_NOARGS, "Stops computing."},
+    {"setMul", (PyCFunction)TrigBurstDurStream_setMul, METH_O, "Sets oscillator mul factor."},
+    {"setAdd", (PyCFunction)TrigBurstDurStream_setAdd, METH_O, "Sets oscillator add factor."},
+    {"setSub", (PyCFunction)TrigBurstDurStream_setSub, METH_O, "Sets inverse add factor."},
+    {"setDiv", (PyCFunction)TrigBurstDurStream_setDiv, METH_O, "Sets inverse mul factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyNumberMethods TrigBurstDurStream_as_number = {
+    (binaryfunc)TrigBurstDurStream_add,                         /*nb_add*/
+    (binaryfunc)TrigBurstDurStream_sub,                         /*nb_subtract*/
+    (binaryfunc)TrigBurstDurStream_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)TrigBurstDurStream_inplace_add,                 /*inplace_add*/
+    (binaryfunc)TrigBurstDurStream_inplace_sub,                 /*inplace_subtract*/
+    (binaryfunc)TrigBurstDurStream_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)TrigBurstDurStream_div,                       /*nb_true_divide*/
+    0,                                              /*nb_inplace_floor_divide*/
+    (binaryfunc)TrigBurstDurStream_inplace_div,                       /*nb_inplace_true_divide*/
+    0,                                              /* nb_index */
+};
+
+PyTypeObject TrigBurstDurStreamType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.TrigBurstDurStream_base",         /*tp_name*/
+    sizeof(TrigBurstDurStream),         /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)TrigBurstDurStream_dealloc, /*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
+    0,                         /*tp_repr*/
+    &TrigBurstDurStream_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*/
+    "TrigBurstDurStream objects. Reads a duration channel from a TrigBurster object.",           /* tp_doc */
+    (traverseproc)TrigBurstDurStream_traverse,   /* tp_traverse */
+    (inquiry)TrigBurstDurStream_clear,           /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    TrigBurstDurStream_methods,             /* tp_methods */
+    TrigBurstDurStream_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 */
+    TrigBurstDurStream_new,                 /* tp_new */
+};
+
+/************************************************************************************************/
+/* TrigBurstEndStream object per channel */
+/************************************************************************************************/
+typedef struct {
+    pyo_audio_HEAD
+    TrigBurster *mainPlayer;
+    int chnl;
+    int modebuffer[2];
+} TrigBurstEndStream;
+
+static void TrigBurstEndStream_postprocessing_ii(TrigBurstEndStream *self) { POST_PROCESSING_II };
+static void TrigBurstEndStream_postprocessing_ai(TrigBurstEndStream *self) { POST_PROCESSING_AI };
+static void TrigBurstEndStream_postprocessing_ia(TrigBurstEndStream *self) { POST_PROCESSING_IA };
+static void TrigBurstEndStream_postprocessing_aa(TrigBurstEndStream *self) { POST_PROCESSING_AA };
+static void TrigBurstEndStream_postprocessing_ireva(TrigBurstEndStream *self) { POST_PROCESSING_IREVA };
+static void TrigBurstEndStream_postprocessing_areva(TrigBurstEndStream *self) { POST_PROCESSING_AREVA };
+static void TrigBurstEndStream_postprocessing_revai(TrigBurstEndStream *self) { POST_PROCESSING_REVAI };
+static void TrigBurstEndStream_postprocessing_revaa(TrigBurstEndStream *self) { POST_PROCESSING_REVAA };
+static void TrigBurstEndStream_postprocessing_revareva(TrigBurstEndStream *self) { POST_PROCESSING_REVAREVA };
+
+static void
+TrigBurstEndStream_setProcMode(TrigBurstEndStream *self) {
+    int muladdmode;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+    switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = TrigBurstEndStream_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = TrigBurstEndStream_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = TrigBurstEndStream_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = TrigBurstEndStream_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = TrigBurstEndStream_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = TrigBurstEndStream_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = TrigBurstEndStream_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = TrigBurstEndStream_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = TrigBurstEndStream_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+TrigBurstEndStream_compute_next_data_frame(TrigBurstEndStream *self)
+{
+    int i;
+    MYFLT *tmp;
+    int offset = self->chnl * self->bufsize;
+    tmp = TrigBurster_getEndBuffer((TrigBurster *)self->mainPlayer);
+    for (i=0; i<self->bufsize; i++) {
+        self->data[i] = tmp[i + offset];
+    }
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+TrigBurstEndStream_traverse(TrigBurstEndStream *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->mainPlayer);
+    return 0;
+}
+
+static int
+TrigBurstEndStream_clear(TrigBurstEndStream *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->mainPlayer);
+    return 0;
+}
+
+static void
+TrigBurstEndStream_dealloc(TrigBurstEndStream* self)
+{
+    pyo_DEALLOC
+    TrigBurstEndStream_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+TrigBurstEndStream_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *maintmp=NULL;
+    TrigBurstEndStream *self;
+    self = (TrigBurstEndStream *)type->tp_alloc(type, 0);
+
+    self->chnl = 0;
+    self->modebuffer[0] = 0;
+    self->modebuffer[1] = 0;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, TrigBurstEndStream_compute_next_data_frame);
+    self->mode_func_ptr = TrigBurstEndStream_setProcMode;
+
+    static char *kwlist[] = {"mainPlayer", "chnl", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &maintmp, &self->chnl))
+        Py_RETURN_NONE;
+
+    Py_XDECREF(self->mainPlayer);
+    Py_INCREF(maintmp);
+    self->mainPlayer = (TrigBurster *)maintmp;
+
+    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
+
+    (*self->mode_func_ptr)(self);
+
+    return (PyObject *)self;
+}
+
+static PyObject * TrigBurstEndStream_getServer(TrigBurstEndStream* self) { GET_SERVER };
+static PyObject * TrigBurstEndStream_getStream(TrigBurstEndStream* self) { GET_STREAM };
+static PyObject * TrigBurstEndStream_setMul(TrigBurstEndStream *self, PyObject *arg) { SET_MUL };
+static PyObject * TrigBurstEndStream_setAdd(TrigBurstEndStream *self, PyObject *arg) { SET_ADD };
+static PyObject * TrigBurstEndStream_setSub(TrigBurstEndStream *self, PyObject *arg) { SET_SUB };
+static PyObject * TrigBurstEndStream_setDiv(TrigBurstEndStream *self, PyObject *arg) { SET_DIV };
+
+static PyObject * TrigBurstEndStream_play(TrigBurstEndStream *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * TrigBurstEndStream_out(TrigBurstEndStream *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * TrigBurstEndStream_stop(TrigBurstEndStream *self) { STOP };
+
+static PyObject * TrigBurstEndStream_multiply(TrigBurstEndStream *self, PyObject *arg) { MULTIPLY };
+static PyObject * TrigBurstEndStream_inplace_multiply(TrigBurstEndStream *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * TrigBurstEndStream_add(TrigBurstEndStream *self, PyObject *arg) { ADD };
+static PyObject * TrigBurstEndStream_inplace_add(TrigBurstEndStream *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * TrigBurstEndStream_sub(TrigBurstEndStream *self, PyObject *arg) { SUB };
+static PyObject * TrigBurstEndStream_inplace_sub(TrigBurstEndStream *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * TrigBurstEndStream_div(TrigBurstEndStream *self, PyObject *arg) { DIV };
+static PyObject * TrigBurstEndStream_inplace_div(TrigBurstEndStream *self, PyObject *arg) { INPLACE_DIV };
+
+static PyMemberDef TrigBurstEndStream_members[] = {
+    {"server", T_OBJECT_EX, offsetof(TrigBurstEndStream, server), 0, "Pyo server."},
+    {"stream", T_OBJECT_EX, offsetof(TrigBurstEndStream, stream), 0, "Stream object."},
+    {"mul", T_OBJECT_EX, offsetof(TrigBurstEndStream, mul), 0, "Mul factor."},
+    {"add", T_OBJECT_EX, offsetof(TrigBurstEndStream, add), 0, "Add factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef TrigBurstEndStream_methods[] = {
+    {"getServer", (PyCFunction)TrigBurstEndStream_getServer, METH_NOARGS, "Returns server object."},
+    {"_getStream", (PyCFunction)TrigBurstEndStream_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)TrigBurstEndStream_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+    {"out", (PyCFunction)TrigBurstEndStream_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+    {"stop", (PyCFunction)TrigBurstEndStream_stop, METH_NOARGS, "Stops computing."},
+    {"setMul", (PyCFunction)TrigBurstEndStream_setMul, METH_O, "Sets oscillator mul factor."},
+    {"setAdd", (PyCFunction)TrigBurstEndStream_setAdd, METH_O, "Sets oscillator add factor."},
+    {"setSub", (PyCFunction)TrigBurstEndStream_setSub, METH_O, "Sets inverse add factor."},
+    {"setDiv", (PyCFunction)TrigBurstEndStream_setDiv, METH_O, "Sets inverse mul factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyNumberMethods TrigBurstEndStream_as_number = {
+    (binaryfunc)TrigBurstEndStream_add,                         /*nb_add*/
+    (binaryfunc)TrigBurstEndStream_sub,                         /*nb_subtract*/
+    (binaryfunc)TrigBurstEndStream_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)TrigBurstEndStream_inplace_add,                 /*inplace_add*/
+    (binaryfunc)TrigBurstEndStream_inplace_sub,                 /*inplace_subtract*/
+    (binaryfunc)TrigBurstEndStream_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)TrigBurstEndStream_div,                       /*nb_true_divide*/
+    0,                                              /*nb_inplace_floor_divide*/
+    (binaryfunc)TrigBurstEndStream_inplace_div,                       /*nb_inplace_true_divide*/
+    0,                                              /* nb_index */
+};
+
+PyTypeObject TrigBurstEndStreamType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.TrigBurstEndStream_base",         /*tp_name*/
+    sizeof(TrigBurstEndStream),         /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)TrigBurstEndStream_dealloc, /*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
+    0,                         /*tp_repr*/
+    &TrigBurstEndStream_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*/
+    "TrigBurstEndStream objects. Reads a duration channel from a TrigBurster object.",           /* tp_doc */
+    (traverseproc)TrigBurstEndStream_traverse,   /* tp_traverse */
+    (inquiry)TrigBurstEndStream_clear,           /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    TrigBurstEndStream_methods,             /* tp_methods */
+    TrigBurstEndStream_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 */
+    TrigBurstEndStream_new,                 /* tp_new */
+};
\ No newline at end of file
diff --git a/src/objects/midimodule.c b/src/objects/midimodule.c
index cc35226..be090eb 100644
--- a/src/objects/midimodule.c
+++ b/src/objects/midimodule.c
@@ -1,31 +1,31 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
 #include "streammodule.h"
 #include "servermodule.h"
 #include "dummymodule.h"
-#include "portmidi.h"
 
 typedef struct {
     pyo_audio_HEAD
@@ -39,8 +39,8 @@ CtlScan_setProcMode(CtlScan *self) {}
 
 static void
 CtlScan_compute_next_data_frame(CtlScan *self)
-{   
-    PmEvent *buffer;
+{
+    PyoMidiEvent *buffer;
     int i, count;
 
     buffer = Server_getMidiEventBuffer((Server *)self->server);
@@ -48,10 +48,10 @@ CtlScan_compute_next_data_frame(CtlScan *self)
 
     if (count > 0) {
         PyObject *tup;
-        for (i=count-1; i>=0; i--) {
-            int status = Pm_MessageStatus(buffer[i].message);	// Temp note event holders
-            int number = Pm_MessageData1(buffer[i].message);
-            int value = Pm_MessageData2(buffer[i].message);
+        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 ((status & 0xF0) == 0xB0) {
                 if (number != self->ctlnumber) {
@@ -61,7 +61,7 @@ CtlScan_compute_next_data_frame(CtlScan *self)
                     PyObject_Call((PyObject *)self->callable, tup, NULL);
                 }
                 if (self->toprint == 1)
-                    printf("ctl number : %i, ctl value : %i, midi channel : %i\n", self->ctlnumber, value, status - 0xB0 + 1);    
+                    PySys_WriteStdout("ctl number : %i, ctl value : %i, midi channel : %i\n", self->ctlnumber, value, status - 0xB0 + 1);
             }
         }
     }
@@ -75,7 +75,7 @@ CtlScan_traverse(CtlScan *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 CtlScan_clear(CtlScan *self)
 {
     pyo_CLEAR
@@ -88,14 +88,14 @@ CtlScan_dealloc(CtlScan* self)
 {
     pyo_DEALLOC
     CtlScan_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
 CtlScan_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
-    PyObject *calltmp=NULL;    
+    PyObject *calltmp=NULL;
     CtlScan *self;
     self = (CtlScan *)type->tp_alloc(type, 0);
 
@@ -116,7 +116,7 @@ CtlScan_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     }
 
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     return (PyObject *)self;
 }
 
@@ -127,35 +127,43 @@ static PyObject * CtlScan_play(CtlScan *self, PyObject *args, PyObject *kwds) {
 static PyObject * CtlScan_stop(CtlScan *self) { STOP };
 
 static PyObject *
+CtlScan_reset(CtlScan *self)
+{
+    self->ctlnumber = -1;
+    Py_INCREF(Py_None);
+    return Py_None;
+};
+
+static PyObject *
 CtlScan_setFunction(CtlScan *self, PyObject *arg)
 {
-	PyObject *tmp;
-	
-	if (! PyCallable_Check(arg)) {
+    PyObject *tmp;
+
+    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."},
@@ -168,14 +176,14 @@ static PyMethodDef CtlScan_methods[] = {
     {"_getStream", (PyCFunction)CtlScan_getStream, METH_NOARGS, "Returns stream object."},
     {"play", (PyCFunction)CtlScan_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
     {"stop", (PyCFunction)CtlScan_stop, METH_NOARGS, "Stops computing."},
+    {"reset", (PyCFunction)CtlScan_reset, METH_NOARGS, "Resets the scanned number."},
     {"setFunction", (PyCFunction)CtlScan_setFunction, METH_O, "Sets the function to be called."},
     {"setToprint", (PyCFunction)CtlScan_setToprint, METH_O, "If True, print values to the console."},
     {NULL}  /* Sentinel */
 };
 
 PyTypeObject CtlScanType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.CtlScan_base",         /*tp_name*/
     sizeof(CtlScan),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -183,7 +191,7 @@ PyTypeObject CtlScanType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     0,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -198,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 */
@@ -228,20 +236,20 @@ CtlScan2_setProcMode(CtlScan2 *self) {}
 
 static void
 CtlScan2_compute_next_data_frame(CtlScan2 *self)
-{   
-    PmEvent *buffer;
+{
+    PyoMidiEvent *buffer;
     int i, count, midichnl;
-    
+
     buffer = Server_getMidiEventBuffer((Server *)self->server);
     count = Server_getMidiEventCount((Server *)self->server);
-    
+
     if (count > 0) {
         PyObject *tup;
-        for (i=count-1; i>=0; i--) {
-            int status = Pm_MessageStatus(buffer[i].message);	// Temp note event holders
-            int number = Pm_MessageData1(buffer[i].message);
-            int value = Pm_MessageData2(buffer[i].message);
-            
+        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 ((status & 0xF0) == 0xB0) {
                 midichnl = status - 0xB0 + 1;
                 if (number != self->ctlnumber || midichnl != self->midichnl) {
@@ -253,7 +261,7 @@ CtlScan2_compute_next_data_frame(CtlScan2 *self)
                     PyObject_Call((PyObject *)self->callable, tup, NULL);
                 }
                 if (self->toprint == 1)
-                    printf("ctl number : %i, ctl value : %i, midi channel : %i\n", self->ctlnumber, value, midichnl);    
+                    PySys_WriteStdout("ctl number : %i, ctl value : %i, midi channel : %i\n", self->ctlnumber, value, midichnl);
             }
         }
     }
@@ -267,7 +275,7 @@ CtlScan2_traverse(CtlScan2 *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 CtlScan2_clear(CtlScan2 *self)
 {
     pyo_CLEAR
@@ -280,35 +288,35 @@ CtlScan2_dealloc(CtlScan2* self)
 {
     pyo_DEALLOC
     CtlScan2_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
 CtlScan2_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
-    PyObject *calltmp=NULL;    
+    PyObject *calltmp=NULL;
     CtlScan2 *self;
     self = (CtlScan2 *)type->tp_alloc(type, 0);
-    
+
     self->ctlnumber = self->midichnl = -1;
     self->toprint = 1;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, CtlScan2_compute_next_data_frame);
     self->mode_func_ptr = CtlScan2_setProcMode;
-    
+
     static char *kwlist[] = {"callable", "toprint", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|i", kwlist, &calltmp, &self->toprint))
         Py_RETURN_NONE;
-    
+
     if (calltmp) {
         PyObject_CallMethod((PyObject *)self, "setFunction", "O", calltmp);
     }
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     return (PyObject *)self;
 }
 
@@ -319,35 +327,43 @@ static PyObject * CtlScan2_play(CtlScan2 *self, PyObject *args, PyObject *kwds)
 static PyObject * CtlScan2_stop(CtlScan2 *self) { STOP };
 
 static PyObject *
+CtlScan2_reset(CtlScan2 *self)
+{
+    self->ctlnumber = self->midichnl = -1;
+    Py_INCREF(Py_None);
+    return Py_None;
+};
+
+static PyObject *
 CtlScan2_setFunction(CtlScan2 *self, PyObject *arg)
 {
-	PyObject *tmp;
-	
-	if (! PyCallable_Check(arg)) {
+    PyObject *tmp;
+
+    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."},
@@ -360,14 +376,14 @@ static PyMethodDef CtlScan2_methods[] = {
     {"_getStream", (PyCFunction)CtlScan2_getStream, METH_NOARGS, "Returns stream object."},
     {"play", (PyCFunction)CtlScan2_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
     {"stop", (PyCFunction)CtlScan2_stop, METH_NOARGS, "Stops computing."},
+    {"reset", (PyCFunction)CtlScan2_reset, METH_NOARGS, "Reset scanned numbers."},
     {"setFunction", (PyCFunction)CtlScan2_setFunction, METH_O, "Sets the function to be called."},
     {"setToprint", (PyCFunction)CtlScan2_setToprint, METH_O, "If True, print values to the console."},
     {NULL}  /* Sentinel */
 };
 
 PyTypeObject CtlScan2Type = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.CtlScan2_base",         /*tp_name*/
     sizeof(CtlScan2),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -375,7 +391,7 @@ PyTypeObject CtlScan2Type = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     0,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -390,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 */
@@ -407,17 +423,31 @@ PyTypeObject CtlScan2Type = {
     CtlScan2_new,                 /* tp_new */
 };
 
+int
+getPosToWrite(long timestamp, Server *server, double sr, int bufsize)
+{
+    int offset = 0;
+    long realtimestamp, elapsed, ms;
+    realtimestamp = timestamp - Server_getMidiTimeOffset(server);
+    if (realtimestamp < 0)
+        return 0;
+    elapsed = (long)(Server_getElapsedTime(server) / sr * 1000);
+    ms = realtimestamp - (elapsed - (long)(bufsize / sr * 1000));
+    offset = (int)(ms * 0.001 * sr);
+    if (offset < 0)
+        offset = 0;
+    else if (offset >= bufsize)
+        offset = bufsize - 1;
+    return offset;
+}
 
 typedef struct {
     pyo_audio_HEAD
     int ctlnumber;
     int channel;
-    int interp;
     MYFLT minscale;
     MYFLT maxscale;
     MYFLT value;
-    MYFLT oldValue;
-    MYFLT sampleToSec;
     int modebuffer[2];
 } Midictl;
 
@@ -437,90 +467,95 @@ Midictl_setProcMode(Midictl *self)
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
-	switch (muladdmode) {
-        case 0:        
+    switch (muladdmode) {
+        case 0:
             self->muladd_func_ptr = Midictl_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Midictl_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Midictl_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Midictl_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Midictl_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Midictl_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Midictl_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Midictl_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Midictl_postprocessing_revareva;
             break;
     }
 }
 
-// Take MIDI events and translate them...
-void translateMidi(Midictl *self, PmEvent *buffer, int count)
+int
+Midictl_translateMidi(Midictl *self, PyoMidiEvent *buffer, int j)
 {
-    int i, ok;
-    for (i=count-1; i>=0; i--) {
-        int status = Pm_MessageStatus(buffer[i].message);	// Temp note event holders
-        int number = Pm_MessageData1(buffer[i].message);
-        int value = Pm_MessageData2(buffer[i].message);
-        
-        if (self->channel == 0) {
-            if ((status & 0xF0) == 0xB0)
-                ok = 1;
-            else
-                ok = 0;
-        }
-        else {
-            if (status == (0xB0 | (self->channel - 1)))
-                ok = 1;
-            else
-                ok = 0;
-        }
+    int ok, posto = -1;
+    int status = PyoMidi_MessageStatus(buffer[j].message);    // Temp note event holders
+    int number = PyoMidi_MessageData1(buffer[j].message);
+    int value = PyoMidi_MessageData2(buffer[j].message);
 
-        if (ok == 1 && number == self->ctlnumber) {
-            self->oldValue = self->value;
-            self->value = (value / 127.) * (self->maxscale - self->minscale) + self->minscale;
-            break;
-        }
-    }    
+    if (self->channel == 0) {
+        if ((status & 0xF0) == 0xB0)
+            ok = 1;
+        else
+            ok = 0;
+    }
+    else {
+        if (status == (0xB0 | (self->channel - 1)))
+            ok = 1;
+        else
+            ok = 0;
+    }
+
+    if (ok == 1 && number == self->ctlnumber) {
+        self->value = (value / 127.) * (self->maxscale - self->minscale) + self->minscale;
+        posto = getPosToWrite(buffer[j].timestamp, (Server *)self->server, self->sr, self->bufsize);
+    }
+
+    return posto;
 }
 
 static void
 Midictl_compute_next_data_frame(Midictl *self)
-{   
-    PmEvent *tmp;
-    int i, count;
-    MYFLT step;
+{
+    PyoMidiEvent *tmp;
+    int i, j, count, posto, oldpos = 0;
+    MYFLT oldval = 0.0;
 
     tmp = Server_getMidiEventBuffer((Server *)self->server);
     count = Server_getMidiEventCount((Server *)self->server);
 
-    if (count > 0)
-        translateMidi((Midictl *)self, tmp, count);
-    
-    if (self->interp == 0) {
+    if (count == 0) {
         for (i=0; i<self->bufsize; i++) {
             self->data[i] = self->value;
         }
     }
     else {
-        step = (self->value - self->oldValue) / self->bufsize;
-        for (i=0; i<self->bufsize; i++) {
-            self->data[i] = self->oldValue + step;
-        }          
+        for (j=0; j<count; j++) {
+            oldval = self->value;
+            posto = Midictl_translateMidi((Midictl *)self, tmp, j);
+            if (posto == -1)
+                continue;
+            for (i=oldpos; i<posto; i++) {
+                self->data[i] = oldval;
+            }
+            oldpos = posto;
+        }
+        for (i=oldpos; i<self->bufsize; i++) {
+            self->data[i] = self->value;
+        }
     }
     (*self->muladd_func_ptr)(self);
 }
@@ -532,7 +567,7 @@ Midictl_traverse(Midictl *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Midictl_clear(Midictl *self)
 {
     pyo_CLEAR
@@ -544,25 +579,23 @@ Midictl_dealloc(Midictl* self)
 {
     pyo_DEALLOC
     Midictl_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
 Midictl_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
-    int i;    
+    int i;
     PyObject *multmp=NULL, *addtmp=NULL;
     Midictl *self;
     self = (Midictl *)type->tp_alloc(type, 0);
 
     self->channel = 0;
     self->value = 0.;
-    self->oldValue = 0.;
     self->minscale = 0.;
     self->maxscale = 1.;
-    self->interp = 1;
-	self->modebuffer[0] = 0;
-	self->modebuffer[1] = 0;
+    self->modebuffer[0] = 0;
+    self->modebuffer[1] = 0;
 
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Midictl_compute_next_data_frame);
@@ -570,9 +603,9 @@ Midictl_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
     static char *kwlist[] = {"ctlnumber", "minscale", "maxscale", "init", "channel", "mul", "add", NULL};
 
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_I_FFFIOO, kwlist, &self->ctlnumber, &self->minscale, &self->maxscale, &self->oldValue, &self->channel, &multmp, &addtmp))
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_I_FFFIOO, kwlist, &self->ctlnumber, &self->minscale, &self->maxscale, &self->value, &self->channel, &multmp, &addtmp))
         Py_RETURN_NONE;
- 
+
     if (multmp) {
         PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
     }
@@ -580,22 +613,20 @@ Midictl_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (addtmp) {
         PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
     }
-            
-    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
-    self->value = self->oldValue;
+    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * Midictl_getServer(Midictl* self) { GET_SERVER };
 static PyObject * Midictl_getStream(Midictl* self) { GET_STREAM };
-static PyObject * Midictl_setMul(Midictl *self, PyObject *arg) { SET_MUL };	
-static PyObject * Midictl_setAdd(Midictl *self, PyObject *arg) { SET_ADD };	
-static PyObject * Midictl_setSub(Midictl *self, PyObject *arg) { SET_SUB };	
-static PyObject * Midictl_setDiv(Midictl *self, PyObject *arg) { SET_DIV };	
+static PyObject * Midictl_setMul(Midictl *self, PyObject *arg) { SET_MUL };
+static PyObject * Midictl_setAdd(Midictl *self, PyObject *arg) { SET_ADD };
+static PyObject * Midictl_setSub(Midictl *self, PyObject *arg) { SET_SUB };
+static PyObject * Midictl_setDiv(Midictl *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Midictl_play(Midictl *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Midictl_stop(Midictl *self) { STOP };
@@ -610,135 +641,87 @@ static PyObject * Midictl_div(Midictl *self, PyObject *arg) { DIV };
 static PyObject * Midictl_inplace_div(Midictl *self, PyObject *arg) { INPLACE_DIV };
 
 static PyObject *
-Midictl_setInterpolation(Midictl *self, PyObject *arg)
-{
-    int tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	
-	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 PyObject *
 Midictl_setValue(Midictl *self, PyObject *arg)
 {
-    int tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	
-	int isNum = PyNumber_Check(arg);
-    
-	if (isNum == 1) {
-		tmp = PyFloat_AsDouble(PyNumber_Float(arg));
-        self->oldValue = self->value = tmp;
-	}
-    
-	Py_INCREF(Py_None);
-	return Py_None;
+    ASSERT_ARG_NOT_NULL
+
+    int isNum = PyNumber_Check(arg);
+
+    if (isNum == 1) {
+        self->value = PyFloat_AsDouble(arg);
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
 static PyObject *
 Midictl_setMinScale(Midictl *self, PyObject *arg)
 {
-    int tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	
-	int isNum = PyNumber_Check(arg);
-    
-	if (isNum == 1) {
-		tmp = PyFloat_AsDouble(PyNumber_Float(arg));
-        self->minscale = tmp;
-	}
-    
-	Py_INCREF(Py_None);
-	return Py_None;
-}	
+    ASSERT_ARG_NOT_NULL
+
+    int isNum = PyNumber_Check(arg);
+
+    if (isNum == 1) {
+        self->minscale = PyFloat_AsDouble(arg);
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
 
 static PyObject *
 Midictl_setMaxScale(Midictl *self, PyObject *arg)
 {
-    int tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	
-	int isNum = PyNumber_Check(arg);
-    
-	if (isNum == 1) {
-		tmp = PyFloat_AsDouble(PyNumber_Float(arg));
-        self->maxscale = tmp;
-	}
-    
-	Py_INCREF(Py_None);
-	return Py_None;
-}	
+    ASSERT_ARG_NOT_NULL
+
+    int isNum = PyNumber_Check(arg);
+
+    if (isNum == 1) {
+        self->maxscale = PyFloat_AsDouble(arg);
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
 
 static PyObject *
 Midictl_setCtlNumber(Midictl *self, PyObject *arg)
 {
     int tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	
-	int isInt = PyInt_Check(arg);
-    
-	if (isInt == 1) {
-		tmp = PyInt_AsLong(arg);
+
+    ASSERT_ARG_NOT_NULL
+
+    int isInt = PyInt_Check(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 *
 Midictl_setChannel(Midictl *self, PyObject *arg)
 {
     int tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	
-	int isInt = PyInt_Check(arg);
-    
-	if (isInt == 1) {
-		tmp = PyInt_AsLong(arg);
+
+    ASSERT_ARG_NOT_NULL
+
+    int isInt = PyInt_Check(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[] = {
     {"server", T_OBJECT_EX, offsetof(Midictl, server), 0, "Pyo server."},
@@ -753,14 +736,13 @@ 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."},
+    {"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 */
@@ -770,7 +752,7 @@ static PyNumberMethods Midictl_as_number = {
     (binaryfunc)Midictl_add,                      /*nb_add*/
     (binaryfunc)Midictl_sub,                 /*nb_subtract*/
     (binaryfunc)Midictl_multiply,                 /*nb_multiply*/
-    (binaryfunc)Midictl_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -784,16 +766,16 @@ static PyNumberMethods Midictl_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)Midictl_inplace_add,              /*inplace_add*/
     (binaryfunc)Midictl_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)Midictl_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)Midictl_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -802,15 +784,14 @@ static PyNumberMethods Midictl_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)Midictl_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)Midictl_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject MidictlType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Midictl_base",         /*tp_name*/
     sizeof(Midictl),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -818,7 +799,7 @@ PyTypeObject MidictlType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &Midictl_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -833,10 +814,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 */
@@ -856,8 +837,6 @@ typedef struct {
     int scale; /* 0 = midi, 1 = transpo */
     MYFLT range;
     MYFLT value;
-    MYFLT oldValue;
-    MYFLT sampleToSec;
     int modebuffer[2];
 } Bendin;
 
@@ -876,90 +855,104 @@ Bendin_setProcMode(Bendin *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
-	switch (muladdmode) {
-        case 0:        
+
+    switch (muladdmode) {
+        case 0:
             self->muladd_func_ptr = Bendin_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Bendin_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Bendin_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Bendin_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Bendin_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Bendin_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Bendin_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Bendin_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Bendin_postprocessing_revareva;
             break;
     }
 }
 
-// Take MIDI events and translate them...
-void Bendin_translateMidi(Bendin *self, PmEvent *buffer, int count)
+int
+Bendin_translateMidi(Bendin *self, PyoMidiEvent *buffer, int j)
 {
-    int i, ok;
+    int ok, posto = -1;
     MYFLT val;
-    for (i=count-1; i>=0; i--) {
-        int status = Pm_MessageStatus(buffer[i].message);	// Temp note event holders
-        int number = Pm_MessageData1(buffer[i].message);
-        int value = Pm_MessageData2(buffer[i].message);
-        
-        if (self->channel == 0) {
-            if ((status & 0xF0) == 0xe0)
-                ok = 1;
-            else
-                ok = 0;
-        }
-        else {
-            if (status == (0xe0 | (self->channel - 1)))
-                ok = 1;
-            else
-                ok = 0;
-        }
-        
-        if (ok == 1) {
-            self->oldValue = self->value;
-            val = (number + (value << 7) - 8192) / 8192.0 * self->range;
-            if (self->scale == 0)
-                self->value = val;
-            else
-                self->value = MYPOW(1.0594630943593, val);
-            break;
-        }
-    }    
+
+    int status = PyoMidi_MessageStatus(buffer[j].message);    // Temp note event holders
+    int number = PyoMidi_MessageData1(buffer[j].message);
+    int value = PyoMidi_MessageData2(buffer[j].message);
+
+    if (self->channel == 0) {
+        if ((status & 0xF0) == 0xe0)
+            ok = 1;
+        else
+            ok = 0;
+    }
+    else {
+        if (status == (0xe0 | (self->channel - 1)))
+            ok = 1;
+        else
+            ok = 0;
+    }
+
+    if (ok == 1) {
+        val = (number + (value << 7) - 8192) / 8192.0 * self->range;
+        if (self->scale == 0)
+            self->value = val;
+        else
+            self->value = MYPOW(1.0594630943593, val);
+        posto = getPosToWrite(buffer[j].timestamp, (Server *)self->server, self->sr, self->bufsize);
+    }
+
+    return posto;
 }
 
 static void
 Bendin_compute_next_data_frame(Bendin *self)
-{   
-    PmEvent *tmp;
-    int i, count;
-    
+{
+    PyoMidiEvent *tmp;
+    int i, j, count, posto, oldpos = 0;
+    MYFLT oldval = 0.0;
+
     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 (count == 0) {
+        for (i=0; i<self->bufsize; i++) {
+            self->data[i] = self->value;
+        }
+    }
+    else {
+        for (j=0; j<count; j++) {
+            oldval = self->value;
+            posto = Bendin_translateMidi((Bendin *)self, tmp, j);
+            if (posto == -1)
+                continue;
+            for (i=oldpos; i<posto; i++) {
+                self->data[i] = oldval;
+            }
+            oldpos = posto;
+        }
+        for (i=oldpos; i<self->bufsize; i++) {
+            self->data[i] = self->value;
+        }
+    }
+
     (*self->muladd_func_ptr)(self);
 }
 
@@ -970,7 +963,7 @@ Bendin_traverse(Bendin *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Bendin_clear(Bendin *self)
 {
     pyo_CLEAR
@@ -982,60 +975,57 @@ Bendin_dealloc(Bendin* self)
 {
     pyo_DEALLOC
     Bendin_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
 Bendin_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
-    PyObject *multmp=NULL, *addtmp=NULL;    
+    PyObject *multmp=NULL, *addtmp=NULL;
     Bendin *self;
     self = (Bendin *)type->tp_alloc(type, 0);
-    
+
     self->channel = 0;
     self->scale = 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);
     self->mode_func_ptr = Bendin_setProcMode;
 
     static char *kwlist[] = {"brange", "scale", "channel", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__FIIOO, kwlist, &self->range, &self->scale, &self->channel, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     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);
 
-    if (self->scale == 0)
-        self->oldValue = self->value = 0.;
-    else
-        self->oldValue = self->value = 1.;
-        
+    if (self->scale == 1)
+        self->value = 1.0;
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * Bendin_getServer(Bendin* self) { GET_SERVER };
 static PyObject * Bendin_getStream(Bendin* self) { GET_STREAM };
-static PyObject * Bendin_setMul(Bendin *self, PyObject *arg) { SET_MUL };	
-static PyObject * Bendin_setAdd(Bendin *self, PyObject *arg) { SET_ADD };	
-static PyObject * Bendin_setSub(Bendin *self, PyObject *arg) { SET_SUB };	
-static PyObject * Bendin_setDiv(Bendin *self, PyObject *arg) { SET_DIV };	
+static PyObject * Bendin_setMul(Bendin *self, PyObject *arg) { SET_MUL };
+static PyObject * Bendin_setAdd(Bendin *self, PyObject *arg) { SET_ADD };
+static PyObject * Bendin_setSub(Bendin *self, PyObject *arg) { SET_SUB };
+static PyObject * Bendin_setDiv(Bendin *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Bendin_play(Bendin *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Bendin_stop(Bendin *self) { STOP };
@@ -1053,58 +1043,49 @@ static PyObject *
 Bendin_setBrange(Bendin *self, PyObject *arg)
 {
     MYFLT tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	
-	int isNum = PyNumber_Check(arg);
-    
-	if (isNum == 1) {
-		tmp = PyFloat_AsDouble(PyNumber_Float(arg));
+
+    ASSERT_ARG_NOT_NULL
+
+    int isNum = PyNumber_Check(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 *
 Bendin_setChannel(Bendin *self, PyObject *arg)
 {
     int tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	
-	int isInt = PyInt_Check(arg);
-    
-	if (isInt == 1) {
-		tmp = PyInt_AsLong(arg);
+
+    ASSERT_ARG_NOT_NULL
+
+    int isInt = PyInt_Check(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 *
 Bendin_setScale(Bendin *self, PyObject *arg)
 {
     int tmp;
-    
-    if (arg == NULL) {
-        Py_INCREF(Py_None);
-        return Py_None;
-    }
-    
+
+    ASSERT_ARG_NOT_NULL
+
     int isInt = PyInt_Check(arg);
-    
+
     if (isInt == 1) {
         tmp = PyInt_AsLong(arg);
         if (tmp == 0)
@@ -1112,11 +1093,10 @@ Bendin_setScale(Bendin *self, PyObject *arg)
         else if (tmp == 1)
             self->scale = 1;
     }
-    
+
     Py_INCREF(Py_None);
     return Py_None;
-}	
-
+}
 
 static PyMemberDef Bendin_members[] = {
     {"server", T_OBJECT_EX, offsetof(Bendin, server), 0, "Pyo server."},
@@ -1131,11 +1111,11 @@ 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."},
+    {"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 */
@@ -1145,7 +1125,7 @@ static PyNumberMethods Bendin_as_number = {
     (binaryfunc)Bendin_add,                      /*nb_add*/
     (binaryfunc)Bendin_sub,                 /*nb_subtract*/
     (binaryfunc)Bendin_multiply,                 /*nb_multiply*/
-    (binaryfunc)Bendin_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -1159,16 +1139,16 @@ static PyNumberMethods Bendin_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)Bendin_inplace_add,              /*inplace_add*/
     (binaryfunc)Bendin_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)Bendin_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)Bendin_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -1177,15 +1157,14 @@ static PyNumberMethods Bendin_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)Bendin_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)Bendin_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject BendinType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Bendin_base",         /*tp_name*/
     sizeof(Bendin),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -1193,7 +1172,7 @@ PyTypeObject BendinType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &Bendin_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -1208,10 +1187,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 */
@@ -1231,8 +1210,6 @@ typedef struct {
     MYFLT minscale;
     MYFLT maxscale;
     MYFLT value;
-    MYFLT oldValue;
-    MYFLT sampleToSec;
     int modebuffer[2];
 } Touchin;
 
@@ -1251,85 +1228,97 @@ Touchin_setProcMode(Touchin *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
-	switch (muladdmode) {
-        case 0:        
+
+    switch (muladdmode) {
+        case 0:
             self->muladd_func_ptr = Touchin_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Touchin_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Touchin_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Touchin_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Touchin_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Touchin_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Touchin_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Touchin_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Touchin_postprocessing_revareva;
             break;
     }
 }
 
-// Take MIDI events and translate them...
-void Touchin_translateMidi(Touchin *self, PmEvent *buffer, int count)
+int
+Touchin_translateMidi(Touchin *self, PyoMidiEvent *buffer, int j)
 {
-    int i, ok;
-    for (i=count-1; i>=0; i--) {
-        int status = Pm_MessageStatus(buffer[i].message);	// Temp note event holders
-        int number = Pm_MessageData1(buffer[i].message);
-        /* int value = Pm_MessageData2(buffer[i].message); */
-
-        if (self->channel == 0) {
-            if ((status & 0xF0) == 0xd0)
-                ok = 1;
-            else
-                ok = 0;
-        }
-        else {
-            if (status == (0xd0 | (self->channel - 1)))
-                ok = 1;
-            else
-                ok = 0;
-        }
-        
-        if (ok == 1) {
-            self->oldValue = self->value;
-            self->value = (number / 127.) * (self->maxscale - self->minscale) + self->minscale;
-            break;
-        }
-    }    
-}
+    int ok, posto = -1;
+    int status = PyoMidi_MessageStatus(buffer[j].message);    // Temp note event holders
+    int number = PyoMidi_MessageData1(buffer[j].message);
+
+    if (self->channel == 0) {
+        if ((status & 0xF0) == 0xd0)
+            ok = 1;
+        else
+            ok = 0;
+    }
+    else {
+        if (status == (0xd0 | (self->channel - 1)))
+            ok = 1;
+        else
+            ok = 0;
+    }
+
+    if (ok == 1) {
+        self->value = (number / 127.) * (self->maxscale - self->minscale) + self->minscale;
+        posto = getPosToWrite(buffer[j].timestamp, (Server *)self->server, self->sr, self->bufsize);
+    }
+
+    return posto;
+}
 
 static void
 Touchin_compute_next_data_frame(Touchin *self)
-{   
-    PmEvent *tmp;
-    int i, count;
-    
+{
+    PyoMidiEvent *tmp;
+    int i, j, count, posto, oldpos = 0;
+    MYFLT oldval = 0.0;
+
     tmp = Server_getMidiEventBuffer((Server *)self->server);
     count = Server_getMidiEventCount((Server *)self->server);
-    
-    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 (count == 0) {
+        for (i=0; i<self->bufsize; i++) {
+            self->data[i] = self->value;
+        }
+    }
+    else {
+        for (j=0; j<count; j++) {
+            oldval = self->value;
+            posto = Touchin_translateMidi((Touchin *)self, tmp, j);
+            if (posto == -1)
+                continue;
+            for (i=oldpos; i<posto; i++) {
+                self->data[i] = oldval;
+            }
+            oldpos = posto;
+        }
+        for (i=oldpos; i<self->bufsize; i++) {
+            self->data[i] = self->value;
+        }
+    }
+
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1340,7 +1329,7 @@ Touchin_traverse(Touchin *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Touchin_clear(Touchin *self)
 {
     pyo_CLEAR
@@ -1352,57 +1341,54 @@ Touchin_dealloc(Touchin* self)
 {
     pyo_DEALLOC
     Touchin_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
 Touchin_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
-    PyObject *multmp=NULL, *addtmp=NULL;    
+    PyObject *multmp=NULL, *addtmp=NULL;
     Touchin *self;
     self = (Touchin *)type->tp_alloc(type, 0);
-    
+
     self->channel = 0;
     self->value = 0.;
-    self->oldValue = 0.;
     self->minscale = 0.;
     self->maxscale = 1.;
-	self->modebuffer[0] = 0;
-	self->modebuffer[1] = 0;
-    
+    self->modebuffer[0] = 0;
+    self->modebuffer[1] = 0;
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Touchin_compute_next_data_frame);
     self->mode_func_ptr = Touchin_setProcMode;
 
     static char *kwlist[] = {"minscale", "maxscale", "init", "channel", "mul", "add", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__FFFIOO, kwlist, &self->minscale, &self->maxscale, &self->oldValue, &self->channel, &multmp, &addtmp))
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__FFFIOO, kwlist, &self->minscale, &self->maxscale, &self->value, &self->channel, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     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->value = self->oldValue;
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * Touchin_getServer(Touchin* self) { GET_SERVER };
 static PyObject * Touchin_getStream(Touchin* self) { GET_STREAM };
-static PyObject * Touchin_setMul(Touchin *self, PyObject *arg) { SET_MUL };	
-static PyObject * Touchin_setAdd(Touchin *self, PyObject *arg) { SET_ADD };	
-static PyObject * Touchin_setSub(Touchin *self, PyObject *arg) { SET_SUB };	
-static PyObject * Touchin_setDiv(Touchin *self, PyObject *arg) { SET_DIV };	
+static PyObject * Touchin_setMul(Touchin *self, PyObject *arg) { SET_MUL };
+static PyObject * Touchin_setAdd(Touchin *self, PyObject *arg) { SET_ADD };
+static PyObject * Touchin_setSub(Touchin *self, PyObject *arg) { SET_SUB };
+static PyObject * Touchin_setDiv(Touchin *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Touchin_play(Touchin *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Touchin_stop(Touchin *self) { STOP };
@@ -1419,66 +1405,45 @@ static PyObject * Touchin_inplace_div(Touchin *self, PyObject *arg) { INPLACE_DI
 static PyObject *
 Touchin_setMinScale(Touchin *self, PyObject *arg)
 {
-    int tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	
-	int isNum = PyNumber_Check(arg);
-    
-	if (isNum == 1) {
-		tmp = PyFloat_AsDouble(PyNumber_Float(arg));
-            self->minscale = tmp;
-	}
-    
-	Py_INCREF(Py_None);
-	return Py_None;
-}	
+    ASSERT_ARG_NOT_NULL
+
+    if (PyNumber_Check(arg) == 1) {
+        self->minscale = PyFloat_AsDouble(arg);
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
 
 static PyObject *
 Touchin_setMaxScale(Touchin *self, PyObject *arg)
 {
-    int tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	
-	int isNum = PyNumber_Check(arg);
-    
-	if (isNum == 1) {
-		tmp = PyFloat_AsDouble(PyNumber_Float(arg));
-        self->maxscale = tmp;
-	}
-    
-	Py_INCREF(Py_None);
-	return Py_None;
-}	
+    ASSERT_ARG_NOT_NULL
+
+    if (PyNumber_Check(arg) == 1) {
+        self->maxscale = PyFloat_AsDouble(arg);
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
 
 static PyObject *
 Touchin_setChannel(Touchin *self, PyObject *arg)
 {
     int tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	
-	int isInt = PyInt_Check(arg);
-    
-	if (isInt == 1) {
-		tmp = PyInt_AsLong(arg);
+
+    ASSERT_ARG_NOT_NULL
+
+    if (PyInt_Check(arg) == 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 Touchin_members[] = {
     {"server", T_OBJECT_EX, offsetof(Touchin, server), 0, "Pyo server."},
@@ -1493,11 +1458,11 @@ 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."},
+    {"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 */
@@ -1507,7 +1472,7 @@ static PyNumberMethods Touchin_as_number = {
     (binaryfunc)Touchin_add,                      /*nb_add*/
     (binaryfunc)Touchin_sub,                 /*nb_subtract*/
     (binaryfunc)Touchin_multiply,                 /*nb_multiply*/
-    (binaryfunc)Touchin_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -1521,16 +1486,16 @@ static PyNumberMethods Touchin_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)Touchin_inplace_add,              /*inplace_add*/
     (binaryfunc)Touchin_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)Touchin_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)Touchin_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -1539,15 +1504,14 @@ static PyNumberMethods Touchin_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)Touchin_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)Touchin_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject TouchinType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Touchin_base",         /*tp_name*/
     sizeof(Touchin),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -1555,7 +1519,7 @@ PyTypeObject TouchinType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &Touchin_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -1570,10 +1534,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 */
@@ -1609,47 +1573,47 @@ Programin_setProcMode(Programin *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
-	switch (muladdmode) {
-        case 0:        
+
+    switch (muladdmode) {
+        case 0:
             self->muladd_func_ptr = Programin_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Programin_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Programin_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Programin_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Programin_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Programin_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Programin_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Programin_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Programin_postprocessing_revareva;
             break;
     }
 }
 
 // Take MIDI events and translate them...
-void Programin_translateMidi(Programin *self, PmEvent *buffer, int count)
+void Programin_translateMidi(Programin *self, PyoMidiEvent *buffer, int count)
 {
     int i, ok;
-    
-    for (i=count-1; i>=0; i--) {
-        int status = Pm_MessageStatus(buffer[i].message);	// Temp note event holders
-        int number = Pm_MessageData1(buffer[i].message);
-        
+
+    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) {
             if ((status & 0xF0) == 0xc0)
                 ok = 1;
@@ -1662,30 +1626,30 @@ void Programin_translateMidi(Programin *self, PmEvent *buffer, int count)
             else
                 ok = 0;
         }
-        
+
         if (ok == 1) {
             self->value = (MYFLT)number;
             break;
         }
-    }    
+    }
 }
 
 static void
 Programin_compute_next_data_frame(Programin *self)
-{   
-    PmEvent *tmp;
+{
+    PyoMidiEvent *tmp;
     int i, count;
-    
+
     tmp = Server_getMidiEventBuffer((Server *)self->server);
     count = Server_getMidiEventCount((Server *)self->server);
-    
+
     if (count > 0)
         Programin_translateMidi((Programin *)self, tmp, count);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = self->value;
-    }  
-    
+    }
+
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1696,7 +1660,7 @@ Programin_traverse(Programin *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Programin_clear(Programin *self)
 {
     pyo_CLEAR
@@ -1708,52 +1672,52 @@ Programin_dealloc(Programin* self)
 {
     pyo_DEALLOC
     Programin_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
 Programin_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
-    PyObject *multmp=NULL, *addtmp=NULL;    
+    PyObject *multmp=NULL, *addtmp=NULL;
     Programin *self;
     self = (Programin *)type->tp_alloc(type, 0);
-    
+
     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);
     self->mode_func_ptr = Programin_setProcMode;
 
     static char *kwlist[] = {"channel", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "iOO", kwlist, &self->channel, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     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 * Programin_getServer(Programin* self) { GET_SERVER };
 static PyObject * Programin_getStream(Programin* self) { GET_STREAM };
-static PyObject * Programin_setMul(Programin *self, PyObject *arg) { SET_MUL };	
-static PyObject * Programin_setAdd(Programin *self, PyObject *arg) { SET_ADD };	
-static PyObject * Programin_setSub(Programin *self, PyObject *arg) { SET_SUB };	
-static PyObject * Programin_setDiv(Programin *self, PyObject *arg) { SET_DIV };	
+static PyObject * Programin_setMul(Programin *self, PyObject *arg) { SET_MUL };
+static PyObject * Programin_setAdd(Programin *self, PyObject *arg) { SET_ADD };
+static PyObject * Programin_setSub(Programin *self, PyObject *arg) { SET_SUB };
+static PyObject * Programin_setDiv(Programin *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Programin_play(Programin *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Programin_stop(Programin *self) { STOP };
@@ -1771,23 +1735,20 @@ static PyObject *
 Programin_setChannel(Programin *self, PyObject *arg)
 {
     int tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	
-	int isInt = PyInt_Check(arg);
-    
-	if (isInt == 1) {
-		tmp = PyInt_AsLong(arg);
+
+    ASSERT_ARG_NOT_NULL
+
+    int isInt = PyInt_Check(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[] = {
     {"server", T_OBJECT_EX, offsetof(Programin, server), 0, "Pyo server."},
@@ -1802,9 +1763,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 */
@@ -1814,7 +1775,7 @@ static PyNumberMethods Programin_as_number = {
     (binaryfunc)Programin_add,                      /*nb_add*/
     (binaryfunc)Programin_sub,                 /*nb_subtract*/
     (binaryfunc)Programin_multiply,                 /*nb_multiply*/
-    (binaryfunc)Programin_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -1828,16 +1789,16 @@ static PyNumberMethods Programin_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)Programin_inplace_add,              /*inplace_add*/
     (binaryfunc)Programin_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)Programin_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)Programin_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -1846,15 +1807,14 @@ static PyNumberMethods Programin_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)Programin_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)Programin_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject PrograminType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Programin_base",         /*tp_name*/
     sizeof(Programin),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -1862,7 +1822,7 @@ PyTypeObject PrograminType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &Programin_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -1877,10 +1837,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 */
@@ -1896,7 +1856,7 @@ PyTypeObject PrograminType = {
 
 typedef struct {
     pyo_audio_HEAD
-    int *notebuf; /* pitch, velocity, ... */
+    int *notebuf; /* pitch, velocity, posToWrite */
     int voices;
     int vcount;
     int scale; /* 0 = midi, 1 = hertz, 2 = transpo */
@@ -1905,6 +1865,7 @@ typedef struct {
     int centralkey;
     int channel;
     int stealing;
+    MYFLT *trigger_streams;
 } MidiNote;
 
 static void
@@ -1915,10 +1876,10 @@ pitchIsIn(int *buf, int pitch, int len) {
     int i;
     int isIn = 0;
     for (i=0; i<len; i++) {
-        if (buf[i*2] == pitch) {
+        if (buf[i*3] == pitch) {
             isIn = 1;
             break;
-        }    
+        }
     }
     return isIn;
 }
@@ -1928,10 +1889,10 @@ int firstEmpty(int *buf, int len) {
     int i;
     int voice = -1;
     for (i=0; i<len; i++) {
-        if (buf[i*2+1] == 0) {
+        if (buf[i*3+1] == 0) {
             voice = i;
             break;
-        }    
+        }
     }
     return voice;
 }
@@ -1939,21 +1900,21 @@ int firstEmpty(int *buf, int len) {
 int nextEmptyVoice(int *buf, int voice, int len) {
     int i, tmp;
     int next = -1;
-    for (i=0; i<len; i++) {
+    for (i=1; i<=len; i++) {
         tmp = (i + voice) % len;
-        if (buf[tmp*2+1] == 0) {
+        if (buf[tmp*3+1] == 0) {
             next = tmp;
             break;
         }
-    }    
-    return next;    
+    }
+    return next;
 }
 
 int whichVoice(int *buf, int pitch, int len) {
     int i;
     int voice = 0;
     for (i=0; i<len; i++) {
-        if (buf[i*2] == pitch) {
+        if (buf[i*3] == pitch) {
             voice = i;
             break;
         }
@@ -1962,14 +1923,14 @@ int whichVoice(int *buf, int pitch, int len) {
 }
 
 // Take MIDI events and keep track of notes
-void grabMidiNotes(MidiNote *self, PmEvent *buffer, int count)
+void grabMidiNotes(MidiNote *self, PyoMidiEvent *buffer, int count)
 {
-    int i, ok, voice, kind;
-    
+    int i, ok, voice, kind, samp = 0;
+
     for (i=0; i<count; i++) {
-        int status = Pm_MessageStatus(buffer[i].message);	// Temp note event holders
-        int pitch = Pm_MessageData1(buffer[i].message);
-        int velocity = Pm_MessageData2(buffer[i].message);
+        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);
 
         if (self->channel == 0) {
             if ((status & 0xF0) == 0x90 || (status & 0xF0) == 0x80)
@@ -1983,8 +1944,10 @@ void grabMidiNotes(MidiNote *self, PmEvent *buffer, int count)
             else
                 ok = 0;
         }
-        
+
         if (ok == 1) {
+            samp = getPosToWrite(buffer[i].timestamp, (Server *)self->server, self->sr, self->bufsize);
+
             if ((status & 0xF0) == 0x80)
                 kind = 0;
             else if ((status & 0xF0) == 0x90 && velocity == 0)
@@ -1993,41 +1956,51 @@ void grabMidiNotes(MidiNote *self, PmEvent *buffer, int count)
                 kind = 1;
 
             if (pitchIsIn(self->notebuf, pitch, self->voices) == 0 && kind == 1 && pitch >= self->first && pitch <= self->last) {
-                //printf("%i, %i, %i\n", status, pitch, velocity);
+                //PySys_WriteStdout("%i, %i, %i\n", status, pitch, velocity);
                 if (!self->stealing) {
                     voice = nextEmptyVoice(self->notebuf, self->vcount, self->voices);
                     if (voice != -1) {
                         self->vcount = voice;
-                        self->notebuf[voice*2] = pitch;
-                        self->notebuf[voice*2+1] = velocity;
+                        self->notebuf[voice*3] = pitch;
+                        self->notebuf[voice*3+1] = velocity;
+                        self->notebuf[voice*3+2] = samp;
+                        self->trigger_streams[self->bufsize*(self->vcount*2)+samp] = 1.0;
                     }
                 }
                 else {
                     self->vcount = (self->vcount + 1) % self->voices;
-                    self->notebuf[self->vcount*2] = pitch;
-                    self->notebuf[self->vcount*2+1] = velocity;
+                    self->notebuf[self->vcount*3] = pitch;
+                    self->notebuf[self->vcount*3+1] = velocity;
+                    self->notebuf[self->vcount*3+2] = samp;
+                    self->trigger_streams[self->bufsize*(self->vcount*2)+samp] = 1.0;
                 }
-            }    
+            }
             else if (pitchIsIn(self->notebuf, pitch, self->voices) == 1 && kind == 0 && pitch >= self->first && pitch <= self->last) {
-                //printf("%i, %i, %i\n", status, pitch, velocity);
+                //PySys_WriteStdout("%i, %i, %i\n", status, pitch, velocity);
                 voice = whichVoice(self->notebuf, pitch, self->voices);
-                self->notebuf[voice*2] = -1;
-                self->notebuf[voice*2+1] = 0.;
+                self->notebuf[voice*3] = -1;
+                self->notebuf[voice*3+1] = 0;
+                self->notebuf[voice*3+2] = samp;
+                self->trigger_streams[self->bufsize*(voice*2+1)+samp] = 1.0;
             }
         }
-    }    
-}    
+    }
+}
 
 static void
 MidiNote_compute_next_data_frame(MidiNote *self)
-{   
-    PmEvent *tmp;
-    int count;
-    
+{
+    PyoMidiEvent *tmp;
+    int i, count;
+
+    for (i=0; i<self->bufsize*self->voices*2; i++) {
+        self->trigger_streams[i] = 0.0;
+    }
+
     tmp = Server_getMidiEventBuffer((Server *)self->server);
     count = Server_getMidiEventCount((Server *)self->server);
     if (count > 0)
-        grabMidiNotes((MidiNote *)self, tmp, count);  
+        grabMidiNotes((MidiNote *)self, tmp, count);
 }
 
 static int
@@ -2037,7 +2010,7 @@ MidiNote_traverse(MidiNote *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 MidiNote_clear(MidiNote *self)
 {
     pyo_CLEAR
@@ -2049,15 +2022,22 @@ MidiNote_dealloc(MidiNote* self)
 {
     pyo_DEALLOC
     free(self->notebuf);
+    free(self->trigger_streams);
     MidiNote_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static MYFLT *
+MidiNote_get_trigger_buffer(MidiNote *self)
+{
+    return self->trigger_streams;
 }
 
 static PyObject *
 MidiNote_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
-    
+
     MidiNote *self;
     self = (MidiNote *)type->tp_alloc(type, 0);
 
@@ -2068,36 +2048,43 @@ MidiNote_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->last = 127;
     self->channel = 0;
     self->stealing = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, MidiNote_compute_next_data_frame);
     self->mode_func_ptr = MidiNote_setProcMode;
 
     static char *kwlist[] = {"voices", "scale", "first", "last", "channel", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|iiiii", kwlist, &self->voices, &self->scale, &self->first, &self->last, &self->channel))
         Py_RETURN_NONE;
 
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
-    self->notebuf = (int *)realloc(self->notebuf, self->voices * 2 * sizeof(int));
+    self->notebuf = (int *)realloc(self->notebuf, self->voices * 3 * sizeof(int));
+    self->trigger_streams = (MYFLT *)realloc(self->trigger_streams, self->bufsize * self->voices * 2 * sizeof(MYFLT));
+
+    for (i=0; i<self->bufsize*self->voices*2; i++) {
+        self->trigger_streams[i] = 0.0;
+    }
 
     for (i=0; i<self->voices; i++) {
-        self->notebuf[i*2] = -1;
-        self->notebuf[i*2+1] = 0;
+        self->notebuf[i*3] = -1;
+        self->notebuf[i*3+1] = 0;
+        self->notebuf[i*3+2] = 0;
     }
 
     self->centralkey = (self->first + self->last) / 2;
-    
+
     (*self->mode_func_ptr)(self);
-     
+
     return (PyObject *)self;
 }
 
-MYFLT MidiNote_getValue(MidiNote *self, int voice, int which)
+MYFLT
+MidiNote_getValue(MidiNote *self, int voice, int which, int *posto)
 {
     MYFLT val = -1.0;
-    int midival = self->notebuf[voice*2+which];
+    int midival = self->notebuf[voice*3+which];
     if (which == 0 && midival != -1) {
         if (self->scale == 0)
             val = midival;
@@ -2110,6 +2097,9 @@ MYFLT MidiNote_getValue(MidiNote *self, int voice, int which)
         val = (MYFLT)midival;
     else if (which == 1)
         val = (MYFLT)midival / 127.;
+
+    *posto = self->notebuf[voice*3+2];
+
     return val;
 }
 
@@ -2120,65 +2110,89 @@ static PyObject * MidiNote_play(MidiNote *self, PyObject *args, PyObject *kwds)
 static PyObject * MidiNote_stop(MidiNote *self) { STOP };
 
 static PyObject *
+MidiNote_setScale(MidiNote *self, PyObject *arg)
+{
+    ASSERT_ARG_NOT_NULL
+
+    if (PyInt_Check(arg) == 1) {
+        int tmp = PyInt_AsLong(arg);
+        if (tmp >= 0 && tmp < 3)
+            self->scale = tmp;
+    }
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+MidiNote_setFirst(MidiNote *self, PyObject *arg)
+{
+    ASSERT_ARG_NOT_NULL
+
+    if (PyInt_Check(arg) == 1) {
+        int tmp = PyInt_AsLong(arg);
+        if (tmp >= 0 && tmp < 128)
+            self->first = tmp;
+    }
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+MidiNote_setLast(MidiNote *self, PyObject *arg)
+{
+    ASSERT_ARG_NOT_NULL
+
+    if (PyInt_Check(arg) == 1) {
+        int tmp = PyInt_AsLong(arg);
+        if (tmp >= 0 && tmp < 128)
+            self->last = tmp;
+    }
+    Py_RETURN_NONE;
+}
+
+static PyObject *
 MidiNote_setChannel(MidiNote *self, PyObject *arg)
 {
-    int tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	
-	int isInt = PyInt_Check(arg);
-    
-	if (isInt == 1) {
-		tmp = PyInt_AsLong(arg);
+    ASSERT_ARG_NOT_NULL
+
+    if (PyInt_Check(arg) == 1) {
+        int tmp = PyInt_AsLong(arg);
         if (tmp >= 0 && tmp < 128)
             self->channel = tmp;
-	}
-    
-	Py_INCREF(Py_None);
-	return Py_None;
-}	
+    }
+    Py_RETURN_NONE;
+}
 
 static PyObject *
 MidiNote_setCentralKey(MidiNote *self, PyObject *arg)
 {
     int tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	
-	int isInt = PyInt_Check(arg);
-    
-	if (isInt == 1) {
-		tmp = PyInt_AsLong(arg);
+
+    ASSERT_ARG_NOT_NULL
+
+    int isInt = PyInt_Check(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 *
 MidiNote_setStealing(MidiNote *self, PyObject *arg)
-{	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-	
-	int isInt = PyInt_Check(arg);
-    
-	if (isInt == 1)
-		self->stealing = PyInt_AsLong(arg);
-    
-	Py_INCREF(Py_None);
-	return Py_None;
-}	
+{
+    ASSERT_ARG_NOT_NULL
+
+    int isInt = PyInt_Check(arg);
+
+    if (isInt == 1)
+        self->stealing = PyInt_AsLong(arg);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
 
 static PyMemberDef MidiNote_members[] = {
 {"server", T_OBJECT_EX, offsetof(MidiNote, server), 0, "Pyo server."},
@@ -2191,6 +2205,9 @@ static PyMethodDef MidiNote_methods[] = {
 {"_getStream", (PyCFunction)MidiNote_getStream, METH_NOARGS, "Returns stream object."},
 {"play", (PyCFunction)MidiNote_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
 {"stop", (PyCFunction)MidiNote_stop, METH_NOARGS, "Stops computing."},
+{"setScale", (PyCFunction)MidiNote_setScale, METH_O, "Sets the scale factor."},
+{"setFirst", (PyCFunction)MidiNote_setFirst, METH_O, "Sets the lowest midi note."},
+{"setLast", (PyCFunction)MidiNote_setLast, METH_O, "Sets the highest midi note."},
 {"setChannel", (PyCFunction)MidiNote_setChannel, METH_O, "Sets the midi channel."},
 {"setCentralKey", (PyCFunction)MidiNote_setCentralKey, METH_O, "Sets the midi key where there is no transposition."},
 {"setStealing", (PyCFunction)MidiNote_setStealing, METH_O, "Sets the stealing mode."},
@@ -2198,8 +2215,7 @@ static PyMethodDef MidiNote_methods[] = {
 };
 
 PyTypeObject MidiNoteType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.MidiNote_base",         /*tp_name*/
 sizeof(MidiNote),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -2207,7 +2223,7 @@ sizeof(MidiNote),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 0,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -2222,10 +2238,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 */
@@ -2247,6 +2263,8 @@ typedef struct {
     int modebuffer[2];
     int voice;
     int mode; /* 0 = pitch, 1 = velocity */
+    MYFLT lastval;
+    MYFLT lastpitch;
 } Notein;
 
 static void Notein_postprocessing_ii(Notein *self) { POST_PROCESSING_II };
@@ -2264,33 +2282,33 @@ Notein_setProcMode(Notein *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
-	switch (muladdmode) {
-        case 0:        
+
+    switch (muladdmode) {
+        case 0:
             self->muladd_func_ptr = Notein_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Notein_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Notein_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Notein_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Notein_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Notein_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Notein_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Notein_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Notein_postprocessing_revareva;
             break;
     }
@@ -2299,20 +2317,44 @@ Notein_setProcMode(Notein *self)
 static void
 Notein_compute_next_data_frame(Notein *self)
 {
-    int i;
-    MYFLT tmp = MidiNote_getValue(self->handler, self->voice, self->mode);
-    
-    if (self->mode == 0 && tmp != -1) {
-        for (i=0; i<self->bufsize; i++) {
-            self->data[i] = tmp;
-        }    
-    } 
-    else if (self->mode == 1) {
-        for (i=0; i<self->bufsize; i++) {
-            self->data[i] = tmp;
-        }         
-        (*self->muladd_func_ptr)(self);
-    }    
+    int i, posto;
+    MYFLT tmp = MidiNote_getValue(self->handler, self->voice, self->mode, &posto);
+
+    if (self->lastval == tmp) {
+        if (self->mode == 0 && tmp != -1) {
+            for (i=0; i<self->bufsize; i++) {
+                self->data[i] = tmp;
+            }
+        }
+        else if (self->mode == 1) {
+            for (i=0; i<self->bufsize; i++) {
+                self->data[i] = tmp;
+            }
+            (*self->muladd_func_ptr)(self);
+        }
+    }
+    else { /* There is a new note to compute. */
+        if (self->mode == 0 && tmp != -1) {
+            for (i=0; i<self->bufsize; i++) {
+                if (i < posto)
+                    self->data[i] = self->lastpitch;
+                else
+                    self->data[i] = tmp;
+            }
+        }
+        else if (self->mode == 1) {
+            for (i=0; i<self->bufsize; i++) {
+                if (i < posto)
+                    self->data[i] = self->lastval;
+                else
+                    self->data[i] = tmp;
+            }
+            (*self->muladd_func_ptr)(self);
+        }
+        self->lastval = tmp;
+        if (tmp != -1)
+            self->lastpitch = tmp;
+    }
 }
 
 static int
@@ -2323,11 +2365,11 @@ Notein_traverse(Notein *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Notein_clear(Notein *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->handler);    
+    Py_CLEAR(self->handler);
     return 0;
 }
 
@@ -2336,7 +2378,7 @@ Notein_dealloc(Notein* self)
 {
     pyo_DEALLOC
     Notein_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2346,46 +2388,48 @@ Notein_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *handlertmp=NULL, *multmp=NULL, *addtmp=NULL;
     Notein *self;
     self = (Notein *)type->tp_alloc(type, 0);
-    
+
     self->voice = 0;
     self->mode = 0;
+    self->lastval = -1.0;
+    self->lastpitch = 0.0;
     self->modebuffer[0] = 0;
     self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Notein_compute_next_data_frame);
     self->mode_func_ptr = Notein_setProcMode;
 
     static char *kwlist[] = {"handler", "voice", "mode", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iiOO", kwlist, &handlertmp, &self->voice, &self->mode, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     Py_XDECREF(self->handler);
     Py_INCREF(handlertmp);
     self->handler = (MidiNote *)handlertmp;
-    
+
     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 * Notein_getServer(Notein* self) { GET_SERVER };
 static PyObject * Notein_getStream(Notein* self) { GET_STREAM };
-static PyObject * Notein_setMul(Notein *self, PyObject *arg) { SET_MUL };	
-static PyObject * Notein_setAdd(Notein *self, PyObject *arg) { SET_ADD };	
-static PyObject * Notein_setSub(Notein *self, PyObject *arg) { SET_SUB };	
-static PyObject * Notein_setDiv(Notein *self, PyObject *arg) { SET_DIV };	
+static PyObject * Notein_setMul(Notein *self, PyObject *arg) { SET_MUL };
+static PyObject * Notein_setAdd(Notein *self, PyObject *arg) { SET_ADD };
+static PyObject * Notein_setSub(Notein *self, PyObject *arg) { SET_SUB };
+static PyObject * Notein_setDiv(Notein *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Notein_play(Notein *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Notein_stop(Notein *self) { STOP };
@@ -2423,7 +2467,7 @@ static PyNumberMethods Notein_as_number = {
 (binaryfunc)Notein_add,                      /*nb_add*/
 (binaryfunc)Notein_sub,                 /*nb_subtract*/
 (binaryfunc)Notein_multiply,                 /*nb_multiply*/
-(binaryfunc)Notein_div,                   /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -2437,16 +2481,16 @@ static PyNumberMethods Notein_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
 (binaryfunc)Notein_inplace_add,              /*inplace_add*/
 (binaryfunc)Notein_inplace_sub,         /*inplace_subtract*/
 (binaryfunc)Notein_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)Notein_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -2455,15 +2499,14 @@ static PyNumberMethods Notein_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)Notein_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)Notein_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
 PyTypeObject NoteinType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Notein_base",         /*tp_name*/
 sizeof(Notein),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -2471,7 +2514,7 @@ sizeof(Notein),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &Notein_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -2486,10 +2529,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 */
@@ -2503,74 +2546,343 @@ Notein_members,             /* tp_members */
 Notein_new,                 /* tp_new */
 };
 
+/* NoteinTrig trig streamer */
 typedef struct {
     pyo_audio_HEAD
-    PyObject *input;
-    Stream *input_stream;
+    MidiNote *handler;
     int modebuffer[2];
-    int fademode;
-    int changed;
-    MYFLT topValue;
-    MYFLT offsetAmp;
-    MYFLT initAmp;
-    MYFLT sustainAmp;
-    MYFLT attack;
-    MYFLT decay;
-    MYFLT sustain;
-    MYFLT release;
-    MYFLT invAttack;
-    MYFLT initAmpMinusOffsetAmp;
-    MYFLT attackPlusDecay;
-    MYFLT invDecay;
-    MYFLT initAmpMinusSustainAmp;
-    MYFLT invRelease;
-    double currentTime;
-    MYFLT sampleToSec;
-} MidiAdsr;
+    int voice;
+    int mode; /* 0 = noteon, 1 = noteoff */
+} NoteinTrig;
+
+static void NoteinTrig_postprocessing_ii(NoteinTrig *self) { POST_PROCESSING_II };
+static void NoteinTrig_postprocessing_ai(NoteinTrig *self) { POST_PROCESSING_AI };
+static void NoteinTrig_postprocessing_ia(NoteinTrig *self) { POST_PROCESSING_IA };
+static void NoteinTrig_postprocessing_aa(NoteinTrig *self) { POST_PROCESSING_AA };
+static void NoteinTrig_postprocessing_ireva(NoteinTrig *self) { POST_PROCESSING_IREVA };
+static void NoteinTrig_postprocessing_areva(NoteinTrig *self) { POST_PROCESSING_AREVA };
+static void NoteinTrig_postprocessing_revai(NoteinTrig *self) { POST_PROCESSING_REVAI };
+static void NoteinTrig_postprocessing_revaa(NoteinTrig *self) { POST_PROCESSING_REVAA };
+static void NoteinTrig_postprocessing_revareva(NoteinTrig *self) { POST_PROCESSING_REVAREVA };
 
 static void
-MidiAdsr_generates(MidiAdsr *self) {
-    MYFLT val;
-    int i;
+NoteinTrig_setProcMode(NoteinTrig *self)
+{
+    int muladdmode;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
-    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+    switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = NoteinTrig_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = NoteinTrig_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = NoteinTrig_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = NoteinTrig_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = NoteinTrig_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = NoteinTrig_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = NoteinTrig_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = NoteinTrig_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = NoteinTrig_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+NoteinTrig_compute_next_data_frame(NoteinTrig *self)
+{
+    int i;
+    MYFLT *tmp = MidiNote_get_trigger_buffer(self->handler);
 
     for (i=0; i<self->bufsize; i++) {
-        if (self->fademode == 0 && in[i] > 0.0) {
-            self->fademode = 1;
-            self->initAmp = in[i];
-            self->offsetAmp = self->data[i];
-            self->sustainAmp = self->initAmp * self->sustain;
-            self->currentTime = 0.0;
-            self->invAttack = 1.0 / self->attack;
-            self->invDecay = 1.0 / self->decay; 
-            self->attackPlusDecay = self->attack + self->decay;
-            self->initAmpMinusOffsetAmp = self->initAmp - self->offsetAmp;
-            self->initAmpMinusSustainAmp = self->initAmp - self->sustainAmp;
-        }
-        else if (self->fademode == 1 && in[i] == 0.0) {
-            self->fademode = 0;
-            self->currentTime = 0.0;
-            self->invRelease = 1.0 / self->release;
-        }
-        
-        if (self->fademode == 1) {
-            if (self->currentTime <= self->attack)
-                val = self->currentTime * self->invAttack * self->initAmpMinusOffsetAmp + self->offsetAmp;
-            else if (self->currentTime <= self->attackPlusDecay)
-                val = (self->decay - (self->currentTime - self->attack)) * self->invDecay * self->initAmpMinusSustainAmp + self->sustainAmp;
+        self->data[i] = tmp[self->bufsize*(self->voice*2+self->mode)+i];
+    }
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+NoteinTrig_traverse(NoteinTrig *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->handler);
+    return 0;
+}
+
+static int
+NoteinTrig_clear(NoteinTrig *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->handler);
+    return 0;
+}
+
+static void
+NoteinTrig_dealloc(NoteinTrig* self)
+{
+    pyo_DEALLOC
+    NoteinTrig_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+NoteinTrig_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *handlertmp=NULL, *multmp=NULL, *addtmp=NULL;
+    NoteinTrig *self;
+    self = (NoteinTrig *)type->tp_alloc(type, 0);
+
+    self->voice = 0;
+    self->mode = 0;
+    self->modebuffer[0] = 0;
+    self->modebuffer[1] = 0;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, NoteinTrig_compute_next_data_frame);
+    self->mode_func_ptr = NoteinTrig_setProcMode;
+
+    static char *kwlist[] = {"handler", "voice", "mode", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iiOO", kwlist, &handlertmp, &self->voice, &self->mode, &multmp, &addtmp))
+        Py_RETURN_NONE;
+
+    Py_XDECREF(self->handler);
+    Py_INCREF(handlertmp);
+    self->handler = (MidiNote *)handlertmp;
+
+    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 * NoteinTrig_getServer(NoteinTrig* self) { GET_SERVER };
+static PyObject * NoteinTrig_getStream(NoteinTrig* self) { GET_STREAM };
+static PyObject * NoteinTrig_setMul(NoteinTrig *self, PyObject *arg) { SET_MUL };
+static PyObject * NoteinTrig_setAdd(NoteinTrig *self, PyObject *arg) { SET_ADD };
+static PyObject * NoteinTrig_setSub(NoteinTrig *self, PyObject *arg) { SET_SUB };
+static PyObject * NoteinTrig_setDiv(NoteinTrig *self, PyObject *arg) { SET_DIV };
+
+static PyObject * NoteinTrig_play(NoteinTrig *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * NoteinTrig_stop(NoteinTrig *self) { STOP };
+
+static PyObject * NoteinTrig_multiply(NoteinTrig *self, PyObject *arg) { MULTIPLY };
+static PyObject * NoteinTrig_inplace_multiply(NoteinTrig *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * NoteinTrig_add(NoteinTrig *self, PyObject *arg) { ADD };
+static PyObject * NoteinTrig_inplace_add(NoteinTrig *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * NoteinTrig_sub(NoteinTrig *self, PyObject *arg) { SUB };
+static PyObject * NoteinTrig_inplace_sub(NoteinTrig *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * NoteinTrig_div(NoteinTrig *self, PyObject *arg) { DIV };
+static PyObject * NoteinTrig_inplace_div(NoteinTrig *self, PyObject *arg) { INPLACE_DIV };
+
+static PyMemberDef NoteinTrig_members[] = {
+{"server", T_OBJECT_EX, offsetof(NoteinTrig, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(NoteinTrig, stream), 0, "Stream object."},
+{"mul", T_OBJECT_EX, offsetof(NoteinTrig, mul), 0, "Mul factor."},
+{"add", T_OBJECT_EX, offsetof(NoteinTrig, add), 0, "Add factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyMethodDef NoteinTrig_methods[] = {
+{"getServer", (PyCFunction)NoteinTrig_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)NoteinTrig_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)NoteinTrig_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"stop", (PyCFunction)NoteinTrig_stop, METH_NOARGS, "Stops computing."},
+{"setMul", (PyCFunction)NoteinTrig_setMul, METH_O, "Sets NoteinTrig mul factor."},
+{"setAdd", (PyCFunction)NoteinTrig_setAdd, METH_O, "Sets NoteinTrig add factor."},
+{"setSub", (PyCFunction)NoteinTrig_setSub, METH_O, "Sets inverse add factor."},
+{"setDiv", (PyCFunction)NoteinTrig_setDiv, METH_O, "Sets inverse mul factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyNumberMethods NoteinTrig_as_number = {
+(binaryfunc)NoteinTrig_add,                      /*nb_add*/
+(binaryfunc)NoteinTrig_sub,                 /*nb_subtract*/
+(binaryfunc)NoteinTrig_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)NoteinTrig_inplace_add,              /*inplace_add*/
+(binaryfunc)NoteinTrig_inplace_sub,         /*inplace_subtract*/
+(binaryfunc)NoteinTrig_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)NoteinTrig_div,                       /*nb_true_divide*/
+0,     /*nb_inplace_floor_divide*/
+(binaryfunc)NoteinTrig_inplace_div,                       /*nb_inplace_true_divide*/
+0,                     /* nb_index */
+};
+
+PyTypeObject NoteinTrigType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.NoteinTrig_base",         /*tp_name*/
+sizeof(NoteinTrig),         /*tp_basicsize*/
+0,                         /*tp_itemsize*/
+(destructor)NoteinTrig_dealloc, /*tp_dealloc*/
+0,                         /*tp_print*/
+0,                         /*tp_getattr*/
+0,                         /*tp_setattr*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
+0,                         /*tp_repr*/
+&NoteinTrig_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*/
+"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 */
+NoteinTrig_methods,             /* tp_methods */
+NoteinTrig_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 */
+NoteinTrig_new,                 /* tp_new */
+};
+
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *input;
+    Stream *input_stream;
+    int modebuffer[2];
+    int fademode;
+    int changed;
+    MYFLT topValue;
+    MYFLT offsetAmp;
+    MYFLT initAmp;
+    MYFLT sustainAmp;
+    MYFLT attack;
+    MYFLT decay;
+    MYFLT sustain;
+    MYFLT release;
+    MYFLT exp;
+    MYFLT expscl;
+    MYFLT invAttack;
+    MYFLT initAmpMinusOffsetAmp;
+    MYFLT attackPlusDecay;
+    MYFLT invDecay;
+    MYFLT initAmpMinusSustainAmp;
+    MYFLT invRelease;
+    double currentTime;
+    MYFLT sampleToSec;
+    MYFLT *buf;
+} MidiAdsr;
+
+static void
+MidiAdsr_generates(MidiAdsr *self) {
+    MYFLT val;
+    int i;
+
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+
+    for (i=0; i<self->bufsize; i++) {
+        if (self->fademode == 0 && in[i] > 0.0) {
+            self->fademode = 1;
+            self->initAmp = in[i];
+            self->expscl = MYPOW(self->initAmp, 1.0 / self->exp) / self->initAmp;
+            self->offsetAmp = self->buf[i]; 
+            self->sustainAmp = self->initAmp * self->sustain;
+            self->currentTime = 0.0;
+            self->invAttack = 1.0 / self->attack;
+            self->invDecay = 1.0 / self->decay;
+            self->attackPlusDecay = self->attack + self->decay;
+            self->initAmpMinusOffsetAmp = self->initAmp - self->offsetAmp;
+            self->initAmpMinusSustainAmp = self->initAmp - self->sustainAmp;
+        }
+        else if (self->fademode == 1 && in[i] == 0.0) {
+            self->fademode = 0;
+            self->currentTime = 0.0;
+            self->invRelease = 1.0 / self->release;
+        }
+
+        if (self->fademode == 1) {
+            if (self->currentTime <= self->attack)
+                val = self->currentTime * self->invAttack * self->initAmpMinusOffsetAmp + self->offsetAmp;
+            else if (self->currentTime <= self->attackPlusDecay)
+                val = (self->decay - (self->currentTime - self->attack)) * self->invDecay * self->initAmpMinusSustainAmp + self->sustainAmp;
             else
                 val = self->sustainAmp;
             self->topValue = val;
-        }    
-        else {  
+        }
+        else {
             if (self->currentTime <= self->release)
                 val = self->topValue * (1. - self->currentTime * self->invRelease);
-            else 
+            else
                 val = 0.;
-        }    
-        self->data[i] = val;
-        self->currentTime += self->sampleToSec;    
+        }
+        self->buf[i] = val;
+        self->currentTime += self->sampleToSec;
+    }
+
+    if (self->exp != 1.0) {
+        for (i=0; i<self->bufsize; i++) {
+            self->data[i] = MYPOW(self->buf[i] * self->expscl, self->exp);
+        }
+    } else {
+        for (i=0; i<self->bufsize; i++) {
+            self->data[i] = self->buf[i];
+        }
     }
 }
 
@@ -2589,44 +2901,44 @@ MidiAdsr_setProcMode(MidiAdsr *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = MidiAdsr_generates;
-    
-	switch (muladdmode) {
-        case 0:        
+
+    switch (muladdmode) {
+        case 0:
             self->muladd_func_ptr = MidiAdsr_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = MidiAdsr_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = MidiAdsr_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = MidiAdsr_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = MidiAdsr_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = MidiAdsr_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = MidiAdsr_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = MidiAdsr_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = MidiAdsr_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 MidiAdsr_compute_next_data_frame(MidiAdsr *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -2639,7 +2951,7 @@ MidiAdsr_traverse(MidiAdsr *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 MidiAdsr_clear(MidiAdsr *self)
 {
     pyo_CLEAR
@@ -2652,8 +2964,9 @@ static void
 MidiAdsr_dealloc(MidiAdsr* self)
 {
     pyo_DEALLOC
+    free(self->buf);
     MidiAdsr_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2663,9 +2976,9 @@ MidiAdsr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     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;
@@ -2674,7 +2987,8 @@ MidiAdsr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->sustain = 0.707;
     self->release = 0.1;
     self->currentTime = 0.0;
-    
+    self->exp = self->expscl = 1.0;
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, MidiAdsr_compute_next_data_frame);
     self->mode_func_ptr = MidiAdsr_setProcMode;
@@ -2682,22 +2996,27 @@ MidiAdsr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->sampleToSec = 1. / self->sr;
 
     static char *kwlist[] = {"input", "attack", "decay", "sustain", "release", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_FFFFOO, kwlist, &inputtmp, &self->attack, &self->decay, &self->sustain, &self->release, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
 
     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->buf = (MYFLT *)realloc(self->buf, self->bufsize * sizeof(MYFLT));
+    for (i=0; i<self->bufsize; i++) {
+        self->buf[i] = 0.0;
+    }
+
     if (self->attack < 0.000001)
         self->attack = 0.000001;
     if (self->decay < 0.000001)
@@ -2716,10 +3035,10 @@ MidiAdsr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * MidiAdsr_getServer(MidiAdsr* self) { GET_SERVER };
 static PyObject * MidiAdsr_getStream(MidiAdsr* self) { GET_STREAM };
-static PyObject * MidiAdsr_setMul(MidiAdsr *self, PyObject *arg) { SET_MUL };	
-static PyObject * MidiAdsr_setAdd(MidiAdsr *self, PyObject *arg) { SET_ADD };	
-static PyObject * MidiAdsr_setSub(MidiAdsr *self, PyObject *arg) { SET_SUB };	
-static PyObject * MidiAdsr_setDiv(MidiAdsr *self, PyObject *arg) { SET_DIV };	
+static PyObject * MidiAdsr_setMul(MidiAdsr *self, PyObject *arg) { SET_MUL };
+static PyObject * MidiAdsr_setAdd(MidiAdsr *self, PyObject *arg) { SET_ADD };
+static PyObject * MidiAdsr_setSub(MidiAdsr *self, PyObject *arg) { SET_SUB };
+static PyObject * MidiAdsr_setDiv(MidiAdsr *self, PyObject *arg) { SET_DIV };
 
 static PyObject * MidiAdsr_play(MidiAdsr *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * MidiAdsr_stop(MidiAdsr *self) { STOP }
@@ -2736,11 +3055,13 @@ static PyObject * MidiAdsr_inplace_div(MidiAdsr *self, PyObject *arg) { INPLACE_
 static PyObject *
 MidiAdsr_setAttack(MidiAdsr *self, PyObject *arg)
 {
-    self->attack = PyFloat_AsDouble(PyNumber_Float(arg));
-    if (self->attack < 0.000001)
-        self->attack = 0.000001;
-    self->invAttack = 1.0 / self->attack;
-    self->attackPlusDecay = self->attack + self->decay;
+    if (PyNumber_Check(arg)) {
+        self->attack = PyFloat_AsDouble(arg);
+        if (self->attack < 0.000001)
+            self->attack = 0.000001;
+        self->invAttack = 1.0 / self->attack;
+        self->attackPlusDecay = self->attack + self->decay;
+    }
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -2748,11 +3069,13 @@ MidiAdsr_setAttack(MidiAdsr *self, PyObject *arg)
 static PyObject *
 MidiAdsr_setDecay(MidiAdsr *self, PyObject *arg)
 {
-    self->decay = PyFloat_AsDouble(PyNumber_Float(arg));
-    if (self->decay < 0.000001)
-        self->decay = 0.000001;
-    self->invDecay = 1.0 / self->decay; 
-    self->attackPlusDecay = self->attack + self->decay;
+    if (PyNumber_Check(arg)) {
+        self->decay = PyFloat_AsDouble(arg);
+        if (self->decay < 0.000001)
+            self->decay = 0.000001;
+        self->invDecay = 1.0 / self->decay;
+        self->attackPlusDecay = self->attack + self->decay;
+    }
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -2760,11 +3083,13 @@ MidiAdsr_setDecay(MidiAdsr *self, PyObject *arg)
 static PyObject *
 MidiAdsr_setSustain(MidiAdsr *self, PyObject *arg)
 {
-    self->sustain = PyFloat_AsDouble(PyNumber_Float(arg));
-    if (self->sustain < 0.0)
-        self->sustain = 0.0;
-    else if (self->sustain > 1.0)
-        self->sustain = 1.0;
+    if (PyNumber_Check(arg)) {
+        self->sustain = PyFloat_AsDouble(arg);
+        if (self->sustain < 0.0)
+            self->sustain = 0.0;
+        else if (self->sustain > 1.0)
+            self->sustain = 1.0;
+    }
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -2772,10 +3097,24 @@ MidiAdsr_setSustain(MidiAdsr *self, PyObject *arg)
 static PyObject *
 MidiAdsr_setRelease(MidiAdsr *self, PyObject *arg)
 {
-    self->release = PyFloat_AsDouble(PyNumber_Float(arg));
-    if (self->release < 0.000001)
-        self->release = 0.000001;
-    self->invRelease = 1.0 / self->release;
+    if (PyNumber_Check(arg)) {
+        self->release = PyFloat_AsDouble(arg);
+        if (self->release < 0.000001)
+            self->release = 0.000001;
+        self->invRelease = 1.0 / self->release;
+    }
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *
+MidiAdsr_setExp(MidiAdsr *self, PyObject *arg)
+{
+    if (PyNumber_Check(arg)) {
+        MYFLT tmp = PyFloat_AsDouble(arg);
+        if (tmp > 0.0)
+            self->exp = tmp;
+    }
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -2801,6 +3140,7 @@ static PyMethodDef MidiAdsr_methods[] = {
     {"setDecay", (PyCFunction)MidiAdsr_setDecay, METH_O, "Sets decay time in seconds."},
     {"setSustain", (PyCFunction)MidiAdsr_setSustain, METH_O, "Sets sustain level in percent of note amplitude."},
     {"setRelease", (PyCFunction)MidiAdsr_setRelease, METH_O, "Sets release time in seconds."},
+    {"setExp", (PyCFunction)MidiAdsr_setExp, METH_O, "Sets the exponent factor for exponential envelope."},
     {"setDiv", (PyCFunction)MidiAdsr_setDiv, METH_O, "Sets inverse mul factor."},
     {NULL}  /* Sentinel */
 };
@@ -2809,7 +3149,7 @@ static PyNumberMethods MidiAdsr_as_number = {
     (binaryfunc)MidiAdsr_add,                      /*nb_add*/
     (binaryfunc)MidiAdsr_sub,                 /*nb_subtract*/
     (binaryfunc)MidiAdsr_multiply,                 /*nb_multiply*/
-    (binaryfunc)MidiAdsr_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -2823,16 +3163,16 @@ static PyNumberMethods MidiAdsr_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)MidiAdsr_inplace_add,              /*inplace_add*/
     (binaryfunc)MidiAdsr_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)MidiAdsr_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)MidiAdsr_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -2841,15 +3181,14 @@ static PyNumberMethods MidiAdsr_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)MidiAdsr_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)MidiAdsr_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject MidiAdsrType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.MidiAdsr_base",         /*tp_name*/
     sizeof(MidiAdsr),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -2857,7 +3196,7 @@ PyTypeObject MidiAdsrType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &MidiAdsr_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -2872,10 +3211,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 */
@@ -2905,6 +3244,8 @@ typedef struct {
     MYFLT decay;
     MYFLT sustain;
     MYFLT release;
+    MYFLT exp;
+    MYFLT expscl;
     MYFLT invAttack;
     MYFLT initAmpMinusOffsetAmp;
     MYFLT invDecay;
@@ -2914,24 +3255,26 @@ typedef struct {
     MYFLT invRelease;
     double currentTime;
     MYFLT sampleToSec;
+    MYFLT *buf;
 } MidiDelAdsr;
 
 static void
 MidiDelAdsr_generates(MidiDelAdsr *self) {
     MYFLT val;
     int i;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (self->fademode == 0 && in[i] > 0.0) {
             self->fademode = 1;
             self->initAmp = in[i];
-            self->offsetAmp = self->data[i];
+            self->expscl = MYPOW(self->initAmp, 1.0 / self->exp) / self->initAmp;
+            self->offsetAmp = self->buf[i]; 
             self->sustainAmp = self->initAmp * self->sustain;
             self->currentTime = 0.0;
             self->invAttack = 1.0 / self->attack;
-            self->invDecay = 1.0 / self->decay; 
+            self->invDecay = 1.0 / self->decay;
             self->delayPlusAttack = self->delay + self->attack;
             self->delayPlusAttackPlusDecay = self->delay + self->attack + self->decay;
             self->initAmpMinusOffsetAmp = self->initAmp - self->offsetAmp;
@@ -2942,7 +3285,7 @@ MidiDelAdsr_generates(MidiDelAdsr *self) {
             self->currentTime = 0.0;
             self->invRelease = 1.0 / self->release;
         }
-        
+
         if (self->fademode == 1) {
             if (self->currentTime < self->delay)
                 val = 0.0;
@@ -2953,15 +3296,25 @@ MidiDelAdsr_generates(MidiDelAdsr *self) {
             else
                 val = self->sustainAmp;
             self->topValue = val;
-        }    
-        else {  
+        }
+        else {
             if (self->currentTime <= self->release)
                 val = self->topValue * (1. - self->currentTime * self->invRelease);
-            else 
+            else
                 val = 0.;
-        }    
-        self->data[i] = val;
-        self->currentTime += self->sampleToSec;    
+        }
+        self->buf[i] = val;
+        self->currentTime += self->sampleToSec;
+    }
+
+    if (self->exp != 1.0) {
+        for (i=0; i<self->bufsize; i++) {
+            self->data[i] = MYPOW(self->buf[i] * self->expscl, self->exp);
+        }
+    } else {
+        for (i=0; i<self->bufsize; i++) {
+            self->data[i] = self->buf[i];
+        }
     }
 }
 
@@ -2980,44 +3333,44 @@ MidiDelAdsr_setProcMode(MidiDelAdsr *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = MidiDelAdsr_generates;
-    
-	switch (muladdmode) {
-        case 0:        
+
+    switch (muladdmode) {
+        case 0:
             self->muladd_func_ptr = MidiDelAdsr_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = MidiDelAdsr_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = MidiDelAdsr_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = MidiDelAdsr_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = MidiDelAdsr_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = MidiDelAdsr_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = MidiDelAdsr_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = MidiDelAdsr_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = MidiDelAdsr_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 MidiDelAdsr_compute_next_data_frame(MidiDelAdsr *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -3030,7 +3383,7 @@ MidiDelAdsr_traverse(MidiDelAdsr *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 MidiDelAdsr_clear(MidiDelAdsr *self)
 {
     pyo_CLEAR
@@ -3043,8 +3396,9 @@ static void
 MidiDelAdsr_dealloc(MidiDelAdsr* self)
 {
     pyo_DEALLOC
+    free(self->buf);
     MidiDelAdsr_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -3054,9 +3408,9 @@ MidiDelAdsr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     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;
@@ -3066,30 +3420,36 @@ MidiDelAdsr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->sustain = 0.707;
     self->release = 0.1;
     self->currentTime = 0.0;
-    
+    self->exp = self->expscl = 1.0;
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, MidiDelAdsr_compute_next_data_frame);
     self->mode_func_ptr = MidiDelAdsr_setProcMode;
-    
+
     self->sampleToSec = 1. / self->sr;
 
     static char *kwlist[] = {"input", "delay", "attack", "decay", "sustain", "release", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_FFFFFOO, kwlist, &inputtmp, &self->delay, &self->attack, &self->decay, &self->sustain, &self->release, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     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->buf = (MYFLT *)realloc(self->buf, self->bufsize * sizeof(MYFLT));
+    for (i=0; i<self->bufsize; i++) {
+        self->buf[i] = 0.0;
+    }
+
     if (self->attack < 0.000001)
         self->attack = 0.000001;
     if (self->decay < 0.000001)
@@ -3100,18 +3460,18 @@ MidiDelAdsr_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         self->sustain = 0.0;
     else if (self->sustain > 1.0)
         self->sustain = 1.0;
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * MidiDelAdsr_getServer(MidiDelAdsr* self) { GET_SERVER };
 static PyObject * MidiDelAdsr_getStream(MidiDelAdsr* self) { GET_STREAM };
-static PyObject * MidiDelAdsr_setMul(MidiDelAdsr *self, PyObject *arg) { SET_MUL };	
-static PyObject * MidiDelAdsr_setAdd(MidiDelAdsr *self, PyObject *arg) { SET_ADD };	
-static PyObject * MidiDelAdsr_setSub(MidiDelAdsr *self, PyObject *arg) { SET_SUB };	
-static PyObject * MidiDelAdsr_setDiv(MidiDelAdsr *self, PyObject *arg) { SET_DIV };	
+static PyObject * MidiDelAdsr_setMul(MidiDelAdsr *self, PyObject *arg) { SET_MUL };
+static PyObject * MidiDelAdsr_setAdd(MidiDelAdsr *self, PyObject *arg) { SET_ADD };
+static PyObject * MidiDelAdsr_setSub(MidiDelAdsr *self, PyObject *arg) { SET_SUB };
+static PyObject * MidiDelAdsr_setDiv(MidiDelAdsr *self, PyObject *arg) { SET_DIV };
 
 static PyObject * MidiDelAdsr_play(MidiDelAdsr *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * MidiDelAdsr_stop(MidiDelAdsr *self) { STOP }
@@ -3128,9 +3488,11 @@ static PyObject * MidiDelAdsr_inplace_div(MidiDelAdsr *self, PyObject *arg) { IN
 static PyObject *
 MidiDelAdsr_setDelay(MidiDelAdsr *self, PyObject *arg)
 {
-    self->delay = PyFloat_AsDouble(PyNumber_Float(arg));
-    self->delayPlusAttack = self->delay + self->attack;
-    self->delayPlusAttackPlusDecay = self->delay + self->attack + self->decay;
+    if (PyNumber_Check(arg)) {
+        self->delay = PyFloat_AsDouble(arg);
+        self->delayPlusAttack = self->delay + self->attack;
+        self->delayPlusAttackPlusDecay = self->delay + self->attack + self->decay;
+    }
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -3138,12 +3500,14 @@ MidiDelAdsr_setDelay(MidiDelAdsr *self, PyObject *arg)
 static PyObject *
 MidiDelAdsr_setAttack(MidiDelAdsr *self, PyObject *arg)
 {
-    self->attack = PyFloat_AsDouble(PyNumber_Float(arg));
-    if (self->attack < 0.000001)
-        self->attack = 0.000001;
-    self->invAttack = 1.0 / self->attack;
-    self->delayPlusAttack = self->delay + self->attack;
-    self->delayPlusAttackPlusDecay = self->delay + self->attack + self->decay;
+    if (PyNumber_Check(arg)) {
+        self->attack = PyFloat_AsDouble(arg);
+        if (self->attack < 0.000001)
+            self->attack = 0.000001;
+        self->invAttack = 1.0 / self->attack;
+        self->delayPlusAttack = self->delay + self->attack;
+        self->delayPlusAttackPlusDecay = self->delay + self->attack + self->decay;
+    }
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -3151,11 +3515,13 @@ MidiDelAdsr_setAttack(MidiDelAdsr *self, PyObject *arg)
 static PyObject *
 MidiDelAdsr_setDecay(MidiDelAdsr *self, PyObject *arg)
 {
-    self->decay = PyFloat_AsDouble(PyNumber_Float(arg));
-    if (self->decay < 0.000001)
-        self->decay = 0.000001;
-    self->invDecay = 1.0 / self->decay; 
-    self->delayPlusAttackPlusDecay = self->delay + self->attack + self->decay;
+    if (PyNumber_Check(arg)) {
+        self->decay = PyFloat_AsDouble(arg);
+        if (self->decay < 0.000001)
+            self->decay = 0.000001;
+        self->invDecay = 1.0 / self->decay;
+        self->delayPlusAttackPlusDecay = self->delay + self->attack + self->decay;
+    }
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -3163,11 +3529,13 @@ MidiDelAdsr_setDecay(MidiDelAdsr *self, PyObject *arg)
 static PyObject *
 MidiDelAdsr_setSustain(MidiDelAdsr *self, PyObject *arg)
 {
-    self->sustain = PyFloat_AsDouble(PyNumber_Float(arg));
-    if (self->sustain < 0.0)
-        self->sustain = 0.0;
-    else if (self->sustain > 1.0)
-        self->sustain = 1.0;
+    if (PyNumber_Check(arg)) {
+        self->sustain = PyFloat_AsDouble(arg);
+        if (self->sustain < 0.0)
+            self->sustain = 0.0;
+        else if (self->sustain > 1.0)
+            self->sustain = 1.0;
+    }
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -3175,10 +3543,24 @@ MidiDelAdsr_setSustain(MidiDelAdsr *self, PyObject *arg)
 static PyObject *
 MidiDelAdsr_setRelease(MidiDelAdsr *self, PyObject *arg)
 {
-    self->release = PyFloat_AsDouble(PyNumber_Float(arg));
-    if (self->release < 0.000001)
-        self->release = 0.000001;
-    self->invRelease = 1.0 / self->release;
+    if (PyNumber_Check(arg)) {
+        self->release = PyFloat_AsDouble(arg);
+        if (self->release < 0.000001)
+            self->release = 0.000001;
+        self->invRelease = 1.0 / self->release;
+    }
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *
+MidiDelAdsr_setExp(MidiDelAdsr *self, PyObject *arg)
+{
+    if (PyNumber_Check(arg)) {
+        MYFLT tmp = PyFloat_AsDouble(arg);
+        if (tmp > 0.0)
+            self->exp = tmp;
+    }
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -3205,6 +3587,7 @@ static PyMethodDef MidiDelAdsr_methods[] = {
     {"setDecay", (PyCFunction)MidiDelAdsr_setDecay, METH_O, "Sets decay time in seconds."},
     {"setSustain", (PyCFunction)MidiDelAdsr_setSustain, METH_O, "Sets sustain level in percent of note amplitude."},
     {"setRelease", (PyCFunction)MidiDelAdsr_setRelease, METH_O, "Sets release time in seconds."},
+    {"setExp", (PyCFunction)MidiDelAdsr_setExp, METH_O, "Sets the exponent factor for exponential envelope."},
     {"setDiv", (PyCFunction)MidiDelAdsr_setDiv, METH_O, "Sets inverse mul factor."},
     {NULL}  /* Sentinel */
 };
@@ -3213,7 +3596,7 @@ static PyNumberMethods MidiDelAdsr_as_number = {
     (binaryfunc)MidiDelAdsr_add,                      /*nb_add*/
     (binaryfunc)MidiDelAdsr_sub,                 /*nb_subtract*/
     (binaryfunc)MidiDelAdsr_multiply,                 /*nb_multiply*/
-    (binaryfunc)MidiDelAdsr_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -3227,16 +3610,16 @@ static PyNumberMethods MidiDelAdsr_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)MidiDelAdsr_inplace_add,              /*inplace_add*/
     (binaryfunc)MidiDelAdsr_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)MidiDelAdsr_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)MidiDelAdsr_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -3245,15 +3628,14 @@ static PyNumberMethods MidiDelAdsr_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)MidiDelAdsr_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)MidiDelAdsr_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject MidiDelAdsrType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.MidiDelAdsr_base",         /*tp_name*/
     sizeof(MidiDelAdsr),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -3261,7 +3643,7 @@ PyTypeObject MidiDelAdsrType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &MidiDelAdsr_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -3276,10 +3658,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 */
@@ -3293,3 +3675,166 @@ PyTypeObject MidiDelAdsrType = {
     MidiDelAdsr_new,                 /* tp_new */
 };
 
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *callable;
+} RawMidi;
+
+static void
+RawMidi_setProcMode(RawMidi *self) {}
+
+static void
+RawMidi_compute_next_data_frame(RawMidi *self)
+{
+    PyoMidiEvent *buffer;
+    int i, count, status, data1, data2;
+
+    buffer = Server_getMidiEventBuffer((Server *)self->server);
+    count = Server_getMidiEventCount((Server *)self->server);
+
+    if (count > 0) {
+        PyObject *tup;
+        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);
+            PyTuple_SetItem(tup, 0, PyInt_FromLong(status));
+            PyTuple_SetItem(tup, 1, PyInt_FromLong(data1));
+            PyTuple_SetItem(tup, 2, PyInt_FromLong(data2));
+            PyObject_Call((PyObject *)self->callable, tup, NULL);
+        }
+    }
+}
+
+static int
+RawMidi_traverse(RawMidi *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->callable);
+    return 0;
+}
+
+static int
+RawMidi_clear(RawMidi *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->callable);
+    return 0;
+}
+
+static void
+RawMidi_dealloc(RawMidi* self)
+{
+    pyo_DEALLOC
+    RawMidi_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+RawMidi_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *calltmp=NULL;
+    RawMidi *self;
+    self = (RawMidi *)type->tp_alloc(type, 0);
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, RawMidi_compute_next_data_frame);
+    self->mode_func_ptr = RawMidi_setProcMode;
+
+    static char *kwlist[] = {"callable", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &calltmp))
+        Py_RETURN_NONE;
+
+    if (calltmp) {
+        PyObject_CallMethod((PyObject *)self, "setFunction", "O", calltmp);
+    }
+
+    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
+
+    return (PyObject *)self;
+}
+
+static PyObject * RawMidi_getServer(RawMidi* self) { GET_SERVER };
+static PyObject * RawMidi_getStream(RawMidi* self) { GET_STREAM };
+
+static PyObject * RawMidi_play(RawMidi *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * RawMidi_stop(RawMidi *self) { STOP };
+
+static PyObject *
+RawMidi_setFunction(RawMidi *self, PyObject *arg)
+{
+    PyObject *tmp;
+
+    if (! PyCallable_Check(arg)) {
+        PyErr_SetString(PyExc_TypeError, "The callable attribute must be a valid Python function.");
+        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;
+}
+
+static PyMemberDef RawMidi_members[] = {
+    {"server", T_OBJECT_EX, offsetof(RawMidi, server), 0, "Pyo server."},
+    {"stream", T_OBJECT_EX, offsetof(RawMidi, stream), 0, "Stream object."},
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef RawMidi_methods[] = {
+    {"getServer", (PyCFunction)RawMidi_getServer, METH_NOARGS, "Returns server object."},
+    {"_getStream", (PyCFunction)RawMidi_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)RawMidi_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+    {"stop", (PyCFunction)RawMidi_stop, METH_NOARGS, "Stops computing."},
+    {"setFunction", (PyCFunction)RawMidi_setFunction, METH_O, "Sets the function to be called."},
+    {NULL}  /* Sentinel */
+};
+
+PyTypeObject RawMidiType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.RawMidi_base",         /*tp_name*/
+    sizeof(RawMidi),         /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)RawMidi_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*/
+    "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 */
+    RawMidi_methods,             /* tp_methods */
+    RawMidi_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 */
+    RawMidi_new,                 /* tp_new */
+};
diff --git a/src/objects/noisemodule.c b/src/objects/noisemodule.c
index 681b905..e3226d7 100644
--- a/src/objects/noisemodule.c
+++ b/src/objects/noisemodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include "pyomodule.h"
 #include "streammodule.h"
@@ -37,14 +38,14 @@ Noise_generate(Noise *self) {
     int i;
 
     for (i=0; i<self->bufsize; i++) {
-        self->data[i] = rand()/((MYFLT)(RAND_MAX)+1)*1.98-0.99;
+        self->data[i] = RANDOM_UNIFORM * 1.98 - 0.99;
     }
 }
 
 static void
 Noise_generate_cheap(Noise *self) {
     int i;
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->seed = (self->seed * 15625 + 1) & 0xFFFF;
         self->data[i] = (self->seed - 0x8000) * 3.0517578125e-05;
@@ -66,7 +67,7 @@ Noise_setProcMode(Noise *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     switch (self->type) {
         case 0:
             self->proc_func_ptr = Noise_generate;
@@ -76,31 +77,31 @@ Noise_setProcMode(Noise *self)
             break;
     }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Noise_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Noise_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Noise_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Noise_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Noise_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Noise_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Noise_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Noise_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Noise_postprocessing_revareva;
             break;
     }
@@ -109,7 +110,7 @@ Noise_setProcMode(Noise *self)
 static void
 Noise_compute_next_data_frame(Noise *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -120,7 +121,7 @@ Noise_traverse(Noise *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Noise_clear(Noise *self)
 {
     pyo_CLEAR
@@ -132,7 +133,7 @@ Noise_dealloc(Noise* self)
 {
     pyo_DEALLOC
     Noise_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -142,7 +143,7 @@ Noise_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *multmp=NULL, *addtmp=NULL;
     Noise *self;
     self = (Noise *)type->tp_alloc(type, 0);
-    
+
     self->type = 0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
@@ -152,35 +153,35 @@ Noise_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = Noise_setProcMode;
 
     static char *kwlist[] = {"mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &multmp, &addtmp))
-        Py_RETURN_NONE; 
- 
+        Py_RETURN_NONE;
+
     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);
 
     Server_generateSeed((Server *)self->server, NOISE_ID);
-    
-    self->seed = rand();
+
+    self->seed = pyorand();
 
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * Noise_getServer(Noise* self) { GET_SERVER };
 static PyObject * Noise_getStream(Noise* self) { GET_STREAM };
-static PyObject * Noise_setMul(Noise *self, PyObject *arg) { SET_MUL };	
-static PyObject * Noise_setAdd(Noise *self, PyObject *arg) { SET_ADD };	
-static PyObject * Noise_setSub(Noise *self, PyObject *arg) { SET_SUB };	
-static PyObject * Noise_setDiv(Noise *self, PyObject *arg) { SET_DIV };	
+static PyObject * Noise_setMul(Noise *self, PyObject *arg) { SET_MUL };
+static PyObject * Noise_setAdd(Noise *self, PyObject *arg) { SET_ADD };
+static PyObject * Noise_setSub(Noise *self, PyObject *arg) { SET_SUB };
+static PyObject * Noise_setDiv(Noise *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Noise_play(Noise *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Noise_out(Noise *self, PyObject *args, PyObject *kwds) { OUT };
@@ -197,12 +198,9 @@ static PyObject * Noise_inplace_div(Noise *self, PyObject *arg) { INPLACE_DIV };
 
 static PyObject *
 Noise_setType(Noise *self, PyObject *arg)
-{	
-    if (arg == NULL) {
-        Py_INCREF(Py_None);
-        return Py_None;
-    }
-    
+{
+    ASSERT_ARG_NOT_NULL
+
     if (PyInt_AS_LONG(arg) == 0)
         self->type = 0;
     else if (PyInt_AS_LONG(arg) == 1)
@@ -212,7 +210,7 @@ Noise_setType(Noise *self, PyObject *arg)
 
     Py_INCREF(Py_None);
     return Py_None;
-}	
+}
 
 static PyMemberDef Noise_members[] = {
 {"server", T_OBJECT_EX, offsetof(Noise, server), 0, "Pyo server."},
@@ -240,7 +238,7 @@ static PyNumberMethods Noise_as_number = {
 (binaryfunc)Noise_add,                      /*nb_add*/
 (binaryfunc)Noise_sub,                 /*nb_subtract*/
 (binaryfunc)Noise_multiply,                 /*nb_multiply*/
-(binaryfunc)Noise_div,                   /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -254,16 +252,16 @@ static PyNumberMethods Noise_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
 (binaryfunc)Noise_inplace_add,              /*inplace_add*/
 (binaryfunc)Noise_inplace_sub,         /*inplace_subtract*/
 (binaryfunc)Noise_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)Noise_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -272,15 +270,14 @@ static PyNumberMethods Noise_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)Noise_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)Noise_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
 PyTypeObject NoiseType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Noise_base",         /*tp_name*/
 sizeof(Noise),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -288,7 +285,7 @@ sizeof(Noise),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &Noise_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -336,9 +333,9 @@ static void
 PinkNoise_generate(PinkNoise *self) {
     MYFLT in, val;
     int i;
-    
+
     for (i=0; i<self->bufsize; i++) {
-        in = rand()/((MYFLT)(RAND_MAX)+1)*1.98-0.99;
+        in = RANDOM_UNIFORM * 1.98 - 0.99;
         self->c0 = self->c0 * 0.99886 + in * 0.0555179;
         self->c1 = self->c1 * 0.99332 + in * 0.0750759;
         self->c2 = self->c2 * 0.96900 + in * 0.1538520;
@@ -366,33 +363,33 @@ PinkNoise_setProcMode(PinkNoise *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = PinkNoise_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = PinkNoise_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = PinkNoise_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = PinkNoise_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = PinkNoise_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = PinkNoise_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = PinkNoise_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = PinkNoise_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = PinkNoise_postprocessing_revareva;
             break;
     }
@@ -401,7 +398,7 @@ PinkNoise_setProcMode(PinkNoise *self)
 static void
 PinkNoise_compute_next_data_frame(PinkNoise *self)
 {
-    PinkNoise_generate(self); 
+    PinkNoise_generate(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -412,7 +409,7 @@ PinkNoise_traverse(PinkNoise *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 PinkNoise_clear(PinkNoise *self)
 {
     pyo_CLEAR
@@ -424,7 +421,7 @@ PinkNoise_dealloc(PinkNoise* self)
 {
     pyo_DEALLOC
     PinkNoise_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -434,32 +431,32 @@ PinkNoise_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *multmp=NULL, *addtmp=NULL;
     PinkNoise *self;
     self = (PinkNoise *)type->tp_alloc(type, 0);
-    
+
     self->c0 = self->c1 = self->c2 = self->c3 = self->c4 = self->c5 = self->c6 = 0.0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, PinkNoise_compute_next_data_frame);
     self->mode_func_ptr = PinkNoise_setProcMode;
 
     static char *kwlist[] = {"mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     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);
-    
+
     Server_generateSeed((Server *)self->server, PINKNOISE_ID);
 
     return (PyObject *)self;
@@ -467,10 +464,10 @@ PinkNoise_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * PinkNoise_getServer(PinkNoise* self) { GET_SERVER };
 static PyObject * PinkNoise_getStream(PinkNoise* self) { GET_STREAM };
-static PyObject * PinkNoise_setMul(PinkNoise *self, PyObject *arg) { SET_MUL };	
-static PyObject * PinkNoise_setAdd(PinkNoise *self, PyObject *arg) { SET_ADD };	
-static PyObject * PinkNoise_setSub(PinkNoise *self, PyObject *arg) { SET_SUB };	
-static PyObject * PinkNoise_setDiv(PinkNoise *self, PyObject *arg) { SET_DIV };	
+static PyObject * PinkNoise_setMul(PinkNoise *self, PyObject *arg) { SET_MUL };
+static PyObject * PinkNoise_setAdd(PinkNoise *self, PyObject *arg) { SET_ADD };
+static PyObject * PinkNoise_setSub(PinkNoise *self, PyObject *arg) { SET_SUB };
+static PyObject * PinkNoise_setDiv(PinkNoise *self, PyObject *arg) { SET_DIV };
 
 static PyObject * PinkNoise_play(PinkNoise *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * PinkNoise_out(PinkNoise *self, PyObject *args, PyObject *kwds) { OUT };
@@ -510,7 +507,7 @@ static PyNumberMethods PinkNoise_as_number = {
     (binaryfunc)PinkNoise_add,                      /*nb_add*/
     (binaryfunc)PinkNoise_sub,                 /*nb_subtract*/
     (binaryfunc)PinkNoise_multiply,                 /*nb_multiply*/
-    (binaryfunc)PinkNoise_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -524,16 +521,16 @@ static PyNumberMethods PinkNoise_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)PinkNoise_inplace_add,              /*inplace_add*/
     (binaryfunc)PinkNoise_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)PinkNoise_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)PinkNoise_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -542,15 +539,14 @@ static PyNumberMethods PinkNoise_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)PinkNoise_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)PinkNoise_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject PinkNoiseType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.PinkNoise_base",         /*tp_name*/
     sizeof(PinkNoise),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -558,7 +554,7 @@ PyTypeObject PinkNoiseType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &PinkNoise_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -602,9 +598,9 @@ static void
 BrownNoise_generate(BrownNoise *self) {
     MYFLT rnd, val;
     int i;
-    
+
     for (i=0; i<self->bufsize; i++) {
-        rnd = rand()/((MYFLT)(RAND_MAX)+1)*1.98-0.99;
+        rnd = RANDOM_UNIFORM * 1.98 - 0.99;
         val = self->c1 * rnd + self->c2 * self->y1;
         self->y1 = val;
         self->data[i] = val * 20.0; /* gain compensation */
@@ -626,33 +622,33 @@ BrownNoise_setProcMode(BrownNoise *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = BrownNoise_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = BrownNoise_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = BrownNoise_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = BrownNoise_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = BrownNoise_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = BrownNoise_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = BrownNoise_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = BrownNoise_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = BrownNoise_postprocessing_revareva;
             break;
     }
@@ -661,7 +657,7 @@ BrownNoise_setProcMode(BrownNoise *self)
 static void
 BrownNoise_compute_next_data_frame(BrownNoise *self)
 {
-    BrownNoise_generate(self); 
+    BrownNoise_generate(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -672,7 +668,7 @@ BrownNoise_traverse(BrownNoise *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 BrownNoise_clear(BrownNoise *self)
 {
     pyo_CLEAR
@@ -684,7 +680,7 @@ BrownNoise_dealloc(BrownNoise* self)
 {
     pyo_DEALLOC
     BrownNoise_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -695,47 +691,47 @@ BrownNoise_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *multmp=NULL, *addtmp=NULL;
     BrownNoise *self;
     self = (BrownNoise *)type->tp_alloc(type, 0);
-    
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
     self->y1 = self->c1 = self->c2 = 0.0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, BrownNoise_compute_next_data_frame);
     self->mode_func_ptr = BrownNoise_setProcMode;
 
     static char *kwlist[] = {"mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     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);
 
     b = 2.0 - MYCOS(TWOPI * 20.0 / self->sr);
     self->c2 = (b - MYSQRT(b * b - 1.0));
     self->c1 = 1.0 - self->c2;
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     Server_generateSeed((Server *)self->server, BROWNNOISE_ID);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * BrownNoise_getServer(BrownNoise* self) { GET_SERVER };
 static PyObject * BrownNoise_getStream(BrownNoise* self) { GET_STREAM };
-static PyObject * BrownNoise_setMul(BrownNoise *self, PyObject *arg) { SET_MUL };	
-static PyObject * BrownNoise_setAdd(BrownNoise *self, PyObject *arg) { SET_ADD };	
-static PyObject * BrownNoise_setSub(BrownNoise *self, PyObject *arg) { SET_SUB };	
-static PyObject * BrownNoise_setDiv(BrownNoise *self, PyObject *arg) { SET_DIV };	
+static PyObject * BrownNoise_setMul(BrownNoise *self, PyObject *arg) { SET_MUL };
+static PyObject * BrownNoise_setAdd(BrownNoise *self, PyObject *arg) { SET_ADD };
+static PyObject * BrownNoise_setSub(BrownNoise *self, PyObject *arg) { SET_SUB };
+static PyObject * BrownNoise_setDiv(BrownNoise *self, PyObject *arg) { SET_DIV };
 
 static PyObject * BrownNoise_play(BrownNoise *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * BrownNoise_out(BrownNoise *self, PyObject *args, PyObject *kwds) { OUT };
@@ -775,7 +771,7 @@ static PyNumberMethods BrownNoise_as_number = {
     (binaryfunc)BrownNoise_add,                      /*nb_add*/
     (binaryfunc)BrownNoise_sub,                 /*nb_subtract*/
     (binaryfunc)BrownNoise_multiply,                 /*nb_multiply*/
-    (binaryfunc)BrownNoise_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -789,16 +785,16 @@ static PyNumberMethods BrownNoise_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)BrownNoise_inplace_add,              /*inplace_add*/
     (binaryfunc)BrownNoise_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)BrownNoise_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)BrownNoise_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -807,15 +803,14 @@ static PyNumberMethods BrownNoise_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)BrownNoise_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)BrownNoise_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject BrownNoiseType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.BrownNoise_base",         /*tp_name*/
     sizeof(BrownNoise),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -823,7 +818,7 @@ PyTypeObject BrownNoiseType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &BrownNoise_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -854,4 +849,3 @@ PyTypeObject BrownNoiseType = {
     0,                         /* tp_alloc */
     BrownNoise_new,                 /* tp_new */
 };
-
diff --git a/src/objects/oscbankmodule.c b/src/objects/oscbankmodule.c
index b8b4cd3..86f90e9 100644
--- a/src/objects/oscbankmodule.c
+++ b/src/objects/oscbankmodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
@@ -87,20 +88,20 @@ OscBank_setFrequencies(OscBank *self, MYFLT freq, MYFLT spread) {
     int i, seed;
     MYFLT rnd;
     MYFLT scl = freq * spread;
-    
+
     if (self->fjit == 1) {
-        seed = rand();
+        seed = pyorand();
         for (i=0; i<self->stages; i++) {
             seed = (seed * 15625 + 1) & 0xFFFF;
             rnd = seed * 1.52587890625e-07 - 0.005 + 1.0;
             self->frequencies[i] = (freq + scl * i) * rnd;
-            /* printf("harm %d : %f Hz\n", i, self->frequencies[i]); */
+            /* PySys_WriteStdout("harm %d : %f Hz\n", i, self->frequencies[i]); */
         }
     }
     else {
         for (i=0; i<self->stages; i++) {
             self->frequencies[i] = freq + scl * i;
-            /* printf("harm %d : %f Hz\n", i, self->frequencies[i]); */
+            /* PySys_WriteStdout("harm %d : %f Hz\n", i, self->frequencies[i]); */
         }
     }
 }
@@ -115,7 +116,7 @@ OscBank_pickNewFrnds(OscBank *self, MYFLT frndf, MYFLT frnda) {
     else if (frnda > 1.0)
         frnda = 1.0;
 
-    seed = rand();
+    seed = pyorand();
     for (i=0; i<self->stages; i++) {
         self->fOldValues[i] = self->fValues[i];
         seed = (seed * 15625 + 1) & 0xFFFF;
@@ -133,8 +134,8 @@ OscBank_pickNewArnds(OscBank *self, MYFLT arndf, MYFLT arnda) {
         arnda = 0.0;
     else if (arnda > 1.0)
         arnda = 1.0;
-    
-    seed = rand();
+
+    seed = pyorand();
     for (i=0; i<self->stages; i++) {
         self->aOldValues[i] = self->aValues[i];
         seed = (seed * 15625 + 1) & 0xFFFF;
@@ -154,7 +155,7 @@ OscBank_readframes(OscBank *self) {
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = 0.0;
     }
-    
+
     if (self->modebuffer[2] == 0)
         freq = PyFloat_AS_DOUBLE(self->freq);
     else
@@ -183,7 +184,7 @@ OscBank_readframes(OscBank *self) {
         arnda = PyFloat_AS_DOUBLE(self->arnda);
     else
         arnda = Stream_getData((Stream *)self->arnda_stream)[0];
-    
+
     if (freq != self->lastFreq || spread != self->lastSpread) {
         self->lastFreq = freq;
         self->lastSpread = spread;
@@ -201,7 +202,7 @@ OscBank_readframes(OscBank *self) {
 
     if (frnda == 0.0 && arnda == 0.0) {
         amp = self->amplitude;
-        for (j=0; j<self->stages; j++) {          
+        for (j=0; j<self->stages; j++) {
             inc = self->frequencies[j] * tabscl;
             pos = self->pointerPos[j];
             for (i=0; i<self->bufsize; i++) {
@@ -289,7 +290,7 @@ OscBank_readframes(OscBank *self) {
         }
         self->atime += self->ainc;
     }
-    
+
 }
 
 static void OscBank_postprocessing_ii(OscBank *self) { POST_PROCESSING_II };
@@ -311,40 +312,40 @@ OscBank_setProcMode(OscBank *self)
     self->proc_func_ptr = OscBank_readframes;
 
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = OscBank_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = OscBank_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = OscBank_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = OscBank_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = OscBank_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = OscBank_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = OscBank_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = OscBank_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = OscBank_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 OscBank_compute_next_data_frame(OscBank *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -353,42 +354,42 @@ OscBank_traverse(OscBank *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->table);
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
-    Py_VISIT(self->spread);    
-    Py_VISIT(self->spread_stream);    
-    Py_VISIT(self->slope);    
-    Py_VISIT(self->slope_stream); 
-    Py_VISIT(self->frndf);    
-    Py_VISIT(self->frndf_stream); 
-    Py_VISIT(self->frnda);    
-    Py_VISIT(self->frnda_stream); 
-    Py_VISIT(self->arndf);    
-    Py_VISIT(self->arndf_stream); 
-    Py_VISIT(self->arnda);    
-    Py_VISIT(self->arnda_stream); 
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->spread);
+    Py_VISIT(self->spread_stream);
+    Py_VISIT(self->slope);
+    Py_VISIT(self->slope_stream);
+    Py_VISIT(self->frndf);
+    Py_VISIT(self->frndf_stream);
+    Py_VISIT(self->frnda);
+    Py_VISIT(self->frnda_stream);
+    Py_VISIT(self->arndf);
+    Py_VISIT(self->arndf_stream);
+    Py_VISIT(self->arnda);
+    Py_VISIT(self->arnda_stream);
     return 0;
 }
 
-static int 
+static int
 OscBank_clear(OscBank *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->table);
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
-    Py_CLEAR(self->spread);    
-    Py_CLEAR(self->spread_stream);    
-    Py_CLEAR(self->slope);    
-    Py_CLEAR(self->slope_stream);    
-    Py_CLEAR(self->frndf);    
-    Py_CLEAR(self->frndf_stream); 
-    Py_CLEAR(self->frnda);    
-    Py_CLEAR(self->frnda_stream); 
-    Py_CLEAR(self->arndf);    
-    Py_CLEAR(self->arndf_stream); 
-    Py_CLEAR(self->arnda);    
-    Py_CLEAR(self->arnda_stream); 
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->spread);
+    Py_CLEAR(self->spread_stream);
+    Py_CLEAR(self->slope);
+    Py_CLEAR(self->slope_stream);
+    Py_CLEAR(self->frndf);
+    Py_CLEAR(self->frndf_stream);
+    Py_CLEAR(self->frnda);
+    Py_CLEAR(self->frnda_stream);
+    Py_CLEAR(self->arndf);
+    Py_CLEAR(self->arndf_stream);
+    Py_CLEAR(self->arnda);
+    Py_CLEAR(self->arnda_stream);
     return 0;
 }
 
@@ -405,7 +406,7 @@ OscBank_dealloc(OscBank* self)
     free(self->aValues);
     free(self->aDiffs);
     OscBank_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -415,7 +416,7 @@ OscBank_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *tabletmp, *freqtmp=NULL, *spreadtmp=NULL, *slopetmp=NULL, *frndftmp=NULL, *frndatmp=NULL, *arndftmp=NULL, *arndatmp=NULL, *multmp=NULL, *addtmp=NULL;
     OscBank *self;
     self = (OscBank *)type->tp_alloc(type, 0);
-    
+
     self->freq = PyFloat_FromDouble(100.0);
     self->spread = PyFloat_FromDouble(1.0);
     self->slope = PyFloat_FromDouble(0.9);
@@ -440,23 +441,20 @@ OscBank_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[6] = 0;
 	self->modebuffer[7] = 0;
 	self->modebuffer[8] = 0;
-    
+
     INIT_OBJECT_COMMON
 
     Stream_setFunctionPtr(self->stream, OscBank_compute_next_data_frame);
     self->mode_func_ptr = OscBank_setProcMode;
 
     static char *kwlist[] = {"table", "freq", "spread", "slope", "frndf", "frnda", "arndf", "arnda", "num", "fjit", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOOOOOiiOO", kwlist, &tabletmp, &freqtmp, &spreadtmp, &slopetmp, &frndftmp, &frndatmp, &arndftmp, &arndatmp, &self->stages, &self->fjit, &multmp, &addtmp))
         Py_RETURN_NONE;
 
     if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
-        PySys_WriteStderr("TypeError: \"table\" argument of OscBank must be a PyoTableObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"table\" argument of OscBank must be a PyoTableObject.\n");
+        Py_RETURN_NONE;
     }
     Py_XDECREF(self->table);
     self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", "");
@@ -464,7 +462,7 @@ OscBank_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    
+
     if (spreadtmp) {
         PyObject_CallMethod((PyObject *)self, "setSpread", "O", spreadtmp);
     }
@@ -486,17 +484,17 @@ OscBank_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (arndatmp) {
         PyObject_CallMethod((PyObject *)self, "setArnda", "O", arndatmp);
     }
-    
+
     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);
 
     self->pointerPos = (MYFLT *)realloc(self->pointerPos, self->stages * sizeof(MYFLT));
@@ -507,11 +505,11 @@ OscBank_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->aOldValues = (MYFLT *)realloc(self->aOldValues, self->stages * sizeof(MYFLT));
     self->aValues = (MYFLT *)realloc(self->aValues, self->stages * sizeof(MYFLT));
     self->aDiffs = (MYFLT *)realloc(self->aDiffs, self->stages * sizeof(MYFLT));
-    
+
     for (i=0; i<self->stages; i++) {
         self->pointerPos[i] = self->frequencies[i] = self->fOldValues[i] = self->fValues[i] = self->fDiffs[i] = self->aOldValues[i] = self->aValues[i] = self->aDiffs[i] = 0.0;
     }
-    
+
     self->amplitude = 1. / self->stages;
 
     Server_generateSeed((Server *)self->server, OSCBANK_ID);
@@ -521,10 +519,10 @@ OscBank_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * OscBank_getServer(OscBank* self) { GET_SERVER };
 static PyObject * OscBank_getStream(OscBank* self) { GET_STREAM };
-static PyObject * OscBank_setMul(OscBank *self, PyObject *arg) { SET_MUL };	
-static PyObject * OscBank_setAdd(OscBank *self, PyObject *arg) { SET_ADD };	
-static PyObject * OscBank_setSub(OscBank *self, PyObject *arg) { SET_SUB };	
-static PyObject * OscBank_setDiv(OscBank *self, PyObject *arg) { SET_DIV };	
+static PyObject * OscBank_setMul(OscBank *self, PyObject *arg) { SET_MUL };
+static PyObject * OscBank_setAdd(OscBank *self, PyObject *arg) { SET_ADD };
+static PyObject * OscBank_setSub(OscBank *self, PyObject *arg) { SET_SUB };
+static PyObject * OscBank_setDiv(OscBank *self, PyObject *arg) { SET_DIV };
 
 static PyObject * OscBank_play(OscBank *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * OscBank_out(OscBank *self, PyObject *args, PyObject *kwds) { OUT };
@@ -550,32 +548,26 @@ static PyObject *
 OscBank_setTable(OscBank *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    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 *
 OscBank_setFreq(OscBank *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -594,20 +586,17 @@ OscBank_setFreq(OscBank *self, PyObject *arg)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 OscBank_setSpread(OscBank *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->spread);
@@ -626,20 +615,17 @@ OscBank_setSpread(OscBank *self, PyObject *arg)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 OscBank_setSlope(OscBank *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->slope);
@@ -655,23 +641,20 @@ OscBank_setSlope(OscBank *self, PyObject *arg)
         self->slope_stream = (Stream *)streamtmp;
 		self->modebuffer[4] = 1;
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 OscBank_setFrndf(OscBank *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->frndf);
@@ -687,23 +670,20 @@ OscBank_setFrndf(OscBank *self, PyObject *arg)
         self->frndf_stream = (Stream *)streamtmp;
 		self->modebuffer[5] = 1;
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 OscBank_setFrnda(OscBank *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->frnda);
@@ -719,23 +699,20 @@ OscBank_setFrnda(OscBank *self, PyObject *arg)
         self->frnda_stream = (Stream *)streamtmp;
 		self->modebuffer[6] = 1;
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 OscBank_setArndf(OscBank *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->arndf);
@@ -751,23 +728,20 @@ OscBank_setArndf(OscBank *self, PyObject *arg)
         self->arndf_stream = (Stream *)streamtmp;
 		self->modebuffer[7] = 1;
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 OscBank_setArnda(OscBank *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->arnda);
@@ -783,14 +757,14 @@ OscBank_setArnda(OscBank *self, PyObject *arg)
         self->arnda_stream = (Stream *)streamtmp;
 		self->modebuffer[8] = 1;
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 OscBank_setFjit(OscBank *self, PyObject *arg)
-{	
+{
     int isInt = PyInt_Check(arg);
 
 	if (isInt) {
@@ -799,7 +773,7 @@ OscBank_setFjit(OscBank *self, PyObject *arg)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef OscBank_members[] = {
     {"server", T_OBJECT_EX, offsetof(OscBank, server), 0, "Pyo server."},
@@ -842,7 +816,7 @@ static PyNumberMethods OscBank_as_number = {
     (binaryfunc)OscBank_add,                         /*nb_add*/
     (binaryfunc)OscBank_sub,                         /*nb_subtract*/
     (binaryfunc)OscBank_multiply,                    /*nb_multiply*/
-    (binaryfunc)OscBank_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -856,16 +830,16 @@ static PyNumberMethods OscBank_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)OscBank_inplace_add,                 /*inplace_add*/
     (binaryfunc)OscBank_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)OscBank_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)OscBank_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -874,15 +848,14 @@ static PyNumberMethods OscBank_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)OscBank_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)OscBank_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject OscBankType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.OscBank_base",                                   /*tp_name*/
     sizeof(OscBank),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -890,7 +863,7 @@ PyTypeObject OscBankType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &OscBank_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -921,4 +894,3 @@ PyTypeObject OscBankType = {
     0,                                              /* tp_alloc */
     OscBank_new,                                     /* tp_new */
 };
-
diff --git a/src/objects/oscilmodule.c b/src/objects/oscilmodule.c
index 5c7f1e0..5549677 100644
--- a/src/objects/oscilmodule.c
+++ b/src/objects/oscilmodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
@@ -29,14 +30,16 @@
 #include "interpolation.h"
 
 static MYFLT SINE_ARRAY[513] = {0.0, 0.012271538285719925, 0.024541228522912288, 0.036807222941358832, 0.049067674327418015, 0.061320736302208578, 0.073564563599667426, 0.085797312344439894, 0.098017140329560604, 0.11022220729388306, 0.1224106751992162, 0.13458070850712617, 0.14673047445536175, 0.15885814333386145, 0.17096188876030122, 0.18303988795514095, 0.19509032201612825, 0.20711137619221856, 0.2191012401568698, 0.23105810828067111, 0.24298017990326387, 0.25486565960451457, 0.26671275747489837, 0.27851968938505306, 0.29028467725446233, 0.30200594931922808, 0.31368174039889152, 0.32531029216226293, 0.33688985339222005, 0.34841868024943456, 0.35989503653498811, 0.37131719395183754, 0.38268343236508978, 0.3939920400610481, 0.40524131400498986, 0.41642956009763715, 0.42755509343028208, 0.43861623853852766, 0.44961132965460654, 0.46053871095824001, 0.47139673682599764, 0.48218377207912272, 0.49289819222978404, 0.50353838372571758, 0.51410274419322166, 0.52458968267846895, 0.53499761988709715, 0.54532498842204646, 0.55557023301960218, 0.56573181078361312, 0.57580819141784534, 0.58579785745643886, 0.59569930449243336, 0.60551104140432555, 0.61523159058062682, 0.62485948814238634, 0.63439328416364549, 0.64383154288979139, 0.65317284295377676, 0.66241577759017178, 0.67155895484701833, 0.68060099779545302, 0.68954054473706683, 0.69837624940897292, 0.70710678118654746, 0.71573082528381859, 0.72424708295146689, 0.7326542716724127, 0.74095112535495899, 0.74913639452345926, 0.75720884650648446, 0.76516726562245885, 0.77301045336273688, 0.78073722857209438, 0.78834642762660623, 0.79583690460888346, 0.80320753148064483, 0.81045719825259477, 0.81758481315158371, 0.82458930278502529, 0.83146961230254512, 0.83822470555483797, 0.84485356524970701, 0.8513551931052652, 0.85772861000027212, 0.8639728561215867, 0.87008699110871135, 0.87607009419540649, 0.88192126434835494, 0.88763962040285393, 0.89322430119551532, 0.89867446569395382, 0.90398929312344334, 0.90916798309052238, 0.91420975570353069, 0.91911385169005777, 0.92387953251128674, 0.92850608047321548, 0.93299279883473885, 0.93733901191257496, 0.94154406518302081, 0.94560732538052128, 0.94952818059303667, 0.95330604035419375, 0.95694033573220894, 0.96043051941556579, 0.96377606579543984, 0.96697647104485207, 0.97003125319454397, 0.97293995220556007, 0.97570213003852857, 0.97831737071962765, 0.98078528040323043, 0.98310548743121629, 0.98527764238894122, 0.98730141815785843, 0.98917650996478101, 0.99090263542778001, 0.99247953459870997, 0.99390697000235606, 0.99518472667219682, 0.996312612182778, 0.99729045667869021, 0.99811811290014918, 0.99879545620517241, 0.99932238458834954, 0.99969881869620425, 0.9999247018391445, 1.0, 0.9999247018391445, 0.99969881869620425, 0.99932238458834954, 0.99879545620517241, 0.99811811290014918, 0.99729045667869021, 0.996312612182778, 0.99518472667219693, 0.99390697000235606, 0.99247953459870997, 0.99090263542778001, 0.98917650996478101, 0.98730141815785843, 0.98527764238894122, 0.98310548743121629, 0.98078528040323043, 0.97831737071962765, 0.97570213003852857, 0.97293995220556018, 0.97003125319454397, 0.96697647104485207, 0.96377606579543984, 0.9604305194155659, 0.95694033573220894, 0.95330604035419386, 0.94952818059303667, 0.94560732538052139, 0.94154406518302081, 0.93733901191257496, 0.93299279883473885, 0.92850608047321559, 0.92387953251128674, 0.91911385169005777, 0.91420975570353069, 0.90916798309052249, 0.90398929312344345, 0.89867446569395393, 0.89322430119551521, 0.88763962040285393, 0.88192126434835505, 0.8760700941954066, 0.87008699110871146, 0.86397285612158681, 0.85772861000027212, 0.8513551931052652, 0.84485356524970723, 0.83822470555483819, 0.83146961230254546, 0.82458930278502529, 0.81758481315158371, 0.81045719825259477, 0.80320753148064494, 0.79583690460888357, 0.78834642762660634, 0.7807372285720946, 0.7730104533627371, 0.76516726562245907, 0.75720884650648479, 0.74913639452345926, 0.74095112535495899, 0.73265427167241282, 0.724247082951467, 0.71573082528381871, 0.70710678118654757, 0.69837624940897292, 0.68954054473706705, 0.68060099779545324, 0.67155895484701855, 0.66241577759017201, 0.65317284295377664, 0.64383154288979139, 0.63439328416364549, 0.62485948814238634, 0.61523159058062693, 0.60551104140432555, 0.59569930449243347, 0.58579785745643898, 0.57580819141784545, 0.56573181078361345, 0.55557023301960218, 0.54532498842204635, 0.53499761988709715, 0.52458968267846895, 0.51410274419322177, 0.50353838372571758, 0.49289819222978415, 0.48218377207912289, 0.47139673682599781, 0.46053871095824023, 0.44961132965460687, 0.43861623853852755, 0.42755509343028203, 0.41642956009763715, 0.40524131400498986, 0.39399204006104815, 0.38268343236508984, 0.37131719395183765, 0.35989503653498833, 0.34841868024943479, 0.33688985339222027, 0.3253102921622632, 0.31368174039889141, 0.30200594931922803, 0.29028467725446233, 0.27851968938505312, 0.26671275747489848, 0.25486565960451468, 0.24298017990326404, 0.2310581082806713, 0.21910124015687002, 0.20711137619221884, 0.19509032201612858, 0.1830398879551409, 0.17096188876030119, 0.15885814333386145, 0.1467304744553618, 0.13458070850712628, 0.12241067519921635, 0.11022220729388325, 0.09801714032956084, 0.085797312344440158, 0.073564563599667745, 0.061320736302208495, 0.049067674327417973, 0.036807222941358832, 0.024541228522912326, 0.012271538285720007, 1.2246467991473532e-16, -0.012271538285719761, -0.024541228522912083, -0.036807222941358582, -0.049067674327417724, -0.061320736302208245, -0.073564563599667496, -0.085797312344439922, -0.09801714032956059, -0.110222207293883, -0.1224106751992161, -0.13458070850712606, -0.14673047445536158, -0.15885814333386122, -0.17096188876030097, -0.18303988795514067, -0.19509032201612836, -0.20711137619221862, -0.21910124015686983, -0.23105810828067111, -0.24298017990326382, -0.25486565960451446, -0.26671275747489825, -0.27851968938505289, -0.29028467725446216, -0.30200594931922781, -0.31368174039889118, -0.32531029216226304, -0.33688985339222011, -0.34841868024943456, -0.35989503653498811, -0.37131719395183749, -0.38268343236508967, -0.39399204006104793, -0.40524131400498969, -0.41642956009763693, -0.42755509343028181, -0.43861623853852733, -0.44961132965460665, -0.46053871095824006, -0.47139673682599764, -0.48218377207912272, -0.49289819222978393, -0.50353838372571746, -0.51410274419322155, -0.52458968267846873, -0.53499761988709693, -0.54532498842204613, -0.55557023301960196, -0.56573181078361323, -0.57580819141784534, -0.58579785745643886, -0.59569930449243325, -0.60551104140432543, -0.61523159058062671, -0.62485948814238623, -0.63439328416364527, -0.64383154288979128, -0.65317284295377653, -0.66241577759017178, -0.67155895484701844, -0.68060099779545302, -0.68954054473706683, -0.6983762494089728, -0.70710678118654746, -0.71573082528381848, -0.72424708295146667, -0.73265427167241259, -0.74095112535495877, -0.74913639452345904, -0.75720884650648423, -0.76516726562245885, -0.77301045336273666, -0.78073722857209438, -0.78834642762660589, -0.79583690460888334, -0.80320753148064505, -0.81045719825259466, -0.81758481315158371, -0.82458930278502507, -0.83146961230254524, -0.83822470555483775, -0.84485356524970712, -0.85135519310526486, -0.85772861000027201, -0.86397285612158647, -0.87008699110871135, -0.87607009419540671, -0.88192126434835494, -0.88763962040285405, -0.89322430119551521, -0.89867446569395382, -0.90398929312344312, -0.90916798309052238, -0.91420975570353047, -0.91911385169005766, -0.92387953251128652, -0.92850608047321548, -0.93299279883473896, -0.93733901191257485, -0.94154406518302081, -0.94560732538052117, -0.94952818059303667, -0.95330604035419375, -0.95694033573220882, -0.96043051941556568, -0.96377606579543984, -0.96697647104485218, -0.97003125319454397, -0.97293995220556018, -0.97570213003852846, -0.97831737071962765, -0.98078528040323032, -0.98310548743121629, -0.98527764238894111, -0.98730141815785832, -0.9891765099647809, -0.99090263542778001, -0.99247953459871008, -0.99390697000235606, -0.99518472667219693, -0.996312612182778, -0.99729045667869021, -0.99811811290014918, -0.99879545620517241, -0.99932238458834943, -0.99969881869620425, -0.9999247018391445, -1.0, -0.9999247018391445, -0.99969881869620425, -0.99932238458834954, -0.99879545620517241, -0.99811811290014918, -0.99729045667869021, -0.996312612182778, -0.99518472667219693, -0.99390697000235606, -0.99247953459871008, -0.99090263542778001, -0.9891765099647809, -0.98730141815785843, -0.98527764238894122, -0.9831054874312164, -0.98078528040323043, -0.97831737071962777, -0.97570213003852857, -0.97293995220556029, -0.97003125319454397, -0.96697647104485229, -0.96377606579543995, -0.96043051941556579, -0.95694033573220894, -0.95330604035419375, -0.94952818059303679, -0.94560732538052128, -0.94154406518302092, -0.93733901191257496, -0.93299279883473907, -0.92850608047321559, -0.92387953251128663, -0.91911385169005788, -0.91420975570353058, -0.90916798309052249, -0.90398929312344334, -0.89867446569395404, -0.89322430119551532, -0.88763962040285416, -0.88192126434835505, -0.87607009419540693, -0.87008699110871146, -0.8639728561215867, -0.85772861000027223, -0.85135519310526508, -0.84485356524970734, -0.83822470555483797, -0.83146961230254557, -0.82458930278502529, -0.81758481315158404, -0.81045719825259488, -0.80320753148064528, -0.79583690460888368, -0.78834642762660612, -0.78073722857209471, -0.77301045336273688, -0.76516726562245918, -0.75720884650648457, -0.7491363945234597, -0.74095112535495922, -0.73265427167241315, -0.72424708295146711, -0.71573082528381904, -0.70710678118654768, -0.69837624940897269, -0.68954054473706716, -0.68060099779545302, -0.67155895484701866, -0.66241577759017178, -0.65317284295377709, -0.6438315428897915, -0.63439328416364593, -0.62485948814238645, -0.61523159058062737, -0.60551104140432566, -0.59569930449243325, -0.58579785745643909, -0.57580819141784523, -0.56573181078361356, -0.55557023301960218, -0.5453249884220468, -0.53499761988709726, -0.52458968267846939, -0.51410274419322188, -0.50353838372571813, -0.49289819222978426, -0.48218377207912261, -0.47139673682599792, -0.46053871095823995, -0.44961132965460698, -0.43861623853852766, -0.42755509343028253, -0.41642956009763726, -0.40524131400499042, -0.39399204006104827, -0.38268343236509039, -0.37131719395183777, -0.359895036534988, -0.3484186802494349, -0.33688985339222, -0.32531029216226331, -0.31368174039889152, -0.30200594931922853, -0.29028467725446244, -0.27851968938505367, -0.26671275747489859, -0.25486565960451435, -0.24298017990326418, -0.23105810828067103, -0.21910124015687016, -0.20711137619221853, -0.19509032201612872, -0.18303988795514103, -0.17096188876030177, -0.15885814333386158, -0.14673047445536239, -0.13458070850712642, -0.12241067519921603, -0.11022220729388338, -0.09801714032956052, -0.085797312344440282, -0.073564563599667426, -0.06132073630220905, -0.049067674327418091, -0.036807222941359394, -0.024541228522912451, -0.012271538285720572, 0.0};
-static MYFLT COSINE_ARRAY[513] = {1.0, 0.9999247018391445, 0.9996988186962042, 0.9993223845883495, 0.9987954562051724, 0.9981181129001492, 0.9972904566786902, 0.996312612182778, 0.9951847266721969, 0.9939069700023561, 0.99247953459871, 0.99090263542778, 0.989176509964781, 0.9873014181578584, 0.9852776423889412, 0.9831054874312163, 0.9807852804032304, 0.9783173707196277, 0.9757021300385286, 0.9729399522055602, 0.970031253194544, 0.9669764710448521, 0.9637760657954398, 0.9604305194155658, 0.9569403357322088, 0.9533060403541939, 0.9495281805930367, 0.9456073253805213, 0.9415440651830208, 0.937339011912575, 0.932992798834739, 0.9285060804732156, 0.9238795325112867, 0.9191138516900578, 0.9142097557035307, 0.9091679830905224, 0.9039892931234433, 0.8986744656939538, 0.8932243011955153, 0.8876396204028539, 0.881921264348355, 0.8760700941954066, 0.8700869911087115, 0.8639728561215868, 0.8577286100002721, 0.8513551931052652, 0.8448535652497071, 0.8382247055548381, 0.8314696123025452, 0.8245893027850253, 0.8175848131515837, 0.8104571982525948, 0.8032075314806449, 0.7958369046088836, 0.7883464276266063, 0.7807372285720945, 0.773010453362737, 0.765167265622459, 0.7572088465064846, 0.7491363945234594, 0.7409511253549591, 0.7326542716724128, 0.724247082951467, 0.7157308252838186, 0.7071067811865476, 0.6983762494089729, 0.6895405447370669, 0.6806009977954531, 0.6715589548470183, 0.6624157775901718, 0.6531728429537768, 0.6438315428897915, 0.6343932841636455, 0.6248594881423865, 0.6152315905806268, 0.6055110414043255, 0.5956993044924335, 0.5857978574564389, 0.5758081914178453, 0.5657318107836132, 0.5555702330196023, 0.5453249884220465, 0.5349976198870973, 0.5245896826784688, 0.5141027441932217, 0.5035383837257176, 0.4928981922297841, 0.48218377207912283, 0.4713967368259978, 0.46053871095824, 0.4496113296546066, 0.4386162385385277, 0.4275550934302822, 0.4164295600976373, 0.40524131400498986, 0.3939920400610481, 0.38268343236508984, 0.3713171939518376, 0.3598950365349883, 0.3484186802494345, 0.33688985339222005, 0.325310292162263, 0.3136817403988916, 0.3020059493192282, 0.29028467725446233, 0.27851968938505306, 0.2667127574748984, 0.2548656596045146, 0.24298017990326398, 0.23105810828067128, 0.21910124015686977, 0.20711137619221856, 0.19509032201612833, 0.18303988795514106, 0.17096188876030136, 0.1588581433338614, 0.14673047445536175, 0.13458070850712622, 0.12241067519921628, 0.11022220729388318, 0.09801714032956077, 0.08579731234443988, 0.07356456359966745, 0.06132073630220865, 0.049067674327418126, 0.03680722294135899, 0.024541228522912264, 0.012271538285719944, 6.123031769111886e-17, -0.012271538285719823, -0.024541228522912142, -0.036807222941358866, -0.04906767432741801, -0.06132073630220853, -0.07356456359966733, -0.08579731234443976, -0.09801714032956065, -0.11022220729388306, -0.12241067519921615, -0.1345807085071261, -0.14673047445536164, -0.15885814333386128, -0.17096188876030124, -0.18303988795514092, -0.1950903220161282, -0.20711137619221845, -0.21910124015686966, -0.23105810828067114, -0.24298017990326387, -0.2548656596045145, -0.2667127574748983, -0.27851968938505295, -0.29028467725446216, -0.3020059493192281, -0.3136817403988914, -0.32531029216226287, -0.33688985339221994, -0.3484186802494344, -0.35989503653498817, -0.3713171939518375, -0.3826834323650897, -0.393992040061048, -0.40524131400498975, -0.416429560097637, -0.42755509343028186, -0.4386162385385274, -0.4496113296546067, -0.46053871095824006, -0.4713967368259977, -0.4821837720791227, -0.492898192229784, -0.5035383837257175, -0.5141027441932217, -0.5245896826784687, -0.534997619887097, -0.5453249884220462, -0.555570233019602, -0.5657318107836132, -0.5758081914178453, -0.5857978574564389, -0.5956993044924334, -0.6055110414043254, -0.6152315905806267, -0.6248594881423862, -0.6343932841636454, -0.6438315428897913, -0.6531728429537765, -0.6624157775901719, -0.6715589548470184, -0.680600997795453, -0.6895405447370669, -0.6983762494089728, -0.7071067811865475, -0.7157308252838186, -0.7242470829514668, -0.7326542716724127, -0.7409511253549589, -0.7491363945234591, -0.7572088465064846, -0.765167265622459, -0.773010453362737, -0.7807372285720945, -0.7883464276266062, -0.7958369046088835, -0.8032075314806448, -0.8104571982525947, -0.8175848131515836, -0.8245893027850251, -0.8314696123025453, -0.8382247055548381, -0.8448535652497071, -0.8513551931052652, -0.857728610000272, -0.8639728561215867, -0.8700869911087113, -0.8760700941954065, -0.8819212643483549, -0.8876396204028538, -0.8932243011955152, -0.8986744656939539, -0.9039892931234433, -0.9091679830905224, -0.9142097557035307, -0.9191138516900578, -0.9238795325112867, -0.9285060804732155, -0.9329927988347388, -0.9373390119125748, -0.9415440651830207, -0.9456073253805212, -0.9495281805930367, -0.9533060403541939, -0.9569403357322088, -0.9604305194155658, 
--0.9637760657954398, -0.9669764710448521, -0.970031253194544, -0.9729399522055601, -0.9757021300385285, -0.9783173707196275, -0.9807852804032304, -0.9831054874312163, -0.9852776423889412, -0.9873014181578584, -0.989176509964781, -0.99090263542778, -0.99247953459871, -0.9939069700023561, -0.9951847266721968, -0.996312612182778, -0.9972904566786902, -0.9981181129001492, -0.9987954562051724, -0.9993223845883495, -0.9996988186962042, -0.9999247018391445, -1.0, -0.9999247018391445, -0.9996988186962042, -0.9993223845883495, -0.9987954562051724, -0.9981181129001492, -0.9972904566786902, -0.996312612182778, -0.9951847266721969, -0.9939069700023561, -0.99247953459871, -0.99090263542778, -0.989176509964781, -0.9873014181578584, -0.9852776423889413, -0.9831054874312164, -0.9807852804032304, -0.9783173707196277, -0.9757021300385286, -0.9729399522055602, -0.970031253194544, -0.9669764710448522, -0.96377606579544, -0.9604305194155659, -0.9569403357322089, -0.953306040354194, -0.9495281805930368, -0.9456073253805213, -0.9415440651830208, -0.937339011912575, -0.932992798834739, -0.9285060804732156, -0.9238795325112868, -0.9191138516900578, -0.9142097557035307, -0.9091679830905225, -0.9039892931234434, -0.898674465693954, -0.8932243011955153, -0.8876396204028539, -0.881921264348355, -0.8760700941954066, -0.8700869911087115, -0.8639728561215868, -0.8577286100002721, -0.8513551931052653, -0.8448535652497072, -0.8382247055548382, -0.8314696123025455, -0.8245893027850253, -0.8175848131515837, -0.8104571982525948, -0.8032075314806449, -0.7958369046088836, -0.7883464276266063, -0.7807372285720946, -0.7730104533627371, -0.7651672656224591, -0.7572088465064848, -0.7491363945234593, -0.7409511253549591, -0.7326542716724128, -0.724247082951467, -0.7157308252838187, -0.7071067811865477, -0.698376249408973, -0.689540544737067, -0.6806009977954532, -0.6715589548470187, -0.662415777590172, -0.6531728429537771, -0.6438315428897915, -0.6343932841636459, -0.6248594881423865, -0.6152315905806273, -0.6055110414043257, -0.5956993044924331, -0.5857978574564391, -0.5758081914178452, -0.5657318107836135, -0.5555702330196022, -0.5453249884220468, -0.5349976198870973, -0.5245896826784694, -0.5141027441932218, -0.503538383725718, -0.4928981922297842, -0.48218377207912255, -0.47139673682599786, -0.4605387109582399, -0.44961132965460693, -0.4386162385385276, -0.4275550934302825, -0.4164295600976372, -0.40524131400499036, -0.3939920400610482, -0.38268343236509034, -0.37131719395183777, -0.35989503653498794, -0.34841868024943484, -0.33688985339221994, -0.3253102921622633, -0.31368174039889146, -0.30200594931922853, -0.29028467725446244, -0.2785196893850536, -0.26671275747489853, -0.25486565960451435, -0.24298017990326412, -0.23105810828067094, -0.2191012401568701, -0.20711137619221848, -0.19509032201612866, -0.18303988795514095, -0.1709618887603017, -0.15885814333386153, -0.1467304744553623, -0.13458070850712636, -0.12241067519921596, -0.11022220729388331, -0.09801714032956045, -0.08579731234444023, -0.07356456359966736, -0.061320736302208995, -0.04906767432741803, -0.03680722294135933, -0.02454122852291239, -0.012271538285720512, -1.836909530733566e-16, 0.012271538285720144, 0.02454122852291202, 0.036807222941358964, 0.04906767432741766, 0.06132073630220863, 0.07356456359966698, 0.08579731234443985, 0.09801714032956009, 0.11022220729388293, 0.1224106751992156, 0.13458070850712597, 0.14673047445536194, 0.15885814333386117, 0.17096188876030133, 0.1830398879551406, 0.1950903220161283, 0.20711137619221812, 0.21910124015686974, 0.23105810828067058, 0.24298017990326376, 0.25486565960451396, 0.2667127574748982, 0.2785196893850533, 0.29028467725446205, 0.30200594931922814, 0.31368174039889113, 0.3253102921622629, 0.3368898533922196, 0.3484186802494345, 0.3598950365349876, 0.3713171939518374, 0.38268343236509, 0.3939920400610479, 0.40524131400499, 0.4164295600976369, 0.42755509343028214, 0.43861623853852727, 0.4496113296546066, 0.46053871095823956, 0.4713967368259976, 0.4821837720791222, 0.49289819222978387, 0.5035383837257178, 0.5141027441932216, 0.5245896826784691, 0.5349976198870969, 0.5453249884220465, 0.5555702330196018, 0.5657318107836131, 0.5758081914178449, 0.5857978574564388, 0.5956993044924329, 0.6055110414043253, 0.615231590580627, 0.6248594881423861, 0.6343932841636456, 0.6438315428897912, 0.6531728429537768, 0.6624157775901715, 0.6715589548470183, 0.6806009977954527, 0.6895405447370668, 0.6983762494089724, 0.7071067811865474, 0.7157308252838188, 0.7242470829514667, 0.7326542716724129, 0.7409511253549589, 0.7491363945234594, 0.7572088465064842, 0.7651672656224588, 0.7730104533627367, 0.7807372285720944, 0.7883464276266059, 0.7958369046088833, 0.803207531480645, 0.8104571982525947, 0.8175848131515837, 0.8245893027850251, 0.8314696123025452, 0.8382247055548377, 
+static MYFLT COSINE_ARRAY[513] = {1.0, 0.9999247018391445, 0.9996988186962042, 0.9993223845883495, 0.9987954562051724, 0.9981181129001492, 0.9972904566786902, 0.996312612182778, 0.9951847266721969, 0.9939069700023561, 0.99247953459871, 0.99090263542778, 0.989176509964781, 0.9873014181578584, 0.9852776423889412, 0.9831054874312163, 0.9807852804032304, 0.9783173707196277, 0.9757021300385286, 0.9729399522055602, 0.970031253194544, 0.9669764710448521, 0.9637760657954398, 0.9604305194155658, 0.9569403357322088, 0.9533060403541939, 0.9495281805930367, 0.9456073253805213, 0.9415440651830208, 0.937339011912575, 0.932992798834739, 0.9285060804732156, 0.9238795325112867, 0.9191138516900578, 0.9142097557035307, 0.9091679830905224, 0.9039892931234433, 0.8986744656939538, 0.8932243011955153, 0.8876396204028539, 0.881921264348355, 0.8760700941954066, 0.8700869911087115, 0.8639728561215868, 0.8577286100002721, 0.8513551931052652, 0.8448535652497071, 0.8382247055548381, 0.8314696123025452, 0.8245893027850253, 0.8175848131515837, 0.8104571982525948, 0.8032075314806449, 0.7958369046088836, 0.7883464276266063, 0.7807372285720945, 0.773010453362737, 0.765167265622459, 0.7572088465064846, 0.7491363945234594, 0.7409511253549591, 0.7326542716724128, 0.724247082951467, 0.7157308252838186, 0.7071067811865476, 0.6983762494089729, 0.6895405447370669, 0.6806009977954531, 0.6715589548470183, 0.6624157775901718, 0.6531728429537768, 0.6438315428897915, 0.6343932841636455, 0.6248594881423865, 0.6152315905806268, 0.6055110414043255, 0.5956993044924335, 0.5857978574564389, 0.5758081914178453, 0.5657318107836132, 0.5555702330196023, 0.5453249884220465, 0.5349976198870973, 0.5245896826784688, 0.5141027441932217, 0.5035383837257176, 0.4928981922297841, 0.48218377207912283, 0.4713967368259978, 0.46053871095824, 0.4496113296546066, 0.4386162385385277, 0.4275550934302822, 0.4164295600976373, 0.40524131400498986, 0.3939920400610481, 0.38268343236508984, 0.3713171939518376, 0.3598950365349883, 0.3484186802494345, 0.33688985339222005, 0.325310292162263, 0.3136817403988916, 0.3020059493192282, 0.29028467725446233, 0.27851968938505306, 0.2667127574748984, 0.2548656596045146, 0.24298017990326398, 0.23105810828067128, 0.21910124015686977, 0.20711137619221856, 0.19509032201612833, 0.18303988795514106, 0.17096188876030136, 0.1588581433338614, 0.14673047445536175, 0.13458070850712622, 0.12241067519921628, 0.11022220729388318, 0.09801714032956077, 0.08579731234443988, 0.07356456359966745, 0.06132073630220865, 0.049067674327418126, 0.03680722294135899, 0.024541228522912264, 0.012271538285719944, 6.123031769111886e-17, -0.012271538285719823, -0.024541228522912142, -0.036807222941358866, -0.04906767432741801, -0.06132073630220853, -0.07356456359966733, -0.08579731234443976, -0.09801714032956065, -0.11022220729388306, -0.12241067519921615, -0.1345807085071261, -0.14673047445536164, -0.15885814333386128, -0.17096188876030124, -0.18303988795514092, -0.1950903220161282, -0.20711137619221845, -0.21910124015686966, -0.23105810828067114, -0.24298017990326387, -0.2548656596045145, -0.2667127574748983, -0.27851968938505295, -0.29028467725446216, -0.3020059493192281, -0.3136817403988914, -0.32531029216226287, -0.33688985339221994, -0.3484186802494344, -0.35989503653498817, -0.3713171939518375, -0.3826834323650897, -0.393992040061048, -0.40524131400498975, -0.416429560097637, -0.42755509343028186, -0.4386162385385274, -0.4496113296546067, -0.46053871095824006, -0.4713967368259977, -0.4821837720791227, -0.492898192229784, -0.5035383837257175, -0.5141027441932217, -0.5245896826784687, -0.534997619887097, -0.5453249884220462, -0.555570233019602, -0.5657318107836132, -0.5758081914178453, -0.5857978574564389, -0.5956993044924334, -0.6055110414043254, -0.6152315905806267, -0.6248594881423862, -0.6343932841636454, -0.6438315428897913, -0.6531728429537765, -0.6624157775901719, -0.6715589548470184, -0.680600997795453, -0.6895405447370669, -0.6983762494089728, -0.7071067811865475, -0.7157308252838186, -0.7242470829514668, -0.7326542716724127, -0.7409511253549589, -0.7491363945234591, -0.7572088465064846, -0.765167265622459, -0.773010453362737, -0.7807372285720945, -0.7883464276266062, -0.7958369046088835, -0.8032075314806448, -0.8104571982525947, -0.8175848131515836, -0.8245893027850251, -0.8314696123025453, -0.8382247055548381, -0.8448535652497071, -0.8513551931052652, -0.857728610000272, -0.8639728561215867, -0.8700869911087113, -0.8760700941954065, -0.8819212643483549, -0.8876396204028538, -0.8932243011955152, -0.8986744656939539, -0.9039892931234433, -0.9091679830905224, -0.9142097557035307, -0.9191138516900578, -0.9238795325112867, -0.9285060804732155, -0.9329927988347388, -0.9373390119125748, -0.9415440651830207, -0.9456073253805212, -0.9495281805930367, -0.9533060403541939, -0.9569403357322088, -0.9604305194155658,
+-0.9637760657954398, -0.9669764710448521, -0.970031253194544, -0.9729399522055601, -0.9757021300385285, -0.9783173707196275, -0.9807852804032304, -0.9831054874312163, -0.9852776423889412, -0.9873014181578584, -0.989176509964781, -0.99090263542778, -0.99247953459871, -0.9939069700023561, -0.9951847266721968, -0.996312612182778, -0.9972904566786902, -0.9981181129001492, -0.9987954562051724, -0.9993223845883495, -0.9996988186962042, -0.9999247018391445, -1.0, -0.9999247018391445, -0.9996988186962042, -0.9993223845883495, -0.9987954562051724, -0.9981181129001492, -0.9972904566786902, -0.996312612182778, -0.9951847266721969, -0.9939069700023561, -0.99247953459871, -0.99090263542778, -0.989176509964781, -0.9873014181578584, -0.9852776423889413, -0.9831054874312164, -0.9807852804032304, -0.9783173707196277, -0.9757021300385286, -0.9729399522055602, -0.970031253194544, -0.9669764710448522, -0.96377606579544, -0.9604305194155659, -0.9569403357322089, -0.953306040354194, -0.9495281805930368, -0.9456073253805213, -0.9415440651830208, -0.937339011912575, -0.932992798834739, -0.9285060804732156, -0.9238795325112868, -0.9191138516900578, -0.9142097557035307, -0.9091679830905225, -0.9039892931234434, -0.898674465693954, -0.8932243011955153, -0.8876396204028539, -0.881921264348355, -0.8760700941954066, -0.8700869911087115, -0.8639728561215868, -0.8577286100002721, -0.8513551931052653, -0.8448535652497072, -0.8382247055548382, -0.8314696123025455, -0.8245893027850253, -0.8175848131515837, -0.8104571982525948, -0.8032075314806449, -0.7958369046088836, -0.7883464276266063, -0.7807372285720946, -0.7730104533627371, -0.7651672656224591, -0.7572088465064848, -0.7491363945234593, -0.7409511253549591, -0.7326542716724128, -0.724247082951467, -0.7157308252838187, -0.7071067811865477, -0.698376249408973, -0.689540544737067, -0.6806009977954532, -0.6715589548470187, -0.662415777590172, -0.6531728429537771, -0.6438315428897915, -0.6343932841636459, -0.6248594881423865, -0.6152315905806273, -0.6055110414043257, -0.5956993044924331, -0.5857978574564391, -0.5758081914178452, -0.5657318107836135, -0.5555702330196022, -0.5453249884220468, -0.5349976198870973, -0.5245896826784694, -0.5141027441932218, -0.503538383725718, -0.4928981922297842, -0.48218377207912255, -0.47139673682599786, -0.4605387109582399, -0.44961132965460693, -0.4386162385385276, -0.4275550934302825, -0.4164295600976372, -0.40524131400499036, -0.3939920400610482, -0.38268343236509034, -0.37131719395183777, -0.35989503653498794, -0.34841868024943484, -0.33688985339221994, -0.3253102921622633, -0.31368174039889146, -0.30200594931922853, -0.29028467725446244, -0.2785196893850536, -0.26671275747489853, -0.25486565960451435, -0.24298017990326412, -0.23105810828067094, -0.2191012401568701, -0.20711137619221848, -0.19509032201612866, -0.18303988795514095, -0.1709618887603017, -0.15885814333386153, -0.1467304744553623, -0.13458070850712636, -0.12241067519921596, -0.11022220729388331, -0.09801714032956045, -0.08579731234444023, -0.07356456359966736, -0.061320736302208995, -0.04906767432741803, -0.03680722294135933, -0.02454122852291239, -0.012271538285720512, -1.836909530733566e-16, 0.012271538285720144, 0.02454122852291202, 0.036807222941358964, 0.04906767432741766, 0.06132073630220863, 0.07356456359966698, 0.08579731234443985, 0.09801714032956009, 0.11022220729388293, 0.1224106751992156, 0.13458070850712597, 0.14673047445536194, 0.15885814333386117, 0.17096188876030133, 0.1830398879551406, 0.1950903220161283, 0.20711137619221812, 0.21910124015686974, 0.23105810828067058, 0.24298017990326376, 0.25486565960451396, 0.2667127574748982, 0.2785196893850533, 0.29028467725446205, 0.30200594931922814, 0.31368174039889113, 0.3253102921622629, 0.3368898533922196, 0.3484186802494345, 0.3598950365349876, 0.3713171939518374, 0.38268343236509, 0.3939920400610479, 0.40524131400499, 0.4164295600976369, 0.42755509343028214, 0.43861623853852727, 0.4496113296546066, 0.46053871095823956, 0.4713967368259976, 0.4821837720791222, 0.49289819222978387, 0.5035383837257178, 0.5141027441932216, 0.5245896826784691, 0.5349976198870969, 0.5453249884220465, 0.5555702330196018, 0.5657318107836131, 0.5758081914178449, 0.5857978574564388, 0.5956993044924329, 0.6055110414043253, 0.615231590580627, 0.6248594881423861, 0.6343932841636456, 0.6438315428897912, 0.6531728429537768, 0.6624157775901715, 0.6715589548470183, 0.6806009977954527, 0.6895405447370668, 0.6983762494089724, 0.7071067811865474, 0.7157308252838188, 0.7242470829514667, 0.7326542716724129, 0.7409511253549589, 0.7491363945234594, 0.7572088465064842, 0.7651672656224588, 0.7730104533627367, 0.7807372285720944, 0.7883464276266059, 0.7958369046088833, 0.803207531480645, 0.8104571982525947, 0.8175848131515837, 0.8245893027850251, 0.8314696123025452, 0.8382247055548377,
 0.844853565249707, 0.8513551931052649, 0.857728610000272, 0.8639728561215864, 0.8700869911087113, 0.8760700941954067, 0.8819212643483548, 0.8876396204028539, 0.8932243011955151, 0.8986744656939538, 0.9039892931234431, 0.9091679830905224, 0.9142097557035305, 0.9191138516900577, 0.9238795325112865, 0.9285060804732155, 0.932992798834739, 0.9373390119125748, 0.9415440651830208, 0.9456073253805212, 0.9495281805930367, 0.9533060403541936, 0.9569403357322088, 0.9604305194155657, 0.9637760657954398, 0.9669764710448522, 0.970031253194544, 0.9729399522055602, 0.9757021300385285, 0.9783173707196277, 0.9807852804032303, 0.9831054874312163, 0.9852776423889411, 0.9873014181578583, 0.9891765099647809, 0.99090263542778, 0.99247953459871, 0.9939069700023561, 0.9951847266721969, 0.996312612182778, 0.9972904566786902, 0.9981181129001492, 0.9987954562051724, 0.9993223845883494, 0.9996988186962042, 0.9999247018391445, 1.0};
 static MYFLT ONE_OVER_512 = 1.0 / 512.0;
-static const MYFLT ROSSLER_SCALE     = 0.05757;
-static const MYFLT ROSSLER_ALT_SCALE = 0.06028;
-static const MYFLT LORENZ_SCALE     = 0.05107;
-static const MYFLT LORENZ_ALT_SCALE = 0.03679;
+static const MYFLT ROSSLER_SCALE     = 0.054;
+static const MYFLT ROSSLER_ALT_SCALE = 0.0569;
+static const MYFLT LORENZ_SCALE     = 0.044;
+static const MYFLT LORENZ_ALT_SCALE = 0.0328;
+static const MYFLT CHENLEE_SCALE     = 0.02;
+static const MYFLT CHENLEE_ALT_SCALE = 0.02;
 
 static MYFLT
 _clip(MYFLT x) {
@@ -74,11 +77,11 @@ static void
 Sine_readframes_ii(Sine *self) {
     MYFLT inc, fr, ph, pos, fpart;
     int i, ipart;
-    
+
     fr = PyFloat_AS_DOUBLE(self->freq);
     ph = PyFloat_AS_DOUBLE(self->phase) * 512;
     inc = fr * 512 / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->pointerPos = Sine_clip(self->pointerPos);
         pos = self->pointerPos + ph;
@@ -95,10 +98,10 @@ static void
 Sine_readframes_ai(Sine *self) {
     MYFLT inc, ph, pos, fpart, fac;
     int i, ipart;
-    
+
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
     ph = PyFloat_AS_DOUBLE(self->phase) * 512;
-    
+
     fac = 512 / self->sr;
     for (i=0; i<self->bufsize; i++) {
         inc = fr[i] * fac;
@@ -117,11 +120,11 @@ static void
 Sine_readframes_ia(Sine *self) {
     MYFLT inc, fr, pos, fpart;
     int i, ipart;
-    
+
     fr = PyFloat_AS_DOUBLE(self->freq);
     MYFLT *ph = Stream_getData((Stream *)self->phase_stream);
     inc = fr * 512 / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->pointerPos = Sine_clip(self->pointerPos);
         pos = self->pointerPos + ph[i] * 512;
@@ -138,10 +141,10 @@ static void
 Sine_readframes_aa(Sine *self) {
     MYFLT inc, pos, fpart, fac;
     int i, ipart;
-    
+
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
     MYFLT *ph = Stream_getData((Stream *)self->phase_stream);
-    
+
     fac = 512 / self->sr;
     for (i=0; i<self->bufsize; i++) {
         inc = fr[i] * fac;
@@ -172,48 +175,48 @@ Sine_setProcMode(Sine *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:        
+        case 0:
             self->proc_func_ptr = Sine_readframes_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Sine_readframes_ai;
             break;
-        case 10:    
+        case 10:
             self->proc_func_ptr = Sine_readframes_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Sine_readframes_aa;
             break;
-    } 
-    
+    }
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Sine_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Sine_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Sine_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Sine_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Sine_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Sine_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Sine_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Sine_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Sine_postprocessing_revareva;
             break;
     }
@@ -222,7 +225,7 @@ Sine_setProcMode(Sine *self)
 static void
 Sine_compute_next_data_frame(Sine *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -230,21 +233,21 @@ static int
 Sine_traverse(Sine *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
-    Py_VISIT(self->phase);    
-    Py_VISIT(self->phase_stream);    
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->phase);
+    Py_VISIT(self->phase_stream);
     return 0;
 }
 
-static int 
+static int
 Sine_clear(Sine *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
-    Py_CLEAR(self->phase);    
-    Py_CLEAR(self->phase_stream);    
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->phase);
+    Py_CLEAR(self->phase_stream);
     return 0;
 }
 
@@ -253,7 +256,7 @@ Sine_dealloc(Sine* self)
 {
     pyo_DEALLOC
     Sine_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -264,7 +267,7 @@ Sine_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
     Sine *self;
     self = (Sine *)type->tp_alloc(type, 0);
-    
+
     self->freq = PyFloat_FromDouble(1000);
     self->phase = PyFloat_FromDouble(0.0);
 	self->modebuffer[0] = 0;
@@ -272,34 +275,34 @@ Sine_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
     self->pointerPos = 0.;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Sine_compute_next_data_frame);
     self->mode_func_ptr = Sine_setProcMode;
-    
+
     static char *kwlist[] = {"freq", "phase", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &freqtmp, &phasetmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    
+
     if (phasetmp) {
         PyObject_CallMethod((PyObject *)self, "setPhase", "O", phasetmp);
     }
-    
+
     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;
@@ -307,10 +310,10 @@ Sine_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Sine_getServer(Sine* self) { GET_SERVER };
 static PyObject * Sine_getStream(Sine* self) { GET_STREAM };
-static PyObject * Sine_setMul(Sine *self, PyObject *arg) { SET_MUL };	
-static PyObject * Sine_setAdd(Sine *self, PyObject *arg) { SET_ADD };	
-static PyObject * Sine_setSub(Sine *self, PyObject *arg) { SET_SUB };	
-static PyObject * Sine_setDiv(Sine *self, PyObject *arg) { SET_DIV };	
+static PyObject * Sine_setMul(Sine *self, PyObject *arg) { SET_MUL };
+static PyObject * Sine_setAdd(Sine *self, PyObject *arg) { SET_ADD };
+static PyObject * Sine_setSub(Sine *self, PyObject *arg) { SET_SUB };
+static PyObject * Sine_setDiv(Sine *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Sine_play(Sine *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Sine_out(Sine *self, PyObject *args, PyObject *kwds) { OUT };
@@ -329,14 +332,11 @@ static PyObject *
 Sine_setFreq(Sine *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -352,25 +352,22 @@ Sine_setFreq(Sine *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Sine_setPhase(Sine *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->phase);
@@ -386,15 +383,15 @@ Sine_setPhase(Sine *self, PyObject *arg)
         self->phase_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
-static PyObject * 
-Sine_reset(Sine *self) 
+static PyObject *
+Sine_reset(Sine *self)
 {
     self->pointerPos = 0.0;
     Py_INCREF(Py_None);
@@ -431,7 +428,7 @@ static PyNumberMethods Sine_as_number = {
 (binaryfunc)Sine_add,                      /*nb_add*/
 (binaryfunc)Sine_sub,                 /*nb_subtract*/
 (binaryfunc)Sine_multiply,                 /*nb_multiply*/
-(binaryfunc)Sine_div,                   /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -445,16 +442,16 @@ static PyNumberMethods Sine_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
 (binaryfunc)Sine_inplace_add,              /*inplace_add*/
 (binaryfunc)Sine_inplace_sub,         /*inplace_subtract*/
 (binaryfunc)Sine_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)Sine_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -463,15 +460,14 @@ static PyNumberMethods Sine_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)Sine_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)Sine_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
 PyTypeObject SineType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Sine_base",         /*tp_name*/
 sizeof(Sine),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -479,7 +475,7 @@ sizeof(Sine),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &Sine_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -511,280 +507,388 @@ Sine_members,             /* tp_members */
 Sine_new,                 /* tp_new */
 };
 
-/*******************/
-/* SineLoop object */
-/*******************/
+
+/* FastSine object */
 typedef struct {
     pyo_audio_HEAD
     PyObject *freq;
     Stream *freq_stream;
-    PyObject *feedback;
-    Stream *feedback_stream;
-    int modebuffer[4];
+    int modebuffer[3];
+    MYFLT initphase;
+    int quality;
     MYFLT pointerPos;
-    MYFLT lastValue;
-} SineLoop;
+    MYFLT twoPiOnSr;
+    MYFLT B;
+    MYFLT C;
+} FastSine;
 
 static void
-SineLoop_readframes_ii(SineLoop *self) {
-    MYFLT inc, fr, feed, pos, fpart;
-    int i, ipart;
-    
+FastSine_readframes_low_i(FastSine *self) {
+    int i;
+    MYFLT inc, fr, pos, b, c;
+
     fr = PyFloat_AS_DOUBLE(self->freq);
-    feed = _clip(PyFloat_AS_DOUBLE(self->feedback)) * 512;
-    inc = fr * 512 / self->sr;
-    
+    inc = fr * self->twoPiOnSr;
+
+    pos = self->pointerPos;
+    b = self->B;
+    c = self->C;
     for (i=0; i<self->bufsize; i++) {
-        self->pointerPos = Sine_clip(self->pointerPos);
-        pos = Sine_clip(self->pointerPos + self->lastValue * feed);
-        ipart = (int)pos;
-        fpart = pos - ipart;
-        self->data[i] = self->lastValue = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
-        self->pointerPos += inc;
+        if (pos > PI)
+            pos -= TWOPI;
+        self->data[i] = b * pos + c * pos * MYFABS(pos);
+        pos += inc;
     }
+    self->pointerPos = pos;
 }
 
 static void
-SineLoop_readframes_ai(SineLoop *self) {
-    MYFLT inc, feed, pos, fpart, fac;
-    int i, ipart;
-    
+FastSine_readframes_low_a(FastSine *self) {
+    int i;
+    MYFLT pos, b, c;
+
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    feed = _clip(PyFloat_AS_DOUBLE(self->feedback)) * 512;
-    
-    fac = 512 / self->sr;
+
+    pos = self->pointerPos;
+    b = self->B;
+    c = self->C;
     for (i=0; i<self->bufsize; i++) {
-        inc = fr[i] * fac;
-        self->pointerPos = Sine_clip(self->pointerPos);
-        pos = Sine_clip(self->pointerPos + self->lastValue * feed);
-        ipart = (int)pos;
-        fpart = pos - ipart;
-        self->data[i] = self->lastValue = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
-        self->pointerPos += inc;
+        if (pos > PI)
+            pos -= TWOPI;
+        self->data[i] = b * pos + c * pos * MYFABS(pos);
+        pos += fr[i] * self->twoPiOnSr;
     }
+    self->pointerPos = pos;
 }
 
 static void
-SineLoop_readframes_ia(SineLoop *self) {
-    MYFLT inc, fr, feed, pos, fpart;
-    int i, ipart;
-    
+FastSine_readframes_high_i(FastSine *self) {
+    int i;
+    MYFLT inc, fr, pos, b, c, y;
+
     fr = PyFloat_AS_DOUBLE(self->freq);
-    MYFLT *fd = Stream_getData((Stream *)self->feedback_stream);
-    inc = fr * 512 / self->sr;
-    
+    inc = fr * self->twoPiOnSr;
+
+    pos = self->pointerPos;
+    b = self->B;
+    c = self->C;
     for (i=0; i<self->bufsize; i++) {
-        feed = _clip(fd[i]) * 512;
-        self->pointerPos = Sine_clip(self->pointerPos);
-        pos = Sine_clip(self->pointerPos + self->lastValue * feed);
-        ipart = (int)pos;
-        fpart = pos - ipart;
-        self->data[i] = self->lastValue = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
-        self->pointerPos += inc;
+        if (pos > PI)
+            pos -= TWOPI;
+        y = b * pos + c * pos * MYFABS(pos);
+        self->data[i] = y + (y * MYFABS(y) - y) * 0.218;
+        pos += inc;
     }
+    self->pointerPos = pos;
 }
 
 static void
-SineLoop_readframes_aa(SineLoop *self) {
-    MYFLT inc, feed, pos, fpart, fac;
-    int i, ipart;
-    
+FastSine_readframes_high_a(FastSine *self) {
+    int i;
+    MYFLT pos, b, c, y;
+
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    MYFLT *fd = Stream_getData((Stream *)self->feedback_stream);
-    
-    fac = 512 / self->sr;
+
+    pos = self->pointerPos;
+    b = self->B;
+    c = self->C;
     for (i=0; i<self->bufsize; i++) {
-        inc = fr[i] * fac;
-        feed = _clip(fd[i]) * 512;
-        self->pointerPos = Sine_clip(self->pointerPos);
-        pos = Sine_clip(self->pointerPos + self->lastValue * feed);
-        ipart = (int)pos;
-        fpart = pos - ipart;
-        self->data[i] = self->lastValue = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
-        self->pointerPos += inc;
+        if (pos > PI)
+            pos -= TWOPI;
+        y = b * pos + c * pos * MYFABS(pos);
+        self->data[i] = y + (y * MYFABS(y) - y) * 0.218;
+        pos += fr[i] * self->twoPiOnSr;
     }
+    self->pointerPos = pos;
 }
 
-static void SineLoop_postprocessing_ii(SineLoop *self) { POST_PROCESSING_II };
-static void SineLoop_postprocessing_ai(SineLoop *self) { POST_PROCESSING_AI };
-static void SineLoop_postprocessing_ia(SineLoop *self) { POST_PROCESSING_IA };
-static void SineLoop_postprocessing_aa(SineLoop *self) { POST_PROCESSING_AA };
-static void SineLoop_postprocessing_ireva(SineLoop *self) { POST_PROCESSING_IREVA };
-static void SineLoop_postprocessing_areva(SineLoop *self) { POST_PROCESSING_AREVA };
-static void SineLoop_postprocessing_revai(SineLoop *self) { POST_PROCESSING_REVAI };
-static void SineLoop_postprocessing_revaa(SineLoop *self) { POST_PROCESSING_REVAA };
-static void SineLoop_postprocessing_revareva(SineLoop *self) { POST_PROCESSING_REVAREVA };
+/*
+static void
+FastSine_readframes_low_i(FastSine *self) {
+    MYFLT inc, fr, pos;
+    int i;
+
+    fr = PyFloat_AS_DOUBLE(self->freq);
+    inc = fr * self->fourOnSr;
+
+    pos = self->pointerPos;
+    for (i=0; i<self->bufsize; i++) {
+        if (pos > 2.0)
+            pos -= 4.0;
+
+        if (pos < 0) {
+            self->data[i] = pos * (pos + 2.0);
+        }
+        else {
+            self->data[i] = pos * (2.0 - pos);
+        }
+        pos += inc;
+    }
+    self->pointerPos = pos;
+}
 
 static void
-SineLoop_setProcMode(SineLoop *self)
+FastSine_readframes_low_a(FastSine *self) {
+    MYFLT inc, pos;
+    int i;
+
+    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
+
+    pos = self->pointerPos;
+    for (i=0; i<self->bufsize; i++) {
+        inc = fr[i] * self->fourOnSr;
+        if (pos > 2.0)
+            pos -= 4.0;
+
+        if (pos < 0) {
+            self->data[i] = pos * (pos + 2.0);
+        }
+        else {
+            self->data[i] = pos * (2.0 - pos);
+        }
+        pos += inc;
+    }
+    self->pointerPos = pos;
+}
+
+static void
+FastSine_readframes_high_i(FastSine *self) {
+    MYFLT inc, fr, pos, sine;
+    int i;
+
+    fr = PyFloat_AS_DOUBLE(self->freq);
+    inc = fr * self->fourOnSr;
+
+    pos = self->pointerPos;
+    for (i=0; i<self->bufsize; i++) {
+        if (pos > 2.0)
+            pos -= 4.0;
+
+        if (pos < 0) {
+            sine = -pos * (pos + 2.0);
+            self->data[i] = -sine * (0.225 * (sine - 1) + 1);
+        }
+        else {
+            sine = pos * (2.0 - pos);
+            self->data[i] = sine * (0.225 * (sine - 1) + 1);
+        }
+        pos += inc;
+    }
+    self->pointerPos = pos;
+}
+
+static void
+FastSine_readframes_high_a(FastSine *self) {
+    MYFLT inc, pos, sine;
+    int i;
+
+    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
+
+    pos = self->pointerPos;
+    for (i=0; i<self->bufsize; i++) {
+        inc = fr[i] * self->fourOnSr;
+        if (pos > 2.0)
+            pos -= 4.0;
+
+        if (pos < 0) {
+            sine = -pos * (pos + 2.0);
+            self->data[i] = -sine * (0.225 * (sine - 1) + 1);
+        }
+        else {
+            sine = pos * (2.0 - pos);
+            self->data[i] = sine * (0.225 * (sine - 1) + 1);
+        }
+        pos += inc;
+    }
+    self->pointerPos = pos;
+}
+*/
+
+static void FastSine_postprocessing_ii(FastSine *self) { POST_PROCESSING_II };
+static void FastSine_postprocessing_ai(FastSine *self) { POST_PROCESSING_AI };
+static void FastSine_postprocessing_ia(FastSine *self) { POST_PROCESSING_IA };
+static void FastSine_postprocessing_aa(FastSine *self) { POST_PROCESSING_AA };
+static void FastSine_postprocessing_ireva(FastSine *self) { POST_PROCESSING_IREVA };
+static void FastSine_postprocessing_areva(FastSine *self) { POST_PROCESSING_AREVA };
+static void FastSine_postprocessing_revai(FastSine *self) { POST_PROCESSING_REVAI };
+static void FastSine_postprocessing_revaa(FastSine *self) { POST_PROCESSING_REVAA };
+static void FastSine_postprocessing_revareva(FastSine *self) { POST_PROCESSING_REVAREVA };
+
+static void
+FastSine_setProcMode(FastSine *self)
 {
     int procmode, muladdmode;
-    procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
+    procmode = self->modebuffer[2];
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:        
-            self->proc_func_ptr = SineLoop_readframes_ii;
-            break;
-        case 1:    
-            self->proc_func_ptr = SineLoop_readframes_ai;
+        case 0:
+            if (self->quality == 0)
+                self->proc_func_ptr = FastSine_readframes_low_i;
+            else if (self->quality == 1)
+                self->proc_func_ptr = FastSine_readframes_high_i;
             break;
-        case 10:    
-            self->proc_func_ptr = SineLoop_readframes_ia;
-            break;
-        case 11:    
-            self->proc_func_ptr = SineLoop_readframes_aa;
+        case 1:
+            if (self->quality == 0)
+                self->proc_func_ptr = FastSine_readframes_low_a;
+            else if (self->quality == 1)
+                self->proc_func_ptr = FastSine_readframes_high_a;
             break;
-    } 
-    
+    }
+
 	switch (muladdmode) {
-        case 0:        
-            self->muladd_func_ptr = SineLoop_postprocessing_ii;
+        case 0:
+            self->muladd_func_ptr = FastSine_postprocessing_ii;
             break;
-        case 1:    
-            self->muladd_func_ptr = SineLoop_postprocessing_ai;
+        case 1:
+            self->muladd_func_ptr = FastSine_postprocessing_ai;
             break;
-        case 2:    
-            self->muladd_func_ptr = SineLoop_postprocessing_revai;
+        case 2:
+            self->muladd_func_ptr = FastSine_postprocessing_revai;
             break;
-        case 10:        
-            self->muladd_func_ptr = SineLoop_postprocessing_ia;
+        case 10:
+            self->muladd_func_ptr = FastSine_postprocessing_ia;
             break;
-        case 11:    
-            self->muladd_func_ptr = SineLoop_postprocessing_aa;
+        case 11:
+            self->muladd_func_ptr = FastSine_postprocessing_aa;
             break;
-        case 12:    
-            self->muladd_func_ptr = SineLoop_postprocessing_revaa;
+        case 12:
+            self->muladd_func_ptr = FastSine_postprocessing_revaa;
             break;
-        case 20:        
-            self->muladd_func_ptr = SineLoop_postprocessing_ireva;
+        case 20:
+            self->muladd_func_ptr = FastSine_postprocessing_ireva;
             break;
-        case 21:    
-            self->muladd_func_ptr = SineLoop_postprocessing_areva;
+        case 21:
+            self->muladd_func_ptr = FastSine_postprocessing_areva;
             break;
-        case 22:    
-            self->muladd_func_ptr = SineLoop_postprocessing_revareva;
+        case 22:
+            self->muladd_func_ptr = FastSine_postprocessing_revareva;
             break;
     }
 }
 
 static void
-SineLoop_compute_next_data_frame(SineLoop *self)
+FastSine_compute_next_data_frame(FastSine *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
 static int
-SineLoop_traverse(SineLoop *self, visitproc visit, void *arg)
+FastSine_traverse(FastSine *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
-    Py_VISIT(self->feedback);    
-    Py_VISIT(self->feedback_stream);    
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
     return 0;
 }
 
-static int 
-SineLoop_clear(SineLoop *self)
+static int
+FastSine_clear(FastSine *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
-    Py_CLEAR(self->feedback);    
-    Py_CLEAR(self->feedback_stream);    
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
     return 0;
 }
 
 static void
-SineLoop_dealloc(SineLoop* self)
+FastSine_dealloc(FastSine* self)
 {
     pyo_DEALLOC
-    SineLoop_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    FastSine_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
-SineLoop_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+FastSine_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
-    PyObject *freqtmp=NULL, *feedbacktmp=NULL, *multmp=NULL, *addtmp=NULL;
-    SineLoop *self;
-    self = (SineLoop *)type->tp_alloc(type, 0);
-    
+    PyObject *freqtmp=NULL, *multmp=NULL, *addtmp=NULL;
+
+    FastSine *self;
+    self = (FastSine *)type->tp_alloc(type, 0);
+
     self->freq = PyFloat_FromDouble(1000);
-    self->feedback = PyFloat_FromDouble(0.0);
+    self->initphase = 0.0;
+    self->quality = 1;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
-	self->modebuffer[3] = 0;
-    self->pointerPos = self->lastValue = 0.;
-    
+
     INIT_OBJECT_COMMON
-    Stream_setFunctionPtr(self->stream, SineLoop_compute_next_data_frame);
-    self->mode_func_ptr = SineLoop_setProcMode;
+    Stream_setFunctionPtr(self->stream, FastSine_compute_next_data_frame);
+    self->mode_func_ptr = FastSine_setProcMode;
 
-    static char *kwlist[] = {"freq", "feedback", "mul", "add", NULL};
+    self->twoPiOnSr = TWOPI / self->sr;
+    self->B = 4.0 / PI;
+    self->C = -4.0 / (PI * PI);
     
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &freqtmp, &feedbacktmp, &multmp, &addtmp))
+    static char *kwlist[] = {"freq", "initphase", "quality", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__OFIOO, kwlist, &freqtmp, &self->initphase, &self->quality, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
+    if (self->initphase < 0.0)
+        self->initphase = 0.0;
+    else if (self->initphase > 1.0)
+        self->initphase = 1.0;
+    self->pointerPos = self->initphase * TWOPI;
+
+    if (self->quality < 0)
+        self->quality = 0;
+    else if (self->quality > 1)
+        self->quality = 1;
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    
-    if (feedbacktmp) {
-        PyObject_CallMethod((PyObject *)self, "setFeedback", "O", feedbacktmp);
-    }
-    
+
     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 * SineLoop_getServer(SineLoop* self) { GET_SERVER };
-static PyObject * SineLoop_getStream(SineLoop* self) { GET_STREAM };
-static PyObject * SineLoop_setMul(SineLoop *self, PyObject *arg) { SET_MUL };	
-static PyObject * SineLoop_setAdd(SineLoop *self, PyObject *arg) { SET_ADD };	
-static PyObject * SineLoop_setSub(SineLoop *self, PyObject *arg) { SET_SUB };	
-static PyObject * SineLoop_setDiv(SineLoop *self, PyObject *arg) { SET_DIV };	
+static PyObject * FastSine_getServer(FastSine* self) { GET_SERVER };
+static PyObject * FastSine_getStream(FastSine* self) { GET_STREAM };
+static PyObject * FastSine_setMul(FastSine *self, PyObject *arg) { SET_MUL };
+static PyObject * FastSine_setAdd(FastSine *self, PyObject *arg) { SET_ADD };
+static PyObject * FastSine_setSub(FastSine *self, PyObject *arg) { SET_SUB };
+static PyObject * FastSine_setDiv(FastSine *self, PyObject *arg) { SET_DIV };
 
-static PyObject * SineLoop_play(SineLoop *self, PyObject *args, PyObject *kwds) { PLAY };
-static PyObject * SineLoop_out(SineLoop *self, PyObject *args, PyObject *kwds) { OUT };
-static PyObject * SineLoop_stop(SineLoop *self) { STOP };
+static PyObject * FastSine_play(FastSine *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * FastSine_out(FastSine *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * FastSine_stop(FastSine *self) { STOP };
 
-static PyObject * SineLoop_multiply(SineLoop *self, PyObject *arg) { MULTIPLY };
-static PyObject * SineLoop_inplace_multiply(SineLoop *self, PyObject *arg) { INPLACE_MULTIPLY };
-static PyObject * SineLoop_add(SineLoop *self, PyObject *arg) { ADD };
-static PyObject * SineLoop_inplace_add(SineLoop *self, PyObject *arg) { INPLACE_ADD };
-static PyObject * SineLoop_sub(SineLoop *self, PyObject *arg) { SUB };
-static PyObject * SineLoop_inplace_sub(SineLoop *self, PyObject *arg) { INPLACE_SUB };
-static PyObject * SineLoop_div(SineLoop *self, PyObject *arg) { DIV };
-static PyObject * SineLoop_inplace_div(SineLoop *self, PyObject *arg) { INPLACE_DIV };
+static PyObject * FastSine_multiply(FastSine *self, PyObject *arg) { MULTIPLY };
+static PyObject * FastSine_inplace_multiply(FastSine *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * FastSine_add(FastSine *self, PyObject *arg) { ADD };
+static PyObject * FastSine_inplace_add(FastSine *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * FastSine_sub(FastSine *self, PyObject *arg) { SUB };
+static PyObject * FastSine_inplace_sub(FastSine *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * FastSine_div(FastSine *self, PyObject *arg) { DIV };
+static PyObject * FastSine_inplace_div(FastSine *self, PyObject *arg) { INPLACE_DIV };
 
 static PyObject *
-SineLoop_setFreq(SineLoop *self, PyObject *arg)
+FastSine_setFreq(FastSine *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -800,430 +904,374 @@ SineLoop_setFreq(SineLoop *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
-SineLoop_setFeedback(SineLoop *self, PyObject *arg)
+FastSine_setQuality(FastSine *self, PyObject *arg)
 {
-	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	int isNumber = PyNumber_Check(arg);
-	
-	tmp = arg;
-	Py_INCREF(tmp);
-	Py_DECREF(self->feedback);
-	if (isNumber == 1) {
-		self->feedback = PyNumber_Float(tmp);
-        self->modebuffer[3] = 0;
-	}
-	else {
-		self->feedback = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->feedback, "_getStream", NULL);
-        Py_INCREF(streamtmp);
-        Py_XDECREF(self->feedback_stream);
-        self->feedback_stream = (Stream *)streamtmp;
-		self->modebuffer[3] = 1;
+    int tmp;
+    ASSERT_ARG_NOT_NULL
+
+	if (PyInt_Check(arg)) {
+        tmp = PyInt_AsLong(arg);
+        if (tmp >= 0 && tmp < 2)
+            self->quality = tmp;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
-static PyMemberDef SineLoop_members[] = {
-	{"server", T_OBJECT_EX, offsetof(SineLoop, server), 0, "Pyo server."},
-	{"stream", T_OBJECT_EX, offsetof(SineLoop, stream), 0, "Stream object."},
-	{"freq", T_OBJECT_EX, offsetof(SineLoop, freq), 0, "Frequency in cycle per second."},
-	{"feedback", T_OBJECT_EX, offsetof(SineLoop, feedback), 0, "Phase of signal (0 -> 1)"},
-	{"mul", T_OBJECT_EX, offsetof(SineLoop, mul), 0, "Mul factor."},
-	{"add", T_OBJECT_EX, offsetof(SineLoop, add), 0, "Add factor."},
-	{NULL}  /* Sentinel */
-};
+static PyObject *
+FastSine_reset(FastSine *self)
+{
+    self->pointerPos = self->initphase * TWOPI;
+    Py_INCREF(Py_None);
+    return Py_None;
+}
 
-static PyMethodDef SineLoop_methods[] = {
-	{"getServer", (PyCFunction)SineLoop_getServer, METH_NOARGS, "Returns server object."},
-	{"_getStream", (PyCFunction)SineLoop_getStream, METH_NOARGS, "Returns stream object."},
-	{"play", (PyCFunction)SineLoop_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
-	{"out", (PyCFunction)SineLoop_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
-	{"stop", (PyCFunction)SineLoop_stop, METH_NOARGS, "Stops computing."},
-	{"setFreq", (PyCFunction)SineLoop_setFreq, METH_O, "Sets oscillator frequency in cycle per second."},
-	{"setFeedback", (PyCFunction)SineLoop_setFeedback, METH_O, "Sets oscillator feedback between 0 and 1."},
-	{"setMul", (PyCFunction)SineLoop_setMul, METH_O, "Sets SineLoop mul factor."},
-	{"setAdd", (PyCFunction)SineLoop_setAdd, METH_O, "Sets SineLoop add factor."},
-	{"setSub", (PyCFunction)SineLoop_setSub, METH_O, "Sets inverse add factor."},
-	{"setDiv", (PyCFunction)SineLoop_setDiv, METH_O, "Sets inverse mul factor."},
-	{NULL}  /* Sentinel */
+static PyMemberDef FastSine_members[] = {
+{"server", T_OBJECT_EX, offsetof(FastSine, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(FastSine, stream), 0, "Stream object."},
+{"freq", T_OBJECT_EX, offsetof(FastSine, freq), 0, "Frequency in cycle per second."},
+{"mul", T_OBJECT_EX, offsetof(FastSine, mul), 0, "Mul factor."},
+{"add", T_OBJECT_EX, offsetof(FastSine, add), 0, "Add factor."},
+{NULL}  /* Sentinel */
 };
 
-static PyNumberMethods SineLoop_as_number = {
-	(binaryfunc)SineLoop_add,                      /*nb_add*/
-	(binaryfunc)SineLoop_sub,                 /*nb_subtract*/
-	(binaryfunc)SineLoop_multiply,                 /*nb_multiply*/
-	(binaryfunc)SineLoop_div,                   /*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*/
-	0,                                          /*nb_coerce*/
-	0,                       /*nb_int*/
-	0,                      /*nb_long*/
-	0,                     /*nb_float*/
-	0,                       /*nb_oct*/
-	0,                       /*nb_hex*/
-	(binaryfunc)SineLoop_inplace_add,              /*inplace_add*/
-	(binaryfunc)SineLoop_inplace_sub,         /*inplace_subtract*/
-	(binaryfunc)SineLoop_inplace_multiply,         /*inplace_multiply*/
-	(binaryfunc)SineLoop_inplace_div,           /*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*/
-	0,              /*nb_true_divide*/
-	0,     /*nb_inplace_floor_divide*/
-	0,      /*nb_inplace_true_divide*/
-	0,                     /* nb_index */
+static PyMethodDef FastSine_methods[] = {
+{"getServer", (PyCFunction)FastSine_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)FastSine_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)FastSine_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"out", (PyCFunction)FastSine_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+{"stop", (PyCFunction)FastSine_stop, METH_NOARGS, "Stops computing."},
+{"setFreq", (PyCFunction)FastSine_setFreq, METH_O, "Sets oscillator frequency in cycle per second."},
+{"setQuality", (PyCFunction)FastSine_setQuality, METH_O, "Sets approximation quality."},
+{"reset", (PyCFunction)FastSine_reset, METH_NOARGS, "Resets pointer position to 0."},
+{"setMul", (PyCFunction)FastSine_setMul, METH_O, "Sets FastSine mul factor."},
+{"setAdd", (PyCFunction)FastSine_setAdd, METH_O, "Sets FastSine add factor."},
+{"setSub", (PyCFunction)FastSine_setSub, METH_O, "Sets inverse add factor."},
+{"setDiv", (PyCFunction)FastSine_setDiv, METH_O, "Sets inverse mul factor."},
+{NULL}  /* Sentinel */
 };
 
-PyTypeObject SineLoopType = {
-	PyObject_HEAD_INIT(NULL)
-	0,                         /*ob_size*/
-	"_pyo.SineLoop_base",         /*tp_name*/
-	sizeof(SineLoop),         /*tp_basicsize*/
-	0,                         /*tp_itemsize*/
-	(destructor)SineLoop_dealloc, /*tp_dealloc*/
-	0,                         /*tp_print*/
-	0,                         /*tp_getattr*/
-	0,                         /*tp_setattr*/
-	0,                         /*tp_compare*/
-	0,                         /*tp_repr*/
-	&SineLoop_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*/
-	"SineLoop objects. Generates a looped sinewave.",           /* tp_doc */
-	(traverseproc)SineLoop_traverse,   /* tp_traverse */
-	(inquiry)SineLoop_clear,           /* tp_clear */
-	0,		               /* tp_richcompare */
-	0,		               /* tp_weaklistoffset */
-	0,		               /* tp_iter */
-	0,		               /* tp_iternext */
-	SineLoop_methods,             /* tp_methods */
-	SineLoop_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 */
-	SineLoop_new,                 /* tp_new */
+static PyNumberMethods FastSine_as_number = {
+(binaryfunc)FastSine_add,                      /*nb_add*/
+(binaryfunc)FastSine_sub,                 /*nb_subtract*/
+(binaryfunc)FastSine_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)FastSine_inplace_add,              /*inplace_add*/
+(binaryfunc)FastSine_inplace_sub,         /*inplace_subtract*/
+(binaryfunc)FastSine_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)FastSine_div,                       /*nb_true_divide*/
+0,     /*nb_inplace_floor_divide*/
+(binaryfunc)FastSine_inplace_div,                       /*nb_inplace_true_divide*/
+0,                     /* nb_index */
 };
 
-/***************/
-/* Osc objects */
-/***************/
-static double
-Osc_clip(double x, int size) {
-    if (x < 0) {
-        x += ((int)(-x / size) + 1) * size;
-    }
-    else if (x >= size) {
-        x -= (int)(x / size) * size;
-    }
-    return x;
-}
+PyTypeObject FastSineType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.FastSine_base",         /*tp_name*/
+sizeof(FastSine),         /*tp_basicsize*/
+0,                         /*tp_itemsize*/
+(destructor)FastSine_dealloc, /*tp_dealloc*/
+0,                         /*tp_print*/
+0,                         /*tp_getattr*/
+0,                         /*tp_setattr*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
+0,                         /*tp_repr*/
+&FastSine_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*/
+"FastSine objects. Generates a sinewave.",           /* tp_doc */
+(traverseproc)FastSine_traverse,   /* tp_traverse */
+(inquiry)FastSine_clear,           /* tp_clear */
+0,		               /* tp_richcompare */
+0,		               /* tp_weaklistoffset */
+0,		               /* tp_iter */
+0,		               /* tp_iternext */
+FastSine_methods,             /* tp_methods */
+FastSine_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 */
+FastSine_new,                 /* tp_new */
+};
 
+/*******************/
+/* SineLoop object */
+/*******************/
 typedef struct {
     pyo_audio_HEAD
-    PyObject *table;
     PyObject *freq;
     Stream *freq_stream;
-    PyObject *phase;
-    Stream *phase_stream;
+    PyObject *feedback;
+    Stream *feedback_stream;
     int modebuffer[4];
-    double pointerPos;
-    int interp; /* 0 = default to 2, 1 = nointerp, 2 = linear, 3 = cos, 4 = cubic */
-    MYFLT (*interp_func_ptr)(MYFLT *, int, MYFLT, int);
-} Osc;
+    MYFLT pointerPos;
+    MYFLT lastValue;
+} SineLoop;
 
 static void
-Osc_readframes_ii(Osc *self) {
-    MYFLT fr, ph, fpart;
-    double inc, pos;
+SineLoop_readframes_ii(SineLoop *self) {
+    MYFLT inc, fr, feed, pos, fpart;
     int i, ipart;
-    MYFLT *tablelist = TableStream_getData(self->table);
-    int size = TableStream_getSize(self->table);
 
     fr = PyFloat_AS_DOUBLE(self->freq);
-    ph = PyFloat_AS_DOUBLE(self->phase);
-    inc = fr * size / self->sr;
+    feed = _clip(PyFloat_AS_DOUBLE(self->feedback)) * 512;
+    inc = fr * 512 / self->sr;
 
-    ph *= size;
     for (i=0; i<self->bufsize; i++) {
-        self->pointerPos += inc;
-        self->pointerPos = Osc_clip(self->pointerPos, size);
-        pos = self->pointerPos + ph;
-        if (pos >= size)
-            pos -= size;
+        self->pointerPos = Sine_clip(self->pointerPos);
+        pos = Sine_clip(self->pointerPos + self->lastValue * feed);
         ipart = (int)pos;
         fpart = pos - ipart;
-        self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
+        self->data[i] = self->lastValue = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
+        self->pointerPos += inc;
     }
 }
 
 static void
-Osc_readframes_ai(Osc *self) {
-    MYFLT ph, fpart, sizeOnSr;
-    double inc, pos;
+SineLoop_readframes_ai(SineLoop *self) {
+    MYFLT inc, feed, pos, fpart, fac;
     int i, ipart;
-    MYFLT *tablelist = TableStream_getData(self->table);
-    int size = TableStream_getSize(self->table);
-    
+
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    ph = PyFloat_AS_DOUBLE(self->phase);
-    ph *= size;
-    
-    sizeOnSr = size / self->sr;
+    feed = _clip(PyFloat_AS_DOUBLE(self->feedback)) * 512;
+
+    fac = 512 / self->sr;
     for (i=0; i<self->bufsize; i++) {
-        inc = fr[i] * sizeOnSr;
-        self->pointerPos += inc;
-        self->pointerPos = Osc_clip(self->pointerPos, size);
-        pos = self->pointerPos + ph;
-        if (pos >= size)
-            pos -= size;
+        inc = fr[i] * fac;
+        self->pointerPos = Sine_clip(self->pointerPos);
+        pos = Sine_clip(self->pointerPos + self->lastValue * feed);
         ipart = (int)pos;
         fpart = pos - ipart;
-        self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
+        self->data[i] = self->lastValue = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
+        self->pointerPos += inc;
     }
 }
 
 static void
-Osc_readframes_ia(Osc *self) {
-    MYFLT fr, pha, fpart;
-    double inc, pos;
+SineLoop_readframes_ia(SineLoop *self) {
+    MYFLT inc, fr, feed, pos, fpart;
     int i, ipart;
-    MYFLT *tablelist = TableStream_getData(self->table);
-    int size = TableStream_getSize(self->table);
-    
+
     fr = PyFloat_AS_DOUBLE(self->freq);
-    MYFLT *ph = Stream_getData((Stream *)self->phase_stream);
-    inc = fr * size / self->sr;
-    
+    MYFLT *fd = Stream_getData((Stream *)self->feedback_stream);
+    inc = fr * 512 / self->sr;
+
     for (i=0; i<self->bufsize; i++) {
-        pha = ph[i] * size;
-        self->pointerPos += inc;
-        self->pointerPos = Osc_clip(self->pointerPos, size);
-        pos = self->pointerPos + pha;
-        if (pos >= size)
-            pos -= size;
+        feed = _clip(fd[i]) * 512;
+        self->pointerPos = Sine_clip(self->pointerPos);
+        pos = Sine_clip(self->pointerPos + self->lastValue * feed);
         ipart = (int)pos;
         fpart = pos - ipart;
-        self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
+        self->data[i] = self->lastValue = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
+        self->pointerPos += inc;
     }
 }
 
 static void
-Osc_readframes_aa(Osc *self) {
-    MYFLT pha, fpart, sizeOnSr;
-    double inc, pos;
+SineLoop_readframes_aa(SineLoop *self) {
+    MYFLT inc, feed, pos, fpart, fac;
     int i, ipart;
-    MYFLT *tablelist = TableStream_getData(self->table);
-    int size = TableStream_getSize(self->table);
-    
+
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    MYFLT *ph = Stream_getData((Stream *)self->phase_stream);
+    MYFLT *fd = Stream_getData((Stream *)self->feedback_stream);
 
-    sizeOnSr = size / self->sr;
+    fac = 512 / self->sr;
     for (i=0; i<self->bufsize; i++) {
-        inc = fr[i] * sizeOnSr;
-        pha = ph[i] * size;
-        self->pointerPos += inc;
-        self->pointerPos = Osc_clip(self->pointerPos, size);
-        pos = self->pointerPos + pha;
-        if (pos >= size)
-            pos -= size;
+        inc = fr[i] * fac;
+        feed = _clip(fd[i]) * 512;
+        self->pointerPos = Sine_clip(self->pointerPos);
+        pos = Sine_clip(self->pointerPos + self->lastValue * feed);
         ipart = (int)pos;
         fpart = pos - ipart;
-        self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
+        self->data[i] = self->lastValue = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
+        self->pointerPos += inc;
     }
 }
 
-static void Osc_postprocessing_ii(Osc *self) { POST_PROCESSING_II };
-static void Osc_postprocessing_ai(Osc *self) { POST_PROCESSING_AI };
-static void Osc_postprocessing_ia(Osc *self) { POST_PROCESSING_IA };
-static void Osc_postprocessing_aa(Osc *self) { POST_PROCESSING_AA };
-static void Osc_postprocessing_ireva(Osc *self) { POST_PROCESSING_IREVA };
-static void Osc_postprocessing_areva(Osc *self) { POST_PROCESSING_AREVA };
-static void Osc_postprocessing_revai(Osc *self) { POST_PROCESSING_REVAI };
-static void Osc_postprocessing_revaa(Osc *self) { POST_PROCESSING_REVAA };
-static void Osc_postprocessing_revareva(Osc *self) { POST_PROCESSING_REVAREVA };
+static void SineLoop_postprocessing_ii(SineLoop *self) { POST_PROCESSING_II };
+static void SineLoop_postprocessing_ai(SineLoop *self) { POST_PROCESSING_AI };
+static void SineLoop_postprocessing_ia(SineLoop *self) { POST_PROCESSING_IA };
+static void SineLoop_postprocessing_aa(SineLoop *self) { POST_PROCESSING_AA };
+static void SineLoop_postprocessing_ireva(SineLoop *self) { POST_PROCESSING_IREVA };
+static void SineLoop_postprocessing_areva(SineLoop *self) { POST_PROCESSING_AREVA };
+static void SineLoop_postprocessing_revai(SineLoop *self) { POST_PROCESSING_REVAI };
+static void SineLoop_postprocessing_revaa(SineLoop *self) { POST_PROCESSING_REVAA };
+static void SineLoop_postprocessing_revareva(SineLoop *self) { POST_PROCESSING_REVAREVA };
 
 static void
-Osc_setProcMode(Osc *self)
+SineLoop_setProcMode(SineLoop *self)
 {
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:        
-            self->proc_func_ptr = Osc_readframes_ii;
+        case 0:
+            self->proc_func_ptr = SineLoop_readframes_ii;
             break;
-        case 1:    
-            self->proc_func_ptr = Osc_readframes_ai;
+        case 1:
+            self->proc_func_ptr = SineLoop_readframes_ai;
             break;
-        case 10:        
-            self->proc_func_ptr = Osc_readframes_ia;
+        case 10:
+            self->proc_func_ptr = SineLoop_readframes_ia;
             break;
-        case 11:    
-            self->proc_func_ptr = Osc_readframes_aa;
+        case 11:
+            self->proc_func_ptr = SineLoop_readframes_aa;
             break;
-    } 
+    }
+
 	switch (muladdmode) {
-        case 0:        
-            self->muladd_func_ptr = Osc_postprocessing_ii;
+        case 0:
+            self->muladd_func_ptr = SineLoop_postprocessing_ii;
             break;
-        case 1:    
-            self->muladd_func_ptr = Osc_postprocessing_ai;
+        case 1:
+            self->muladd_func_ptr = SineLoop_postprocessing_ai;
             break;
-        case 2:    
-            self->muladd_func_ptr = Osc_postprocessing_revai;
+        case 2:
+            self->muladd_func_ptr = SineLoop_postprocessing_revai;
             break;
-        case 10:        
-            self->muladd_func_ptr = Osc_postprocessing_ia;
+        case 10:
+            self->muladd_func_ptr = SineLoop_postprocessing_ia;
             break;
-        case 11:    
-            self->muladd_func_ptr = Osc_postprocessing_aa;
+        case 11:
+            self->muladd_func_ptr = SineLoop_postprocessing_aa;
             break;
-        case 12:    
-            self->muladd_func_ptr = Osc_postprocessing_revaa;
+        case 12:
+            self->muladd_func_ptr = SineLoop_postprocessing_revaa;
             break;
-        case 20:        
-            self->muladd_func_ptr = Osc_postprocessing_ireva;
+        case 20:
+            self->muladd_func_ptr = SineLoop_postprocessing_ireva;
             break;
-        case 21:    
-            self->muladd_func_ptr = Osc_postprocessing_areva;
+        case 21:
+            self->muladd_func_ptr = SineLoop_postprocessing_areva;
             break;
-        case 22:    
-            self->muladd_func_ptr = Osc_postprocessing_revareva;
+        case 22:
+            self->muladd_func_ptr = SineLoop_postprocessing_revareva;
             break;
-    } 
+    }
 }
 
 static void
-Osc_compute_next_data_frame(Osc *self)
+SineLoop_compute_next_data_frame(SineLoop *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
 static int
-Osc_traverse(Osc *self, visitproc visit, void *arg)
+SineLoop_traverse(SineLoop *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->table);
-    Py_VISIT(self->phase);    
-    Py_VISIT(self->phase_stream);    
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->feedback);
+    Py_VISIT(self->feedback_stream);
     return 0;
 }
 
-static int 
-Osc_clear(Osc *self)
+static int
+SineLoop_clear(SineLoop *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->table);
-    Py_CLEAR(self->phase);    
-    Py_CLEAR(self->phase_stream);    
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->feedback);
+    Py_CLEAR(self->feedback_stream);
     return 0;
 }
 
 static void
-Osc_dealloc(Osc* self)
+SineLoop_dealloc(SineLoop* self)
 {
     pyo_DEALLOC
-    Osc_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    SineLoop_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
-Osc_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+SineLoop_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
-    PyObject *tabletmp, *freqtmp=NULL, *phasetmp=NULL, *multmp=NULL, *addtmp=NULL;
-    Osc *self;
-    self = (Osc *)type->tp_alloc(type, 0);
+    PyObject *freqtmp=NULL, *feedbacktmp=NULL, *multmp=NULL, *addtmp=NULL;
+    SineLoop *self;
+    self = (SineLoop *)type->tp_alloc(type, 0);
 
     self->freq = PyFloat_FromDouble(1000);
-    self->phase = PyFloat_FromDouble(0);
+    self->feedback = PyFloat_FromDouble(0.0);
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
-    self->pointerPos = 0.;
-    self->interp = 2;
+    self->pointerPos = self->lastValue = 0.;
 
     INIT_OBJECT_COMMON
-    Stream_setFunctionPtr(self->stream, Osc_compute_next_data_frame);
-    self->mode_func_ptr = Osc_setProcMode;
+    Stream_setFunctionPtr(self->stream, SineLoop_compute_next_data_frame);
+    self->mode_func_ptr = SineLoop_setProcMode;
 
-    static char *kwlist[] = {"table", "freq", "phase", "interp", "mul", "add", NULL};
+    static char *kwlist[] = {"freq", "feedback", "mul", "add", NULL};
 
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOiOO", kwlist, &tabletmp, &freqtmp, &phasetmp, &self->interp, &multmp, &addtmp))
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &freqtmp, &feedbacktmp, &multmp, &addtmp))
         Py_RETURN_NONE;
 
-    if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
-        PySys_WriteStderr("TypeError: \"table\" argument of Osc must be a PyoTableObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
-    }
-    Py_XDECREF(self->table);
-    self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", "");
-    
-    if (phasetmp) {
-        PyObject_CallMethod((PyObject *)self, "setPhase", "O", phasetmp);
-    }
-
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    
+
+    if (feedbacktmp) {
+        PyObject_CallMethod((PyObject *)self, "setFeedback", "O", feedbacktmp);
+    }
+
     if (multmp) {
         PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
     }
@@ -1231,73 +1279,43 @@ Osc_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (addtmp) {
         PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
     }
-            
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     (*self->mode_func_ptr)(self);
 
-    SET_INTERP_POINTER
-
     return (PyObject *)self;
 }
 
-static PyObject * Osc_getServer(Osc* self) { GET_SERVER };
-static PyObject * Osc_getStream(Osc* self) { GET_STREAM };
-static PyObject * Osc_setMul(Osc *self, PyObject *arg) { SET_MUL };	
-static PyObject * Osc_setAdd(Osc *self, PyObject *arg) { SET_ADD };	
-static PyObject * Osc_setSub(Osc *self, PyObject *arg) { SET_SUB };	
-static PyObject * Osc_setDiv(Osc *self, PyObject *arg) { SET_DIV };	
-
-static PyObject * Osc_play(Osc *self, PyObject *args, PyObject *kwds) { PLAY };
-static PyObject * Osc_out(Osc *self, PyObject *args, PyObject *kwds) { OUT };
-static PyObject * Osc_stop(Osc *self) { STOP };
+static PyObject * SineLoop_getServer(SineLoop* self) { GET_SERVER };
+static PyObject * SineLoop_getStream(SineLoop* self) { GET_STREAM };
+static PyObject * SineLoop_setMul(SineLoop *self, PyObject *arg) { SET_MUL };
+static PyObject * SineLoop_setAdd(SineLoop *self, PyObject *arg) { SET_ADD };
+static PyObject * SineLoop_setSub(SineLoop *self, PyObject *arg) { SET_SUB };
+static PyObject * SineLoop_setDiv(SineLoop *self, PyObject *arg) { SET_DIV };
 
-static PyObject * Osc_multiply(Osc *self, PyObject *arg) { MULTIPLY };
-static PyObject * Osc_inplace_multiply(Osc *self, PyObject *arg) { INPLACE_MULTIPLY };
-static PyObject * Osc_add(Osc *self, PyObject *arg) { ADD };
-static PyObject * Osc_inplace_add(Osc *self, PyObject *arg) { INPLACE_ADD };
-static PyObject * Osc_sub(Osc *self, PyObject *arg) { SUB };
-static PyObject * Osc_inplace_sub(Osc *self, PyObject *arg) { INPLACE_SUB };
-static PyObject * Osc_div(Osc *self, PyObject *arg) { DIV };
-static PyObject * Osc_inplace_div(Osc *self, PyObject *arg) { INPLACE_DIV };
+static PyObject * SineLoop_play(SineLoop *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * SineLoop_out(SineLoop *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * SineLoop_stop(SineLoop *self) { STOP };
 
-static PyObject *
-Osc_getTable(Osc* self)
-{
-    Py_INCREF(self->table);
-    return self->table;
-};
+static PyObject * SineLoop_multiply(SineLoop *self, PyObject *arg) { MULTIPLY };
+static PyObject * SineLoop_inplace_multiply(SineLoop *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * SineLoop_add(SineLoop *self, PyObject *arg) { ADD };
+static PyObject * SineLoop_inplace_add(SineLoop *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * SineLoop_sub(SineLoop *self, PyObject *arg) { SUB };
+static PyObject * SineLoop_inplace_sub(SineLoop *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * SineLoop_div(SineLoop *self, PyObject *arg) { DIV };
+static PyObject * SineLoop_inplace_div(SineLoop *self, PyObject *arg) { INPLACE_DIV };
 
 static PyObject *
-Osc_setTable(Osc *self, PyObject *arg)
+SineLoop_setFreq(SineLoop *self, PyObject *arg)
 {
-	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
+	PyObject *tmp, *streamtmp;
 
-	tmp = arg;
-	Py_DECREF(self->table);
-    self->table = PyObject_CallMethod((PyObject *)tmp, "getTableStream", "");
-    
-	Py_INCREF(Py_None);
-	return Py_None;
-}	
+    ASSERT_ARG_NOT_NULL
 
-static PyObject *
-Osc_setFreq(Osc *self, PyObject *arg)
-{
-	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -1313,524 +1331,491 @@ Osc_setFreq(Osc *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
-Osc_setPhase(Osc *self, PyObject *arg)
+SineLoop_setFeedback(SineLoop *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
-	Py_DECREF(self->phase);
+	Py_DECREF(self->feedback);
 	if (isNumber == 1) {
-		self->phase = PyNumber_Float(tmp);
+		self->feedback = PyNumber_Float(tmp);
         self->modebuffer[3] = 0;
 	}
 	else {
-		self->phase = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->phase, "_getStream", NULL);
+		self->feedback = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->feedback, "_getStream", NULL);
         Py_INCREF(streamtmp);
-        Py_XDECREF(self->phase_stream);
-        self->phase_stream = (Stream *)streamtmp;
+        Py_XDECREF(self->feedback_stream);
+        self->feedback_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
-
-static PyObject *
-Osc_setInterp(Osc *self, PyObject *arg)
-{
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-    int isNumber = PyNumber_Check(arg);
-    
-	if (isNumber == 1) {
-		self->interp = PyInt_AsLong(PyNumber_Int(arg));
-    }  
-    
-    SET_INTERP_POINTER
-    
-    Py_INCREF(Py_None);
-    return Py_None;
 }
 
-static PyObject * 
-Osc_reset(Osc *self) 
-{
-    self->pointerPos = 0.0;
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyMemberDef Osc_members[] = {
-    {"server", T_OBJECT_EX, offsetof(Osc, server), 0, "Pyo server."},
-    {"stream", T_OBJECT_EX, offsetof(Osc, stream), 0, "Stream object."},
-    {"table", T_OBJECT_EX, offsetof(Osc, table), 0, "Waveform table."},
-    {"freq", T_OBJECT_EX, offsetof(Osc, freq), 0, "Frequency in cycle per second."},
-    {"phase", T_OBJECT_EX, offsetof(Osc, phase), 0, "Oscillator phase."},
-    {"mul", T_OBJECT_EX, offsetof(Osc, mul), 0, "Mul factor."},
-    {"add", T_OBJECT_EX, offsetof(Osc, add), 0, "Add factor."},
-    {NULL}  /* Sentinel */
+static PyMemberDef SineLoop_members[] = {
+	{"server", T_OBJECT_EX, offsetof(SineLoop, server), 0, "Pyo server."},
+	{"stream", T_OBJECT_EX, offsetof(SineLoop, stream), 0, "Stream object."},
+	{"freq", T_OBJECT_EX, offsetof(SineLoop, freq), 0, "Frequency in cycle per second."},
+	{"feedback", T_OBJECT_EX, offsetof(SineLoop, feedback), 0, "Phase of signal (0 -> 1)"},
+	{"mul", T_OBJECT_EX, offsetof(SineLoop, mul), 0, "Mul factor."},
+	{"add", T_OBJECT_EX, offsetof(SineLoop, add), 0, "Add factor."},
+	{NULL}  /* Sentinel */
 };
 
-static PyMethodDef Osc_methods[] = {
-    {"getTable", (PyCFunction)Osc_getTable, METH_NOARGS, "Returns waveform table object."},
-    {"getServer", (PyCFunction)Osc_getServer, METH_NOARGS, "Returns server object."},
-    {"_getStream", (PyCFunction)Osc_getStream, METH_NOARGS, "Returns stream object."},
-    {"play", (PyCFunction)Osc_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
-    {"out", (PyCFunction)Osc_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
-    {"stop", (PyCFunction)Osc_stop, METH_NOARGS, "Stops computing."},
-    {"setTable", (PyCFunction)Osc_setTable, METH_O, "Sets oscillator table."},
-	{"setFreq", (PyCFunction)Osc_setFreq, METH_O, "Sets oscillator frequency in cycle per second."},
-    {"setPhase", (PyCFunction)Osc_setPhase, METH_O, "Sets oscillator phase."},
-    {"setInterp", (PyCFunction)Osc_setInterp, METH_O, "Sets oscillator interpolation mode."},
-    {"reset", (PyCFunction)Osc_reset, METH_NOARGS, "Resets pointer position to 0."},
-	{"setMul", (PyCFunction)Osc_setMul, METH_O, "Sets oscillator mul factor."},
-	{"setAdd", (PyCFunction)Osc_setAdd, METH_O, "Sets oscillator add factor."},
-    {"setSub", (PyCFunction)Osc_setSub, METH_O, "Sets oscillator inverse add factor."},
-    {"setDiv", (PyCFunction)Osc_setDiv, METH_O, "Sets inverse mul factor."},
-    {NULL}  /* Sentinel */
+static PyMethodDef SineLoop_methods[] = {
+	{"getServer", (PyCFunction)SineLoop_getServer, METH_NOARGS, "Returns server object."},
+	{"_getStream", (PyCFunction)SineLoop_getStream, METH_NOARGS, "Returns stream object."},
+	{"play", (PyCFunction)SineLoop_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+	{"out", (PyCFunction)SineLoop_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+	{"stop", (PyCFunction)SineLoop_stop, METH_NOARGS, "Stops computing."},
+	{"setFreq", (PyCFunction)SineLoop_setFreq, METH_O, "Sets oscillator frequency in cycle per second."},
+	{"setFeedback", (PyCFunction)SineLoop_setFeedback, METH_O, "Sets oscillator feedback between 0 and 1."},
+	{"setMul", (PyCFunction)SineLoop_setMul, METH_O, "Sets SineLoop mul factor."},
+	{"setAdd", (PyCFunction)SineLoop_setAdd, METH_O, "Sets SineLoop add factor."},
+	{"setSub", (PyCFunction)SineLoop_setSub, METH_O, "Sets inverse add factor."},
+	{"setDiv", (PyCFunction)SineLoop_setDiv, METH_O, "Sets inverse mul factor."},
+	{NULL}  /* Sentinel */
 };
 
-static PyNumberMethods Osc_as_number = {
-    (binaryfunc)Osc_add,                      /*nb_add*/
-    (binaryfunc)Osc_sub,                 /*nb_subtract*/
-    (binaryfunc)Osc_multiply,                 /*nb_multiply*/
-    (binaryfunc)Osc_div,                   /*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*/
-    0,                                          /*nb_coerce*/
-    0,                       /*nb_int*/
-    0,                      /*nb_long*/
-    0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
-    (binaryfunc)Osc_inplace_add,              /*inplace_add*/
-    (binaryfunc)Osc_inplace_sub,         /*inplace_subtract*/
-    (binaryfunc)Osc_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)Osc_inplace_div,           /*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*/
-    0,              /*nb_true_divide*/
-    0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
-    0,                     /* nb_index */
+static PyNumberMethods SineLoop_as_number = {
+	(binaryfunc)SineLoop_add,                      /*nb_add*/
+	(binaryfunc)SineLoop_sub,                 /*nb_subtract*/
+	(binaryfunc)SineLoop_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)SineLoop_inplace_add,              /*inplace_add*/
+	(binaryfunc)SineLoop_inplace_sub,         /*inplace_subtract*/
+	(binaryfunc)SineLoop_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)SineLoop_div,                       /*nb_true_divide*/
+	0,     /*nb_inplace_floor_divide*/
+	(binaryfunc)SineLoop_inplace_div,                       /*nb_inplace_true_divide*/
+	0,                     /* nb_index */
 };
 
-PyTypeObject OscType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
-    "_pyo.Osc_base",         /*tp_name*/
-    sizeof(Osc),         /*tp_basicsize*/
-    0,                         /*tp_itemsize*/
-    (destructor)Osc_dealloc, /*tp_dealloc*/
-    0,                         /*tp_print*/
-    0,                         /*tp_getattr*/
-    0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
-    0,                         /*tp_repr*/
-    &Osc_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*/
-    "Osc objects. Generates an oscillatory waveform.",           /* tp_doc */
-    (traverseproc)Osc_traverse,   /* tp_traverse */
-    (inquiry)Osc_clear,           /* tp_clear */
-    0,		               /* tp_richcompare */
-    0,		               /* tp_weaklistoffset */
-    0,		               /* tp_iter */
-    0,		               /* tp_iternext */
-    Osc_methods,             /* tp_methods */
-    Osc_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 */
-    Osc_new,                 /* tp_new */
+PyTypeObject SineLoopType = {
+	PyVarObject_HEAD_INIT(NULL, 0)
+	"_pyo.SineLoop_base",         /*tp_name*/
+	sizeof(SineLoop),         /*tp_basicsize*/
+	0,                         /*tp_itemsize*/
+	(destructor)SineLoop_dealloc, /*tp_dealloc*/
+	0,                         /*tp_print*/
+	0,                         /*tp_getattr*/
+	0,                         /*tp_setattr*/
+	0,                         /*tp_as_async (tp_compare in Python 2)*/
+	0,                         /*tp_repr*/
+	&SineLoop_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*/
+	"SineLoop objects. Generates a looped sinewave.",           /* tp_doc */
+	(traverseproc)SineLoop_traverse,   /* tp_traverse */
+	(inquiry)SineLoop_clear,           /* tp_clear */
+	0,		               /* tp_richcompare */
+	0,		               /* tp_weaklistoffset */
+	0,		               /* tp_iter */
+	0,		               /* tp_iternext */
+	SineLoop_methods,             /* tp_methods */
+	SineLoop_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 */
+	SineLoop_new,                 /* tp_new */
 };
 
-/**************/
-/* OscLoop object */
-/**************/
+/***************/
+/* Osc objects */
+/***************/
+static double
+Osc_clip(double x, int size) {
+    if (x < 0) {
+        x += ((int)(-x / size) + 1) * size;
+    }
+    else if (x >= size) {
+        x -= (int)(x / size) * size;
+    }
+    return x;
+}
+
 typedef struct {
     pyo_audio_HEAD
     PyObject *table;
     PyObject *freq;
     Stream *freq_stream;
-    PyObject *feedback;
-    Stream *feedback_stream;
+    PyObject *phase;
+    Stream *phase_stream;
     int modebuffer[4];
     double pointerPos;
-    MYFLT lastValue;
-} OscLoop;
+    int interp; /* 0 = default to 2, 1 = nointerp, 2 = linear, 3 = cos, 4 = cubic */
+    MYFLT (*interp_func_ptr)(MYFLT *, int, MYFLT, int);
+} Osc;
 
 static void
-OscLoop_readframes_ii(OscLoop *self) {
-    MYFLT fr, feed, pos, inc, fpart;
+Osc_readframes_ii(Osc *self) {
+    MYFLT fr, ph, fpart;
+    double inc, pos;
     int i, ipart;
     MYFLT *tablelist = TableStream_getData(self->table);
     int size = TableStream_getSize(self->table);
-    
+
     fr = PyFloat_AS_DOUBLE(self->freq);
-    feed = _clip(PyFloat_AS_DOUBLE(self->feedback)) * size;
+    ph = PyFloat_AS_DOUBLE(self->phase);
     inc = fr * size / self->sr;
-    
+
+    ph *= size;
     for (i=0; i<self->bufsize; i++) {
         self->pointerPos += inc;
         self->pointerPos = Osc_clip(self->pointerPos, size);
-        pos = self->pointerPos + (self->lastValue * feed);
+        pos = self->pointerPos + ph;
         if (pos >= size)
             pos -= size;
-        else if (pos < 0)
-            pos += size;
         ipart = (int)pos;
         fpart = pos - ipart;
-        self->data[i] = self->lastValue = tablelist[ipart] * (1.0 - fpart) + tablelist[ipart+1] * fpart;
+        self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
     }
 }
 
 static void
-OscLoop_readframes_ai(OscLoop *self) {
-    MYFLT inc, feed, pos, fpart, sizeOnSr;
+Osc_readframes_ai(Osc *self) {
+    MYFLT ph, fpart, sizeOnSr;
+    double inc, pos;
     int i, ipart;
     MYFLT *tablelist = TableStream_getData(self->table);
     int size = TableStream_getSize(self->table);
-    
+
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    feed = _clip(PyFloat_AS_DOUBLE(self->feedback)) * size;
-    
+    ph = PyFloat_AS_DOUBLE(self->phase);
+    ph *= size;
+
     sizeOnSr = size / self->sr;
     for (i=0; i<self->bufsize; i++) {
         inc = fr[i] * sizeOnSr;
         self->pointerPos += inc;
         self->pointerPos = Osc_clip(self->pointerPos, size);
-        pos = self->pointerPos + (self->lastValue * feed);
+        pos = self->pointerPos + ph;
         if (pos >= size)
             pos -= size;
-        else if (pos < 0)
-            pos += size;
         ipart = (int)pos;
         fpart = pos - ipart;
-        self->data[i] = self->lastValue = tablelist[ipart] * (1.0 - fpart) + tablelist[ipart+1] * fpart;
+        self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
     }
 }
 
 static void
-OscLoop_readframes_ia(OscLoop *self) {
-    MYFLT fr, feed, pos, inc, fpart;
+Osc_readframes_ia(Osc *self) {
+    MYFLT fr, pha, fpart;
+    double inc, pos;
     int i, ipart;
     MYFLT *tablelist = TableStream_getData(self->table);
     int size = TableStream_getSize(self->table);
-    
+
     fr = PyFloat_AS_DOUBLE(self->freq);
-    MYFLT *fd = Stream_getData((Stream *)self->feedback_stream);
+    MYFLT *ph = Stream_getData((Stream *)self->phase_stream);
     inc = fr * size / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
-        feed = _clip(fd[i]) * size;
+        pha = ph[i] * size;
         self->pointerPos += inc;
         self->pointerPos = Osc_clip(self->pointerPos, size);
-        pos = self->pointerPos + (self->lastValue * feed);
+        pos = self->pointerPos + pha;
         if (pos >= size)
             pos -= size;
-        else if (pos < 0)
-            pos += size;
         ipart = (int)pos;
         fpart = pos - ipart;
-        self->data[i] = self->lastValue = tablelist[ipart] * (1.0 - fpart) + tablelist[ipart+1] * fpart;
+        self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
     }
 }
 
 static void
-OscLoop_readframes_aa(OscLoop *self) {
-    MYFLT inc, feed, pos, fpart, sizeOnSr;
+Osc_readframes_aa(Osc *self) {
+    MYFLT pha, fpart, sizeOnSr;
+    double inc, pos;
     int i, ipart;
     MYFLT *tablelist = TableStream_getData(self->table);
     int size = TableStream_getSize(self->table);
-    
+
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    MYFLT *fd = Stream_getData((Stream *)self->feedback_stream);
-    
+    MYFLT *ph = Stream_getData((Stream *)self->phase_stream);
+
     sizeOnSr = size / self->sr;
     for (i=0; i<self->bufsize; i++) {
         inc = fr[i] * sizeOnSr;
-        feed = _clip(fd[i]) * size;
+        pha = ph[i] * size;
         self->pointerPos += inc;
         self->pointerPos = Osc_clip(self->pointerPos, size);
-        pos = self->pointerPos + (self->lastValue * feed);
+        pos = self->pointerPos + pha;
         if (pos >= size)
             pos -= size;
-        else if (pos < 0)
-            pos += size;
         ipart = (int)pos;
         fpart = pos - ipart;
-        self->data[i] = self->lastValue = tablelist[ipart] * (1.0 - fpart) + tablelist[ipart+1] * fpart;
+        self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
     }
 }
 
-static void OscLoop_postprocessing_ii(OscLoop *self) { POST_PROCESSING_II };
-static void OscLoop_postprocessing_ai(OscLoop *self) { POST_PROCESSING_AI };
-static void OscLoop_postprocessing_ia(OscLoop *self) { POST_PROCESSING_IA };
-static void OscLoop_postprocessing_aa(OscLoop *self) { POST_PROCESSING_AA };
-static void OscLoop_postprocessing_ireva(OscLoop *self) { POST_PROCESSING_IREVA };
-static void OscLoop_postprocessing_areva(OscLoop *self) { POST_PROCESSING_AREVA };
-static void OscLoop_postprocessing_revai(OscLoop *self) { POST_PROCESSING_REVAI };
-static void OscLoop_postprocessing_revaa(OscLoop *self) { POST_PROCESSING_REVAA };
-static void OscLoop_postprocessing_revareva(OscLoop *self) { POST_PROCESSING_REVAREVA };
+static void Osc_postprocessing_ii(Osc *self) { POST_PROCESSING_II };
+static void Osc_postprocessing_ai(Osc *self) { POST_PROCESSING_AI };
+static void Osc_postprocessing_ia(Osc *self) { POST_PROCESSING_IA };
+static void Osc_postprocessing_aa(Osc *self) { POST_PROCESSING_AA };
+static void Osc_postprocessing_ireva(Osc *self) { POST_PROCESSING_IREVA };
+static void Osc_postprocessing_areva(Osc *self) { POST_PROCESSING_AREVA };
+static void Osc_postprocessing_revai(Osc *self) { POST_PROCESSING_REVAI };
+static void Osc_postprocessing_revaa(Osc *self) { POST_PROCESSING_REVAA };
+static void Osc_postprocessing_revareva(Osc *self) { POST_PROCESSING_REVAREVA };
 
 static void
-OscLoop_setProcMode(OscLoop *self)
+Osc_setProcMode(Osc *self)
 {
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:        
-            self->proc_func_ptr = OscLoop_readframes_ii;
+        case 0:
+            self->proc_func_ptr = Osc_readframes_ii;
             break;
-        case 1:    
-            self->proc_func_ptr = OscLoop_readframes_ai;
+        case 1:
+            self->proc_func_ptr = Osc_readframes_ai;
             break;
-        case 10:        
-            self->proc_func_ptr = OscLoop_readframes_ia;
+        case 10:
+            self->proc_func_ptr = Osc_readframes_ia;
             break;
-        case 11:    
-            self->proc_func_ptr = OscLoop_readframes_aa;
+        case 11:
+            self->proc_func_ptr = Osc_readframes_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
-            self->muladd_func_ptr = OscLoop_postprocessing_ii;
+        case 0:
+            self->muladd_func_ptr = Osc_postprocessing_ii;
             break;
-        case 1:    
-            self->muladd_func_ptr = OscLoop_postprocessing_ai;
+        case 1:
+            self->muladd_func_ptr = Osc_postprocessing_ai;
             break;
-        case 2:    
-            self->muladd_func_ptr = OscLoop_postprocessing_revai;
+        case 2:
+            self->muladd_func_ptr = Osc_postprocessing_revai;
             break;
-        case 10:        
-            self->muladd_func_ptr = OscLoop_postprocessing_ia;
+        case 10:
+            self->muladd_func_ptr = Osc_postprocessing_ia;
             break;
-        case 11:    
-            self->muladd_func_ptr = OscLoop_postprocessing_aa;
+        case 11:
+            self->muladd_func_ptr = Osc_postprocessing_aa;
             break;
-        case 12:    
-            self->muladd_func_ptr = OscLoop_postprocessing_revaa;
+        case 12:
+            self->muladd_func_ptr = Osc_postprocessing_revaa;
             break;
-        case 20:        
-            self->muladd_func_ptr = OscLoop_postprocessing_ireva;
+        case 20:
+            self->muladd_func_ptr = Osc_postprocessing_ireva;
             break;
-        case 21:    
-            self->muladd_func_ptr = OscLoop_postprocessing_areva;
+        case 21:
+            self->muladd_func_ptr = Osc_postprocessing_areva;
             break;
-        case 22:    
-            self->muladd_func_ptr = OscLoop_postprocessing_revareva;
+        case 22:
+            self->muladd_func_ptr = Osc_postprocessing_revareva;
             break;
-    } 
+    }
 }
 
 static void
-OscLoop_compute_next_data_frame(OscLoop *self)
+Osc_compute_next_data_frame(Osc *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
 static int
-OscLoop_traverse(OscLoop *self, visitproc visit, void *arg)
+Osc_traverse(Osc *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->table);
-    Py_VISIT(self->feedback);    
-    Py_VISIT(self->feedback_stream);    
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
+    Py_VISIT(self->phase);
+    Py_VISIT(self->phase_stream);
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
     return 0;
 }
 
-static int 
-OscLoop_clear(OscLoop *self)
+static int
+Osc_clear(Osc *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->table);
-    Py_CLEAR(self->feedback);    
-    Py_CLEAR(self->feedback_stream);    
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
+    Py_CLEAR(self->phase);
+    Py_CLEAR(self->phase_stream);
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
     return 0;
 }
 
 static void
-OscLoop_dealloc(OscLoop* self)
+Osc_dealloc(Osc* self)
 {
     pyo_DEALLOC
-    OscLoop_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Osc_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
-OscLoop_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+Osc_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
-    PyObject *tabletmp, *freqtmp=NULL, *feedbacktmp=NULL, *multmp=NULL, *addtmp=NULL;
-    OscLoop *self;
-    self = (OscLoop *)type->tp_alloc(type, 0);
-    
+    PyObject *tabletmp, *freqtmp=NULL, *phasetmp=NULL, *multmp=NULL, *addtmp=NULL;
+    Osc *self;
+    self = (Osc *)type->tp_alloc(type, 0);
+
     self->freq = PyFloat_FromDouble(1000);
-    self->feedback = PyFloat_FromDouble(0);
+    self->phase = PyFloat_FromDouble(0);
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
-    self->pointerPos = self->lastValue = 0.;
-    
+    self->pointerPos = 0.;
+    self->interp = 2;
+
     INIT_OBJECT_COMMON
-    Stream_setFunctionPtr(self->stream, OscLoop_compute_next_data_frame);
-    self->mode_func_ptr = OscLoop_setProcMode;
+    Stream_setFunctionPtr(self->stream, Osc_compute_next_data_frame);
+    self->mode_func_ptr = Osc_setProcMode;
 
-    static char *kwlist[] = {"table", "freq", "feedback", "mul", "add", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &tabletmp, &freqtmp, &feedbacktmp, &multmp, &addtmp))
+    static char *kwlist[] = {"table", "freq", "phase", "interp", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOiOO", kwlist, &tabletmp, &freqtmp, &phasetmp, &self->interp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
-        PySys_WriteStderr("TypeError: \"table\" argument of OscLoop must be a PyoTableObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"table\" argument of Osc must be a PyoTableObject.\n");
+        Py_RETURN_NONE;
     }
     Py_XDECREF(self->table);
     self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", "");
-    
-    if (feedbacktmp) {
-        PyObject_CallMethod((PyObject *)self, "setFeedback", "O", feedbacktmp);
+
+    if (phasetmp) {
+        PyObject_CallMethod((PyObject *)self, "setPhase", "O", phasetmp);
     }
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    
+
     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);
-    
+
+    SET_INTERP_POINTER
+
     return (PyObject *)self;
 }
 
-static PyObject * OscLoop_getServer(OscLoop* self) { GET_SERVER };
-static PyObject * OscLoop_getStream(OscLoop* self) { GET_STREAM };
-static PyObject * OscLoop_setMul(OscLoop *self, PyObject *arg) { SET_MUL };	
-static PyObject * OscLoop_setAdd(OscLoop *self, PyObject *arg) { SET_ADD };	
-static PyObject * OscLoop_setSub(OscLoop *self, PyObject *arg) { SET_SUB };	
-static PyObject * OscLoop_setDiv(OscLoop *self, PyObject *arg) { SET_DIV };	
+static PyObject * Osc_getServer(Osc* self) { GET_SERVER };
+static PyObject * Osc_getStream(Osc* self) { GET_STREAM };
+static PyObject * Osc_setMul(Osc *self, PyObject *arg) { SET_MUL };
+static PyObject * Osc_setAdd(Osc *self, PyObject *arg) { SET_ADD };
+static PyObject * Osc_setSub(Osc *self, PyObject *arg) { SET_SUB };
+static PyObject * Osc_setDiv(Osc *self, PyObject *arg) { SET_DIV };
 
-static PyObject * OscLoop_play(OscLoop *self, PyObject *args, PyObject *kwds) { PLAY };
-static PyObject * OscLoop_out(OscLoop *self, PyObject *args, PyObject *kwds) { OUT };
-static PyObject * OscLoop_stop(OscLoop *self) { STOP };
+static PyObject * Osc_play(Osc *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * Osc_out(Osc *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * Osc_stop(Osc *self) { STOP };
 
-static PyObject * OscLoop_multiply(OscLoop *self, PyObject *arg) { MULTIPLY };
-static PyObject * OscLoop_inplace_multiply(OscLoop *self, PyObject *arg) { INPLACE_MULTIPLY };
-static PyObject * OscLoop_add(OscLoop *self, PyObject *arg) { ADD };
-static PyObject * OscLoop_inplace_add(OscLoop *self, PyObject *arg) { INPLACE_ADD };
-static PyObject * OscLoop_sub(OscLoop *self, PyObject *arg) { SUB };
-static PyObject * OscLoop_inplace_sub(OscLoop *self, PyObject *arg) { INPLACE_SUB };
-static PyObject * OscLoop_div(OscLoop *self, PyObject *arg) { DIV };
-static PyObject * OscLoop_inplace_div(OscLoop *self, PyObject *arg) { INPLACE_DIV };
+static PyObject * Osc_multiply(Osc *self, PyObject *arg) { MULTIPLY };
+static PyObject * Osc_inplace_multiply(Osc *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * Osc_add(Osc *self, PyObject *arg) { ADD };
+static PyObject * Osc_inplace_add(Osc *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * Osc_sub(Osc *self, PyObject *arg) { SUB };
+static PyObject * Osc_inplace_sub(Osc *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * Osc_div(Osc *self, PyObject *arg) { DIV };
+static PyObject * Osc_inplace_div(Osc *self, PyObject *arg) { INPLACE_DIV };
 
 static PyObject *
-OscLoop_getTable(OscLoop* self)
+Osc_getTable(Osc* self)
 {
     Py_INCREF(self->table);
     return self->table;
 };
 
 static PyObject *
-OscLoop_setTable(OscLoop *self, PyObject *arg)
+Osc_setTable(Osc *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    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 *
-OscLoop_setFreq(OscLoop *self, PyObject *arg)
+Osc_setFreq(Osc *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -1846,80 +1831,104 @@ OscLoop_setFreq(OscLoop *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
-OscLoop_setFeedback(OscLoop *self, PyObject *arg)
+Osc_setPhase(Osc *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
-	Py_DECREF(self->feedback);
+	Py_DECREF(self->phase);
 	if (isNumber == 1) {
-		self->feedback = PyNumber_Float(tmp);
+		self->phase = PyNumber_Float(tmp);
         self->modebuffer[3] = 0;
 	}
 	else {
-		self->feedback = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->feedback, "_getStream", NULL);
+		self->phase = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->phase, "_getStream", NULL);
         Py_INCREF(streamtmp);
-        Py_XDECREF(self->feedback_stream);
-        self->feedback_stream = (Stream *)streamtmp;
+        Py_XDECREF(self->phase_stream);
+        self->phase_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
-static PyMemberDef OscLoop_members[] = {
-    {"server", T_OBJECT_EX, offsetof(OscLoop, server), 0, "Pyo server."},
-    {"stream", T_OBJECT_EX, offsetof(OscLoop, stream), 0, "Stream object."},
-    {"table", T_OBJECT_EX, offsetof(OscLoop, table), 0, "Waveform table."},
-    {"freq", T_OBJECT_EX, offsetof(OscLoop, freq), 0, "Frequency in cycle per second."},
-    {"feedback", T_OBJECT_EX, offsetof(OscLoop, feedback), 0, "Oscillator feedback."},
-    {"mul", T_OBJECT_EX, offsetof(OscLoop, mul), 0, "Mul factor."},
-    {"add", T_OBJECT_EX, offsetof(OscLoop, add), 0, "Add factor."},
+static PyObject *
+Osc_setInterp(Osc *self, PyObject *arg)
+{
+    ASSERT_ARG_NOT_NULL
+
+    int isNumber = PyNumber_Check(arg);
+
+	if (isNumber == 1) {
+		self->interp = PyInt_AsLong(PyNumber_Int(arg));
+    }
+
+    SET_INTERP_POINTER
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *
+Osc_reset(Osc *self)
+{
+    self->pointerPos = 0.0;
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyMemberDef Osc_members[] = {
+    {"server", T_OBJECT_EX, offsetof(Osc, server), 0, "Pyo server."},
+    {"stream", T_OBJECT_EX, offsetof(Osc, stream), 0, "Stream object."},
+    {"table", T_OBJECT_EX, offsetof(Osc, table), 0, "Waveform table."},
+    {"freq", T_OBJECT_EX, offsetof(Osc, freq), 0, "Frequency in cycle per second."},
+    {"phase", T_OBJECT_EX, offsetof(Osc, phase), 0, "Oscillator phase."},
+    {"mul", T_OBJECT_EX, offsetof(Osc, mul), 0, "Mul factor."},
+    {"add", T_OBJECT_EX, offsetof(Osc, add), 0, "Add factor."},
     {NULL}  /* Sentinel */
 };
 
-static PyMethodDef OscLoop_methods[] = {
-    {"getTable", (PyCFunction)OscLoop_getTable, METH_NOARGS, "Returns waveform table object."},
-    {"getServer", (PyCFunction)OscLoop_getServer, METH_NOARGS, "Returns server object."},
-    {"_getStream", (PyCFunction)OscLoop_getStream, METH_NOARGS, "Returns stream object."},
-    {"play", (PyCFunction)OscLoop_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
-    {"out", (PyCFunction)OscLoop_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
-    {"stop", (PyCFunction)OscLoop_stop, METH_NOARGS, "Stops computing."},
-    {"setTable", (PyCFunction)OscLoop_setTable, METH_O, "Sets oscillator table."},
-	{"setFreq", (PyCFunction)OscLoop_setFreq, METH_O, "Sets oscillator frequency in cycle per second."},
-    {"setFeedback", (PyCFunction)OscLoop_setFeedback, METH_O, "Sets oscillator feedback."},
-	{"setMul", (PyCFunction)OscLoop_setMul, METH_O, "Sets oscillator mul factor."},
-	{"setAdd", (PyCFunction)OscLoop_setAdd, METH_O, "Sets oscillator add factor."},
-    {"setSub", (PyCFunction)OscLoop_setSub, METH_O, "Sets oscillator inverse add factor."},
-    {"setDiv", (PyCFunction)OscLoop_setDiv, METH_O, "Sets inverse mul factor."},
+static PyMethodDef Osc_methods[] = {
+    {"getTable", (PyCFunction)Osc_getTable, METH_NOARGS, "Returns waveform table object."},
+    {"getServer", (PyCFunction)Osc_getServer, METH_NOARGS, "Returns server object."},
+    {"_getStream", (PyCFunction)Osc_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)Osc_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+    {"out", (PyCFunction)Osc_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+    {"stop", (PyCFunction)Osc_stop, METH_NOARGS, "Stops computing."},
+    {"setTable", (PyCFunction)Osc_setTable, METH_O, "Sets oscillator table."},
+	{"setFreq", (PyCFunction)Osc_setFreq, METH_O, "Sets oscillator frequency in cycle per second."},
+    {"setPhase", (PyCFunction)Osc_setPhase, METH_O, "Sets oscillator phase."},
+    {"setInterp", (PyCFunction)Osc_setInterp, METH_O, "Sets oscillator interpolation mode."},
+    {"reset", (PyCFunction)Osc_reset, METH_NOARGS, "Resets pointer position to 0."},
+	{"setMul", (PyCFunction)Osc_setMul, METH_O, "Sets oscillator mul factor."},
+	{"setAdd", (PyCFunction)Osc_setAdd, METH_O, "Sets oscillator add factor."},
+    {"setSub", (PyCFunction)Osc_setSub, METH_O, "Sets oscillator inverse add factor."},
+    {"setDiv", (PyCFunction)Osc_setDiv, METH_O, "Sets inverse mul factor."},
     {NULL}  /* Sentinel */
 };
 
-static PyNumberMethods OscLoop_as_number = {
-    (binaryfunc)OscLoop_add,                      /*nb_add*/
-    (binaryfunc)OscLoop_sub,                 /*nb_subtract*/
-    (binaryfunc)OscLoop_multiply,                 /*nb_multiply*/
-    (binaryfunc)OscLoop_div,                   /*nb_divide*/
+static PyNumberMethods Osc_as_number = {
+    (binaryfunc)Osc_add,                      /*nb_add*/
+    (binaryfunc)Osc_sub,                 /*nb_subtract*/
+    (binaryfunc)Osc_multiply,                 /*nb_multiply*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -1933,16 +1942,16 @@ static PyNumberMethods OscLoop_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
-    (binaryfunc)OscLoop_inplace_add,              /*inplace_add*/
-    (binaryfunc)OscLoop_inplace_sub,         /*inplace_subtract*/
-    (binaryfunc)OscLoop_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)OscLoop_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
+    (binaryfunc)Osc_inplace_add,              /*inplace_add*/
+    (binaryfunc)Osc_inplace_sub,         /*inplace_subtract*/
+    (binaryfunc)Osc_inplace_multiply,         /*inplace_multiply*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -1951,25 +1960,24 @@ static PyNumberMethods OscLoop_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)Osc_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)Osc_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
-PyTypeObject OscLoopType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
-    "_pyo.OscLoop_base",         /*tp_name*/
-    sizeof(OscLoop),         /*tp_basicsize*/
+PyTypeObject OscType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.Osc_base",         /*tp_name*/
+    sizeof(Osc),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
-    (destructor)OscLoop_dealloc, /*tp_dealloc*/
+    (destructor)Osc_dealloc, /*tp_dealloc*/
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
-    &OscLoop_as_number,             /*tp_as_number*/
+    &Osc_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
     0,                         /*tp_as_mapping*/
     0,                         /*tp_hash */
@@ -1979,15 +1987,15 @@ PyTypeObject OscLoopType = {
     0,                         /*tp_setattro*/
     0,                         /*tp_as_buffer*/
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
-    "OscLoop objects. Generates an oscillatory waveform.",           /* tp_doc */
-    (traverseproc)OscLoop_traverse,   /* tp_traverse */
-    (inquiry)OscLoop_clear,           /* tp_clear */
+    "Osc objects. Generates an oscillatory waveform.",           /* tp_doc */
+    (traverseproc)Osc_traverse,   /* tp_traverse */
+    (inquiry)Osc_clear,           /* tp_clear */
     0,		               /* tp_richcompare */
     0,		               /* tp_weaklistoffset */
     0,		               /* tp_iter */
     0,		               /* tp_iternext */
-    OscLoop_methods,             /* tp_methods */
-    OscLoop_members,             /* tp_members */
+    Osc_methods,             /* tp_methods */
+    Osc_members,             /* tp_members */
     0,                      /* tp_getset */
     0,                         /* tp_base */
     0,                         /* tp_dict */
@@ -1996,404 +2004,335 @@ PyTypeObject OscLoopType = {
     0,                         /* tp_dictoffset */
     0,      /* tp_init */
     0,                         /* tp_alloc */
-    OscLoop_new,                 /* tp_new */
+    Osc_new,                 /* tp_new */
 };
 
+/**************/
+/* OscLoop object */
+/**************/
 typedef struct {
     pyo_audio_HEAD
     PyObject *table;
     PyObject *freq;
     Stream *freq_stream;
-    PyObject *phase;
-    Stream *phase_stream;
-    PyObject *trig;
-    Stream *trig_stream;
+    PyObject *feedback;
+    Stream *feedback_stream;
     int modebuffer[4];
     double pointerPos;
-    int interp; /* 0 = default to 2, 1 = nointerp, 2 = linear, 3 = cos, 4 = cubic */
-    MYFLT (*interp_func_ptr)(MYFLT *, int, MYFLT, int);
-} OscTrig;
+    MYFLT lastValue;
+} OscLoop;
 
 static void
-OscTrig_readframes_ii(OscTrig *self) {
-    MYFLT fr, ph, fpart;
-    double inc, pos;
+OscLoop_readframes_ii(OscLoop *self) {
+    MYFLT fr, feed, pos, inc, fpart;
     int i, ipart;
     MYFLT *tablelist = TableStream_getData(self->table);
     int size = TableStream_getSize(self->table);
-    
+
     fr = PyFloat_AS_DOUBLE(self->freq);
-    ph = PyFloat_AS_DOUBLE(self->phase);
-    MYFLT *tr = Stream_getData((Stream *)self->trig_stream);
+    feed = _clip(PyFloat_AS_DOUBLE(self->feedback)) * size;
     inc = fr * size / self->sr;
-    
-    ph *= size;
+
     for (i=0; i<self->bufsize; i++) {
-        if (tr[i] == 1)
-            self->pointerPos = 0.0;
-        else {
-            self->pointerPos += inc;
-            self->pointerPos = Osc_clip(self->pointerPos, size);
-        }
-        pos = self->pointerPos + ph;
+        self->pointerPos += inc;
+        self->pointerPos = Osc_clip(self->pointerPos, size);
+        pos = self->pointerPos + (self->lastValue * feed);
         if (pos >= size)
             pos -= size;
+        else if (pos < 0)
+            pos += size;
         ipart = (int)pos;
         fpart = pos - ipart;
-        self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
+        self->data[i] = self->lastValue = tablelist[ipart] * (1.0 - fpart) + tablelist[ipart+1] * fpart;
     }
 }
 
 static void
-OscTrig_readframes_ai(OscTrig *self) {
-    MYFLT ph, fpart, sizeOnSr;
-    double inc, pos;
+OscLoop_readframes_ai(OscLoop *self) {
+    MYFLT inc, feed, pos, fpart, sizeOnSr;
     int i, ipart;
     MYFLT *tablelist = TableStream_getData(self->table);
     int size = TableStream_getSize(self->table);
-    
+
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    ph = PyFloat_AS_DOUBLE(self->phase);
-    MYFLT *tr = Stream_getData((Stream *)self->trig_stream);
-    ph *= size;
-    
+    feed = _clip(PyFloat_AS_DOUBLE(self->feedback)) * size;
+
     sizeOnSr = size / self->sr;
     for (i=0; i<self->bufsize; i++) {
         inc = fr[i] * sizeOnSr;
-        if (tr[i] == 1)
-            self->pointerPos = 0.0;
-        else {
-            self->pointerPos += inc;
-            self->pointerPos = Osc_clip(self->pointerPos, size);
-        }
-        pos = self->pointerPos + ph;
+        self->pointerPos += inc;
+        self->pointerPos = Osc_clip(self->pointerPos, size);
+        pos = self->pointerPos + (self->lastValue * feed);
         if (pos >= size)
             pos -= size;
+        else if (pos < 0)
+            pos += size;
         ipart = (int)pos;
         fpart = pos - ipart;
-        self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
+        self->data[i] = self->lastValue = tablelist[ipart] * (1.0 - fpart) + tablelist[ipart+1] * fpart;
     }
 }
 
 static void
-OscTrig_readframes_ia(OscTrig *self) {
-    MYFLT fr, pha, fpart;
-    double inc, pos;
+OscLoop_readframes_ia(OscLoop *self) {
+    MYFLT fr, feed, pos, inc, fpart;
     int i, ipart;
     MYFLT *tablelist = TableStream_getData(self->table);
     int size = TableStream_getSize(self->table);
-    
+
     fr = PyFloat_AS_DOUBLE(self->freq);
-    MYFLT *ph = Stream_getData((Stream *)self->phase_stream);
-    MYFLT *tr = Stream_getData((Stream *)self->trig_stream);
+    MYFLT *fd = Stream_getData((Stream *)self->feedback_stream);
     inc = fr * size / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
-        pha = ph[i] * size;
-        if (tr[i] == 1)
-            self->pointerPos = 0.0;
-        else {
-            self->pointerPos += inc;
-            self->pointerPos = Osc_clip(self->pointerPos, size);
-        }
-        pos = self->pointerPos + pha;
+        feed = _clip(fd[i]) * size;
+        self->pointerPos += inc;
+        self->pointerPos = Osc_clip(self->pointerPos, size);
+        pos = self->pointerPos + (self->lastValue * feed);
         if (pos >= size)
             pos -= size;
+        else if (pos < 0)
+            pos += size;
         ipart = (int)pos;
         fpart = pos - ipart;
-        self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
+        self->data[i] = self->lastValue = tablelist[ipart] * (1.0 - fpart) + tablelist[ipart+1] * fpart;
     }
 }
 
 static void
-OscTrig_readframes_aa(OscTrig *self) {
-    MYFLT pha, fpart, sizeOnSr;
-    double inc, pos;
+OscLoop_readframes_aa(OscLoop *self) {
+    MYFLT inc, feed, pos, fpart, sizeOnSr;
     int i, ipart;
     MYFLT *tablelist = TableStream_getData(self->table);
     int size = TableStream_getSize(self->table);
-    
+
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    MYFLT *ph = Stream_getData((Stream *)self->phase_stream);
-    MYFLT *tr = Stream_getData((Stream *)self->trig_stream);
-    
+    MYFLT *fd = Stream_getData((Stream *)self->feedback_stream);
+
     sizeOnSr = size / self->sr;
     for (i=0; i<self->bufsize; i++) {
         inc = fr[i] * sizeOnSr;
-        pha = ph[i] * size;
-        if (tr[i] == 1)
-            self->pointerPos = 0.0;
-        else {
-            self->pointerPos += inc;
-            self->pointerPos = Osc_clip(self->pointerPos, size);
-        }
-        pos = self->pointerPos + pha;
+        feed = _clip(fd[i]) * size;
+        self->pointerPos += inc;
+        self->pointerPos = Osc_clip(self->pointerPos, size);
+        pos = self->pointerPos + (self->lastValue * feed);
         if (pos >= size)
             pos -= size;
+        else if (pos < 0)
+            pos += size;
         ipart = (int)pos;
         fpart = pos - ipart;
-        self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
+        self->data[i] = self->lastValue = tablelist[ipart] * (1.0 - fpart) + tablelist[ipart+1] * fpart;
     }
 }
 
-static void OscTrig_postprocessing_ii(OscTrig *self) { POST_PROCESSING_II };
-static void OscTrig_postprocessing_ai(OscTrig *self) { POST_PROCESSING_AI };
-static void OscTrig_postprocessing_ia(OscTrig *self) { POST_PROCESSING_IA };
-static void OscTrig_postprocessing_aa(OscTrig *self) { POST_PROCESSING_AA };
-static void OscTrig_postprocessing_ireva(OscTrig *self) { POST_PROCESSING_IREVA };
-static void OscTrig_postprocessing_areva(OscTrig *self) { POST_PROCESSING_AREVA };
-static void OscTrig_postprocessing_revai(OscTrig *self) { POST_PROCESSING_REVAI };
-static void OscTrig_postprocessing_revaa(OscTrig *self) { POST_PROCESSING_REVAA };
-static void OscTrig_postprocessing_revareva(OscTrig *self) { POST_PROCESSING_REVAREVA };
+static void OscLoop_postprocessing_ii(OscLoop *self) { POST_PROCESSING_II };
+static void OscLoop_postprocessing_ai(OscLoop *self) { POST_PROCESSING_AI };
+static void OscLoop_postprocessing_ia(OscLoop *self) { POST_PROCESSING_IA };
+static void OscLoop_postprocessing_aa(OscLoop *self) { POST_PROCESSING_AA };
+static void OscLoop_postprocessing_ireva(OscLoop *self) { POST_PROCESSING_IREVA };
+static void OscLoop_postprocessing_areva(OscLoop *self) { POST_PROCESSING_AREVA };
+static void OscLoop_postprocessing_revai(OscLoop *self) { POST_PROCESSING_REVAI };
+static void OscLoop_postprocessing_revaa(OscLoop *self) { POST_PROCESSING_REVAA };
+static void OscLoop_postprocessing_revareva(OscLoop *self) { POST_PROCESSING_REVAREVA };
 
 static void
-OscTrig_setProcMode(OscTrig *self)
+OscLoop_setProcMode(OscLoop *self)
 {
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:        
-            self->proc_func_ptr = OscTrig_readframes_ii;
+        case 0:
+            self->proc_func_ptr = OscLoop_readframes_ii;
             break;
-        case 1:    
-            self->proc_func_ptr = OscTrig_readframes_ai;
+        case 1:
+            self->proc_func_ptr = OscLoop_readframes_ai;
             break;
-        case 10:        
-            self->proc_func_ptr = OscTrig_readframes_ia;
+        case 10:
+            self->proc_func_ptr = OscLoop_readframes_ia;
             break;
-        case 11:    
-            self->proc_func_ptr = OscTrig_readframes_aa;
+        case 11:
+            self->proc_func_ptr = OscLoop_readframes_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
-            self->muladd_func_ptr = OscTrig_postprocessing_ii;
+        case 0:
+            self->muladd_func_ptr = OscLoop_postprocessing_ii;
             break;
-        case 1:    
-            self->muladd_func_ptr = OscTrig_postprocessing_ai;
+        case 1:
+            self->muladd_func_ptr = OscLoop_postprocessing_ai;
             break;
-        case 2:    
-            self->muladd_func_ptr = OscTrig_postprocessing_revai;
+        case 2:
+            self->muladd_func_ptr = OscLoop_postprocessing_revai;
             break;
-        case 10:        
-            self->muladd_func_ptr = OscTrig_postprocessing_ia;
+        case 10:
+            self->muladd_func_ptr = OscLoop_postprocessing_ia;
             break;
-        case 11:    
-            self->muladd_func_ptr = OscTrig_postprocessing_aa;
+        case 11:
+            self->muladd_func_ptr = OscLoop_postprocessing_aa;
             break;
-        case 12:    
-            self->muladd_func_ptr = OscTrig_postprocessing_revaa;
+        case 12:
+            self->muladd_func_ptr = OscLoop_postprocessing_revaa;
             break;
-        case 20:        
-            self->muladd_func_ptr = OscTrig_postprocessing_ireva;
+        case 20:
+            self->muladd_func_ptr = OscLoop_postprocessing_ireva;
             break;
-        case 21:    
-            self->muladd_func_ptr = OscTrig_postprocessing_areva;
+        case 21:
+            self->muladd_func_ptr = OscLoop_postprocessing_areva;
             break;
-        case 22:    
-            self->muladd_func_ptr = OscTrig_postprocessing_revareva;
+        case 22:
+            self->muladd_func_ptr = OscLoop_postprocessing_revareva;
             break;
-    } 
+    }
 }
 
 static void
-OscTrig_compute_next_data_frame(OscTrig *self)
+OscLoop_compute_next_data_frame(OscLoop *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
 static int
-OscTrig_traverse(OscTrig *self, visitproc visit, void *arg)
+OscLoop_traverse(OscLoop *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->table);
-    Py_VISIT(self->phase);    
-    Py_VISIT(self->phase_stream);    
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
-    Py_VISIT(self->trig);    
-    Py_VISIT(self->trig_stream);    
+    Py_VISIT(self->feedback);
+    Py_VISIT(self->feedback_stream);
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
     return 0;
 }
 
-static int 
-OscTrig_clear(OscTrig *self)
+static int
+OscLoop_clear(OscLoop *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->table);
-    Py_CLEAR(self->phase);    
-    Py_CLEAR(self->phase_stream);    
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
-    Py_CLEAR(self->trig);    
-    Py_CLEAR(self->trig_stream);    
+    Py_CLEAR(self->feedback);
+    Py_CLEAR(self->feedback_stream);
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
     return 0;
 }
 
 static void
-OscTrig_dealloc(OscTrig* self)
+OscLoop_dealloc(OscLoop* self)
 {
     pyo_DEALLOC
-    OscTrig_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    OscLoop_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
-OscTrig_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+OscLoop_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
-    PyObject *tabletmp, *trigtmp, *freqtmp=NULL, *phasetmp=NULL, *multmp=NULL, *addtmp=NULL;
-    OscTrig *self;
-    self = (OscTrig *)type->tp_alloc(type, 0);
-    
+    PyObject *tabletmp, *freqtmp=NULL, *feedbacktmp=NULL, *multmp=NULL, *addtmp=NULL;
+    OscLoop *self;
+    self = (OscLoop *)type->tp_alloc(type, 0);
+
     self->freq = PyFloat_FromDouble(1000);
-    self->phase = PyFloat_FromDouble(0);
+    self->feedback = PyFloat_FromDouble(0);
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
-    self->pointerPos = 0.;
-    self->interp = 2;
-    
+    self->pointerPos = self->lastValue = 0.;
+
     INIT_OBJECT_COMMON
-    Stream_setFunctionPtr(self->stream, OscTrig_compute_next_data_frame);
-    self->mode_func_ptr = OscTrig_setProcMode;
-    
-    static char *kwlist[] = {"table", "trig", "freq", "phase", "interp", "mul", "add", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOiOO", kwlist, &tabletmp, &trigtmp, &freqtmp, &phasetmp, &self->interp, &multmp, &addtmp))
+    Stream_setFunctionPtr(self->stream, OscLoop_compute_next_data_frame);
+    self->mode_func_ptr = OscLoop_setProcMode;
+
+    static char *kwlist[] = {"table", "freq", "feedback", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &tabletmp, &freqtmp, &feedbacktmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
-        PySys_WriteStderr("TypeError: \"table\" argument of OscTrig must be a PyoTableObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"table\" argument of OscLoop must be a PyoTableObject.\n");
+        Py_RETURN_NONE;
     }
     Py_XDECREF(self->table);
     self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", "");
 
-    if (trigtmp) {
-        PyObject_CallMethod((PyObject *)self, "setTrig", "O", trigtmp);
-    }
-    
-    if (phasetmp) {
-        PyObject_CallMethod((PyObject *)self, "setPhase", "O", phasetmp);
+    if (feedbacktmp) {
+        PyObject_CallMethod((PyObject *)self, "setFeedback", "O", feedbacktmp);
     }
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    
+
     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);
-    
-    SET_INTERP_POINTER
-    
+
     return (PyObject *)self;
 }
 
-static PyObject * OscTrig_getServer(OscTrig* self) { GET_SERVER };
-static PyObject * OscTrig_getStream(OscTrig* self) { GET_STREAM };
-static PyObject * OscTrig_setMul(OscTrig *self, PyObject *arg) { SET_MUL };	
-static PyObject * OscTrig_setAdd(OscTrig *self, PyObject *arg) { SET_ADD };	
-static PyObject * OscTrig_setSub(OscTrig *self, PyObject *arg) { SET_SUB };	
-static PyObject * OscTrig_setDiv(OscTrig *self, PyObject *arg) { SET_DIV };	
+static PyObject * OscLoop_getServer(OscLoop* self) { GET_SERVER };
+static PyObject * OscLoop_getStream(OscLoop* self) { GET_STREAM };
+static PyObject * OscLoop_setMul(OscLoop *self, PyObject *arg) { SET_MUL };
+static PyObject * OscLoop_setAdd(OscLoop *self, PyObject *arg) { SET_ADD };
+static PyObject * OscLoop_setSub(OscLoop *self, PyObject *arg) { SET_SUB };
+static PyObject * OscLoop_setDiv(OscLoop *self, PyObject *arg) { SET_DIV };
 
-static PyObject * OscTrig_play(OscTrig *self, PyObject *args, PyObject *kwds) { PLAY };
-static PyObject * OscTrig_out(OscTrig *self, PyObject *args, PyObject *kwds) { OUT };
-static PyObject * OscTrig_stop(OscTrig *self) { STOP };
+static PyObject * OscLoop_play(OscLoop *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * OscLoop_out(OscLoop *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * OscLoop_stop(OscLoop *self) { STOP };
 
-static PyObject * OscTrig_multiply(OscTrig *self, PyObject *arg) { MULTIPLY };
-static PyObject * OscTrig_inplace_multiply(OscTrig *self, PyObject *arg) { INPLACE_MULTIPLY };
-static PyObject * OscTrig_add(OscTrig *self, PyObject *arg) { ADD };
-static PyObject * OscTrig_inplace_add(OscTrig *self, PyObject *arg) { INPLACE_ADD };
-static PyObject * OscTrig_sub(OscTrig *self, PyObject *arg) { SUB };
-static PyObject * OscTrig_inplace_sub(OscTrig *self, PyObject *arg) { INPLACE_SUB };
-static PyObject * OscTrig_div(OscTrig *self, PyObject *arg) { DIV };
-static PyObject * OscTrig_inplace_div(OscTrig *self, PyObject *arg) { INPLACE_DIV };
+static PyObject * OscLoop_multiply(OscLoop *self, PyObject *arg) { MULTIPLY };
+static PyObject * OscLoop_inplace_multiply(OscLoop *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * OscLoop_add(OscLoop *self, PyObject *arg) { ADD };
+static PyObject * OscLoop_inplace_add(OscLoop *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * OscLoop_sub(OscLoop *self, PyObject *arg) { SUB };
+static PyObject * OscLoop_inplace_sub(OscLoop *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * OscLoop_div(OscLoop *self, PyObject *arg) { DIV };
+static PyObject * OscLoop_inplace_div(OscLoop *self, PyObject *arg) { INPLACE_DIV };
 
 static PyObject *
-OscTrig_getTable(OscTrig* self)
+OscLoop_getTable(OscLoop* self)
 {
     Py_INCREF(self->table);
     return self->table;
 };
 
 static PyObject *
-OscTrig_setTable(OscTrig *self, PyObject *arg)
+OscLoop_setTable(OscLoop *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    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 *
-OscTrig_setTrig(OscTrig *self, PyObject *arg)
+OscLoop_setFreq(OscLoop *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	int isNumber = PyNumber_Check(arg);
-	
-	tmp = arg;
-	Py_INCREF(tmp);
-	Py_XDECREF(self->trig);
-	if (isNumber == 1) {
-        Py_INCREF(Py_None);
-        return Py_None;
-	}
-	else {
-		self->trig = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->trig, "_getStream", NULL);
-        Py_INCREF(streamtmp);
-        Py_XDECREF(self->trig_stream);
-        self->trig_stream = (Stream *)streamtmp;
-	}
 
-	Py_INCREF(Py_None);
-	return Py_None;
-}	
+    ASSERT_ARG_NOT_NULL
 
-static PyObject *
-OscTrig_setFreq(OscTrig *self, PyObject *arg)
-{
-	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -2409,115 +2348,80 @@ OscTrig_setFreq(OscTrig *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
-OscTrig_setPhase(OscTrig *self, PyObject *arg)
+OscLoop_setFeedback(OscLoop *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
-	Py_DECREF(self->phase);
+	Py_DECREF(self->feedback);
 	if (isNumber == 1) {
-		self->phase = PyNumber_Float(tmp);
+		self->feedback = PyNumber_Float(tmp);
         self->modebuffer[3] = 0;
 	}
 	else {
-		self->phase = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->phase, "_getStream", NULL);
+		self->feedback = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->feedback, "_getStream", NULL);
         Py_INCREF(streamtmp);
-        Py_XDECREF(self->phase_stream);
-        self->phase_stream = (Stream *)streamtmp;
+        Py_XDECREF(self->feedback_stream);
+        self->feedback_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
-
-static PyObject *
-OscTrig_setInterp(OscTrig *self, PyObject *arg)
-{
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-    int isNumber = PyNumber_Check(arg);
-    
-	if (isNumber == 1) {
-		self->interp = PyInt_AsLong(PyNumber_Int(arg));
-    }  
-    
-    SET_INTERP_POINTER
-    
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-static PyObject * 
-OscTrig_reset(OscTrig *self) 
-{
-    self->pointerPos = 0.0;
-    Py_INCREF(Py_None);
-    return Py_None;
 }
 
-static PyMemberDef OscTrig_members[] = {
-    {"server", T_OBJECT_EX, offsetof(OscTrig, server), 0, "Pyo server."},
-    {"stream", T_OBJECT_EX, offsetof(OscTrig, stream), 0, "Stream object."},
-    {"table", T_OBJECT_EX, offsetof(OscTrig, table), 0, "Waveform table."},
-    {"trig", T_OBJECT_EX, offsetof(OscTrig, trig), 0, "Trigger signal."},
-    {"freq", T_OBJECT_EX, offsetof(OscTrig, freq), 0, "Frequency in cycle per second."},
-    {"phase", T_OBJECT_EX, offsetof(OscTrig, phase), 0, "OscTrigillator phase."},
-    {"mul", T_OBJECT_EX, offsetof(OscTrig, mul), 0, "Mul factor."},
-    {"add", T_OBJECT_EX, offsetof(OscTrig, add), 0, "Add factor."},
+static PyMemberDef OscLoop_members[] = {
+    {"server", T_OBJECT_EX, offsetof(OscLoop, server), 0, "Pyo server."},
+    {"stream", T_OBJECT_EX, offsetof(OscLoop, stream), 0, "Stream object."},
+    {"table", T_OBJECT_EX, offsetof(OscLoop, table), 0, "Waveform table."},
+    {"freq", T_OBJECT_EX, offsetof(OscLoop, freq), 0, "Frequency in cycle per second."},
+    {"feedback", T_OBJECT_EX, offsetof(OscLoop, feedback), 0, "Oscillator feedback."},
+    {"mul", T_OBJECT_EX, offsetof(OscLoop, mul), 0, "Mul factor."},
+    {"add", T_OBJECT_EX, offsetof(OscLoop, add), 0, "Add factor."},
     {NULL}  /* Sentinel */
 };
 
-static PyMethodDef OscTrig_methods[] = {
-    {"getTable", (PyCFunction)OscTrig_getTable, METH_NOARGS, "Returns waveform table object."},
-    {"getServer", (PyCFunction)OscTrig_getServer, METH_NOARGS, "Returns server object."},
-    {"_getStream", (PyCFunction)OscTrig_getStream, METH_NOARGS, "Returns stream object."},
-    {"play", (PyCFunction)OscTrig_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
-    {"out", (PyCFunction)OscTrig_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
-    {"stop", (PyCFunction)OscTrig_stop, METH_NOARGS, "Stops computing."},
-    {"setTable", (PyCFunction)OscTrig_setTable, METH_O, "Sets oscillator table."},
-	{"setTrig", (PyCFunction)OscTrig_setTrig, METH_O, "Sets the reset trigger signal."},
-	{"setFreq", (PyCFunction)OscTrig_setFreq, METH_O, "Sets oscillator frequency in cycle per second."},
-    {"setPhase", (PyCFunction)OscTrig_setPhase, METH_O, "Sets oscillator phase."},
-    {"setInterp", (PyCFunction)OscTrig_setInterp, METH_O, "Sets oscillator interpolation mode."},
-    {"reset", (PyCFunction)OscTrig_reset, METH_NOARGS, "Resets pointer position to 0."},
-	{"setMul", (PyCFunction)OscTrig_setMul, METH_O, "Sets oscillator mul factor."},
-	{"setAdd", (PyCFunction)OscTrig_setAdd, METH_O, "Sets oscillator add factor."},
-    {"setSub", (PyCFunction)OscTrig_setSub, METH_O, "Sets oscillator inverse add factor."},
-    {"setDiv", (PyCFunction)OscTrig_setDiv, METH_O, "Sets inverse mul factor."},
+static PyMethodDef OscLoop_methods[] = {
+    {"getTable", (PyCFunction)OscLoop_getTable, METH_NOARGS, "Returns waveform table object."},
+    {"getServer", (PyCFunction)OscLoop_getServer, METH_NOARGS, "Returns server object."},
+    {"_getStream", (PyCFunction)OscLoop_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)OscLoop_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+    {"out", (PyCFunction)OscLoop_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+    {"stop", (PyCFunction)OscLoop_stop, METH_NOARGS, "Stops computing."},
+    {"setTable", (PyCFunction)OscLoop_setTable, METH_O, "Sets oscillator table."},
+	{"setFreq", (PyCFunction)OscLoop_setFreq, METH_O, "Sets oscillator frequency in cycle per second."},
+    {"setFeedback", (PyCFunction)OscLoop_setFeedback, METH_O, "Sets oscillator feedback."},
+	{"setMul", (PyCFunction)OscLoop_setMul, METH_O, "Sets oscillator mul factor."},
+	{"setAdd", (PyCFunction)OscLoop_setAdd, METH_O, "Sets oscillator add factor."},
+    {"setSub", (PyCFunction)OscLoop_setSub, METH_O, "Sets oscillator inverse add factor."},
+    {"setDiv", (PyCFunction)OscLoop_setDiv, METH_O, "Sets inverse mul factor."},
     {NULL}  /* Sentinel */
 };
 
-static PyNumberMethods OscTrig_as_number = {
-    (binaryfunc)OscTrig_add,                      /*nb_add*/
-    (binaryfunc)OscTrig_sub,                 /*nb_subtract*/
-    (binaryfunc)OscTrig_multiply,                 /*nb_multiply*/
-    (binaryfunc)OscTrig_div,                   /*nb_divide*/
-    0,                /*nb_remainder*/
-    0,                   /*nb_divmod*/
-    0,                   /*nb_power*/
+static PyNumberMethods OscLoop_as_number = {
+    (binaryfunc)OscLoop_add,                      /*nb_add*/
+    (binaryfunc)OscLoop_sub,                 /*nb_subtract*/
+    (binaryfunc)OscLoop_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,*/
@@ -2528,16 +2432,16 @@ static PyNumberMethods OscTrig_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
-    (binaryfunc)OscTrig_inplace_add,              /*inplace_add*/
-    (binaryfunc)OscTrig_inplace_sub,         /*inplace_subtract*/
-    (binaryfunc)OscTrig_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)OscTrig_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
+    (binaryfunc)OscLoop_inplace_add,              /*inplace_add*/
+    (binaryfunc)OscLoop_inplace_sub,         /*inplace_subtract*/
+    (binaryfunc)OscLoop_inplace_multiply,         /*inplace_multiply*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -2546,25 +2450,24 @@ static PyNumberMethods OscTrig_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)OscLoop_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)OscLoop_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
-PyTypeObject OscTrigType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
-    "_pyo.OscTrig_base",         /*tp_name*/
-    sizeof(OscTrig),         /*tp_basicsize*/
+PyTypeObject OscLoopType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.OscLoop_base",         /*tp_name*/
+    sizeof(OscLoop),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
-    (destructor)OscTrig_dealloc, /*tp_dealloc*/
+    (destructor)OscLoop_dealloc, /*tp_dealloc*/
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
-    &OscTrig_as_number,             /*tp_as_number*/
+    &OscLoop_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
     0,                         /*tp_as_mapping*/
     0,                         /*tp_hash */
@@ -2574,15 +2477,15 @@ PyTypeObject OscTrigType = {
     0,                         /*tp_setattro*/
     0,                         /*tp_as_buffer*/
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
-    "OscTrig objects. Generates an oscillatory waveform with sample accurate reset signal.",           /* tp_doc */
-    (traverseproc)OscTrig_traverse,   /* tp_traverse */
-    (inquiry)OscTrig_clear,           /* tp_clear */
+    "OscLoop objects. Generates an oscillatory waveform.",           /* tp_doc */
+    (traverseproc)OscLoop_traverse,   /* tp_traverse */
+    (inquiry)OscLoop_clear,           /* tp_clear */
     0,		               /* tp_richcompare */
     0,		               /* tp_weaklistoffset */
     0,		               /* tp_iter */
     0,		               /* tp_iternext */
-    OscTrig_methods,             /* tp_methods */
-    OscTrig_members,             /* tp_members */
+    OscLoop_methods,             /* tp_methods */
+    OscLoop_members,             /* tp_members */
     0,                      /* tp_getset */
     0,                         /* tp_base */
     0,                         /* tp_dict */
@@ -2591,305 +2494,392 @@ PyTypeObject OscTrigType = {
     0,                         /* tp_dictoffset */
     0,      /* tp_init */
     0,                         /* tp_alloc */
-    OscTrig_new,                 /* tp_new */
+    OscLoop_new,                 /* tp_new */
 };
 
-/**************/
-/* Phasor object */
-/**************/
 typedef struct {
     pyo_audio_HEAD
+    PyObject *table;
     PyObject *freq;
     Stream *freq_stream;
     PyObject *phase;
     Stream *phase_stream;
+    PyObject *trig;
+    Stream *trig_stream;
     int modebuffer[4];
     double pointerPos;
-} Phasor;
+    int interp; /* 0 = default to 2, 1 = nointerp, 2 = linear, 3 = cos, 4 = cubic */
+    MYFLT (*interp_func_ptr)(MYFLT *, int, MYFLT, int);
+} OscTrig;
 
 static void
-Phasor_readframes_ii(Phasor *self) {
-    MYFLT fr, ph;
+OscTrig_readframes_ii(OscTrig *self) {
+    MYFLT fr, ph, fpart;
     double inc, pos;
-    int i;
-    
+    int i, ipart;
+    MYFLT *tablelist = TableStream_getData(self->table);
+    int size = TableStream_getSize(self->table);
+
     fr = PyFloat_AS_DOUBLE(self->freq);
-    ph = _clip(PyFloat_AS_DOUBLE(self->phase));
-    inc = fr / self->sr;
-    
+    ph = PyFloat_AS_DOUBLE(self->phase);
+    MYFLT *tr = Stream_getData((Stream *)self->trig_stream);
+    inc = fr * size / self->sr;
+
+    ph *= size;
     for (i=0; i<self->bufsize; i++) {
+        if (tr[i] == 1)
+            self->pointerPos = 0.0;
+        else {
+            self->pointerPos += inc;
+            self->pointerPos = Osc_clip(self->pointerPos, size);
+        }
         pos = self->pointerPos + ph;
-        if (pos > 1)
-            pos -= 1.0;
-        self->data[i] = pos;
-        
-        self->pointerPos += inc;
-        if (self->pointerPos < 0)
-            self->pointerPos += 1.0;
-        else if (self->pointerPos >= 1)
-            self->pointerPos -= 1.0;
+        if (pos >= size)
+            pos -= size;
+        ipart = (int)pos;
+        fpart = pos - ipart;
+        self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
     }
 }
 
 static void
-Phasor_readframes_ai(Phasor *self) {
-    MYFLT ph, oneOnSr;
+OscTrig_readframes_ai(OscTrig *self) {
+    MYFLT ph, fpart, sizeOnSr;
     double inc, pos;
-    int i;
-    
+    int i, ipart;
+    MYFLT *tablelist = TableStream_getData(self->table);
+    int size = TableStream_getSize(self->table);
+
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    ph = _clip(PyFloat_AS_DOUBLE(self->phase));
-    
-    oneOnSr = 1.0 / self->sr;
+    ph = PyFloat_AS_DOUBLE(self->phase);
+    MYFLT *tr = Stream_getData((Stream *)self->trig_stream);
+    ph *= size;
+
+    sizeOnSr = size / self->sr;
     for (i=0; i<self->bufsize; i++) {
+        inc = fr[i] * sizeOnSr;
+        if (tr[i] == 1)
+            self->pointerPos = 0.0;
+        else {
+            self->pointerPos += inc;
+            self->pointerPos = Osc_clip(self->pointerPos, size);
+        }
         pos = self->pointerPos + ph;
-        if (pos > 1)
-            pos -= 1.0;
-        self->data[i] = pos;
-        
-        inc = fr[i] * oneOnSr;
-        self->pointerPos += inc;
-        if (self->pointerPos < 0)
-            self->pointerPos += 1.0;
-        else if (self->pointerPos >= 1)
-            self->pointerPos -= 1.0;
+        if (pos >= size)
+            pos -= size;
+        ipart = (int)pos;
+        fpart = pos - ipart;
+        self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
     }
 }
 
 static void
-Phasor_readframes_ia(Phasor *self) {
-    MYFLT fr, pha;
+OscTrig_readframes_ia(OscTrig *self) {
+    MYFLT fr, pha, fpart;
     double inc, pos;
-    int i;
-    
+    int i, ipart;
+    MYFLT *tablelist = TableStream_getData(self->table);
+    int size = TableStream_getSize(self->table);
+
     fr = PyFloat_AS_DOUBLE(self->freq);
     MYFLT *ph = Stream_getData((Stream *)self->phase_stream);
-    
-    inc = fr / self->sr;
-    
-    for (i=0; i<self->bufsize; i++) {
-        pha = _clip(ph[i]);
+    MYFLT *tr = Stream_getData((Stream *)self->trig_stream);
+    inc = fr * size / self->sr;
 
+    for (i=0; i<self->bufsize; i++) {
+        pha = ph[i] * size;
+        if (tr[i] == 1)
+            self->pointerPos = 0.0;
+        else {
+            self->pointerPos += inc;
+            self->pointerPos = Osc_clip(self->pointerPos, size);
+        }
         pos = self->pointerPos + pha;
-        if (pos > 1)
-            pos -= 1.0;
-        self->data[i] = pos;
-        
-        self->pointerPos += inc;
-        if (self->pointerPos < 0)
-            self->pointerPos += 1.0;
-        else if (self->pointerPos >= 1)
-            self->pointerPos -= 1.0;
+        if (pos >= size)
+            pos -= size;
+        ipart = (int)pos;
+        fpart = pos - ipart;
+        self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
     }
 }
 
 static void
-Phasor_readframes_aa(Phasor *self) {
-    MYFLT pha, oneOnSr;
+OscTrig_readframes_aa(OscTrig *self) {
+    MYFLT pha, fpart, sizeOnSr;
     double inc, pos;
-    int i;
-    
+    int i, ipart;
+    MYFLT *tablelist = TableStream_getData(self->table);
+    int size = TableStream_getSize(self->table);
+
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
     MYFLT *ph = Stream_getData((Stream *)self->phase_stream);
+    MYFLT *tr = Stream_getData((Stream *)self->trig_stream);
 
-    oneOnSr = 1.0 / self->sr;
-
+    sizeOnSr = size / self->sr;
     for (i=0; i<self->bufsize; i++) {
-        pha = _clip(ph[i]);
-        
+        inc = fr[i] * sizeOnSr;
+        pha = ph[i] * size;
+        if (tr[i] == 1)
+            self->pointerPos = 0.0;
+        else {
+            self->pointerPos += inc;
+            self->pointerPos = Osc_clip(self->pointerPos, size);
+        }
         pos = self->pointerPos + pha;
-        if (pos > 1)
-            pos -= 1.0;
-        self->data[i] = pos;
-        
-        inc = fr[i] * oneOnSr;
-        self->pointerPos += inc;
-        if (self->pointerPos < 0)
-            self->pointerPos += 1.0;
-        else if (self->pointerPos >= 1)
-            self->pointerPos -= 1.0;
+        if (pos >= size)
+            pos -= size;
+        ipart = (int)pos;
+        fpart = pos - ipart;
+        self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
     }
 }
 
-static void Phasor_postprocessing_ii(Phasor *self) { POST_PROCESSING_II };
-static void Phasor_postprocessing_ai(Phasor *self) { POST_PROCESSING_AI };
-static void Phasor_postprocessing_ia(Phasor *self) { POST_PROCESSING_IA };
-static void Phasor_postprocessing_aa(Phasor *self) { POST_PROCESSING_AA };
-static void Phasor_postprocessing_ireva(Phasor *self) { POST_PROCESSING_IREVA };
-static void Phasor_postprocessing_areva(Phasor *self) { POST_PROCESSING_AREVA };
-static void Phasor_postprocessing_revai(Phasor *self) { POST_PROCESSING_REVAI };
-static void Phasor_postprocessing_revaa(Phasor *self) { POST_PROCESSING_REVAA };
-static void Phasor_postprocessing_revareva(Phasor *self) { POST_PROCESSING_REVAREVA };
+static void OscTrig_postprocessing_ii(OscTrig *self) { POST_PROCESSING_II };
+static void OscTrig_postprocessing_ai(OscTrig *self) { POST_PROCESSING_AI };
+static void OscTrig_postprocessing_ia(OscTrig *self) { POST_PROCESSING_IA };
+static void OscTrig_postprocessing_aa(OscTrig *self) { POST_PROCESSING_AA };
+static void OscTrig_postprocessing_ireva(OscTrig *self) { POST_PROCESSING_IREVA };
+static void OscTrig_postprocessing_areva(OscTrig *self) { POST_PROCESSING_AREVA };
+static void OscTrig_postprocessing_revai(OscTrig *self) { POST_PROCESSING_REVAI };
+static void OscTrig_postprocessing_revaa(OscTrig *self) { POST_PROCESSING_REVAA };
+static void OscTrig_postprocessing_revareva(OscTrig *self) { POST_PROCESSING_REVAREVA };
 
 static void
-Phasor_setProcMode(Phasor *self)
+OscTrig_setProcMode(OscTrig *self)
 {
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:        
-            self->proc_func_ptr = Phasor_readframes_ii;
+        case 0:
+            self->proc_func_ptr = OscTrig_readframes_ii;
             break;
-        case 1:    
-            self->proc_func_ptr = Phasor_readframes_ai;
+        case 1:
+            self->proc_func_ptr = OscTrig_readframes_ai;
             break;
-        case 10:        
-            self->proc_func_ptr = Phasor_readframes_ia;
+        case 10:
+            self->proc_func_ptr = OscTrig_readframes_ia;
             break;
-        case 11:    
-            self->proc_func_ptr = Phasor_readframes_aa;
+        case 11:
+            self->proc_func_ptr = OscTrig_readframes_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
-            self->muladd_func_ptr = Phasor_postprocessing_ii;
+        case 0:
+            self->muladd_func_ptr = OscTrig_postprocessing_ii;
             break;
-        case 1:    
-            self->muladd_func_ptr = Phasor_postprocessing_ai;
+        case 1:
+            self->muladd_func_ptr = OscTrig_postprocessing_ai;
             break;
-        case 2:    
-            self->muladd_func_ptr = Phasor_postprocessing_revai;
+        case 2:
+            self->muladd_func_ptr = OscTrig_postprocessing_revai;
             break;
-        case 10:        
-            self->muladd_func_ptr = Phasor_postprocessing_ia;
+        case 10:
+            self->muladd_func_ptr = OscTrig_postprocessing_ia;
             break;
-        case 11:    
-            self->muladd_func_ptr = Phasor_postprocessing_aa;
+        case 11:
+            self->muladd_func_ptr = OscTrig_postprocessing_aa;
             break;
-        case 12:    
-            self->muladd_func_ptr = Phasor_postprocessing_revaa;
+        case 12:
+            self->muladd_func_ptr = OscTrig_postprocessing_revaa;
             break;
-        case 20:        
-            self->muladd_func_ptr = Phasor_postprocessing_ireva;
+        case 20:
+            self->muladd_func_ptr = OscTrig_postprocessing_ireva;
             break;
-        case 21:    
-            self->muladd_func_ptr = Phasor_postprocessing_areva;
+        case 21:
+            self->muladd_func_ptr = OscTrig_postprocessing_areva;
             break;
-        case 22:    
-            self->muladd_func_ptr = Phasor_postprocessing_revareva;
+        case 22:
+            self->muladd_func_ptr = OscTrig_postprocessing_revareva;
             break;
-    } 
+    }
 }
 
 static void
-Phasor_compute_next_data_frame(Phasor *self)
+OscTrig_compute_next_data_frame(OscTrig *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
 static int
-Phasor_traverse(Phasor *self, visitproc visit, void *arg)
+OscTrig_traverse(OscTrig *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->phase);    
-    Py_VISIT(self->phase_stream);    
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
+    Py_VISIT(self->table);
+    Py_VISIT(self->phase);
+    Py_VISIT(self->phase_stream);
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->trig);
+    Py_VISIT(self->trig_stream);
     return 0;
 }
 
-static int 
-Phasor_clear(Phasor *self)
+static int
+OscTrig_clear(OscTrig *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->phase);    
-    Py_CLEAR(self->phase_stream);    
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
+    Py_CLEAR(self->table);
+    Py_CLEAR(self->phase);
+    Py_CLEAR(self->phase_stream);
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->trig);
+    Py_CLEAR(self->trig_stream);
     return 0;
 }
 
 static void
-Phasor_dealloc(Phasor* self)
+OscTrig_dealloc(OscTrig* self)
 {
     pyo_DEALLOC
-    Phasor_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    OscTrig_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
-Phasor_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+OscTrig_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
-    PyObject *freqtmp=NULL, *phasetmp=NULL, *multmp=NULL, *addtmp=NULL;
-    Phasor *self;
-    self = (Phasor *)type->tp_alloc(type, 0);
-    
-    self->freq = PyFloat_FromDouble(100);
+    PyObject *tabletmp, *trigtmp, *freqtmp=NULL, *phasetmp=NULL, *multmp=NULL, *addtmp=NULL;
+    OscTrig *self;
+    self = (OscTrig *)type->tp_alloc(type, 0);
+
+    self->freq = PyFloat_FromDouble(1000);
     self->phase = PyFloat_FromDouble(0);
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
     self->pointerPos = 0.;
-    
+    self->interp = 2;
+
     INIT_OBJECT_COMMON
-    Stream_setFunctionPtr(self->stream, Phasor_compute_next_data_frame);
-    self->mode_func_ptr = Phasor_setProcMode;
+    Stream_setFunctionPtr(self->stream, OscTrig_compute_next_data_frame);
+    self->mode_func_ptr = OscTrig_setProcMode;
 
-    static char *kwlist[] = {"freq", "phase", "mul", "add", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &freqtmp, &phasetmp, &multmp, &addtmp))
+    static char *kwlist[] = {"table", "trig", "freq", "phase", "interp", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOiOO", kwlist, &tabletmp, &trigtmp, &freqtmp, &phasetmp, &self->interp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
-    if (freqtmp) {
-        PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
+
+    if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
+        PyErr_SetString(PyExc_TypeError, "\"table\" argument of OscTrig must be a PyoTableObject.\n");
+        Py_RETURN_NONE;
+    }
+    Py_XDECREF(self->table);
+    self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", "");
+
+    if (trigtmp) {
+        PyObject_CallMethod((PyObject *)self, "setTrig", "O", trigtmp);
     }
 
     if (phasetmp) {
         PyObject_CallMethod((PyObject *)self, "setPhase", "O", phasetmp);
     }
-    
+
+    if (freqtmp) {
+        PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
+    }
+
     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);
-    
+
+    SET_INTERP_POINTER
+
     return (PyObject *)self;
 }
 
-static PyObject * Phasor_getServer(Phasor* self) { GET_SERVER };
-static PyObject * Phasor_getStream(Phasor* self) { GET_STREAM };
-static PyObject * Phasor_setMul(Phasor *self, PyObject *arg) { SET_MUL };	
-static PyObject * Phasor_setAdd(Phasor *self, PyObject *arg) { SET_ADD };	
-static PyObject * Phasor_setSub(Phasor *self, PyObject *arg) { SET_SUB };	
-static PyObject * Phasor_setDiv(Phasor *self, PyObject *arg) { SET_DIV };	
+static PyObject * OscTrig_getServer(OscTrig* self) { GET_SERVER };
+static PyObject * OscTrig_getStream(OscTrig* self) { GET_STREAM };
+static PyObject * OscTrig_setMul(OscTrig *self, PyObject *arg) { SET_MUL };
+static PyObject * OscTrig_setAdd(OscTrig *self, PyObject *arg) { SET_ADD };
+static PyObject * OscTrig_setSub(OscTrig *self, PyObject *arg) { SET_SUB };
+static PyObject * OscTrig_setDiv(OscTrig *self, PyObject *arg) { SET_DIV };
 
-static PyObject * Phasor_play(Phasor *self, PyObject *args, PyObject *kwds) { PLAY };
-static PyObject * Phasor_out(Phasor *self, PyObject *args, PyObject *kwds) { OUT };
-static PyObject * Phasor_stop(Phasor *self) { STOP };
+static PyObject * OscTrig_play(OscTrig *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * OscTrig_out(OscTrig *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * OscTrig_stop(OscTrig *self) { STOP };
 
-static PyObject * Phasor_multiply(Phasor *self, PyObject *arg) { MULTIPLY };
-static PyObject * Phasor_inplace_multiply(Phasor *self, PyObject *arg) { INPLACE_MULTIPLY };
-static PyObject * Phasor_add(Phasor *self, PyObject *arg) { ADD };
-static PyObject * Phasor_inplace_add(Phasor *self, PyObject *arg) { INPLACE_ADD };
-static PyObject * Phasor_sub(Phasor *self, PyObject *arg) { SUB };
-static PyObject * Phasor_inplace_sub(Phasor *self, PyObject *arg) { INPLACE_SUB };
-static PyObject * Phasor_div(Phasor *self, PyObject *arg) { DIV };
-static PyObject * Phasor_inplace_div(Phasor *self, PyObject *arg) { INPLACE_DIV };
+static PyObject * OscTrig_multiply(OscTrig *self, PyObject *arg) { MULTIPLY };
+static PyObject * OscTrig_inplace_multiply(OscTrig *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * OscTrig_add(OscTrig *self, PyObject *arg) { ADD };
+static PyObject * OscTrig_inplace_add(OscTrig *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * OscTrig_sub(OscTrig *self, PyObject *arg) { SUB };
+static PyObject * OscTrig_inplace_sub(OscTrig *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * OscTrig_div(OscTrig *self, PyObject *arg) { DIV };
+static PyObject * OscTrig_inplace_div(OscTrig *self, PyObject *arg) { INPLACE_DIV };
 
 static PyObject *
-Phasor_setFreq(Phasor *self, PyObject *arg)
+OscTrig_getTable(OscTrig* self)
+{
+    Py_INCREF(self->table);
+    return self->table;
+};
+
+static PyObject *
+OscTrig_setTable(OscTrig *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 *
+OscTrig_setTrig(OscTrig *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_XDECREF(self->trig);
+	if (isNumber == 1) {
+        Py_INCREF(Py_None);
+        return Py_None;
 	}
-    
+	else {
+		self->trig = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->trig, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->trig_stream);
+        self->trig_stream = (Stream *)streamtmp;
+	}
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+OscTrig_setFreq(OscTrig *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -2905,25 +2895,22 @@ Phasor_setFreq(Phasor *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
-Phasor_setPhase(Phasor *self, PyObject *arg)
+OscTrig_setPhase(OscTrig *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->phase);
@@ -2939,401 +2926,538 @@ Phasor_setPhase(Phasor *self, PyObject *arg)
         self->phase_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
-static PyObject * 
-Phasor_reset(Phasor *self) 
+static PyObject *
+OscTrig_setInterp(OscTrig *self, PyObject *arg)
 {
-    self->pointerPos = 0.0;
+    ASSERT_ARG_NOT_NULL
+
+    int isNumber = PyNumber_Check(arg);
+
+	if (isNumber == 1) {
+		self->interp = PyInt_AsLong(PyNumber_Int(arg));
+    }
+
+    SET_INTERP_POINTER
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
-static PyMemberDef Phasor_members[] = {
-{"server", T_OBJECT_EX, offsetof(Phasor, server), 0, "Pyo server."},
-{"stream", T_OBJECT_EX, offsetof(Phasor, stream), 0, "Stream object."},
-{"freq", T_OBJECT_EX, offsetof(Phasor, freq), 0, "Frequency in cycle per second."},
-{"phase", T_OBJECT_EX, offsetof(Phasor, phase), 0, "Phasorillator phase."},
-{"mul", T_OBJECT_EX, offsetof(Phasor, mul), 0, "Mul factor."},
-{"add", T_OBJECT_EX, offsetof(Phasor, add), 0, "Add factor."},
-{NULL}  /* Sentinel */
-};
+static PyObject *
+OscTrig_reset(OscTrig *self)
+{
+    self->pointerPos = 0.0;
+    Py_INCREF(Py_None);
+    return Py_None;
+}
 
-static PyMethodDef Phasor_methods[] = {
-{"getServer", (PyCFunction)Phasor_getServer, METH_NOARGS, "Returns server object."},
-{"_getStream", (PyCFunction)Phasor_getStream, METH_NOARGS, "Returns stream object."},
-{"play", (PyCFunction)Phasor_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
-{"out", (PyCFunction)Phasor_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
-{"stop", (PyCFunction)Phasor_stop, METH_NOARGS, "Stops computing."},
-{"setFreq", (PyCFunction)Phasor_setFreq, METH_O, "Sets oscillator frequency in cycle per second."},
-{"setPhase", (PyCFunction)Phasor_setPhase, METH_O, "Sets oscillator phase."},
-{"reset", (PyCFunction)Phasor_reset, METH_NOARGS, "Resets pointer position to 0."},
-{"setMul", (PyCFunction)Phasor_setMul, METH_O, "Sets oscillator mul factor."},
-{"setAdd", (PyCFunction)Phasor_setAdd, METH_O, "Sets oscillator add factor."},
-{"setSub", (PyCFunction)Phasor_setSub, METH_O, "Sets oscillator inverse add factor."},
-{"setDiv", (PyCFunction)Phasor_setDiv, METH_O, "Sets inverse mul factor."},
-{NULL}  /* Sentinel */
+static PyMemberDef OscTrig_members[] = {
+    {"server", T_OBJECT_EX, offsetof(OscTrig, server), 0, "Pyo server."},
+    {"stream", T_OBJECT_EX, offsetof(OscTrig, stream), 0, "Stream object."},
+    {"table", T_OBJECT_EX, offsetof(OscTrig, table), 0, "Waveform table."},
+    {"trig", T_OBJECT_EX, offsetof(OscTrig, trig), 0, "Trigger signal."},
+    {"freq", T_OBJECT_EX, offsetof(OscTrig, freq), 0, "Frequency in cycle per second."},
+    {"phase", T_OBJECT_EX, offsetof(OscTrig, phase), 0, "OscTrigillator phase."},
+    {"mul", T_OBJECT_EX, offsetof(OscTrig, mul), 0, "Mul factor."},
+    {"add", T_OBJECT_EX, offsetof(OscTrig, add), 0, "Add factor."},
+    {NULL}  /* Sentinel */
 };
 
-static PyNumberMethods Phasor_as_number = {
-(binaryfunc)Phasor_add,                      /*nb_add*/
-(binaryfunc)Phasor_sub,                 /*nb_subtract*/
-(binaryfunc)Phasor_multiply,                 /*nb_multiply*/
-(binaryfunc)Phasor_div,                   /*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*/
-0,                                          /*nb_coerce*/
-0,                       /*nb_int*/
-0,                      /*nb_long*/
-0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
-(binaryfunc)Phasor_inplace_add,              /*inplace_add*/
-(binaryfunc)Phasor_inplace_sub,         /*inplace_subtract*/
-(binaryfunc)Phasor_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)Phasor_inplace_div,           /*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*/
-0,              /*nb_true_divide*/
-0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
-0,                     /* nb_index */
+static PyMethodDef OscTrig_methods[] = {
+    {"getTable", (PyCFunction)OscTrig_getTable, METH_NOARGS, "Returns waveform table object."},
+    {"getServer", (PyCFunction)OscTrig_getServer, METH_NOARGS, "Returns server object."},
+    {"_getStream", (PyCFunction)OscTrig_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)OscTrig_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+    {"out", (PyCFunction)OscTrig_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+    {"stop", (PyCFunction)OscTrig_stop, METH_NOARGS, "Stops computing."},
+    {"setTable", (PyCFunction)OscTrig_setTable, METH_O, "Sets oscillator table."},
+	{"setTrig", (PyCFunction)OscTrig_setTrig, METH_O, "Sets the reset trigger signal."},
+	{"setFreq", (PyCFunction)OscTrig_setFreq, METH_O, "Sets oscillator frequency in cycle per second."},
+    {"setPhase", (PyCFunction)OscTrig_setPhase, METH_O, "Sets oscillator phase."},
+    {"setInterp", (PyCFunction)OscTrig_setInterp, METH_O, "Sets oscillator interpolation mode."},
+    {"reset", (PyCFunction)OscTrig_reset, METH_NOARGS, "Resets pointer position to 0."},
+	{"setMul", (PyCFunction)OscTrig_setMul, METH_O, "Sets oscillator mul factor."},
+	{"setAdd", (PyCFunction)OscTrig_setAdd, METH_O, "Sets oscillator add factor."},
+    {"setSub", (PyCFunction)OscTrig_setSub, METH_O, "Sets oscillator inverse add factor."},
+    {"setDiv", (PyCFunction)OscTrig_setDiv, METH_O, "Sets inverse mul factor."},
+    {NULL}  /* Sentinel */
 };
 
-PyTypeObject PhasorType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
-"_pyo.Phasor_base",         /*tp_name*/
-sizeof(Phasor),         /*tp_basicsize*/
-0,                         /*tp_itemsize*/
-(destructor)Phasor_dealloc, /*tp_dealloc*/
-0,                         /*tp_print*/
-0,                         /*tp_getattr*/
-0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
-0,                         /*tp_repr*/
-&Phasor_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*/
-"Phasor objects. Phase incrementor from 0 to 1.",           /* tp_doc */
-(traverseproc)Phasor_traverse,   /* tp_traverse */
-(inquiry)Phasor_clear,           /* tp_clear */
-0,		               /* tp_richcompare */
-0,		               /* tp_weaklistoffset */
-0,		               /* tp_iter */
-0,		               /* tp_iternext */
-Phasor_methods,             /* tp_methods */
-Phasor_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 */
-Phasor_new,                 /* tp_new */
+static PyNumberMethods OscTrig_as_number = {
+    (binaryfunc)OscTrig_add,                      /*nb_add*/
+    (binaryfunc)OscTrig_sub,                 /*nb_subtract*/
+    (binaryfunc)OscTrig_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)OscTrig_inplace_add,              /*inplace_add*/
+    (binaryfunc)OscTrig_inplace_sub,         /*inplace_subtract*/
+    (binaryfunc)OscTrig_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)OscTrig_div,                       /*nb_true_divide*/
+    0,     /*nb_inplace_floor_divide*/
+    (binaryfunc)OscTrig_inplace_div,                       /*nb_inplace_true_divide*/
+    0,                     /* nb_index */
+};
+
+PyTypeObject OscTrigType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.OscTrig_base",         /*tp_name*/
+    sizeof(OscTrig),         /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)OscTrig_dealloc, /*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
+    0,                         /*tp_repr*/
+    &OscTrig_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*/
+    "OscTrig objects. Generates an oscillatory waveform with sample accurate reset signal.",           /* tp_doc */
+    (traverseproc)OscTrig_traverse,   /* tp_traverse */
+    (inquiry)OscTrig_clear,           /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    OscTrig_methods,             /* tp_methods */
+    OscTrig_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 */
+    OscTrig_new,                 /* tp_new */
 };
 
 /**************/
-/* Pointer object */
+/* Phasor object */
 /**************/
 typedef struct {
     pyo_audio_HEAD
-    PyObject *table;
-    PyObject *index;
-    Stream *index_stream;
-    int modebuffer[2];
-} Pointer;
+    PyObject *freq;
+    Stream *freq_stream;
+    PyObject *phase;
+    Stream *phase_stream;
+    int modebuffer[4];
+    double pointerPos;
+} Phasor;
 
 static void
-Pointer_readframes_a(Pointer *self) {
-    MYFLT fpart;
-    double ph;
-    int i, ipart;
-    MYFLT *tablelist = TableStream_getData(self->table);
-    int size = TableStream_getSize(self->table);
-    
-    MYFLT *pha = Stream_getData((Stream *)self->index_stream);
-    
+Phasor_readframes_ii(Phasor *self) {
+    MYFLT fr, ph;
+    double inc, pos;
+    int i;
+
+    fr = PyFloat_AS_DOUBLE(self->freq);
+    ph = _clip(PyFloat_AS_DOUBLE(self->phase));
+    inc = fr / self->sr;
+
     for (i=0; i<self->bufsize; i++) {
-        ph = Osc_clip(pha[i] * size, size);
-   
-        ipart = (int)ph;
-        fpart = ph - ipart;
-        self->data[i] = tablelist[ipart] * (1.0 - fpart) + tablelist[ipart+1] * fpart;
+        pos = self->pointerPos + ph;
+        if (pos > 1)
+            pos -= 1.0;
+        self->data[i] = pos;
+
+        self->pointerPos += inc;
+        if (self->pointerPos < 0)
+            self->pointerPos += 1.0;
+        else if (self->pointerPos >= 1)
+            self->pointerPos -= 1.0;
     }
 }
 
-static void Pointer_postprocessing_ii(Pointer *self) { POST_PROCESSING_II };
-static void Pointer_postprocessing_ai(Pointer *self) { POST_PROCESSING_AI };
-static void Pointer_postprocessing_ia(Pointer *self) { POST_PROCESSING_IA };
-static void Pointer_postprocessing_aa(Pointer *self) { POST_PROCESSING_AA };
-static void Pointer_postprocessing_ireva(Pointer *self) { POST_PROCESSING_IREVA };
-static void Pointer_postprocessing_areva(Pointer *self) { POST_PROCESSING_AREVA };
-static void Pointer_postprocessing_revai(Pointer *self) { POST_PROCESSING_REVAI };
-static void Pointer_postprocessing_revaa(Pointer *self) { POST_PROCESSING_REVAA };
-static void Pointer_postprocessing_revareva(Pointer *self) { POST_PROCESSING_REVAREVA };
-
 static void
-Pointer_setProcMode(Pointer *self)
-{
-    int muladdmode;
-    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+Phasor_readframes_ai(Phasor *self) {
+    MYFLT ph, oneOnSr;
+    double inc, pos;
+    int i;
 
-    self->proc_func_ptr = Pointer_readframes_a;
+    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
+    ph = _clip(PyFloat_AS_DOUBLE(self->phase));
 
-	switch (muladdmode) {
-        case 0:        
-            self->muladd_func_ptr = Pointer_postprocessing_ii;
-            break;
-        case 1:    
-            self->muladd_func_ptr = Pointer_postprocessing_ai;
-            break;
-        case 2:    
-            self->muladd_func_ptr = Pointer_postprocessing_revai;
-            break;
-        case 10:        
-            self->muladd_func_ptr = Pointer_postprocessing_ia;
-            break;
-        case 11:    
-            self->muladd_func_ptr = Pointer_postprocessing_aa;
-            break;
-        case 12:    
-            self->muladd_func_ptr = Pointer_postprocessing_revaa;
-            break;
-        case 20:        
-            self->muladd_func_ptr = Pointer_postprocessing_ireva;
-            break;
-        case 21:    
-            self->muladd_func_ptr = Pointer_postprocessing_areva;
-            break;
-        case 22:    
-            self->muladd_func_ptr = Pointer_postprocessing_revareva;
-            break;
-    } 
+    oneOnSr = 1.0 / self->sr;
+    for (i=0; i<self->bufsize; i++) {
+        pos = self->pointerPos + ph;
+        if (pos > 1)
+            pos -= 1.0;
+        self->data[i] = pos;
+
+        inc = fr[i] * oneOnSr;
+        self->pointerPos += inc;
+        if (self->pointerPos < 0)
+            self->pointerPos += 1.0;
+        else if (self->pointerPos >= 1)
+            self->pointerPos -= 1.0;
+    }
 }
 
 static void
-Pointer_compute_next_data_frame(Pointer *self)
-{
-    (*self->proc_func_ptr)(self); 
-    (*self->muladd_func_ptr)(self);
-}
+Phasor_readframes_ia(Phasor *self) {
+    MYFLT fr, pha;
+    double inc, pos;
+    int i;
 
-static int
-Pointer_traverse(Pointer *self, visitproc visit, void *arg)
-{
-    pyo_VISIT
-    Py_VISIT(self->table);
-    Py_VISIT(self->index);    
-    Py_VISIT(self->index_stream);    
-    return 0;
-}
+    fr = PyFloat_AS_DOUBLE(self->freq);
+    MYFLT *ph = Stream_getData((Stream *)self->phase_stream);
 
-static int 
-Pointer_clear(Pointer *self)
-{
-    pyo_CLEAR
-    Py_CLEAR(self->table);
-    Py_CLEAR(self->index);    
-    Py_CLEAR(self->index_stream);    
-    return 0;
-}
+    inc = fr / self->sr;
 
-static void
-Pointer_dealloc(Pointer* self)
-{
-    pyo_DEALLOC
-    Pointer_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    for (i=0; i<self->bufsize; i++) {
+        pha = _clip(ph[i]);
+
+        pos = self->pointerPos + pha;
+        if (pos > 1)
+            pos -= 1.0;
+        self->data[i] = pos;
+
+        self->pointerPos += inc;
+        if (self->pointerPos < 0)
+            self->pointerPos += 1.0;
+        else if (self->pointerPos >= 1)
+            self->pointerPos -= 1.0;
+    }
 }
 
-static PyObject *
-Pointer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
+static void
+Phasor_readframes_aa(Phasor *self) {
+    MYFLT pha, oneOnSr;
+    double inc, pos;
     int i;
-    PyObject *tabletmp, *indextmp, *multmp=NULL, *addtmp=NULL;
-    Pointer *self;
-    self = (Pointer *)type->tp_alloc(type, 0);
-    
+
+    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
+    MYFLT *ph = Stream_getData((Stream *)self->phase_stream);
+
+    oneOnSr = 1.0 / self->sr;
+
+    for (i=0; i<self->bufsize; i++) {
+        pha = _clip(ph[i]);
+
+        pos = self->pointerPos + pha;
+        if (pos > 1)
+            pos -= 1.0;
+        self->data[i] = pos;
+
+        inc = fr[i] * oneOnSr;
+        self->pointerPos += inc;
+        if (self->pointerPos < 0)
+            self->pointerPos += 1.0;
+        else if (self->pointerPos >= 1)
+            self->pointerPos -= 1.0;
+    }
+}
+
+static void Phasor_postprocessing_ii(Phasor *self) { POST_PROCESSING_II };
+static void Phasor_postprocessing_ai(Phasor *self) { POST_PROCESSING_AI };
+static void Phasor_postprocessing_ia(Phasor *self) { POST_PROCESSING_IA };
+static void Phasor_postprocessing_aa(Phasor *self) { POST_PROCESSING_AA };
+static void Phasor_postprocessing_ireva(Phasor *self) { POST_PROCESSING_IREVA };
+static void Phasor_postprocessing_areva(Phasor *self) { POST_PROCESSING_AREVA };
+static void Phasor_postprocessing_revai(Phasor *self) { POST_PROCESSING_REVAI };
+static void Phasor_postprocessing_revaa(Phasor *self) { POST_PROCESSING_REVAA };
+static void Phasor_postprocessing_revareva(Phasor *self) { POST_PROCESSING_REVAREVA };
+
+static void
+Phasor_setProcMode(Phasor *self)
+{
+    int procmode, muladdmode;
+    procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+	switch (procmode) {
+        case 0:
+            self->proc_func_ptr = Phasor_readframes_ii;
+            break;
+        case 1:
+            self->proc_func_ptr = Phasor_readframes_ai;
+            break;
+        case 10:
+            self->proc_func_ptr = Phasor_readframes_ia;
+            break;
+        case 11:
+            self->proc_func_ptr = Phasor_readframes_aa;
+            break;
+    }
+	switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = Phasor_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = Phasor_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = Phasor_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = Phasor_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = Phasor_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = Phasor_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = Phasor_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = Phasor_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = Phasor_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+Phasor_compute_next_data_frame(Phasor *self)
+{
+    (*self->proc_func_ptr)(self);
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+Phasor_traverse(Phasor *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->phase);
+    Py_VISIT(self->phase_stream);
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    return 0;
+}
+
+static int
+Phasor_clear(Phasor *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->phase);
+    Py_CLEAR(self->phase_stream);
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    return 0;
+}
+
+static void
+Phasor_dealloc(Phasor* self)
+{
+    pyo_DEALLOC
+    Phasor_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+Phasor_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *freqtmp=NULL, *phasetmp=NULL, *multmp=NULL, *addtmp=NULL;
+    Phasor *self;
+    self = (Phasor *)type->tp_alloc(type, 0);
+
+    self->freq = PyFloat_FromDouble(100);
+    self->phase = PyFloat_FromDouble(0);
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+	self->modebuffer[2] = 0;
+	self->modebuffer[3] = 0;
+    self->pointerPos = 0.;
+
     INIT_OBJECT_COMMON
-    Stream_setFunctionPtr(self->stream, Pointer_compute_next_data_frame);
-    self->mode_func_ptr = Pointer_setProcMode;
+    Stream_setFunctionPtr(self->stream, Phasor_compute_next_data_frame);
+    self->mode_func_ptr = Phasor_setProcMode;
 
-    static char *kwlist[] = {"table", "index", "mul", "add", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist, &tabletmp, &indextmp, &multmp, &addtmp))
+    static char *kwlist[] = {"freq", "phase", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &freqtmp, &phasetmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
-    if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
-        PySys_WriteStderr("TypeError: \"table\" argument of Pointer must be a PyoTableObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+
+    if (freqtmp) {
+        PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    Py_XDECREF(self->table);
-    self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", "");
-    
-    if (indextmp) {
-        PyObject_CallMethod((PyObject *)self, "setIndex", "O", indextmp);
+
+    if (phasetmp) {
+        PyObject_CallMethod((PyObject *)self, "setPhase", "O", phasetmp);
+    }
+
+    if (multmp) {
+        PyObject_CallMethod((PyObject *)self, "setMul", "O", 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 * Pointer_getServer(Pointer* self) { GET_SERVER };
-static PyObject * Pointer_getStream(Pointer* self) { GET_STREAM };
-static PyObject * Pointer_setMul(Pointer *self, PyObject *arg) { SET_MUL };	
-static PyObject * Pointer_setAdd(Pointer *self, PyObject *arg) { SET_ADD };	
-static PyObject * Pointer_setSub(Pointer *self, PyObject *arg) { SET_SUB };	
-static PyObject * Pointer_setDiv(Pointer *self, PyObject *arg) { SET_DIV };	
+static PyObject * Phasor_getServer(Phasor* self) { GET_SERVER };
+static PyObject * Phasor_getStream(Phasor* self) { GET_STREAM };
+static PyObject * Phasor_setMul(Phasor *self, PyObject *arg) { SET_MUL };
+static PyObject * Phasor_setAdd(Phasor *self, PyObject *arg) { SET_ADD };
+static PyObject * Phasor_setSub(Phasor *self, PyObject *arg) { SET_SUB };
+static PyObject * Phasor_setDiv(Phasor *self, PyObject *arg) { SET_DIV };
 
-static PyObject * Pointer_play(Pointer *self, PyObject *args, PyObject *kwds) { PLAY };
-static PyObject * Pointer_out(Pointer *self, PyObject *args, PyObject *kwds) { OUT };
-static PyObject * Pointer_stop(Pointer *self) { STOP };
+static PyObject * Phasor_play(Phasor *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * Phasor_out(Phasor *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * Phasor_stop(Phasor *self) { STOP };
 
-static PyObject * Pointer_multiply(Pointer *self, PyObject *arg) { MULTIPLY };
-static PyObject * Pointer_inplace_multiply(Pointer *self, PyObject *arg) { INPLACE_MULTIPLY };
-static PyObject * Pointer_add(Pointer *self, PyObject *arg) { ADD };
-static PyObject * Pointer_inplace_add(Pointer *self, PyObject *arg) { INPLACE_ADD };
-static PyObject * Pointer_sub(Pointer *self, PyObject *arg) { SUB };
-static PyObject * Pointer_inplace_sub(Pointer *self, PyObject *arg) { INPLACE_SUB };
-static PyObject * Pointer_div(Pointer *self, PyObject *arg) { DIV };
-static PyObject * Pointer_inplace_div(Pointer *self, PyObject *arg) { INPLACE_DIV };
+static PyObject * Phasor_multiply(Phasor *self, PyObject *arg) { MULTIPLY };
+static PyObject * Phasor_inplace_multiply(Phasor *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * Phasor_add(Phasor *self, PyObject *arg) { ADD };
+static PyObject * Phasor_inplace_add(Phasor *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * Phasor_sub(Phasor *self, PyObject *arg) { SUB };
+static PyObject * Phasor_inplace_sub(Phasor *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * Phasor_div(Phasor *self, PyObject *arg) { DIV };
+static PyObject * Phasor_inplace_div(Phasor *self, PyObject *arg) { INPLACE_DIV };
 
 static PyObject *
-Pointer_getTable(Pointer* self)
+Phasor_setFreq(Phasor *self, PyObject *arg)
 {
-    Py_INCREF(self->table);
-    return self->table;
-};
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
 
-static PyObject *
-Pointer_setTable(Pointer *self, PyObject *arg)
-{
-	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
 	tmp = arg;
-	Py_DECREF(self->table);
-    self->table = PyObject_CallMethod((PyObject *)tmp, "getTableStream", "");
-    
+	Py_INCREF(tmp);
+	Py_DECREF(self->freq);
+	if (isNumber == 1) {
+		self->freq = PyNumber_Float(tmp);
+        self->modebuffer[2] = 0;
+	}
+	else {
+		self->freq = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->freq_stream);
+        self->freq_stream = (Stream *)streamtmp;
+		self->modebuffer[2] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
-Pointer_setIndex(Pointer *self, PyObject *arg)
+Phasor_setPhase(Phasor *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	if (isNumber == 1) {
-		PySys_WriteStderr("TypeError: \"index\" attribute of Pointer must be a PyoObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
-	}
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
-	Py_XDECREF(self->index);
+	Py_DECREF(self->phase);
+	if (isNumber == 1) {
+		self->phase = PyNumber_Float(tmp);
+        self->modebuffer[3] = 0;
+	}
+	else {
+		self->phase = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->phase, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->phase_stream);
+        self->phase_stream = (Stream *)streamtmp;
+		self->modebuffer[3] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
 
-    self->index = tmp;
-    streamtmp = PyObject_CallMethod((PyObject *)self->index, "_getStream", NULL);
-    Py_INCREF(streamtmp);
-    Py_XDECREF(self->index_stream);
-    self->index_stream = (Stream *)streamtmp;
-    
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
-static PyMemberDef Pointer_members[] = {
-{"server", T_OBJECT_EX, offsetof(Pointer, server), 0, "Pyo server."},
-{"stream", T_OBJECT_EX, offsetof(Pointer, stream), 0, "Stream object."},
-{"table", T_OBJECT_EX, offsetof(Pointer, table), 0, "Waveform table."},
-{"index", T_OBJECT_EX, offsetof(Pointer, index), 0, "Reader index."},
-{"mul", T_OBJECT_EX, offsetof(Pointer, mul), 0, "Mul factor."},
-{"add", T_OBJECT_EX, offsetof(Pointer, add), 0, "Add factor."},
+static PyObject *
+Phasor_reset(Phasor *self)
+{
+    self->pointerPos = 0.0;
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyMemberDef Phasor_members[] = {
+{"server", T_OBJECT_EX, offsetof(Phasor, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(Phasor, stream), 0, "Stream object."},
+{"freq", T_OBJECT_EX, offsetof(Phasor, freq), 0, "Frequency in cycle per second."},
+{"phase", T_OBJECT_EX, offsetof(Phasor, phase), 0, "Phasorillator phase."},
+{"mul", T_OBJECT_EX, offsetof(Phasor, mul), 0, "Mul factor."},
+{"add", T_OBJECT_EX, offsetof(Phasor, add), 0, "Add factor."},
 {NULL}  /* Sentinel */
 };
 
-static PyMethodDef Pointer_methods[] = {
-{"getTable", (PyCFunction)Pointer_getTable, METH_NOARGS, "Returns waveform table object."},
-{"getServer", (PyCFunction)Pointer_getServer, METH_NOARGS, "Returns server object."},
-{"_getStream", (PyCFunction)Pointer_getStream, METH_NOARGS, "Returns stream object."},
-{"play", (PyCFunction)Pointer_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
-{"out", (PyCFunction)Pointer_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
-{"stop", (PyCFunction)Pointer_stop, METH_NOARGS, "Stops computing."},
-{"setTable", (PyCFunction)Pointer_setTable, METH_O, "Sets oscillator table."},
-{"setIndex", (PyCFunction)Pointer_setIndex, METH_O, "Sets reader index."},
-{"setMul", (PyCFunction)Pointer_setMul, METH_O, "Sets oscillator mul factor."},
-{"setAdd", (PyCFunction)Pointer_setAdd, METH_O, "Sets oscillator add factor."},
-{"setSub", (PyCFunction)Pointer_setSub, METH_O, "Sets oscillator inverse add factor."},
-{"setDiv", (PyCFunction)Pointer_setDiv, METH_O, "Sets inverse mul factor."},
+static PyMethodDef Phasor_methods[] = {
+{"getServer", (PyCFunction)Phasor_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)Phasor_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)Phasor_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"out", (PyCFunction)Phasor_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+{"stop", (PyCFunction)Phasor_stop, METH_NOARGS, "Stops computing."},
+{"setFreq", (PyCFunction)Phasor_setFreq, METH_O, "Sets oscillator frequency in cycle per second."},
+{"setPhase", (PyCFunction)Phasor_setPhase, METH_O, "Sets oscillator phase."},
+{"reset", (PyCFunction)Phasor_reset, METH_NOARGS, "Resets pointer position to 0."},
+{"setMul", (PyCFunction)Phasor_setMul, METH_O, "Sets oscillator mul factor."},
+{"setAdd", (PyCFunction)Phasor_setAdd, METH_O, "Sets oscillator add factor."},
+{"setSub", (PyCFunction)Phasor_setSub, METH_O, "Sets oscillator inverse add factor."},
+{"setDiv", (PyCFunction)Phasor_setDiv, METH_O, "Sets inverse mul factor."},
 {NULL}  /* Sentinel */
 };
 
-static PyNumberMethods Pointer_as_number = {
-(binaryfunc)Pointer_add,                      /*nb_add*/
-(binaryfunc)Pointer_sub,                 /*nb_subtract*/
-(binaryfunc)Pointer_multiply,                 /*nb_multiply*/
-(binaryfunc)Pointer_div,                   /*nb_divide*/
+static PyNumberMethods Phasor_as_number = {
+(binaryfunc)Phasor_add,                      /*nb_add*/
+(binaryfunc)Phasor_sub,                 /*nb_subtract*/
+(binaryfunc)Phasor_multiply,                 /*nb_multiply*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -3347,16 +3471,16 @@ static PyNumberMethods Pointer_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
-(binaryfunc)Pointer_inplace_add,              /*inplace_add*/
-(binaryfunc)Pointer_inplace_sub,         /*inplace_subtract*/
-(binaryfunc)Pointer_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)Pointer_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
+(binaryfunc)Phasor_inplace_add,              /*inplace_add*/
+(binaryfunc)Phasor_inplace_sub,         /*inplace_subtract*/
+(binaryfunc)Phasor_inplace_multiply,         /*inplace_multiply*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -3365,25 +3489,24 @@ static PyNumberMethods Pointer_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)Phasor_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)Phasor_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
-PyTypeObject PointerType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
-"_pyo.Pointer_base",         /*tp_name*/
-sizeof(Pointer),         /*tp_basicsize*/
+PyTypeObject PhasorType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.Phasor_base",         /*tp_name*/
+sizeof(Phasor),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
-(destructor)Pointer_dealloc, /*tp_dealloc*/
+(destructor)Phasor_dealloc, /*tp_dealloc*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
-&Pointer_as_number,             /*tp_as_number*/
+&Phasor_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
 0,                         /*tp_as_mapping*/
 0,                         /*tp_hash */
@@ -3393,15 +3516,15 @@ sizeof(Pointer),         /*tp_basicsize*/
 0,                         /*tp_setattro*/
 0,                         /*tp_as_buffer*/
 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
-"Pointer objects. Read a waveform table with a pointer index.",           /* tp_doc */
-(traverseproc)Pointer_traverse,   /* tp_traverse */
-(inquiry)Pointer_clear,           /* tp_clear */
+"Phasor objects. Phase incrementor from 0 to 1.",           /* tp_doc */
+(traverseproc)Phasor_traverse,   /* tp_traverse */
+(inquiry)Phasor_clear,           /* tp_clear */
 0,		               /* tp_richcompare */
 0,		               /* tp_weaklistoffset */
 0,		               /* tp_iter */
 0,		               /* tp_iternext */
-Pointer_methods,             /* tp_methods */
-Pointer_members,             /* tp_members */
+Phasor_methods,             /* tp_methods */
+Phasor_members,             /* tp_members */
 0,                      /* tp_getset */
 0,                         /* tp_base */
 0,                         /* tp_dict */
@@ -3410,11 +3533,11 @@ Pointer_members,             /* tp_members */
 0,                         /* tp_dictoffset */
 0,      /* tp_init */
 0,                         /* tp_alloc */
-Pointer_new,                 /* tp_new */
+Phasor_new,                 /* tp_new */
 };
 
 /**************/
-/* TableIndex object */
+/* Pointer object */
 /**************/
 typedef struct {
     pyo_audio_HEAD
@@ -3422,348 +3545,333 @@ typedef struct {
     PyObject *index;
     Stream *index_stream;
     int modebuffer[2];
-} TableIndex;
+} Pointer;
 
 static void
-TableIndex_readframes_a(TableIndex *self) {
-    int i, ind;
+Pointer_readframes_a(Pointer *self) {
+    MYFLT fpart;
+    double ph;
+    int i, ipart;
     MYFLT *tablelist = TableStream_getData(self->table);
     int size = TableStream_getSize(self->table);
-    
-    MYFLT *phase = Stream_getData((Stream *)self->index_stream);
-    
+
+    MYFLT *pha = Stream_getData((Stream *)self->index_stream);
+
     for (i=0; i<self->bufsize; i++) {
-        ind = (int)phase[i];
-        if (ind < 0)
-            ind = 0;
-        else if (ind >= size)
-            ind = size - 1;
-        
-        self->data[i] = tablelist[ind];
+        ph = Osc_clip(pha[i] * size, size);
+        ipart = (int)ph;
+        fpart = ph - ipart;
+        self->data[i] = tablelist[ipart] + (tablelist[ipart+1] - tablelist[ipart]) * fpart;
     }
 }
 
-static void TableIndex_postprocessing_ii(TableIndex *self) { POST_PROCESSING_II };
-static void TableIndex_postprocessing_ai(TableIndex *self) { POST_PROCESSING_AI };
-static void TableIndex_postprocessing_ia(TableIndex *self) { POST_PROCESSING_IA };
-static void TableIndex_postprocessing_aa(TableIndex *self) { POST_PROCESSING_AA };
-static void TableIndex_postprocessing_ireva(TableIndex *self) { POST_PROCESSING_IREVA };
-static void TableIndex_postprocessing_areva(TableIndex *self) { POST_PROCESSING_AREVA };
-static void TableIndex_postprocessing_revai(TableIndex *self) { POST_PROCESSING_REVAI };
-static void TableIndex_postprocessing_revaa(TableIndex *self) { POST_PROCESSING_REVAA };
-static void TableIndex_postprocessing_revareva(TableIndex *self) { POST_PROCESSING_REVAREVA };
+static void Pointer_postprocessing_ii(Pointer *self) { POST_PROCESSING_II };
+static void Pointer_postprocessing_ai(Pointer *self) { POST_PROCESSING_AI };
+static void Pointer_postprocessing_ia(Pointer *self) { POST_PROCESSING_IA };
+static void Pointer_postprocessing_aa(Pointer *self) { POST_PROCESSING_AA };
+static void Pointer_postprocessing_ireva(Pointer *self) { POST_PROCESSING_IREVA };
+static void Pointer_postprocessing_areva(Pointer *self) { POST_PROCESSING_AREVA };
+static void Pointer_postprocessing_revai(Pointer *self) { POST_PROCESSING_REVAI };
+static void Pointer_postprocessing_revaa(Pointer *self) { POST_PROCESSING_REVAA };
+static void Pointer_postprocessing_revareva(Pointer *self) { POST_PROCESSING_REVAREVA };
 
 static void
-TableIndex_setProcMode(TableIndex *self)
+Pointer_setProcMode(Pointer *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
-    self->proc_func_ptr = TableIndex_readframes_a;
-    
+
+    self->proc_func_ptr = Pointer_readframes_a;
+
 	switch (muladdmode) {
-        case 0:        
-            self->muladd_func_ptr = TableIndex_postprocessing_ii;
+        case 0:
+            self->muladd_func_ptr = Pointer_postprocessing_ii;
             break;
-        case 1:    
-            self->muladd_func_ptr = TableIndex_postprocessing_ai;
+        case 1:
+            self->muladd_func_ptr = Pointer_postprocessing_ai;
             break;
-        case 2:    
-            self->muladd_func_ptr = TableIndex_postprocessing_revai;
+        case 2:
+            self->muladd_func_ptr = Pointer_postprocessing_revai;
             break;
-        case 10:        
-            self->muladd_func_ptr = TableIndex_postprocessing_ia;
+        case 10:
+            self->muladd_func_ptr = Pointer_postprocessing_ia;
             break;
-        case 11:    
-            self->muladd_func_ptr = TableIndex_postprocessing_aa;
+        case 11:
+            self->muladd_func_ptr = Pointer_postprocessing_aa;
             break;
-        case 12:    
-            self->muladd_func_ptr = TableIndex_postprocessing_revaa;
+        case 12:
+            self->muladd_func_ptr = Pointer_postprocessing_revaa;
             break;
-        case 20:        
-            self->muladd_func_ptr = TableIndex_postprocessing_ireva;
+        case 20:
+            self->muladd_func_ptr = Pointer_postprocessing_ireva;
             break;
-        case 21:    
-            self->muladd_func_ptr = TableIndex_postprocessing_areva;
+        case 21:
+            self->muladd_func_ptr = Pointer_postprocessing_areva;
             break;
-        case 22:    
-            self->muladd_func_ptr = TableIndex_postprocessing_revareva;
+        case 22:
+            self->muladd_func_ptr = Pointer_postprocessing_revareva;
             break;
-    } 
+    }
 }
 
 static void
-TableIndex_compute_next_data_frame(TableIndex *self)
+Pointer_compute_next_data_frame(Pointer *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
 static int
-TableIndex_traverse(TableIndex *self, visitproc visit, void *arg)
+Pointer_traverse(Pointer *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->table);
-    Py_VISIT(self->index);    
-    Py_VISIT(self->index_stream);    
+    Py_VISIT(self->index);
+    Py_VISIT(self->index_stream);
     return 0;
 }
 
-static int 
-TableIndex_clear(TableIndex *self)
+static int
+Pointer_clear(Pointer *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->table);
-    Py_CLEAR(self->index);    
-    Py_CLEAR(self->index_stream);    
+    Py_CLEAR(self->index);
+    Py_CLEAR(self->index_stream);
     return 0;
 }
 
 static void
-TableIndex_dealloc(TableIndex* self)
+Pointer_dealloc(Pointer* self)
 {
     pyo_DEALLOC
-    TableIndex_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Pointer_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
-TableIndex_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+Pointer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
     PyObject *tabletmp, *indextmp, *multmp=NULL, *addtmp=NULL;
-    TableIndex *self;
-    self = (TableIndex *)type->tp_alloc(type, 0);
-    
+    Pointer *self;
+    self = (Pointer *)type->tp_alloc(type, 0);
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
-    Stream_setFunctionPtr(self->stream, TableIndex_compute_next_data_frame);
-    self->mode_func_ptr = TableIndex_setProcMode;
+    Stream_setFunctionPtr(self->stream, Pointer_compute_next_data_frame);
+    self->mode_func_ptr = Pointer_setProcMode;
 
     static char *kwlist[] = {"table", "index", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist, &tabletmp, &indextmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
-        PySys_WriteStderr("TypeError: \"table\" argument of TableIndex must be a PyoTableObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"table\" argument of Pointer must be a PyoTableObject.\n");
+        Py_RETURN_NONE;
     }
     Py_XDECREF(self->table);
     self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", "");
-    
+
     if (indextmp) {
         PyObject_CallMethod((PyObject *)self, "setIndex", "O", indextmp);
     }
-    
+
     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 * TableIndex_getServer(TableIndex* self) { GET_SERVER };
-static PyObject * TableIndex_getStream(TableIndex* self) { GET_STREAM };
-static PyObject * TableIndex_setMul(TableIndex *self, PyObject *arg) { SET_MUL };	
-static PyObject * TableIndex_setAdd(TableIndex *self, PyObject *arg) { SET_ADD };	
-static PyObject * TableIndex_setSub(TableIndex *self, PyObject *arg) { SET_SUB };	
-static PyObject * TableIndex_setDiv(TableIndex *self, PyObject *arg) { SET_DIV };	
+static PyObject * Pointer_getServer(Pointer* self) { GET_SERVER };
+static PyObject * Pointer_getStream(Pointer* self) { GET_STREAM };
+static PyObject * Pointer_setMul(Pointer *self, PyObject *arg) { SET_MUL };
+static PyObject * Pointer_setAdd(Pointer *self, PyObject *arg) { SET_ADD };
+static PyObject * Pointer_setSub(Pointer *self, PyObject *arg) { SET_SUB };
+static PyObject * Pointer_setDiv(Pointer *self, PyObject *arg) { SET_DIV };
 
-static PyObject * TableIndex_play(TableIndex *self, PyObject *args, PyObject *kwds) { PLAY };
-static PyObject * TableIndex_out(TableIndex *self, PyObject *args, PyObject *kwds) { OUT };
-static PyObject * TableIndex_stop(TableIndex *self) { STOP };
+static PyObject * Pointer_play(Pointer *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * Pointer_out(Pointer *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * Pointer_stop(Pointer *self) { STOP };
 
-static PyObject * TableIndex_multiply(TableIndex *self, PyObject *arg) { MULTIPLY };
-static PyObject * TableIndex_inplace_multiply(TableIndex *self, PyObject *arg) { INPLACE_MULTIPLY };
-static PyObject * TableIndex_add(TableIndex *self, PyObject *arg) { ADD };
-static PyObject * TableIndex_inplace_add(TableIndex *self, PyObject *arg) { INPLACE_ADD };
-static PyObject * TableIndex_sub(TableIndex *self, PyObject *arg) { SUB };
-static PyObject * TableIndex_inplace_sub(TableIndex *self, PyObject *arg) { INPLACE_SUB };
-static PyObject * TableIndex_div(TableIndex *self, PyObject *arg) { DIV };
-static PyObject * TableIndex_inplace_div(TableIndex *self, PyObject *arg) { INPLACE_DIV };
+static PyObject * Pointer_multiply(Pointer *self, PyObject *arg) { MULTIPLY };
+static PyObject * Pointer_inplace_multiply(Pointer *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * Pointer_add(Pointer *self, PyObject *arg) { ADD };
+static PyObject * Pointer_inplace_add(Pointer *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * Pointer_sub(Pointer *self, PyObject *arg) { SUB };
+static PyObject * Pointer_inplace_sub(Pointer *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * Pointer_div(Pointer *self, PyObject *arg) { DIV };
+static PyObject * Pointer_inplace_div(Pointer *self, PyObject *arg) { INPLACE_DIV };
 
 static PyObject *
-TableIndex_getTable(TableIndex* self)
+Pointer_getTable(Pointer* self)
 {
     Py_INCREF(self->table);
     return self->table;
 };
 
 static PyObject *
-TableIndex_setTable(TableIndex *self, PyObject *arg)
+Pointer_setTable(Pointer *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    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 *
-TableIndex_setIndex(TableIndex *self, PyObject *arg)
+Pointer_setIndex(Pointer *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	int isNumber = PyNumber_Check(arg);
-	if (isNumber == 1) {
-		PySys_WriteStderr("TypeError: \"index\" attribute of TableIndex must be a PyoObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
-	}
-	
+
+    ASSERT_ARG_NOT_NULL
+
 	tmp = arg;
+	if (PyObject_HasAttrString((PyObject *)tmp, "server") == 0) {
+        PyErr_SetString(PyExc_TypeError, "\"index\" argument of Pointer must be a PyoObject.\n");
+        Py_RETURN_NONE;
+	}
+
 	Py_INCREF(tmp);
 	Py_XDECREF(self->index);
-    
+
     self->index = tmp;
     streamtmp = PyObject_CallMethod((PyObject *)self->index, "_getStream", NULL);
     Py_INCREF(streamtmp);
     Py_XDECREF(self->index_stream);
     self->index_stream = (Stream *)streamtmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
-
-static PyMemberDef TableIndex_members[] = {
-    {"server", T_OBJECT_EX, offsetof(TableIndex, server), 0, "Pyo server."},
-    {"stream", T_OBJECT_EX, offsetof(TableIndex, stream), 0, "Stream object."},
-    {"table", T_OBJECT_EX, offsetof(TableIndex, table), 0, "Waveform table."},
-    {"index", T_OBJECT_EX, offsetof(TableIndex, index), 0, "Reader index."},
-    {"mul", T_OBJECT_EX, offsetof(TableIndex, mul), 0, "Mul factor."},
-    {"add", T_OBJECT_EX, offsetof(TableIndex, add), 0, "Add factor."},
-    {NULL}  /* Sentinel */
-};
+}
 
-static PyMethodDef TableIndex_methods[] = {
-    {"getTable", (PyCFunction)TableIndex_getTable, METH_NOARGS, "Returns waveform table object."},
-    {"getServer", (PyCFunction)TableIndex_getServer, METH_NOARGS, "Returns server object."},
-    {"_getStream", (PyCFunction)TableIndex_getStream, METH_NOARGS, "Returns stream object."},
-    {"play", (PyCFunction)TableIndex_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
-    {"out", (PyCFunction)TableIndex_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
-    {"stop", (PyCFunction)TableIndex_stop, METH_NOARGS, "Stops computing."},
-    {"setTable", (PyCFunction)TableIndex_setTable, METH_O, "Sets oscillator table."},
-    {"setIndex", (PyCFunction)TableIndex_setIndex, METH_O, "Sets reader index."},
-    {"setMul", (PyCFunction)TableIndex_setMul, METH_O, "Sets oscillator mul factor."},
-    {"setAdd", (PyCFunction)TableIndex_setAdd, METH_O, "Sets oscillator add factor."},
-    {"setSub", (PyCFunction)TableIndex_setSub, METH_O, "Sets oscillator inverse add factor."},
-    {"setDiv", (PyCFunction)TableIndex_setDiv, METH_O, "Sets inverse mul factor."},
-    {NULL}  /* Sentinel */
+static PyMemberDef Pointer_members[] = {
+{"server", T_OBJECT_EX, offsetof(Pointer, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(Pointer, stream), 0, "Stream object."},
+{"table", T_OBJECT_EX, offsetof(Pointer, table), 0, "Waveform table."},
+{"index", T_OBJECT_EX, offsetof(Pointer, index), 0, "Reader index."},
+{"mul", T_OBJECT_EX, offsetof(Pointer, mul), 0, "Mul factor."},
+{"add", T_OBJECT_EX, offsetof(Pointer, add), 0, "Add factor."},
+{NULL}  /* Sentinel */
 };
 
-static PyNumberMethods TableIndex_as_number = {
-    (binaryfunc)TableIndex_add,                      /*nb_add*/
-    (binaryfunc)TableIndex_sub,                 /*nb_subtract*/
-    (binaryfunc)TableIndex_multiply,                 /*nb_multiply*/
-    (binaryfunc)TableIndex_div,                   /*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*/
-    0,                                          /*nb_coerce*/
-    0,                       /*nb_int*/
-    0,                      /*nb_long*/
-    0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
-    (binaryfunc)TableIndex_inplace_add,              /*inplace_add*/
-    (binaryfunc)TableIndex_inplace_sub,         /*inplace_subtract*/
-    (binaryfunc)TableIndex_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)TableIndex_inplace_div,           /*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*/
-    0,              /*nb_true_divide*/
-    0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
-    0,                     /* nb_index */
+static PyMethodDef Pointer_methods[] = {
+{"getTable", (PyCFunction)Pointer_getTable, METH_NOARGS, "Returns waveform table object."},
+{"getServer", (PyCFunction)Pointer_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)Pointer_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)Pointer_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"out", (PyCFunction)Pointer_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+{"stop", (PyCFunction)Pointer_stop, METH_NOARGS, "Stops computing."},
+{"setTable", (PyCFunction)Pointer_setTable, METH_O, "Sets oscillator table."},
+{"setIndex", (PyCFunction)Pointer_setIndex, METH_O, "Sets reader index."},
+{"setMul", (PyCFunction)Pointer_setMul, METH_O, "Sets oscillator mul factor."},
+{"setAdd", (PyCFunction)Pointer_setAdd, METH_O, "Sets oscillator add factor."},
+{"setSub", (PyCFunction)Pointer_setSub, METH_O, "Sets oscillator inverse add factor."},
+{"setDiv", (PyCFunction)Pointer_setDiv, METH_O, "Sets inverse mul factor."},
+{NULL}  /* Sentinel */
 };
 
-PyTypeObject TableIndexType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
-    "_pyo.TableIndex_base",         /*tp_name*/
-    sizeof(TableIndex),         /*tp_basicsize*/
-    0,                         /*tp_itemsize*/
-    (destructor)TableIndex_dealloc, /*tp_dealloc*/
-    0,                         /*tp_print*/
-    0,                         /*tp_getattr*/
-    0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
-    0,                         /*tp_repr*/
-    &TableIndex_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*/
-    "TableIndex objects. Read a table by indexing without interpolation.",           /* tp_doc */
-    (traverseproc)TableIndex_traverse,   /* tp_traverse */
-    (inquiry)TableIndex_clear,           /* tp_clear */
-    0,		               /* tp_richcompare */
-    0,		               /* tp_weaklistoffset */
-    0,		               /* tp_iter */
-    0,		               /* tp_iternext */
-    TableIndex_methods,             /* tp_methods */
-    TableIndex_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 */
-    TableIndex_new,                 /* tp_new */
+static PyNumberMethods Pointer_as_number = {
+(binaryfunc)Pointer_add,                      /*nb_add*/
+(binaryfunc)Pointer_sub,                 /*nb_subtract*/
+(binaryfunc)Pointer_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)Pointer_inplace_add,              /*inplace_add*/
+(binaryfunc)Pointer_inplace_sub,         /*inplace_subtract*/
+(binaryfunc)Pointer_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)Pointer_div,                       /*nb_true_divide*/
+0,     /*nb_inplace_floor_divide*/
+(binaryfunc)Pointer_inplace_div,                       /*nb_inplace_true_divide*/
+0,                     /* nb_index */
+};
+
+PyTypeObject PointerType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.Pointer_base",         /*tp_name*/
+sizeof(Pointer),         /*tp_basicsize*/
+0,                         /*tp_itemsize*/
+(destructor)Pointer_dealloc, /*tp_dealloc*/
+0,                         /*tp_print*/
+0,                         /*tp_getattr*/
+0,                         /*tp_setattr*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
+0,                         /*tp_repr*/
+&Pointer_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*/
+"Pointer objects. Read a waveform table with a pointer index.",           /* tp_doc */
+(traverseproc)Pointer_traverse,   /* tp_traverse */
+(inquiry)Pointer_clear,           /* tp_clear */
+0,		               /* tp_richcompare */
+0,		               /* tp_weaklistoffset */
+0,		               /* tp_iter */
+0,		               /* tp_iternext */
+Pointer_methods,             /* tp_methods */
+Pointer_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 */
+Pointer_new,                 /* tp_new */
 };
 
 /**************/
-/* Lookup object */
+/* Pointer2 object */
 /**************/
 typedef struct {
     pyo_audio_HEAD
@@ -3771,275 +3879,321 @@ typedef struct {
     PyObject *index;
     Stream *index_stream;
     int modebuffer[2];
-} Lookup;
-
-static MYFLT
-Lookup_clip(MYFLT x) {
-    if (x < -1.0)
-        return -1.0;
-    else if (x > 1.0)
-        return 1.0;
-    else
-        return x;
-}
+    int interp; /* 0 = default to 2, 1 = nointerp, 2 = linear, 3 = cos, 4 = cubic */
+    int autosmooth; /* 0 = off, > 0 = on */
+    MYFLT y1;
+    MYFLT y2;
+    MYFLT c;
+    MYFLT lastPh;
+    MYFLT (*interp_func_ptr)(MYFLT *, int, MYFLT, int);
+} Pointer2;
 
 static void
-Lookup_readframes_a(Lookup *self) {
-    MYFLT ph, fpart;
+Pointer2_readframes_a(Pointer2 *self) {
+    MYFLT fpart, phdiff, b, fr;
+    double ph;
     int i, ipart;
     MYFLT *tablelist = TableStream_getData(self->table);
     int size = TableStream_getSize(self->table);
-    
+    double tableSr = TableStream_getSamplingRate(self->table);
+
     MYFLT *pha = Stream_getData((Stream *)self->index_stream);
-    
-    for (i=0; i<self->bufsize; i++) {
-        ph = (Lookup_clip(pha[i]) * 0.5 + 0.5) * size;   
-        ipart = (int)ph;
-        fpart = ph - ipart;
-        self->data[i] = tablelist[ipart] * (1.0 - fpart) + tablelist[ipart+1] * fpart;
+
+    if (!self->autosmooth) {
+        for (i=0; i<self->bufsize; i++) {
+            ph = Osc_clip(pha[i] * size, size);
+            ipart = (int)ph;
+            fpart = ph - ipart;
+            self->y1 = self->y2 = self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
+        }
+    }
+    else {
+        for (i=0; i<self->bufsize; i++) {
+            ph = Osc_clip(pha[i] * size, size);
+            ipart = (int)ph;
+            fpart = ph - ipart;
+            self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
+            phdiff = MYFABS(ph - self->lastPh);
+            self->lastPh = ph;
+            if (phdiff < 1) {
+                fr = phdiff * tableSr * 0.45;
+                b = 2.0 - MYCOS(TWOPI * fr / self->sr);
+                self->c = (b - MYSQRT(b * b - 1.0));
+                self->y1 = self->data[i] + (self->y1 - self->data[i]) * self->c;
+                self->data[i] = self->y2 = self->y1 + (self->y2 - self->y1) * self->c;
+            }
+            else
+                self->y1 = self->y2 = self->data[i];
+        }
     }
 }
 
-static void Lookup_postprocessing_ii(Lookup *self) { POST_PROCESSING_II };
-static void Lookup_postprocessing_ai(Lookup *self) { POST_PROCESSING_AI };
-static void Lookup_postprocessing_ia(Lookup *self) { POST_PROCESSING_IA };
-static void Lookup_postprocessing_aa(Lookup *self) { POST_PROCESSING_AA };
-static void Lookup_postprocessing_ireva(Lookup *self) { POST_PROCESSING_IREVA };
-static void Lookup_postprocessing_areva(Lookup *self) { POST_PROCESSING_AREVA };
-static void Lookup_postprocessing_revai(Lookup *self) { POST_PROCESSING_REVAI };
-static void Lookup_postprocessing_revaa(Lookup *self) { POST_PROCESSING_REVAA };
-static void Lookup_postprocessing_revareva(Lookup *self) { POST_PROCESSING_REVAREVA };
+static void Pointer2_postprocessing_ii(Pointer2 *self) { POST_PROCESSING_II };
+static void Pointer2_postprocessing_ai(Pointer2 *self) { POST_PROCESSING_AI };
+static void Pointer2_postprocessing_ia(Pointer2 *self) { POST_PROCESSING_IA };
+static void Pointer2_postprocessing_aa(Pointer2 *self) { POST_PROCESSING_AA };
+static void Pointer2_postprocessing_ireva(Pointer2 *self) { POST_PROCESSING_IREVA };
+static void Pointer2_postprocessing_areva(Pointer2 *self) { POST_PROCESSING_AREVA };
+static void Pointer2_postprocessing_revai(Pointer2 *self) { POST_PROCESSING_REVAI };
+static void Pointer2_postprocessing_revaa(Pointer2 *self) { POST_PROCESSING_REVAA };
+static void Pointer2_postprocessing_revareva(Pointer2 *self) { POST_PROCESSING_REVAREVA };
 
 static void
-Lookup_setProcMode(Lookup *self)
+Pointer2_setProcMode(Pointer2 *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
-    self->proc_func_ptr = Lookup_readframes_a;
-    
+
+    self->proc_func_ptr = Pointer2_readframes_a;
+
 	switch (muladdmode) {
-        case 0:        
-            self->muladd_func_ptr = Lookup_postprocessing_ii;
+        case 0:
+            self->muladd_func_ptr = Pointer2_postprocessing_ii;
             break;
-        case 1:    
-            self->muladd_func_ptr = Lookup_postprocessing_ai;
+        case 1:
+            self->muladd_func_ptr = Pointer2_postprocessing_ai;
             break;
-        case 2:    
-            self->muladd_func_ptr = Lookup_postprocessing_revai;
+        case 2:
+            self->muladd_func_ptr = Pointer2_postprocessing_revai;
             break;
-        case 10:        
-            self->muladd_func_ptr = Lookup_postprocessing_ia;
+        case 10:
+            self->muladd_func_ptr = Pointer2_postprocessing_ia;
             break;
-        case 11:    
-            self->muladd_func_ptr = Lookup_postprocessing_aa;
+        case 11:
+            self->muladd_func_ptr = Pointer2_postprocessing_aa;
             break;
-        case 12:    
-            self->muladd_func_ptr = Lookup_postprocessing_revaa;
+        case 12:
+            self->muladd_func_ptr = Pointer2_postprocessing_revaa;
             break;
-        case 20:        
-            self->muladd_func_ptr = Lookup_postprocessing_ireva;
+        case 20:
+            self->muladd_func_ptr = Pointer2_postprocessing_ireva;
             break;
-        case 21:    
-            self->muladd_func_ptr = Lookup_postprocessing_areva;
+        case 21:
+            self->muladd_func_ptr = Pointer2_postprocessing_areva;
             break;
-        case 22:    
-            self->muladd_func_ptr = Lookup_postprocessing_revareva;
+        case 22:
+            self->muladd_func_ptr = Pointer2_postprocessing_revareva;
             break;
-    } 
+    }
 }
 
 static void
-Lookup_compute_next_data_frame(Lookup *self)
+Pointer2_compute_next_data_frame(Pointer2 *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
 static int
-Lookup_traverse(Lookup *self, visitproc visit, void *arg)
+Pointer2_traverse(Pointer2 *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->table);
-    Py_VISIT(self->index);    
-    Py_VISIT(self->index_stream);    
+    Py_VISIT(self->index);
+    Py_VISIT(self->index_stream);
     return 0;
 }
 
-static int 
-Lookup_clear(Lookup *self)
+static int
+Pointer2_clear(Pointer2 *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->table);
-    Py_CLEAR(self->index);    
-    Py_CLEAR(self->index_stream);    
+    Py_CLEAR(self->index);
+    Py_CLEAR(self->index_stream);
     return 0;
 }
 
 static void
-Lookup_dealloc(Lookup* self)
+Pointer2_dealloc(Pointer2* self)
 {
     pyo_DEALLOC
-    Lookup_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Pointer2_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
-Lookup_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+Pointer2_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
     PyObject *tabletmp, *indextmp, *multmp=NULL, *addtmp=NULL;
-    Lookup *self;
-    self = (Lookup *)type->tp_alloc(type, 0);
-    
+    Pointer2 *self;
+    self = (Pointer2 *)type->tp_alloc(type, 0);
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+    self->interp = 4;
+    self->autosmooth = 1;
+    self->y1 = self->y2 = self->c = self->lastPh = 0.0;
+
     INIT_OBJECT_COMMON
-    Stream_setFunctionPtr(self->stream, Lookup_compute_next_data_frame);
-    self->mode_func_ptr = Lookup_setProcMode;
+    Stream_setFunctionPtr(self->stream, Pointer2_compute_next_data_frame);
+    self->mode_func_ptr = Pointer2_setProcMode;
 
-    static char *kwlist[] = {"table", "index", "mul", "add", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist, &tabletmp, &indextmp, &multmp, &addtmp))
+    static char *kwlist[] = {"table", "index", "interp", "autosmooth", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|iiOO", kwlist, &tabletmp, &indextmp, &self->interp, &self->autosmooth, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
-        PySys_WriteStderr("TypeError: \"table\" argument of Lookup must be a PyoTableObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"table\" argument of Pointer2 must be a PyoTableObject.\n");
+        Py_RETURN_NONE;
     }
     Py_XDECREF(self->table);
     self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", "");
-    
+
     if (indextmp) {
         PyObject_CallMethod((PyObject *)self, "setIndex", "O", indextmp);
     }
-    
+
     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);
-     
+
+    SET_INTERP_POINTER
+
     return (PyObject *)self;
 }
 
-static PyObject * Lookup_getServer(Lookup* self) { GET_SERVER };
-static PyObject * Lookup_getStream(Lookup* self) { GET_STREAM };
-static PyObject * Lookup_setMul(Lookup *self, PyObject *arg) { SET_MUL };	
-static PyObject * Lookup_setAdd(Lookup *self, PyObject *arg) { SET_ADD };	
-static PyObject * Lookup_setSub(Lookup *self, PyObject *arg) { SET_SUB };	
-static PyObject * Lookup_setDiv(Lookup *self, PyObject *arg) { SET_DIV };	
+static PyObject * Pointer2_getServer(Pointer2* self) { GET_SERVER };
+static PyObject * Pointer2_getStream(Pointer2* self) { GET_STREAM };
+static PyObject * Pointer2_setMul(Pointer2 *self, PyObject *arg) { SET_MUL };
+static PyObject * Pointer2_setAdd(Pointer2 *self, PyObject *arg) { SET_ADD };
+static PyObject * Pointer2_setSub(Pointer2 *self, PyObject *arg) { SET_SUB };
+static PyObject * Pointer2_setDiv(Pointer2 *self, PyObject *arg) { SET_DIV };
 
-static PyObject * Lookup_play(Lookup *self, PyObject *args, PyObject *kwds) { PLAY };
-static PyObject * Lookup_out(Lookup *self, PyObject *args, PyObject *kwds) { OUT };
-static PyObject * Lookup_stop(Lookup *self) { STOP };
+static PyObject * Pointer2_play(Pointer2 *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * Pointer2_out(Pointer2 *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * Pointer2_stop(Pointer2 *self) { STOP };
 
-static PyObject * Lookup_multiply(Lookup *self, PyObject *arg) { MULTIPLY };
-static PyObject * Lookup_inplace_multiply(Lookup *self, PyObject *arg) { INPLACE_MULTIPLY };
-static PyObject * Lookup_add(Lookup *self, PyObject *arg) { ADD };
-static PyObject * Lookup_inplace_add(Lookup *self, PyObject *arg) { INPLACE_ADD };
-static PyObject * Lookup_sub(Lookup *self, PyObject *arg) { SUB };
-static PyObject * Lookup_inplace_sub(Lookup *self, PyObject *arg) { INPLACE_SUB };
-static PyObject * Lookup_div(Lookup *self, PyObject *arg) { DIV };
-static PyObject * Lookup_inplace_div(Lookup *self, PyObject *arg) { INPLACE_DIV };
+static PyObject * Pointer2_multiply(Pointer2 *self, PyObject *arg) { MULTIPLY };
+static PyObject * Pointer2_inplace_multiply(Pointer2 *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * Pointer2_add(Pointer2 *self, PyObject *arg) { ADD };
+static PyObject * Pointer2_inplace_add(Pointer2 *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * Pointer2_sub(Pointer2 *self, PyObject *arg) { SUB };
+static PyObject * Pointer2_inplace_sub(Pointer2 *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * Pointer2_div(Pointer2 *self, PyObject *arg) { DIV };
+static PyObject * Pointer2_inplace_div(Pointer2 *self, PyObject *arg) { INPLACE_DIV };
 
 static PyObject *
-Lookup_getTable(Lookup* self)
+Pointer2_getTable(Pointer2* self)
 {
     Py_INCREF(self->table);
     return self->table;
 };
 
 static PyObject *
-Lookup_setTable(Lookup *self, PyObject *arg)
+Pointer2_setTable(Pointer2 *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    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 *
-Lookup_setIndex(Lookup *self, PyObject *arg)
+Pointer2_setIndex(Pointer2 *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	int isNumber = PyNumber_Check(arg);
-	if (isNumber == 1) {
-		PySys_WriteStderr("TypeError: \"index\" attribute of Lookup must be a PyoObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
-	}
-	
+
+    ASSERT_ARG_NOT_NULL
+
 	tmp = arg;
+	if (PyObject_HasAttrString((PyObject *)tmp, "server") == 0) {
+        PyErr_SetString(PyExc_TypeError, "\"index\" argument of Pointer2 must be a PyoObject.\n");
+        Py_RETURN_NONE;
+	}
+
 	Py_INCREF(tmp);
 	Py_XDECREF(self->index);
-    
+
     self->index = tmp;
     streamtmp = PyObject_CallMethod((PyObject *)self->index, "_getStream", NULL);
     Py_INCREF(streamtmp);
     Py_XDECREF(self->index_stream);
     self->index_stream = (Stream *)streamtmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
-static PyMemberDef Lookup_members[] = {
-{"server", T_OBJECT_EX, offsetof(Lookup, server), 0, "Pyo server."},
-{"stream", T_OBJECT_EX, offsetof(Lookup, stream), 0, "Stream object."},
-{"table", T_OBJECT_EX, offsetof(Lookup, table), 0, "Waveform table."},
-{"index", T_OBJECT_EX, offsetof(Lookup, index), 0, "Reader index."},
-{"mul", T_OBJECT_EX, offsetof(Lookup, mul), 0, "Mul factor."},
-{"add", T_OBJECT_EX, offsetof(Lookup, add), 0, "Add factor."},
+static PyObject *
+Pointer2_setInterp(Pointer2 *self, PyObject *arg)
+{
+    ASSERT_ARG_NOT_NULL
+
+    int isNumber = PyNumber_Check(arg);
+
+	if (isNumber == 1) {
+		self->interp = PyInt_AsLong(PyNumber_Int(arg));
+    }
+
+    SET_INTERP_POINTER
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *
+Pointer2_setAutoSmooth(Pointer2 *self, PyObject *arg)
+{
+    ASSERT_ARG_NOT_NULL
+
+    int isNumber = PyNumber_Check(arg);
+
+	if (isNumber == 1) {
+		self->autosmooth = PyInt_AsLong(PyNumber_Int(arg));
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyMemberDef Pointer2_members[] = {
+{"server", T_OBJECT_EX, offsetof(Pointer2, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(Pointer2, stream), 0, "Stream object."},
+{"table", T_OBJECT_EX, offsetof(Pointer2, table), 0, "Waveform table."},
+{"index", T_OBJECT_EX, offsetof(Pointer2, index), 0, "Reader index."},
+{"mul", T_OBJECT_EX, offsetof(Pointer2, mul), 0, "Mul factor."},
+{"add", T_OBJECT_EX, offsetof(Pointer2, add), 0, "Add factor."},
 {NULL}  /* Sentinel */
 };
 
-static PyMethodDef Lookup_methods[] = {
-{"getTable", (PyCFunction)Lookup_getTable, METH_NOARGS, "Returns waveform table object."},
-{"getServer", (PyCFunction)Lookup_getServer, METH_NOARGS, "Returns server object."},
-{"_getStream", (PyCFunction)Lookup_getStream, METH_NOARGS, "Returns stream object."},
-{"play", (PyCFunction)Lookup_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
-{"out", (PyCFunction)Lookup_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
-{"stop", (PyCFunction)Lookup_stop, METH_NOARGS, "Stops computing."},
-{"setTable", (PyCFunction)Lookup_setTable, METH_O, "Sets oscillator table."},
-{"setIndex", (PyCFunction)Lookup_setIndex, METH_O, "Sets reader index."},
-{"setMul", (PyCFunction)Lookup_setMul, METH_O, "Sets oscillator mul factor."},
-{"setAdd", (PyCFunction)Lookup_setAdd, METH_O, "Sets oscillator add factor."},
-{"setSub", (PyCFunction)Lookup_setSub, METH_O, "Sets oscillator inverse add factor."},
-{"setDiv", (PyCFunction)Lookup_setDiv, METH_O, "Sets inverse mul factor."},
+static PyMethodDef Pointer2_methods[] = {
+{"getTable", (PyCFunction)Pointer2_getTable, METH_NOARGS, "Returns waveform table object."},
+{"getServer", (PyCFunction)Pointer2_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)Pointer2_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)Pointer2_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"out", (PyCFunction)Pointer2_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+{"stop", (PyCFunction)Pointer2_stop, METH_NOARGS, "Stops computing."},
+{"setTable", (PyCFunction)Pointer2_setTable, METH_O, "Sets oscillator table."},
+{"setIndex", (PyCFunction)Pointer2_setIndex, METH_O, "Sets reader index."},
+{"setInterp", (PyCFunction)Pointer2_setInterp, METH_O, "Sets oscillator interpolation mode."},
+{"setAutoSmooth", (PyCFunction)Pointer2_setAutoSmooth, METH_O, "Activates auto smoother filter."},
+{"setMul", (PyCFunction)Pointer2_setMul, METH_O, "Sets oscillator mul factor."},
+{"setAdd", (PyCFunction)Pointer2_setAdd, METH_O, "Sets oscillator add factor."},
+{"setSub", (PyCFunction)Pointer2_setSub, METH_O, "Sets oscillator inverse add factor."},
+{"setDiv", (PyCFunction)Pointer2_setDiv, METH_O, "Sets inverse mul factor."},
 {NULL}  /* Sentinel */
 };
 
-static PyNumberMethods Lookup_as_number = {
-(binaryfunc)Lookup_add,                      /*nb_add*/
-(binaryfunc)Lookup_sub,                 /*nb_subtract*/
-(binaryfunc)Lookup_multiply,                 /*nb_multiply*/
-(binaryfunc)Lookup_div,                   /*nb_divide*/
+static PyNumberMethods Pointer2_as_number = {
+(binaryfunc)Pointer2_add,                      /*nb_add*/
+(binaryfunc)Pointer2_sub,                 /*nb_subtract*/
+(binaryfunc)Pointer2_multiply,                 /*nb_multiply*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -4053,16 +4207,16 @@ static PyNumberMethods Lookup_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
-(binaryfunc)Lookup_inplace_add,              /*inplace_add*/
-(binaryfunc)Lookup_inplace_sub,         /*inplace_subtract*/
-(binaryfunc)Lookup_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)Lookup_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
+(binaryfunc)Pointer2_inplace_add,              /*inplace_add*/
+(binaryfunc)Pointer2_inplace_sub,         /*inplace_subtract*/
+(binaryfunc)Pointer2_inplace_multiply,         /*inplace_multiply*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -4071,25 +4225,24 @@ static PyNumberMethods Lookup_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)Pointer2_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)Pointer2_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
-PyTypeObject LookupType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
-"_pyo.Lookup_base",         /*tp_name*/
-sizeof(Lookup),         /*tp_basicsize*/
+PyTypeObject Pointer2Type = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.Pointer2_base",         /*tp_name*/
+sizeof(Pointer2),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
-(destructor)Lookup_dealloc, /*tp_dealloc*/
+(destructor)Pointer2_dealloc, /*tp_dealloc*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
-&Lookup_as_number,             /*tp_as_number*/
+&Pointer2_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
 0,                         /*tp_as_mapping*/
 0,                         /*tp_hash */
@@ -4099,15 +4252,15 @@ sizeof(Lookup),         /*tp_basicsize*/
 0,                         /*tp_setattro*/
 0,                         /*tp_as_buffer*/
 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
-"Lookup objects. Modify a signal by reading a table with the signal as the index.",           /* tp_doc */
-(traverseproc)Lookup_traverse,   /* tp_traverse */
-(inquiry)Lookup_clear,           /* tp_clear */
+"Pointer2 objects. High quality table reader with a pointer index.",           /* tp_doc */
+(traverseproc)Pointer2_traverse,   /* tp_traverse */
+(inquiry)Pointer2_clear,           /* tp_clear */
 0,		               /* tp_richcompare */
 0,		               /* tp_weaklistoffset */
 0,		               /* tp_iter */
 0,		               /* tp_iternext */
-Lookup_methods,             /* tp_methods */
-Lookup_members,             /* tp_members */
+Pointer2_methods,             /* tp_methods */
+Pointer2_members,             /* tp_members */
 0,                      /* tp_getset */
 0,                         /* tp_base */
 0,                         /* tp_dict */
@@ -4116,1325 +4269,609 @@ Lookup_members,             /* tp_members */
 0,                         /* tp_dictoffset */
 0,      /* tp_init */
 0,                         /* tp_alloc */
-Lookup_new,                 /* tp_new */
+Pointer2_new,                 /* tp_new */
 };
 
 /**************/
-/* Pulsar object */
+/* TableIndex object */
 /**************/
 typedef struct {
     pyo_audio_HEAD
     PyObject *table;
-    PyObject *env;
-    PyObject *freq;
-    Stream *freq_stream;
-    PyObject *phase;
-    Stream *phase_stream;
-    PyObject *frac;
-    Stream *frac_stream;
-    int modebuffer[5];
-    MYFLT pointerPos;
-    int interp; /* 0 = default to 2, 1 = nointerp, 2 = linear, 3 = cos, 4 = cubic */
-    MYFLT (*interp_func_ptr)(MYFLT *, int, MYFLT, int);
-} Pulsar;
+    PyObject *index;
+    Stream *index_stream;
+    int modebuffer[2];
+} TableIndex;
 
 static void
-Pulsar_readframes_iii(Pulsar *self) {
-    MYFLT fr, ph, frac, invfrac, pos, scl_pos, t_pos, e_pos, fpart, tmp;
-    double inc;
-    int i, ipart;
+TableIndex_readframes_a(TableIndex *self) {
+    int i, ind;
     MYFLT *tablelist = TableStream_getData(self->table);
-    MYFLT *envlist = TableStream_getData(self->env);
     int size = TableStream_getSize(self->table);
-    int envsize = TableStream_getSize(self->env);
-    
-    fr = PyFloat_AS_DOUBLE(self->freq);
-    ph = PyFloat_AS_DOUBLE(self->phase);
-    frac = _clip(PyFloat_AS_DOUBLE(self->frac));
-    invfrac = 1.0 / frac;
-    inc = fr / self->sr;
-    
+
+    MYFLT *phase = Stream_getData((Stream *)self->index_stream);
+
     for (i=0; i<self->bufsize; i++) {
-        self->pointerPos += inc;
-        if (self->pointerPos < 0)
-            self->pointerPos = 1.0 + self->pointerPos;
-        else if (self->pointerPos >= 1.0)
-            self->pointerPos -= 1.0;
-        pos = self->pointerPos + ph;
-        if (pos >= 1.0)
-            pos -= 1.0;
-        if (pos < frac) {
-            scl_pos = pos * invfrac;
-            t_pos = scl_pos * size;
-            ipart = (int)t_pos;
-            fpart = t_pos - ipart;
-            tmp = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
-            
-            e_pos = scl_pos * envsize;
-            ipart = (int)e_pos;
-            fpart = e_pos - ipart;
-            self->data[i] = tmp * (envlist[ipart] * (1.0 - fpart) + envlist[ipart+1] * fpart);
-        }    
-        else {
-            self->data[i] = 0.0;
-        }    
+        ind = (int)phase[i];
+        if (ind < 0)
+            ind = 0;
+        else if (ind >= size)
+            ind = size - 1;
+
+        self->data[i] = tablelist[ind];
     }
 }
 
+static void TableIndex_postprocessing_ii(TableIndex *self) { POST_PROCESSING_II };
+static void TableIndex_postprocessing_ai(TableIndex *self) { POST_PROCESSING_AI };
+static void TableIndex_postprocessing_ia(TableIndex *self) { POST_PROCESSING_IA };
+static void TableIndex_postprocessing_aa(TableIndex *self) { POST_PROCESSING_AA };
+static void TableIndex_postprocessing_ireva(TableIndex *self) { POST_PROCESSING_IREVA };
+static void TableIndex_postprocessing_areva(TableIndex *self) { POST_PROCESSING_AREVA };
+static void TableIndex_postprocessing_revai(TableIndex *self) { POST_PROCESSING_REVAI };
+static void TableIndex_postprocessing_revaa(TableIndex *self) { POST_PROCESSING_REVAA };
+static void TableIndex_postprocessing_revareva(TableIndex *self) { POST_PROCESSING_REVAREVA };
+
 static void
-Pulsar_readframes_aii(Pulsar *self) {
-    MYFLT ph, frac, invfrac, pos, scl_pos, t_pos, e_pos, fpart, tmp, oneOnSr;
-    double inc;
-    int i, ipart;
-    MYFLT *tablelist = TableStream_getData(self->table);
-    MYFLT *envlist = TableStream_getData(self->env);
-    int size = TableStream_getSize(self->table);
-    int envsize = TableStream_getSize(self->env);
-    
-    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    ph = PyFloat_AS_DOUBLE(self->phase);
-    frac = _clip(PyFloat_AS_DOUBLE(self->frac));
-    invfrac = 1.0 / frac;
-    
-    oneOnSr = 1.0 / self->sr;
-    for (i=0; i<self->bufsize; i++) {
-        inc = fr[i] * oneOnSr;
-        self->pointerPos += inc;
-        if (self->pointerPos < 0)
-            self->pointerPos = 1.0 + self->pointerPos;
-        else if (self->pointerPos >= 1.0)
-            self->pointerPos -= 1.0;
-        pos = self->pointerPos + ph;
-        if (pos >= 1.0)
-            pos -= 1.0;
-        if (pos < frac) {
-            scl_pos = pos * invfrac;
-            t_pos = scl_pos * size;
-            ipart = (int)t_pos;
-            fpart = t_pos - ipart;
-            tmp = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
-            
-            e_pos = scl_pos * envsize;
-            ipart = (int)e_pos;
-            fpart = e_pos - ipart;
-            self->data[i] = tmp * (envlist[ipart] * (1.0 - fpart) + envlist[ipart+1] * fpart);
-        }    
-        else {
-            self->data[i] = 0.0;
-        }    
+TableIndex_setProcMode(TableIndex *self)
+{
+    int muladdmode;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+    self->proc_func_ptr = TableIndex_readframes_a;
+
+	switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = TableIndex_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = TableIndex_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = TableIndex_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = TableIndex_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = TableIndex_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = TableIndex_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = TableIndex_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = TableIndex_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = TableIndex_postprocessing_revareva;
+            break;
     }
 }
 
 static void
-Pulsar_readframes_iai(Pulsar *self) {
-    MYFLT fr, frac, invfrac, pos, scl_pos, t_pos, e_pos, fpart, tmp;
-    double inc;
-    int i, ipart;
-    MYFLT *tablelist = TableStream_getData(self->table);
-    MYFLT *envlist = TableStream_getData(self->env);
-    int size = TableStream_getSize(self->table);
-    int envsize = TableStream_getSize(self->env);
-    
-    fr = PyFloat_AS_DOUBLE(self->freq);
-    MYFLT *ph = Stream_getData((Stream *)self->phase_stream);
-    frac = _clip(PyFloat_AS_DOUBLE(self->frac));
-    invfrac = 1.0 / frac;
-    inc = fr / self->sr;
-    
-    for (i=0; i<self->bufsize; i++) {
-        self->pointerPos += inc;
-        if (self->pointerPos < 0)
-            self->pointerPos = 1.0 + self->pointerPos;
-        else if (self->pointerPos >= 1.0)
-            self->pointerPos -= 1.0;
-        pos = self->pointerPos + ph[i];
-        if (pos >= 1.0)
-            pos -= 1.0;
-        if (pos < frac) {
-            scl_pos = pos * invfrac;
-            t_pos = scl_pos * size;
-            ipart = (int)t_pos;
-            fpart = t_pos - ipart;
-            tmp = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
-            
-            e_pos = scl_pos * envsize;
-            ipart = (int)e_pos;
-            fpart = e_pos - ipart;
-            self->data[i] = tmp * (envlist[ipart] * (1.0 - fpart) + envlist[ipart+1] * fpart);
-        }    
-        else {
-            self->data[i] = 0.0;
-        }    
-    }
+TableIndex_compute_next_data_frame(TableIndex *self)
+{
+    (*self->proc_func_ptr)(self);
+    (*self->muladd_func_ptr)(self);
 }
 
-static void
-Pulsar_readframes_aai(Pulsar *self) {
-    MYFLT frac, invfrac, pos, scl_pos, t_pos, e_pos, fpart, tmp, oneOnSr;
-    double inc;
-    int i, ipart;
-    MYFLT *tablelist = TableStream_getData(self->table);
-    MYFLT *envlist = TableStream_getData(self->env);
-    int size = TableStream_getSize(self->table);
-    int envsize = TableStream_getSize(self->env);
-    
-    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    MYFLT *ph = Stream_getData((Stream *)self->phase_stream);
-    frac = _clip(PyFloat_AS_DOUBLE(self->frac));
-    invfrac = 1.0 / frac;
-    
-    oneOnSr = 1.0 / self->sr;
-    for (i=0; i<self->bufsize; i++) {
-        inc = fr[i] * oneOnSr;
-        self->pointerPos += inc;
-        if (self->pointerPos < 0)
-            self->pointerPos = 1.0 + self->pointerPos;
-        else if (self->pointerPos >= 1.0)
-            self->pointerPos -= 1.0;
-        pos = self->pointerPos + ph[i];
-        if (pos >= 1.0)
-            pos -= 1.0;
-        if (pos < frac) {
-            scl_pos = pos * invfrac;
-            t_pos = scl_pos * size;
-            ipart = (int)t_pos;
-            fpart = t_pos - ipart;
-            tmp = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
-            
-            e_pos = scl_pos * envsize;
-            ipart = (int)e_pos;
-            fpart = e_pos - ipart;
-            self->data[i] = tmp * (envlist[ipart] * (1.0 - fpart) + envlist[ipart+1] * fpart);
-        }    
-        else {
-            self->data[i] = 0.0;
-        }    
-    }
+static int
+TableIndex_traverse(TableIndex *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->table);
+    Py_VISIT(self->index);
+    Py_VISIT(self->index_stream);
+    return 0;
 }
 
-static void
-Pulsar_readframes_iia(Pulsar *self) {
-    MYFLT fr, ph, pos, curfrac, scl_pos, t_pos, e_pos, fpart, tmp;
-    double inc;
-    int i, ipart;
-    MYFLT *tablelist = TableStream_getData(self->table);
-    MYFLT *envlist = TableStream_getData(self->env);
-    int size = TableStream_getSize(self->table);
-    int envsize = TableStream_getSize(self->env);
-    
-    fr = PyFloat_AS_DOUBLE(self->freq);
-    ph = PyFloat_AS_DOUBLE(self->phase);
-    MYFLT *frac = Stream_getData((Stream *)self->frac_stream);
-    inc = fr / self->sr;
-    
-    for (i=0; i<self->bufsize; i++) {
-        curfrac = frac[i];
-        self->pointerPos += inc;
-        if (self->pointerPos < 0)
-            self->pointerPos = 1.0 + self->pointerPos;
-        else if (self->pointerPos >= 1.0)
-            self->pointerPos -= 1.0;
-        pos = self->pointerPos + ph;
-        if (pos >= 1.0)
-            pos -= 1.0;
-        if (pos < curfrac) {
-            scl_pos = pos / curfrac;
-            t_pos = scl_pos * size;
-            ipart = (int)t_pos;
-            fpart = t_pos - ipart;
-            tmp = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
-            
-            e_pos = scl_pos * envsize;
-            ipart = (int)e_pos;
-            fpart = e_pos - ipart;
-            self->data[i] = tmp * (envlist[ipart] * (1.0 - fpart) + envlist[ipart+1] * fpart);
-        }    
-        else {
-            self->data[i] = 0.0;
-        }    
-    }
+static int
+TableIndex_clear(TableIndex *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->table);
+    Py_CLEAR(self->index);
+    Py_CLEAR(self->index_stream);
+    return 0;
 }
 
 static void
-Pulsar_readframes_aia(Pulsar *self) {
-    MYFLT ph, pos, curfrac, scl_pos, t_pos, e_pos, fpart, tmp, oneOnSr;
-    double inc;
-    int i, ipart;
-    MYFLT *tablelist = TableStream_getData(self->table);
-    MYFLT *envlist = TableStream_getData(self->env);
-    int size = TableStream_getSize(self->table);
-    int envsize = TableStream_getSize(self->env);
-    
-    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    ph = PyFloat_AS_DOUBLE(self->phase);
-    MYFLT *frac = Stream_getData((Stream *)self->frac_stream);
-    
-    oneOnSr = 1.0 / self->sr;
-    for (i=0; i<self->bufsize; i++) {
-        curfrac = frac[i];
-        inc = fr[i] * oneOnSr;
-        self->pointerPos += inc;
-        if (self->pointerPos < 0)
-            self->pointerPos = 1.0 + self->pointerPos;
-        else if (self->pointerPos >= 1.0)
-            self->pointerPos -= 1.0;
-        pos = self->pointerPos + ph;
-        if (pos >= 1.0)
-            pos -= 1.0;
-        if (pos < curfrac) {
-            scl_pos = pos / curfrac;
-            t_pos = scl_pos * size;
-            ipart = (int)t_pos;
-            fpart = t_pos - ipart;
-            tmp = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
-            
-            e_pos = scl_pos * envsize;
-            ipart = (int)e_pos;
-            fpart = e_pos - ipart;
-            self->data[i] = tmp * (envlist[ipart] * (1.0 - fpart) + envlist[ipart+1] * fpart);
-        }    
-        else {
-            self->data[i] = 0.0;
-        }    
-    }
+TableIndex_dealloc(TableIndex* self)
+{
+    pyo_DEALLOC
+    TableIndex_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
-static void
-Pulsar_readframes_iaa(Pulsar *self) {
-    MYFLT fr, pos, curfrac, scl_pos, t_pos, e_pos, fpart, tmp;
-    double inc;
-    int i, ipart;
-    MYFLT *tablelist = TableStream_getData(self->table);
-    MYFLT *envlist = TableStream_getData(self->env);
-    int size = TableStream_getSize(self->table);
-    int envsize = TableStream_getSize(self->env);
-    
-    fr = PyFloat_AS_DOUBLE(self->freq);
-    MYFLT *ph = Stream_getData((Stream *)self->phase_stream);
-    MYFLT *frac = Stream_getData((Stream *)self->frac_stream);
-    inc = fr / self->sr;
-    
-    for (i=0; i<self->bufsize; i++) {
-        curfrac = frac[i];
-        self->pointerPos += inc;
-        if (self->pointerPos < 0)
-            self->pointerPos = 1.0 + self->pointerPos;
-        else if (self->pointerPos >= 1.0)
-            self->pointerPos -= 1.0;
-        pos = self->pointerPos + ph[i];
-        if (pos >= 1.0)
-            pos -= 1.0;
-        if (pos < curfrac) {
-            scl_pos = pos / curfrac;
-            t_pos = scl_pos * size;
-            ipart = (int)t_pos;
-            fpart = t_pos - ipart;
-            tmp = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
-            
-            e_pos = scl_pos * envsize;
-            ipart = (int)e_pos;
-            fpart = e_pos - ipart;
-            self->data[i] = tmp * (envlist[ipart] * (1.0 - fpart) + envlist[ipart+1] * fpart);
-        }    
-        else {
-            self->data[i] = 0.0;
-        }    
+static PyObject *
+TableIndex_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *tabletmp, *indextmp, *multmp=NULL, *addtmp=NULL;
+    TableIndex *self;
+    self = (TableIndex *)type->tp_alloc(type, 0);
+
+	self->modebuffer[0] = 0;
+	self->modebuffer[1] = 0;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, TableIndex_compute_next_data_frame);
+    self->mode_func_ptr = TableIndex_setProcMode;
+
+    static char *kwlist[] = {"table", "index", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist, &tabletmp, &indextmp, &multmp, &addtmp))
+        Py_RETURN_NONE;
+
+    if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
+        PyErr_SetString(PyExc_TypeError, "\"table\" argument of TableIndex must be a PyoTableObject.\n");
+        Py_RETURN_NONE;
+    }
+    Py_XDECREF(self->table);
+    self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", "");
+
+    if (indextmp) {
+        PyObject_CallMethod((PyObject *)self, "setIndex", "O", indextmp);
+    }
+
+    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 void
-Pulsar_readframes_aaa(Pulsar *self) {
-    MYFLT pos, curfrac, scl_pos, t_pos, e_pos, fpart, tmp, oneOnSr;
-    double inc;
-    int i, ipart;
-    MYFLT *tablelist = TableStream_getData(self->table);
-    MYFLT *envlist = TableStream_getData(self->env);
-    int size = TableStream_getSize(self->table);
-    int envsize = TableStream_getSize(self->env);
-    
-    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    MYFLT *ph = Stream_getData((Stream *)self->phase_stream);
-    MYFLT *frac = Stream_getData((Stream *)self->frac_stream);
-    
-    oneOnSr = 1.0 / self->sr;
-    for (i=0; i<self->bufsize; i++) {
-        curfrac = frac[i];
-        inc = fr[i] * oneOnSr;
-        self->pointerPos += inc;
-        if (self->pointerPos < 0)
-            self->pointerPos = 1.0 + self->pointerPos;
-        else if (self->pointerPos >= 1.0)
-            self->pointerPos -= 1.0;
-        pos = self->pointerPos + ph[i];
-        if (pos >= 1.0)
-            pos -= 1.0;
-        if (pos < curfrac) {
-            scl_pos = pos / curfrac;
-            t_pos = scl_pos * size;
-            ipart = (int)t_pos;
-            fpart = t_pos - ipart;
-            tmp = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
-            
-            e_pos = scl_pos * envsize;
-            ipart = (int)e_pos;
-            fpart = e_pos - ipart;
-            self->data[i] = tmp * (envlist[ipart] * (1.0 - fpart) + envlist[ipart+1] * fpart);
-        }    
-        else {
-            self->data[i] = 0.0;
-        }    
-    }
-}
-
-static void Pulsar_postprocessing_ii(Pulsar *self) { POST_PROCESSING_II };
-static void Pulsar_postprocessing_ai(Pulsar *self) { POST_PROCESSING_AI };
-static void Pulsar_postprocessing_ia(Pulsar *self) { POST_PROCESSING_IA };
-static void Pulsar_postprocessing_aa(Pulsar *self) { POST_PROCESSING_AA };
-static void Pulsar_postprocessing_ireva(Pulsar *self) { POST_PROCESSING_IREVA };
-static void Pulsar_postprocessing_areva(Pulsar *self) { POST_PROCESSING_AREVA };
-static void Pulsar_postprocessing_revai(Pulsar *self) { POST_PROCESSING_REVAI };
-static void Pulsar_postprocessing_revaa(Pulsar *self) { POST_PROCESSING_REVAA };
-static void Pulsar_postprocessing_revareva(Pulsar *self) { POST_PROCESSING_REVAREVA };
-
-static void
-Pulsar_setProcMode(Pulsar *self)
-{
-    int procmode, muladdmode;
-    procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100;
-    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
-	switch (procmode) {
-        case 0:        
-            self->proc_func_ptr = Pulsar_readframes_iii;
-            break;
-        case 1:    
-            self->proc_func_ptr = Pulsar_readframes_aii;
-            break;
-        case 10:        
-            self->proc_func_ptr = Pulsar_readframes_iai;
-            break;
-        case 11:    
-            self->proc_func_ptr = Pulsar_readframes_aai;
-            break;
-        case 100:        
-            self->proc_func_ptr = Pulsar_readframes_iia;
-            break;
-        case 101:    
-            self->proc_func_ptr = Pulsar_readframes_aia;
-            break;
-        case 110:        
-            self->proc_func_ptr = Pulsar_readframes_iaa;
-            break;
-        case 111:    
-            self->proc_func_ptr = Pulsar_readframes_aaa;
-            break;
-    } 
-	switch (muladdmode) {
-        case 0:        
-            self->muladd_func_ptr = Pulsar_postprocessing_ii;
-            break;
-        case 1:    
-            self->muladd_func_ptr = Pulsar_postprocessing_ai;
-            break;
-        case 2:    
-            self->muladd_func_ptr = Pulsar_postprocessing_revai;
-            break;
-        case 10:        
-            self->muladd_func_ptr = Pulsar_postprocessing_ia;
-            break;
-        case 11:    
-            self->muladd_func_ptr = Pulsar_postprocessing_aa;
-            break;
-        case 12:    
-            self->muladd_func_ptr = Pulsar_postprocessing_revaa;
-            break;
-        case 20:        
-            self->muladd_func_ptr = Pulsar_postprocessing_ireva;
-            break;
-        case 21:    
-            self->muladd_func_ptr = Pulsar_postprocessing_areva;
-            break;
-        case 22:    
-            self->muladd_func_ptr = Pulsar_postprocessing_revareva;
-            break;
-    } 
-}
-
-static void
-Pulsar_compute_next_data_frame(Pulsar *self)
-{
-    (*self->proc_func_ptr)(self); 
-    (*self->muladd_func_ptr)(self);
-}
-
-static int
-Pulsar_traverse(Pulsar *self, visitproc visit, void *arg)
-{
-    pyo_VISIT
-    Py_VISIT(self->table);
-    Py_VISIT(self->env);
-    Py_VISIT(self->phase);    
-    Py_VISIT(self->phase_stream);    
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
-    Py_VISIT(self->frac);    
-    Py_VISIT(self->frac_stream);
-    return 0;
-}
-
-static int 
-Pulsar_clear(Pulsar *self)
-{
-    pyo_CLEAR
-    Py_CLEAR(self->table);
-    Py_CLEAR(self->env);
-    Py_CLEAR(self->phase);    
-    Py_CLEAR(self->phase_stream);    
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
-    Py_CLEAR(self->frac);    
-    Py_CLEAR(self->frac_stream);
-    return 0;
-}
-
-static void
-Pulsar_dealloc(Pulsar* self)
-{
-    pyo_DEALLOC
-    Pulsar_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
-}
-
-static PyObject *
-Pulsar_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
-    int i;
-    PyObject *tabletmp, *envtmp, *freqtmp=NULL, *phasetmp=NULL, *fractmp=NULL, *multmp=NULL, *addtmp=NULL;
-    Pulsar *self;
-    self = (Pulsar *)type->tp_alloc(type, 0);
-    
-    self->freq = PyFloat_FromDouble(100);
-    self->phase = PyFloat_FromDouble(0);
-    self->frac = PyFloat_FromDouble(0.5);
-    self->interp = 2;
-	self->modebuffer[0] = 0;
-	self->modebuffer[1] = 0;
-	self->modebuffer[2] = 0;
-	self->modebuffer[3] = 0;
-	self->modebuffer[4] = 0;
-    self->pointerPos = 0.;
-    
-    INIT_OBJECT_COMMON
-    Stream_setFunctionPtr(self->stream, Pulsar_compute_next_data_frame);
-    self->mode_func_ptr = Pulsar_setProcMode;
-
-    static char *kwlist[] = {"table", "env", "freq", "frac", "phase", "interp", "mul", "add", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOOiOO", kwlist, &tabletmp, &envtmp, &freqtmp, &fractmp, &phasetmp, &self->interp, &multmp, &addtmp))
-        Py_RETURN_NONE;
-    
-    if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
-        PySys_WriteStderr("TypeError: \"table\" argument of Pulsar must be a PyoTableObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
-    }
-    Py_XDECREF(self->table);
-    self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", "");
-
-    if ( PyObject_HasAttrString((PyObject *)envtmp, "getTableStream") == 0 ) {
-        PySys_WriteStderr("TypeError: \"env\" argument of Pulsar must be a PyoTableObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
-    }
-    Py_XDECREF(self->env);
-    self->env = PyObject_CallMethod((PyObject *)envtmp, "getTableStream", "");
-
-    if (phasetmp) {
-        PyObject_CallMethod((PyObject *)self, "setPhase", "O", phasetmp);
-    }
-    
-    if (freqtmp) {
-        PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
-    }
-
-    if (fractmp) {
-        PyObject_CallMethod((PyObject *)self, "setFrac", "O", fractmp);
-    }
-    
-    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);
-
-    SET_INTERP_POINTER
-    
-    return (PyObject *)self;
-}
-
-static PyObject * Pulsar_getServer(Pulsar* self) { GET_SERVER };
-static PyObject * Pulsar_getStream(Pulsar* self) { GET_STREAM };
-static PyObject * Pulsar_setMul(Pulsar *self, PyObject *arg) { SET_MUL };	
-static PyObject * Pulsar_setAdd(Pulsar *self, PyObject *arg) { SET_ADD };	
-static PyObject * Pulsar_setSub(Pulsar *self, PyObject *arg) { SET_SUB };	
-static PyObject * Pulsar_setDiv(Pulsar *self, PyObject *arg) { SET_DIV };	
+static PyObject * TableIndex_getServer(TableIndex* self) { GET_SERVER };
+static PyObject * TableIndex_getStream(TableIndex* self) { GET_STREAM };
+static PyObject * TableIndex_setMul(TableIndex *self, PyObject *arg) { SET_MUL };
+static PyObject * TableIndex_setAdd(TableIndex *self, PyObject *arg) { SET_ADD };
+static PyObject * TableIndex_setSub(TableIndex *self, PyObject *arg) { SET_SUB };
+static PyObject * TableIndex_setDiv(TableIndex *self, PyObject *arg) { SET_DIV };
 
-static PyObject * Pulsar_play(Pulsar *self, PyObject *args, PyObject *kwds) { PLAY };
-static PyObject * Pulsar_out(Pulsar *self, PyObject *args, PyObject *kwds) { OUT };
-static PyObject * Pulsar_stop(Pulsar *self) { STOP };
+static PyObject * TableIndex_play(TableIndex *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * TableIndex_out(TableIndex *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * TableIndex_stop(TableIndex *self) { STOP };
 
-static PyObject * Pulsar_multiply(Pulsar *self, PyObject *arg) { MULTIPLY };
-static PyObject * Pulsar_inplace_multiply(Pulsar *self, PyObject *arg) { INPLACE_MULTIPLY };
-static PyObject * Pulsar_add(Pulsar *self, PyObject *arg) { ADD };
-static PyObject * Pulsar_inplace_add(Pulsar *self, PyObject *arg) { INPLACE_ADD };
-static PyObject * Pulsar_sub(Pulsar *self, PyObject *arg) { SUB };
-static PyObject * Pulsar_inplace_sub(Pulsar *self, PyObject *arg) { INPLACE_SUB };
-static PyObject * Pulsar_div(Pulsar *self, PyObject *arg) { DIV };
-static PyObject * Pulsar_inplace_div(Pulsar *self, PyObject *arg) { INPLACE_DIV };
+static PyObject * TableIndex_multiply(TableIndex *self, PyObject *arg) { MULTIPLY };
+static PyObject * TableIndex_inplace_multiply(TableIndex *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * TableIndex_add(TableIndex *self, PyObject *arg) { ADD };
+static PyObject * TableIndex_inplace_add(TableIndex *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * TableIndex_sub(TableIndex *self, PyObject *arg) { SUB };
+static PyObject * TableIndex_inplace_sub(TableIndex *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * TableIndex_div(TableIndex *self, PyObject *arg) { DIV };
+static PyObject * TableIndex_inplace_div(TableIndex *self, PyObject *arg) { INPLACE_DIV };
 
 static PyObject *
-Pulsar_getTable(Pulsar* self)
+TableIndex_getTable(TableIndex* self)
 {
     Py_INCREF(self->table);
     return self->table;
 };
 
 static PyObject *
-Pulsar_getEnv(Pulsar* self)
-{
-    Py_INCREF(self->env);
-    return self->env;
-};
-
-static PyObject *
-Pulsar_setTable(Pulsar *self, PyObject *arg)
+TableIndex_setTable(TableIndex *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    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 *
-Pulsar_setEnv(Pulsar *self, PyObject *arg)
-{
-	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	tmp = arg;
-	Py_DECREF(self->env);
-    self->env = PyObject_CallMethod((PyObject *)tmp, "getTableStream", "");
-    
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
-Pulsar_setFreq(Pulsar *self, PyObject *arg)
+TableIndex_setIndex(TableIndex *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	int isNumber = PyNumber_Check(arg);
-	
+
+    ASSERT_ARG_NOT_NULL
+
 	tmp = arg;
+	if (PyObject_HasAttrString((PyObject *)tmp, "server") == 0) {
+        PyErr_SetString(PyExc_TypeError, "\"index\" argument of TableIndex must be a PyoObject.\n");
+        Py_RETURN_NONE;
+	}
+
 	Py_INCREF(tmp);
-	Py_DECREF(self->freq);
-	if (isNumber == 1) {
-		self->freq = PyNumber_Float(tmp);
-        self->modebuffer[2] = 0;
-	}
-	else {
-		self->freq = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL);
-        Py_INCREF(streamtmp);
-        Py_XDECREF(self->freq_stream);
-        self->freq_stream = (Stream *)streamtmp;
-		self->modebuffer[2] = 1;
-	}
-    
-    (*self->mode_func_ptr)(self);
-    
-	Py_INCREF(Py_None);
-	return Py_None;
-}	
+	Py_XDECREF(self->index);
 
-static PyObject *
-Pulsar_setPhase(Pulsar *self, PyObject *arg)
-{
-	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	int isNumber = PyNumber_Check(arg);
-	
-	tmp = arg;
-	Py_INCREF(tmp);
-	Py_DECREF(self->phase);
-	if (isNumber == 1) {
-		self->phase = PyNumber_Float(tmp);
-        self->modebuffer[3] = 0;
-	}
-	else {
-		self->phase = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->phase, "_getStream", NULL);
-        Py_INCREF(streamtmp);
-        Py_XDECREF(self->phase_stream);
-        self->phase_stream = (Stream *)streamtmp;
-		self->modebuffer[3] = 1;
-	}
-    
-    (*self->mode_func_ptr)(self);
-    
-	Py_INCREF(Py_None);
-	return Py_None;
-}	
+    self->index = tmp;
+    streamtmp = PyObject_CallMethod((PyObject *)self->index, "_getStream", NULL);
+    Py_INCREF(streamtmp);
+    Py_XDECREF(self->index_stream);
+    self->index_stream = (Stream *)streamtmp;
 
-static PyObject *
-Pulsar_setFrac(Pulsar *self, PyObject *arg)
-{
-	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	int isNumber = PyNumber_Check(arg);
-	
-	tmp = arg;
-	Py_INCREF(tmp);
-	Py_DECREF(self->frac);
-	if (isNumber == 1) {
-		self->frac = PyNumber_Float(tmp);
-        self->modebuffer[4] = 0;
-	}
-	else {
-		self->frac = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->frac, "_getStream", NULL);
-        Py_INCREF(streamtmp);
-        Py_XDECREF(self->frac_stream);
-        self->frac_stream = (Stream *)streamtmp;
-		self->modebuffer[4] = 1;
-	}
-    
-    (*self->mode_func_ptr)(self);
-    
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
-
-static PyObject *
-Pulsar_setInterp(Pulsar *self, PyObject *arg)
-{
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-    int isNumber = PyNumber_Check(arg);
-    
-	if (isNumber == 1) {
-		self->interp = PyInt_AsLong(PyNumber_Int(arg));
-    }  
-    
-    SET_INTERP_POINTER
-    
-    Py_INCREF(Py_None);
-    return Py_None;
 }
 
-static PyMemberDef Pulsar_members[] = {
-{"server", T_OBJECT_EX, offsetof(Pulsar, server), 0, "Pyo server."},
-{"stream", T_OBJECT_EX, offsetof(Pulsar, stream), 0, "Stream object."},
-{"table", T_OBJECT_EX, offsetof(Pulsar, table), 0, "Waveform table."},
-{"freq", T_OBJECT_EX, offsetof(Pulsar, freq), 0, "Frequency in cycle per second."},
-{"phase", T_OBJECT_EX, offsetof(Pulsar, phase), 0, "Oscillator phase."},
-{"frac", T_OBJECT_EX, offsetof(Pulsar, frac), 0, "Table width inside whole length."},
-{"mul", T_OBJECT_EX, offsetof(Pulsar, mul), 0, "Mul factor."},
-{"add", T_OBJECT_EX, offsetof(Pulsar, add), 0, "Add factor."},
-{NULL}  /* Sentinel */
-};
-
-static PyMethodDef Pulsar_methods[] = {
-{"getTable", (PyCFunction)Pulsar_getTable, METH_NOARGS, "Returns waveform table object."},
-{"getEnv", (PyCFunction)Pulsar_getEnv, METH_NOARGS, "Returns object envelope."},
-{"getServer", (PyCFunction)Pulsar_getServer, METH_NOARGS, "Returns server object."},
-{"_getStream", (PyCFunction)Pulsar_getStream, METH_NOARGS, "Returns stream object."},
-{"play", (PyCFunction)Pulsar_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
-{"out", (PyCFunction)Pulsar_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
-{"stop", (PyCFunction)Pulsar_stop, METH_NOARGS, "Stops computing."},
-{"setTable", (PyCFunction)Pulsar_setTable, METH_O, "Sets oscillator table."},
-{"setEnv", (PyCFunction)Pulsar_setEnv, METH_O, "Sets envelope table."},
-{"setFreq", (PyCFunction)Pulsar_setFreq, METH_O, "Sets oscillator frequency in cycle per second."},
-{"setPhase", (PyCFunction)Pulsar_setPhase, METH_O, "Sets oscillator phase."},
-{"setFrac", (PyCFunction)Pulsar_setFrac, METH_O, "Sets waveform width inside whole period length."},
-{"setInterp", (PyCFunction)Pulsar_setInterp, METH_O, "Sets Pulsar interpolation mode."},
-{"setMul", (PyCFunction)Pulsar_setMul, METH_O, "Sets oscillator mul factor."},
-{"setAdd", (PyCFunction)Pulsar_setAdd, METH_O, "Sets oscillator add factor."},
-{"setSub", (PyCFunction)Pulsar_setSub, METH_O, "Sets oscillator inverse add factor."},
-{"setDiv", (PyCFunction)Pulsar_setDiv, METH_O, "Sets inverse mul factor."},
-{NULL}  /* Sentinel */
+static PyMemberDef TableIndex_members[] = {
+    {"server", T_OBJECT_EX, offsetof(TableIndex, server), 0, "Pyo server."},
+    {"stream", T_OBJECT_EX, offsetof(TableIndex, stream), 0, "Stream object."},
+    {"table", T_OBJECT_EX, offsetof(TableIndex, table), 0, "Waveform table."},
+    {"index", T_OBJECT_EX, offsetof(TableIndex, index), 0, "Reader index."},
+    {"mul", T_OBJECT_EX, offsetof(TableIndex, mul), 0, "Mul factor."},
+    {"add", T_OBJECT_EX, offsetof(TableIndex, add), 0, "Add factor."},
+    {NULL}  /* Sentinel */
 };
 
-static PyNumberMethods Pulsar_as_number = {
-(binaryfunc)Pulsar_add,                      /*nb_add*/
-(binaryfunc)Pulsar_sub,                 /*nb_subtract*/
-(binaryfunc)Pulsar_multiply,                 /*nb_multiply*/
-(binaryfunc)Pulsar_div,                   /*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*/
-0,                                          /*nb_coerce*/
-0,                       /*nb_int*/
-0,                      /*nb_long*/
-0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
-(binaryfunc)Pulsar_inplace_add,              /*inplace_add*/
-(binaryfunc)Pulsar_inplace_sub,         /*inplace_subtract*/
-(binaryfunc)Pulsar_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)Pulsar_inplace_div,           /*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*/
-0,              /*nb_true_divide*/
-0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
-0,                     /* nb_index */
+static PyMethodDef TableIndex_methods[] = {
+    {"getTable", (PyCFunction)TableIndex_getTable, METH_NOARGS, "Returns waveform table object."},
+    {"getServer", (PyCFunction)TableIndex_getServer, METH_NOARGS, "Returns server object."},
+    {"_getStream", (PyCFunction)TableIndex_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)TableIndex_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+    {"out", (PyCFunction)TableIndex_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+    {"stop", (PyCFunction)TableIndex_stop, METH_NOARGS, "Stops computing."},
+    {"setTable", (PyCFunction)TableIndex_setTable, METH_O, "Sets oscillator table."},
+    {"setIndex", (PyCFunction)TableIndex_setIndex, METH_O, "Sets reader index."},
+    {"setMul", (PyCFunction)TableIndex_setMul, METH_O, "Sets oscillator mul factor."},
+    {"setAdd", (PyCFunction)TableIndex_setAdd, METH_O, "Sets oscillator add factor."},
+    {"setSub", (PyCFunction)TableIndex_setSub, METH_O, "Sets oscillator inverse add factor."},
+    {"setDiv", (PyCFunction)TableIndex_setDiv, METH_O, "Sets inverse mul factor."},
+    {NULL}  /* Sentinel */
 };
 
-PyTypeObject PulsarType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
-"_pyo.Pulsar_base",         /*tp_name*/
-sizeof(Pulsar),         /*tp_basicsize*/
-0,                         /*tp_itemsize*/
-(destructor)Pulsar_dealloc, /*tp_dealloc*/
-0,                         /*tp_print*/
-0,                         /*tp_getattr*/
-0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
-0,                         /*tp_repr*/
-&Pulsar_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*/
-"Pulsar objects. Generates pulsar synthesis oscillator.",           /* tp_doc */
-(traverseproc)Pulsar_traverse,   /* tp_traverse */
-(inquiry)Pulsar_clear,           /* tp_clear */
-0,		               /* tp_richcompare */
-0,		               /* tp_weaklistoffset */
-0,		               /* tp_iter */
-0,		               /* tp_iternext */
-Pulsar_methods,             /* tp_methods */
-Pulsar_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 */
-Pulsar_new,                 /* tp_new */
+static PyNumberMethods TableIndex_as_number = {
+    (binaryfunc)TableIndex_add,                      /*nb_add*/
+    (binaryfunc)TableIndex_sub,                 /*nb_subtract*/
+    (binaryfunc)TableIndex_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)TableIndex_inplace_add,              /*inplace_add*/
+    (binaryfunc)TableIndex_inplace_sub,         /*inplace_subtract*/
+    (binaryfunc)TableIndex_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)TableIndex_div,                       /*nb_true_divide*/
+    0,     /*nb_inplace_floor_divide*/
+    (binaryfunc)TableIndex_inplace_div,                       /*nb_inplace_true_divide*/
+    0,                     /* nb_index */
 };
 
-/**************/
-/* TableRead object */
-/**************/
-typedef struct {
-    pyo_audio_HEAD
-    PyObject *table;
-    PyObject *freq;
-    Stream *freq_stream;
-    int loop;
-    int go;
-    int modebuffer[3];
-    double pointerPos;
-    MYFLT *trigsBuffer;
-    TriggerStream *trig_stream;
-    int init;    
-    int interp; /* 0 = default to 2, 1 = nointerp, 2 = linear, 3 = cos, 4 = cubic */
-    MYFLT (*interp_func_ptr)(MYFLT *, int, MYFLT, int);
-} TableRead;
+PyTypeObject TableIndexType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.TableIndex_base",         /*tp_name*/
+    sizeof(TableIndex),         /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)TableIndex_dealloc, /*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
+    0,                         /*tp_repr*/
+    &TableIndex_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*/
+    "TableIndex objects. Read a table by indexing without interpolation.",           /* tp_doc */
+    (traverseproc)TableIndex_traverse,   /* tp_traverse */
+    (inquiry)TableIndex_clear,           /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    TableIndex_methods,             /* tp_methods */
+    TableIndex_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 */
+    TableIndex_new,                 /* tp_new */
+};
 
-static void
-TableRead_readframes_i(TableRead *self) {
-    MYFLT fr, inc, fpart;
-    int i, ipart;
-    MYFLT *tablelist = TableStream_getData(self->table);
-    int size = TableStream_getSize(self->table);
-    
-    fr = PyFloat_AS_DOUBLE(self->freq);
-    inc = fr * size / self->sr;
-    
-    if (self->go == 0)
-        PyObject_CallMethod((PyObject *)self, "stop", NULL);
+/**************/
+/* Lookup object */
+/**************/
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *table;
+    PyObject *index;
+    Stream *index_stream;
+    int modebuffer[2];
+} Lookup;
 
-    for (i=0; i<self->bufsize; i++) {
-        self->trigsBuffer[i] = 0.0;
-        if (self->pointerPos < 0) {
-            if (self->init == 0)
-                self->trigsBuffer[i] = 1.0;
-            else
-                self->init = 0;
-            self->pointerPos = size + self->pointerPos;
-        }    
-        else if (self->pointerPos >= size) {
-            self->trigsBuffer[i] = 1.0;
-            if (self->loop == 1)
-                self->pointerPos -= size;
-            else
-                self->go = 0;
-        }
-        if (self->go == 1) {
-            ipart = (int)self->pointerPos;
-            fpart = self->pointerPos - ipart;
-            self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
-        }
-        else
-            self->data[i] = 0.0;
-        
-        self->pointerPos += inc;
-    }
+static MYFLT
+Lookup_clip(MYFLT x) {
+    if (x < -1.0)
+        return -1.0;
+    else if (x > 1.0)
+        return 1.0;
+    else
+        return x;
 }
 
 static void
-TableRead_readframes_a(TableRead *self) {
-    MYFLT inc, fpart, sizeOnSr;
+Lookup_readframes_a(Lookup *self) {
+    MYFLT ph, fpart;
     int i, ipart;
     MYFLT *tablelist = TableStream_getData(self->table);
     int size = TableStream_getSize(self->table);
-    
-    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    
-    sizeOnSr = size / self->sr;
 
-    if (self->go == 0)
-        PyObject_CallMethod((PyObject *)self, "stop", NULL);
+    MYFLT *pha = Stream_getData((Stream *)self->index_stream);
 
     for (i=0; i<self->bufsize; i++) {
-        self->trigsBuffer[i] = 0.0;
-        if (self->pointerPos < 0) {
-            if (self->init == 0)
-                self->trigsBuffer[i] = 1.0;
-            else
-                self->init = 0;
-            self->pointerPos = size + self->pointerPos;
-        }    
-        else if (self->pointerPos >= size) {
-            self->trigsBuffer[i] = 1.0;
-            if (self->loop == 1)
-                self->pointerPos -= size;
-            else
-                self->go = 0;
-        }
-        if (self->go == 1) {
-            ipart = (int)self->pointerPos;
-            fpart = self->pointerPos - ipart;
-            self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
-        }    
-        else
-            self->data[i] = 0.0;
-        
-        inc = fr[i] * sizeOnSr;
-        self->pointerPos += inc;
+        ph = (Lookup_clip(pha[i]) * 0.495 + 0.5) * size;
+        ipart = (int)ph;
+        fpart = ph - ipart;
+        self->data[i] = tablelist[ipart] + (tablelist[ipart+1] - tablelist[ipart]) * fpart;
     }
 }
 
-static void TableRead_postprocessing_ii(TableRead *self) { POST_PROCESSING_II };
-static void TableRead_postprocessing_ai(TableRead *self) { POST_PROCESSING_AI };
-static void TableRead_postprocessing_ia(TableRead *self) { POST_PROCESSING_IA };
-static void TableRead_postprocessing_aa(TableRead *self) { POST_PROCESSING_AA };
-static void TableRead_postprocessing_ireva(TableRead *self) { POST_PROCESSING_IREVA };
-static void TableRead_postprocessing_areva(TableRead *self) { POST_PROCESSING_AREVA };
-static void TableRead_postprocessing_revai(TableRead *self) { POST_PROCESSING_REVAI };
-static void TableRead_postprocessing_revaa(TableRead *self) { POST_PROCESSING_REVAA };
-static void TableRead_postprocessing_revareva(TableRead *self) { POST_PROCESSING_REVAREVA };
+static void Lookup_postprocessing_ii(Lookup *self) { POST_PROCESSING_II };
+static void Lookup_postprocessing_ai(Lookup *self) { POST_PROCESSING_AI };
+static void Lookup_postprocessing_ia(Lookup *self) { POST_PROCESSING_IA };
+static void Lookup_postprocessing_aa(Lookup *self) { POST_PROCESSING_AA };
+static void Lookup_postprocessing_ireva(Lookup *self) { POST_PROCESSING_IREVA };
+static void Lookup_postprocessing_areva(Lookup *self) { POST_PROCESSING_AREVA };
+static void Lookup_postprocessing_revai(Lookup *self) { POST_PROCESSING_REVAI };
+static void Lookup_postprocessing_revaa(Lookup *self) { POST_PROCESSING_REVAA };
+static void Lookup_postprocessing_revareva(Lookup *self) { POST_PROCESSING_REVAREVA };
 
 static void
-TableRead_setProcMode(TableRead *self)
+Lookup_setProcMode(Lookup *self)
 {
-    int procmode, muladdmode;
-    procmode = self->modebuffer[2];
+    int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
-	switch (procmode) {
-        case 0:        
-            self->proc_func_ptr = TableRead_readframes_i;
-            break;
-        case 1:    
-            self->proc_func_ptr = TableRead_readframes_a;
-            break;
-    } 
+
+    self->proc_func_ptr = Lookup_readframes_a;
+
 	switch (muladdmode) {
-        case 0:        
-            self->muladd_func_ptr = TableRead_postprocessing_ii;
+        case 0:
+            self->muladd_func_ptr = Lookup_postprocessing_ii;
             break;
-        case 1:    
-            self->muladd_func_ptr = TableRead_postprocessing_ai;
+        case 1:
+            self->muladd_func_ptr = Lookup_postprocessing_ai;
             break;
-        case 2:    
-            self->muladd_func_ptr = TableRead_postprocessing_revai;
+        case 2:
+            self->muladd_func_ptr = Lookup_postprocessing_revai;
             break;
-        case 10:        
-            self->muladd_func_ptr = TableRead_postprocessing_ia;
+        case 10:
+            self->muladd_func_ptr = Lookup_postprocessing_ia;
             break;
-        case 11:    
-            self->muladd_func_ptr = TableRead_postprocessing_aa;
+        case 11:
+            self->muladd_func_ptr = Lookup_postprocessing_aa;
             break;
-        case 12:    
-            self->muladd_func_ptr = TableRead_postprocessing_revaa;
+        case 12:
+            self->muladd_func_ptr = Lookup_postprocessing_revaa;
             break;
-        case 20:        
-            self->muladd_func_ptr = TableRead_postprocessing_ireva;
+        case 20:
+            self->muladd_func_ptr = Lookup_postprocessing_ireva;
             break;
-        case 21:    
-            self->muladd_func_ptr = TableRead_postprocessing_areva;
+        case 21:
+            self->muladd_func_ptr = Lookup_postprocessing_areva;
             break;
-        case 22:    
-            self->muladd_func_ptr = TableRead_postprocessing_revareva;
+        case 22:
+            self->muladd_func_ptr = Lookup_postprocessing_revareva;
             break;
-    } 
+    }
 }
 
 static void
-TableRead_compute_next_data_frame(TableRead *self)
+Lookup_compute_next_data_frame(Lookup *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
 static int
-TableRead_traverse(TableRead *self, visitproc visit, void *arg)
+Lookup_traverse(Lookup *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->table);
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
-    Py_VISIT(self->trig_stream);    
+    Py_VISIT(self->index);
+    Py_VISIT(self->index_stream);
     return 0;
 }
 
-static int 
-TableRead_clear(TableRead *self)
+static int
+Lookup_clear(Lookup *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->table);
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
-    Py_CLEAR(self->trig_stream);    
+    Py_CLEAR(self->index);
+    Py_CLEAR(self->index_stream);
     return 0;
 }
 
 static void
-TableRead_dealloc(TableRead* self)
+Lookup_dealloc(Lookup* self)
 {
     pyo_DEALLOC
-    free(self->trigsBuffer);
-    TableRead_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Lookup_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
-TableRead_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+Lookup_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
-    MYFLT *tablelist;
-    PyObject *tabletmp, *freqtmp=NULL, *multmp=NULL, *addtmp=NULL;
-    TableRead *self;
-    self = (TableRead *)type->tp_alloc(type, 0);
-    
-    self->freq = PyFloat_FromDouble(1);
-    self->loop = 0;
-    self->init = 1;
+    PyObject *tabletmp, *indextmp, *multmp=NULL, *addtmp=NULL;
+    Lookup *self;
+    self = (Lookup *)type->tp_alloc(type, 0);
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-	self->modebuffer[2] = 0;
-    self->pointerPos = 0.;
-    self->interp = 2;
-    
+
     INIT_OBJECT_COMMON
-    Stream_setFunctionPtr(self->stream, TableRead_compute_next_data_frame);
-    self->mode_func_ptr = TableRead_setProcMode;
+    Stream_setFunctionPtr(self->stream, Lookup_compute_next_data_frame);
+    self->mode_func_ptr = Lookup_setProcMode;
 
-    static char *kwlist[] = {"table", "freq", "loop", "interp", "mul", "add", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OiiOO", kwlist, &tabletmp, &freqtmp, &self->loop, &self->interp, &multmp, &addtmp))
+    static char *kwlist[] = {"table", "index", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist, &tabletmp, &indextmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
-        PySys_WriteStderr("TypeError: \"table\" argument of TableRead must be a PyoTableObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"table\" argument of Lookup must be a PyoTableObject.\n");
+        Py_RETURN_NONE;
     }
     Py_XDECREF(self->table);
     self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", "");
 
-    if (freqtmp) {
-        PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
-    }
-    
-    if (multmp) {
-        PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
+    if (indextmp) {
+        PyObject_CallMethod((PyObject *)self, "setIndex", "O", indextmp);
     }
-    
+
+    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->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT));
-    
-    tablelist = TableStream_getData(self->table);
-    
-    for (i=0; i<self->bufsize; i++) {
-        self->trigsBuffer[i] = 0.0;
-        self->data[i] = tablelist[0];
-    }    
+    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
-    MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL);
-    TriggerStream_setData(self->trig_stream, self->trigsBuffer);
-    
     (*self->mode_func_ptr)(self);
 
-    SET_INTERP_POINTER
-
-    self->init = 1;
-     
     return (PyObject *)self;
 }
 
-static PyObject * TableRead_getServer(TableRead* self) { GET_SERVER };
-static PyObject * TableRead_getStream(TableRead* self) { GET_STREAM };
-static PyObject * TableRead_getTriggerStream(TableRead* self) { GET_TRIGGER_STREAM };
-static PyObject * TableRead_setMul(TableRead *self, PyObject *arg) { SET_MUL };	
-static PyObject * TableRead_setAdd(TableRead *self, PyObject *arg) { SET_ADD };	
-static PyObject * TableRead_setSub(TableRead *self, PyObject *arg) { SET_SUB };	
-static PyObject * TableRead_setDiv(TableRead *self, PyObject *arg) { SET_DIV };	
-
-static PyObject * TableRead_play(TableRead *self, PyObject *args, PyObject *kwds) 
-{ 
-    self->pointerPos = 0.0;
-    self->init = 1;
-    self->go = 1;
-    PLAY 
-};
+static PyObject * Lookup_getServer(Lookup* self) { GET_SERVER };
+static PyObject * Lookup_getStream(Lookup* self) { GET_STREAM };
+static PyObject * Lookup_setMul(Lookup *self, PyObject *arg) { SET_MUL };
+static PyObject * Lookup_setAdd(Lookup *self, PyObject *arg) { SET_ADD };
+static PyObject * Lookup_setSub(Lookup *self, PyObject *arg) { SET_SUB };
+static PyObject * Lookup_setDiv(Lookup *self, PyObject *arg) { SET_DIV };
 
-static PyObject * TableRead_out(TableRead *self, PyObject *args, PyObject *kwds) 
-{ 
-    self->pointerPos = 0.0;
-    self->init = 1;
-    self->go = 1;
-    OUT 
-};
-static PyObject * TableRead_stop(TableRead *self) 
-{ 
-    self->go = 0;
-    STOP 
-};
+static PyObject * Lookup_play(Lookup *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * Lookup_out(Lookup *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * Lookup_stop(Lookup *self) { STOP };
 
-static PyObject * TableRead_multiply(TableRead *self, PyObject *arg) { MULTIPLY };
-static PyObject * TableRead_inplace_multiply(TableRead *self, PyObject *arg) { INPLACE_MULTIPLY };
-static PyObject * TableRead_add(TableRead *self, PyObject *arg) { ADD };
-static PyObject * TableRead_inplace_add(TableRead *self, PyObject *arg) { INPLACE_ADD };
-static PyObject * TableRead_sub(TableRead *self, PyObject *arg) { SUB };
-static PyObject * TableRead_inplace_sub(TableRead *self, PyObject *arg) { INPLACE_SUB };
-static PyObject * TableRead_div(TableRead *self, PyObject *arg) { DIV };
-static PyObject * TableRead_inplace_div(TableRead *self, PyObject *arg) { INPLACE_DIV };
+static PyObject * Lookup_multiply(Lookup *self, PyObject *arg) { MULTIPLY };
+static PyObject * Lookup_inplace_multiply(Lookup *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * Lookup_add(Lookup *self, PyObject *arg) { ADD };
+static PyObject * Lookup_inplace_add(Lookup *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * Lookup_sub(Lookup *self, PyObject *arg) { SUB };
+static PyObject * Lookup_inplace_sub(Lookup *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * Lookup_div(Lookup *self, PyObject *arg) { DIV };
+static PyObject * Lookup_inplace_div(Lookup *self, PyObject *arg) { INPLACE_DIV };
 
 static PyObject *
-TableRead_getTable(TableRead* self)
+Lookup_getTable(Lookup* self)
 {
     Py_INCREF(self->table);
     return self->table;
 };
 
 static PyObject *
-TableRead_setTable(TableRead *self, PyObject *arg)
+Lookup_setTable(Lookup *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    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 *
-TableRead_setFreq(TableRead *self, PyObject *arg)
+Lookup_setIndex(Lookup *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	int isNumber = PyNumber_Check(arg);
-	
+
+    ASSERT_ARG_NOT_NULL
+
 	tmp = arg;
-	Py_INCREF(tmp);
-	Py_DECREF(self->freq);
-	if (isNumber == 1) {
-		self->freq = PyNumber_Float(tmp);
-        self->modebuffer[2] = 0;
-	}
-	else {
-		self->freq = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL);
-        Py_INCREF(streamtmp);
-        Py_XDECREF(self->freq_stream);
-        self->freq_stream = (Stream *)streamtmp;
-		self->modebuffer[2] = 1;
+	if (PyObject_HasAttrString((PyObject *)tmp, "server") == 0) {
+        PyErr_SetString(PyExc_TypeError, "\"index\" argument of Lookup must be a PyoObject.\n");
+        Py_RETURN_NONE;
 	}
-    
-    (*self->mode_func_ptr)(self);
-    
-	Py_INCREF(Py_None);
-	return Py_None;
-}	
 
-static PyObject *
-TableRead_setLoop(TableRead *self, PyObject *arg)
-{
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-    self->loop = PyInt_AsLong(arg);
-    
-    Py_INCREF(Py_None);
-    return Py_None;
-}
+	Py_INCREF(tmp);
+	Py_XDECREF(self->index);
 
-static PyObject *
-TableRead_setInterp(TableRead *self, PyObject *arg)
-{
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-    int isNumber = PyNumber_Check(arg);
-    
-	if (isNumber == 1) {
-		self->interp = PyInt_AsLong(PyNumber_Int(arg));
-    }  
-    
-    SET_INTERP_POINTER
-    
-    Py_INCREF(Py_None);
-    return Py_None;
-}
+    self->index = tmp;
+    streamtmp = PyObject_CallMethod((PyObject *)self->index, "_getStream", NULL);
+    Py_INCREF(streamtmp);
+    Py_XDECREF(self->index_stream);
+    self->index_stream = (Stream *)streamtmp;
 
-static PyObject * 
-TableRead_reset(TableRead *self) 
-{
-    self->pointerPos = 0.0;
-    Py_INCREF(Py_None);
-    return Py_None;
+	Py_INCREF(Py_None);
+	return Py_None;
 }
 
-static PyMemberDef TableRead_members[] = {
-{"server", T_OBJECT_EX, offsetof(TableRead, server), 0, "Pyo server."},
-{"stream", T_OBJECT_EX, offsetof(TableRead, stream), 0, "Stream object."},
-{"trig_stream", T_OBJECT_EX, offsetof(TableRead, trig_stream), 0, "Trigger Stream object."},
-{"table", T_OBJECT_EX, offsetof(TableRead, table), 0, "Waveform table."},
-{"freq", T_OBJECT_EX, offsetof(TableRead, freq), 0, "Frequency in cycle per second."},
-{"mul", T_OBJECT_EX, offsetof(TableRead, mul), 0, "Mul factor."},
-{"add", T_OBJECT_EX, offsetof(TableRead, add), 0, "Add factor."},
+static PyMemberDef Lookup_members[] = {
+{"server", T_OBJECT_EX, offsetof(Lookup, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(Lookup, stream), 0, "Stream object."},
+{"table", T_OBJECT_EX, offsetof(Lookup, table), 0, "Waveform table."},
+{"index", T_OBJECT_EX, offsetof(Lookup, index), 0, "Reader index."},
+{"mul", T_OBJECT_EX, offsetof(Lookup, mul), 0, "Mul factor."},
+{"add", T_OBJECT_EX, offsetof(Lookup, add), 0, "Add factor."},
 {NULL}  /* Sentinel */
 };
 
-static PyMethodDef TableRead_methods[] = {
-{"getTable", (PyCFunction)TableRead_getTable, METH_NOARGS, "Returns waveform table object."},
-{"getServer", (PyCFunction)TableRead_getServer, METH_NOARGS, "Returns server object."},
-{"_getStream", (PyCFunction)TableRead_getStream, METH_NOARGS, "Returns stream object."},
-{"_getTriggerStream", (PyCFunction)TableRead_getTriggerStream, METH_NOARGS, "Returns trigger stream object."},
-{"play", (PyCFunction)TableRead_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
-{"out", (PyCFunction)TableRead_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
-{"stop", (PyCFunction)TableRead_stop, METH_NOARGS, "Stops computing."},
-{"setTable", (PyCFunction)TableRead_setTable, METH_O, "Sets oscillator table."},
-{"setFreq", (PyCFunction)TableRead_setFreq, METH_O, "Sets oscillator frequency in cycle per second."},
-{"setLoop", (PyCFunction)TableRead_setLoop, METH_O, "Sets the looping mode."},
-{"setInterp", (PyCFunction)TableRead_setInterp, METH_O, "Sets reader interpolation mode."},
-{"reset", (PyCFunction)TableRead_reset, METH_NOARGS, "Resets pointer position to 0."},
-{"setMul", (PyCFunction)TableRead_setMul, METH_O, "Sets oscillator mul factor."},
-{"setAdd", (PyCFunction)TableRead_setAdd, METH_O, "Sets oscillator add factor."},
-{"setSub", (PyCFunction)TableRead_setSub, METH_O, "Sets oscillator inverse add factor."},
-{"setDiv", (PyCFunction)TableRead_setDiv, METH_O, "Sets inverse mul factor."},
+static PyMethodDef Lookup_methods[] = {
+{"getTable", (PyCFunction)Lookup_getTable, METH_NOARGS, "Returns waveform table object."},
+{"getServer", (PyCFunction)Lookup_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)Lookup_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)Lookup_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"out", (PyCFunction)Lookup_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+{"stop", (PyCFunction)Lookup_stop, METH_NOARGS, "Stops computing."},
+{"setTable", (PyCFunction)Lookup_setTable, METH_O, "Sets oscillator table."},
+{"setIndex", (PyCFunction)Lookup_setIndex, METH_O, "Sets reader index."},
+{"setMul", (PyCFunction)Lookup_setMul, METH_O, "Sets oscillator mul factor."},
+{"setAdd", (PyCFunction)Lookup_setAdd, METH_O, "Sets oscillator add factor."},
+{"setSub", (PyCFunction)Lookup_setSub, METH_O, "Sets oscillator inverse add factor."},
+{"setDiv", (PyCFunction)Lookup_setDiv, METH_O, "Sets inverse mul factor."},
 {NULL}  /* Sentinel */
 };
 
-static PyNumberMethods TableRead_as_number = {
-(binaryfunc)TableRead_add,                      /*nb_add*/
-(binaryfunc)TableRead_sub,                 /*nb_subtract*/
-(binaryfunc)TableRead_multiply,                 /*nb_multiply*/
-(binaryfunc)TableRead_div,                   /*nb_divide*/
+static PyNumberMethods Lookup_as_number = {
+(binaryfunc)Lookup_add,                      /*nb_add*/
+(binaryfunc)Lookup_sub,                 /*nb_subtract*/
+(binaryfunc)Lookup_multiply,                 /*nb_multiply*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -5448,16 +4885,16 @@ static PyNumberMethods TableRead_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
-(binaryfunc)TableRead_inplace_add,              /*inplace_add*/
-(binaryfunc)TableRead_inplace_sub,         /*inplace_subtract*/
-(binaryfunc)TableRead_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)TableRead_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
+(binaryfunc)Lookup_inplace_add,              /*inplace_add*/
+(binaryfunc)Lookup_inplace_sub,         /*inplace_subtract*/
+(binaryfunc)Lookup_inplace_multiply,         /*inplace_multiply*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -5466,25 +4903,24 @@ static PyNumberMethods TableRead_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)Lookup_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)Lookup_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
-PyTypeObject TableReadType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
-"_pyo.TableRead_base",         /*tp_name*/
-sizeof(TableRead),         /*tp_basicsize*/
+PyTypeObject LookupType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.Lookup_base",         /*tp_name*/
+sizeof(Lookup),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
-(destructor)TableRead_dealloc, /*tp_dealloc*/
+(destructor)Lookup_dealloc, /*tp_dealloc*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
-&TableRead_as_number,             /*tp_as_number*/
+&Lookup_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
 0,                         /*tp_as_mapping*/
 0,                         /*tp_hash */
@@ -5494,15 +4930,15 @@ sizeof(TableRead),         /*tp_basicsize*/
 0,                         /*tp_setattro*/
 0,                         /*tp_as_buffer*/
 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
-"TableRead objects. Generates an oscillatory waveform.",           /* tp_doc */
-(traverseproc)TableRead_traverse,   /* tp_traverse */
-(inquiry)TableRead_clear,           /* tp_clear */
+"Lookup objects. Modify a signal by reading a table with the signal as the index.",           /* tp_doc */
+(traverseproc)Lookup_traverse,   /* tp_traverse */
+(inquiry)Lookup_clear,           /* tp_clear */
 0,		               /* tp_richcompare */
 0,		               /* tp_weaklistoffset */
 0,		               /* tp_iter */
 0,		               /* tp_iternext */
-TableRead_methods,             /* tp_methods */
-TableRead_members,             /* tp_members */
+Lookup_methods,             /* tp_methods */
+Lookup_members,             /* tp_members */
 0,                      /* tp_getset */
 0,                         /* tp_base */
 0,                         /* tp_dict */
@@ -5511,591 +4947,784 @@ TableRead_members,             /* tp_members */
 0,                         /* tp_dictoffset */
 0,      /* tp_init */
 0,                         /* tp_alloc */
-TableRead_new,                 /* tp_new */
+Lookup_new,                 /* tp_new */
 };
 
-/*************/
-/* Fm object */
-/*************/
+/**************/
+/* Pulsar object */
+/**************/
 typedef struct {
     pyo_audio_HEAD
-    PyObject *car;
-    Stream *car_stream;
-    PyObject *ratio;
-    Stream *ratio_stream;
-    PyObject *index;
-    Stream *index_stream;
+    PyObject *table;
+    PyObject *env;
+    PyObject *freq;
+    Stream *freq_stream;
+    PyObject *phase;
+    Stream *phase_stream;
+    PyObject *frac;
+    Stream *frac_stream;
     int modebuffer[5];
-    MYFLT pointerPos_car;
-    MYFLT pointerPos_mod;
-    MYFLT scaleFactor;
-} Fm;
+    MYFLT pointerPos;
+    int interp; /* 0 = default to 2, 1 = nointerp, 2 = linear, 3 = cos, 4 = cubic */
+    MYFLT (*interp_func_ptr)(MYFLT *, int, MYFLT, int);
+} Pulsar;
 
 static void
-Fm_readframes_iii(Fm *self) {
-    MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_delta, fpart;
+Pulsar_readframes_iii(Pulsar *self) {
+    MYFLT fr, ph, frac, invfrac, pos, scl_pos, t_pos, e_pos, fpart, tmp;
+    double inc;
     int i, ipart;
-    
-    MYFLT car = PyFloat_AS_DOUBLE(self->car);
-    MYFLT rat = PyFloat_AS_DOUBLE(self->ratio);
-    MYFLT ind = PyFloat_AS_DOUBLE(self->index);
-    
-    mod_freq = car * rat;
-    mod_amp = mod_freq * ind;
-    mod_delta = mod_freq * self->scaleFactor;
-    
-    for (i=0; i<self->bufsize; i++) {
-        self->pointerPos_mod = Sine_clip(self->pointerPos_mod);
-        ipart = (int)self->pointerPos_mod;
-        fpart = self->pointerPos_mod - ipart;
-        mod_val = mod_amp * (SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart);
-        self->pointerPos_mod += mod_delta;
-        
-        car_freq = car + mod_val;
-        car_delta = car_freq * self->scaleFactor;
-        self->pointerPos_car = Sine_clip(self->pointerPos_car);
-        ipart = (int)self->pointerPos_car;
-        fpart = self->pointerPos_car - ipart;
-        self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
-        self->pointerPos_car += car_delta;
-    }
-}
+    MYFLT *tablelist = TableStream_getData(self->table);
+    MYFLT *envlist = TableStream_getData(self->env);
+    int size = TableStream_getSize(self->table);
+    int envsize = TableStream_getSize(self->env);
 
-static void
-Fm_readframes_aii(Fm *self) {
-    MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_delta, fpart;
-    int i, ipart;
-    
-    MYFLT *car = Stream_getData((Stream *)self->car_stream);
-    MYFLT rat = PyFloat_AS_DOUBLE(self->ratio);
-    MYFLT ind = PyFloat_AS_DOUBLE(self->index);
+    fr = PyFloat_AS_DOUBLE(self->freq);
+    ph = PyFloat_AS_DOUBLE(self->phase);
+    frac = _clip(PyFloat_AS_DOUBLE(self->frac));
+    invfrac = 1.0 / frac;
+    inc = fr / self->sr;
 
     for (i=0; i<self->bufsize; i++) {
-        mod_freq = car[i] * rat;
-        mod_amp = mod_freq * ind;
-        mod_delta = mod_freq * self->scaleFactor;
-        self->pointerPos_mod = Sine_clip(self->pointerPos_mod);
-        ipart = (int)self->pointerPos_mod;
-        fpart = self->pointerPos_mod - ipart;
-        mod_val = mod_amp * (SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart);
-        self->pointerPos_mod += mod_delta;
-        
-        car_freq = car[i] + mod_val;
-        car_delta = car_freq * self->scaleFactor;
-        self->pointerPos_car = Sine_clip(self->pointerPos_car);
-        ipart = (int)self->pointerPos_car;
-        fpart = self->pointerPos_car - ipart;
-        self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
-        self->pointerPos_car += car_delta;
+        self->pointerPos += inc;
+        if (self->pointerPos < 0)
+            self->pointerPos = 1.0 + self->pointerPos;
+        else if (self->pointerPos >= 1.0)
+            self->pointerPos -= 1.0;
+        pos = self->pointerPos + ph;
+        if (pos >= 1.0)
+            pos -= 1.0;
+        if (pos < frac) {
+            scl_pos = pos * invfrac;
+            t_pos = scl_pos * size;
+            ipart = (int)t_pos;
+            fpart = t_pos - ipart;
+            tmp = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
+
+            e_pos = scl_pos * envsize;
+            ipart = (int)e_pos;
+            fpart = e_pos - ipart;
+            self->data[i] = tmp * (envlist[ipart] * (1.0 - fpart) + envlist[ipart+1] * fpart);
+        }
+        else {
+            self->data[i] = 0.0;
+        }
     }
 }
 
 static void
-Fm_readframes_iai(Fm *self) {
-    MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_delta, fpart;
+Pulsar_readframes_aii(Pulsar *self) {
+    MYFLT ph, frac, invfrac, pos, scl_pos, t_pos, e_pos, fpart, tmp, oneOnSr;
+    double inc;
     int i, ipart;
-    
-    MYFLT car = PyFloat_AS_DOUBLE(self->car);
-    MYFLT *rat = Stream_getData((Stream *)self->ratio_stream);
-    MYFLT ind = PyFloat_AS_DOUBLE(self->index);
+    MYFLT *tablelist = TableStream_getData(self->table);
+    MYFLT *envlist = TableStream_getData(self->env);
+    int size = TableStream_getSize(self->table);
+    int envsize = TableStream_getSize(self->env);
+
+    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
+    ph = PyFloat_AS_DOUBLE(self->phase);
+    frac = _clip(PyFloat_AS_DOUBLE(self->frac));
+    invfrac = 1.0 / frac;
 
+    oneOnSr = 1.0 / self->sr;
     for (i=0; i<self->bufsize; i++) {
-        mod_freq = car * rat[i];
-        mod_amp = mod_freq * ind;
-        mod_delta = mod_freq * self->scaleFactor;
-        self->pointerPos_mod = Sine_clip(self->pointerPos_mod);
-        ipart = (int)self->pointerPos_mod;
-        fpart = self->pointerPos_mod - ipart;
-        mod_val = mod_amp * (SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart);
-        self->pointerPos_mod += mod_delta;
-        
-        car_freq = car + mod_val;
-        car_delta = car_freq * self->scaleFactor;
-        self->pointerPos_car = Sine_clip(self->pointerPos_car);
-        ipart = (int)self->pointerPos_car;
-        fpart = self->pointerPos_car - ipart;
-        self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
-        self->pointerPos_car += car_delta;
+        inc = fr[i] * oneOnSr;
+        self->pointerPos += inc;
+        if (self->pointerPos < 0)
+            self->pointerPos = 1.0 + self->pointerPos;
+        else if (self->pointerPos >= 1.0)
+            self->pointerPos -= 1.0;
+        pos = self->pointerPos + ph;
+        if (pos >= 1.0)
+            pos -= 1.0;
+        if (pos < frac) {
+            scl_pos = pos * invfrac;
+            t_pos = scl_pos * size;
+            ipart = (int)t_pos;
+            fpart = t_pos - ipart;
+            tmp = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
+
+            e_pos = scl_pos * envsize;
+            ipart = (int)e_pos;
+            fpart = e_pos - ipart;
+            self->data[i] = tmp * (envlist[ipart] * (1.0 - fpart) + envlist[ipart+1] * fpart);
+        }
+        else {
+            self->data[i] = 0.0;
+        }
     }
 }
 
 static void
-Fm_readframes_aai(Fm *self) {
-    MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_delta, fpart;
+Pulsar_readframes_iai(Pulsar *self) {
+    MYFLT fr, frac, invfrac, pos, scl_pos, t_pos, e_pos, fpart, tmp;
+    double inc;
     int i, ipart;
-    
-    MYFLT *car = Stream_getData((Stream *)self->car_stream);
-    MYFLT *rat = Stream_getData((Stream *)self->ratio_stream);
-    MYFLT ind = PyFloat_AS_DOUBLE(self->index);
+    MYFLT *tablelist = TableStream_getData(self->table);
+    MYFLT *envlist = TableStream_getData(self->env);
+    int size = TableStream_getSize(self->table);
+    int envsize = TableStream_getSize(self->env);
 
-    for (i=0; i<self->bufsize; i++) {
-        mod_freq = car[i] * rat[i];
-        mod_amp = mod_freq * ind;
-        mod_delta = mod_freq * self->scaleFactor;
-        self->pointerPos_mod = Sine_clip(self->pointerPos_mod);
-        ipart = (int)self->pointerPos_mod;
-        fpart = self->pointerPos_mod - ipart;
-        mod_val = mod_amp * (SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart);
-        self->pointerPos_mod += mod_delta;
-        
-        car_freq = car[i] + mod_val;
-        car_delta = car_freq * self->scaleFactor;
-        self->pointerPos_car = Sine_clip(self->pointerPos_car);
-        ipart = (int)self->pointerPos_car;
-        fpart = self->pointerPos_car - ipart;
-        self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
-        self->pointerPos_car += car_delta;
-    }}
+    fr = PyFloat_AS_DOUBLE(self->freq);
+    MYFLT *ph = Stream_getData((Stream *)self->phase_stream);
+    frac = _clip(PyFloat_AS_DOUBLE(self->frac));
+    invfrac = 1.0 / frac;
+    inc = fr / self->sr;
 
-static void
-Fm_readframes_iia(Fm *self) {
-    MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_delta, fpart;
-    int i, ipart;
-    
-    MYFLT car = PyFloat_AS_DOUBLE(self->car);
-    MYFLT rat = PyFloat_AS_DOUBLE(self->ratio);
-    MYFLT *ind = Stream_getData((Stream *)self->index_stream);
-    
-    mod_freq = car * rat;
-    mod_delta = mod_freq * self->scaleFactor;
-    
     for (i=0; i<self->bufsize; i++) {
-        mod_amp = mod_freq * ind[i];
-        self->pointerPos_mod = Sine_clip(self->pointerPos_mod);
-        ipart = (int)self->pointerPos_mod;
-        fpart = self->pointerPos_mod - ipart;
-        mod_val = mod_amp * (SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart);
-        self->pointerPos_mod += mod_delta;
-        
-        car_freq = car + mod_val;
-        car_delta = car_freq * self->scaleFactor;
-        self->pointerPos_car = Sine_clip(self->pointerPos_car);
-        ipart = (int)self->pointerPos_car;
-        fpart = self->pointerPos_car - ipart;
-        self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
-        self->pointerPos_car += car_delta;
+        self->pointerPos += inc;
+        if (self->pointerPos < 0)
+            self->pointerPos = 1.0 + self->pointerPos;
+        else if (self->pointerPos >= 1.0)
+            self->pointerPos -= 1.0;
+        pos = self->pointerPos + ph[i];
+        if (pos >= 1.0)
+            pos -= 1.0;
+        if (pos < frac) {
+            scl_pos = pos * invfrac;
+            t_pos = scl_pos * size;
+            ipart = (int)t_pos;
+            fpart = t_pos - ipart;
+            tmp = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
+
+            e_pos = scl_pos * envsize;
+            ipart = (int)e_pos;
+            fpart = e_pos - ipart;
+            self->data[i] = tmp * (envlist[ipart] * (1.0 - fpart) + envlist[ipart+1] * fpart);
+        }
+        else {
+            self->data[i] = 0.0;
+        }
     }
 }
 
 static void
-Fm_readframes_aia(Fm *self) {
-    MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_delta, fpart;
+Pulsar_readframes_aai(Pulsar *self) {
+    MYFLT frac, invfrac, pos, scl_pos, t_pos, e_pos, fpart, tmp, oneOnSr;
+    double inc;
     int i, ipart;
-    
-    MYFLT *car = Stream_getData((Stream *)self->car_stream);
-    MYFLT rat = PyFloat_AS_DOUBLE(self->ratio);
-    MYFLT *ind = Stream_getData((Stream *)self->index_stream);
-    
+    MYFLT *tablelist = TableStream_getData(self->table);
+    MYFLT *envlist = TableStream_getData(self->env);
+    int size = TableStream_getSize(self->table);
+    int envsize = TableStream_getSize(self->env);
+
+    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
+    MYFLT *ph = Stream_getData((Stream *)self->phase_stream);
+    frac = _clip(PyFloat_AS_DOUBLE(self->frac));
+    invfrac = 1.0 / frac;
+
+    oneOnSr = 1.0 / self->sr;
     for (i=0; i<self->bufsize; i++) {
-        mod_freq = car[i] * rat;
-        mod_amp = mod_freq * ind[i];
-        mod_delta = mod_freq * self->scaleFactor;
-        self->pointerPos_mod = Sine_clip(self->pointerPos_mod);
-        ipart = (int)self->pointerPos_mod;
-        fpart = self->pointerPos_mod - ipart;
-        mod_val = mod_amp * (SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart);
-        self->pointerPos_mod += mod_delta;
-        
-        car_freq = car[i] + mod_val;
-        car_delta = car_freq * self->scaleFactor;
-        self->pointerPos_car = Sine_clip(self->pointerPos_car);
-        ipart = (int)self->pointerPos_car;
-        fpart = self->pointerPos_car - ipart;
-        self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
-        self->pointerPos_car += car_delta;
+        inc = fr[i] * oneOnSr;
+        self->pointerPos += inc;
+        if (self->pointerPos < 0)
+            self->pointerPos = 1.0 + self->pointerPos;
+        else if (self->pointerPos >= 1.0)
+            self->pointerPos -= 1.0;
+        pos = self->pointerPos + ph[i];
+        if (pos >= 1.0)
+            pos -= 1.0;
+        if (pos < frac) {
+            scl_pos = pos * invfrac;
+            t_pos = scl_pos * size;
+            ipart = (int)t_pos;
+            fpart = t_pos - ipart;
+            tmp = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
+
+            e_pos = scl_pos * envsize;
+            ipart = (int)e_pos;
+            fpart = e_pos - ipart;
+            self->data[i] = tmp * (envlist[ipart] * (1.0 - fpart) + envlist[ipart+1] * fpart);
+        }
+        else {
+            self->data[i] = 0.0;
+        }
     }
 }
 
 static void
-Fm_readframes_iaa(Fm *self) {
-    MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_delta, fpart;
+Pulsar_readframes_iia(Pulsar *self) {
+    MYFLT fr, ph, pos, curfrac, scl_pos, t_pos, e_pos, fpart, tmp;
+    double inc;
     int i, ipart;
-    
-    MYFLT car = PyFloat_AS_DOUBLE(self->car);
-    MYFLT *rat = Stream_getData((Stream *)self->ratio_stream);
-    MYFLT *ind = Stream_getData((Stream *)self->index_stream);
-    
-    for (i=0; i<self->bufsize; i++) {
-        mod_freq = car * rat[i];
-        mod_amp = mod_freq * ind[i];
-        mod_delta = mod_freq * self->scaleFactor;
-        self->pointerPos_mod = Sine_clip(self->pointerPos_mod);
-        ipart = (int)self->pointerPos_mod;
-        fpart = self->pointerPos_mod - ipart;
-        mod_val = mod_amp * (SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart);
-        self->pointerPos_mod += mod_delta;
-        
-        car_freq = car + mod_val;
-        car_delta = car_freq * self->scaleFactor;
-        self->pointerPos_car = Sine_clip(self->pointerPos_car);
-        ipart = (int)self->pointerPos_car;
-        fpart = self->pointerPos_car - ipart;
-        self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
-        self->pointerPos_car += car_delta;
+    MYFLT *tablelist = TableStream_getData(self->table);
+    MYFLT *envlist = TableStream_getData(self->env);
+    int size = TableStream_getSize(self->table);
+    int envsize = TableStream_getSize(self->env);
+
+    fr = PyFloat_AS_DOUBLE(self->freq);
+    ph = PyFloat_AS_DOUBLE(self->phase);
+    MYFLT *frac = Stream_getData((Stream *)self->frac_stream);
+    inc = fr / self->sr;
+
+    for (i=0; i<self->bufsize; i++) {
+        curfrac = frac[i];
+        self->pointerPos += inc;
+        if (self->pointerPos < 0)
+            self->pointerPos = 1.0 + self->pointerPos;
+        else if (self->pointerPos >= 1.0)
+            self->pointerPos -= 1.0;
+        pos = self->pointerPos + ph;
+        if (pos >= 1.0)
+            pos -= 1.0;
+        if (pos < curfrac) {
+            scl_pos = pos / curfrac;
+            t_pos = scl_pos * size;
+            ipart = (int)t_pos;
+            fpart = t_pos - ipart;
+            tmp = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
+
+            e_pos = scl_pos * envsize;
+            ipart = (int)e_pos;
+            fpart = e_pos - ipart;
+            self->data[i] = tmp * (envlist[ipart] * (1.0 - fpart) + envlist[ipart+1] * fpart);
+        }
+        else {
+            self->data[i] = 0.0;
+        }
     }
 }
 
 static void
-Fm_readframes_aaa(Fm *self) {
-    MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_delta, fpart;
+Pulsar_readframes_aia(Pulsar *self) {
+    MYFLT ph, pos, curfrac, scl_pos, t_pos, e_pos, fpart, tmp, oneOnSr;
+    double inc;
     int i, ipart;
-    
-    MYFLT *car = Stream_getData((Stream *)self->car_stream);
-    MYFLT *rat = Stream_getData((Stream *)self->ratio_stream);
-    MYFLT *ind = Stream_getData((Stream *)self->index_stream);
-    
+    MYFLT *tablelist = TableStream_getData(self->table);
+    MYFLT *envlist = TableStream_getData(self->env);
+    int size = TableStream_getSize(self->table);
+    int envsize = TableStream_getSize(self->env);
+
+    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
+    ph = PyFloat_AS_DOUBLE(self->phase);
+    MYFLT *frac = Stream_getData((Stream *)self->frac_stream);
+
+    oneOnSr = 1.0 / self->sr;
     for (i=0; i<self->bufsize; i++) {
-        mod_freq = car[i] * rat[i];
-        mod_amp = mod_freq * ind[i];
-        mod_delta = mod_freq * self->scaleFactor;
-        self->pointerPos_mod = Sine_clip(self->pointerPos_mod);
-        ipart = (int)self->pointerPos_mod;
-        fpart = self->pointerPos_mod - ipart;
-        mod_val = mod_amp * (SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart);
-        self->pointerPos_mod += mod_delta;
-        
-        car_freq = car[i] + mod_val;
-        car_delta = car_freq * self->scaleFactor;
-        self->pointerPos_car = Sine_clip(self->pointerPos_car);
-        ipart = (int)self->pointerPos_car;
-        fpart = self->pointerPos_car - ipart;
-        self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
-        self->pointerPos_car += car_delta;
+        curfrac = frac[i];
+        inc = fr[i] * oneOnSr;
+        self->pointerPos += inc;
+        if (self->pointerPos < 0)
+            self->pointerPos = 1.0 + self->pointerPos;
+        else if (self->pointerPos >= 1.0)
+            self->pointerPos -= 1.0;
+        pos = self->pointerPos + ph;
+        if (pos >= 1.0)
+            pos -= 1.0;
+        if (pos < curfrac) {
+            scl_pos = pos / curfrac;
+            t_pos = scl_pos * size;
+            ipart = (int)t_pos;
+            fpart = t_pos - ipart;
+            tmp = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
+
+            e_pos = scl_pos * envsize;
+            ipart = (int)e_pos;
+            fpart = e_pos - ipart;
+            self->data[i] = tmp * (envlist[ipart] * (1.0 - fpart) + envlist[ipart+1] * fpart);
+        }
+        else {
+            self->data[i] = 0.0;
+        }
     }
 }
 
-static void Fm_postprocessing_ii(Fm *self) { POST_PROCESSING_II };
-static void Fm_postprocessing_ai(Fm *self) { POST_PROCESSING_AI };
-static void Fm_postprocessing_ia(Fm *self) { POST_PROCESSING_IA };
-static void Fm_postprocessing_aa(Fm *self) { POST_PROCESSING_AA };
-static void Fm_postprocessing_ireva(Fm *self) { POST_PROCESSING_IREVA };
-static void Fm_postprocessing_areva(Fm *self) { POST_PROCESSING_AREVA };
-static void Fm_postprocessing_revai(Fm *self) { POST_PROCESSING_REVAI };
-static void Fm_postprocessing_revaa(Fm *self) { POST_PROCESSING_REVAA };
-static void Fm_postprocessing_revareva(Fm *self) { POST_PROCESSING_REVAREVA };
+static void
+Pulsar_readframes_iaa(Pulsar *self) {
+    MYFLT fr, pos, curfrac, scl_pos, t_pos, e_pos, fpart, tmp;
+    double inc;
+    int i, ipart;
+    MYFLT *tablelist = TableStream_getData(self->table);
+    MYFLT *envlist = TableStream_getData(self->env);
+    int size = TableStream_getSize(self->table);
+    int envsize = TableStream_getSize(self->env);
+
+    fr = PyFloat_AS_DOUBLE(self->freq);
+    MYFLT *ph = Stream_getData((Stream *)self->phase_stream);
+    MYFLT *frac = Stream_getData((Stream *)self->frac_stream);
+    inc = fr / self->sr;
+
+    for (i=0; i<self->bufsize; i++) {
+        curfrac = frac[i];
+        self->pointerPos += inc;
+        if (self->pointerPos < 0)
+            self->pointerPos = 1.0 + self->pointerPos;
+        else if (self->pointerPos >= 1.0)
+            self->pointerPos -= 1.0;
+        pos = self->pointerPos + ph[i];
+        if (pos >= 1.0)
+            pos -= 1.0;
+        if (pos < curfrac) {
+            scl_pos = pos / curfrac;
+            t_pos = scl_pos * size;
+            ipart = (int)t_pos;
+            fpart = t_pos - ipart;
+            tmp = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
+
+            e_pos = scl_pos * envsize;
+            ipart = (int)e_pos;
+            fpart = e_pos - ipart;
+            self->data[i] = tmp * (envlist[ipart] * (1.0 - fpart) + envlist[ipart+1] * fpart);
+        }
+        else {
+            self->data[i] = 0.0;
+        }
+    }
+}
 
 static void
-Fm_setProcMode(Fm *self)
+Pulsar_readframes_aaa(Pulsar *self) {
+    MYFLT pos, curfrac, scl_pos, t_pos, e_pos, fpart, tmp, oneOnSr;
+    double inc;
+    int i, ipart;
+    MYFLT *tablelist = TableStream_getData(self->table);
+    MYFLT *envlist = TableStream_getData(self->env);
+    int size = TableStream_getSize(self->table);
+    int envsize = TableStream_getSize(self->env);
+
+    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
+    MYFLT *ph = Stream_getData((Stream *)self->phase_stream);
+    MYFLT *frac = Stream_getData((Stream *)self->frac_stream);
+
+    oneOnSr = 1.0 / self->sr;
+    for (i=0; i<self->bufsize; i++) {
+        curfrac = frac[i];
+        inc = fr[i] * oneOnSr;
+        self->pointerPos += inc;
+        if (self->pointerPos < 0)
+            self->pointerPos = 1.0 + self->pointerPos;
+        else if (self->pointerPos >= 1.0)
+            self->pointerPos -= 1.0;
+        pos = self->pointerPos + ph[i];
+        if (pos >= 1.0)
+            pos -= 1.0;
+        if (pos < curfrac) {
+            scl_pos = pos / curfrac;
+            t_pos = scl_pos * size;
+            ipart = (int)t_pos;
+            fpart = t_pos - ipart;
+            tmp = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
+
+            e_pos = scl_pos * envsize;
+            ipart = (int)e_pos;
+            fpart = e_pos - ipart;
+            self->data[i] = tmp * (envlist[ipart] * (1.0 - fpart) + envlist[ipart+1] * fpart);
+        }
+        else {
+            self->data[i] = 0.0;
+        }
+    }
+}
+
+static void Pulsar_postprocessing_ii(Pulsar *self) { POST_PROCESSING_II };
+static void Pulsar_postprocessing_ai(Pulsar *self) { POST_PROCESSING_AI };
+static void Pulsar_postprocessing_ia(Pulsar *self) { POST_PROCESSING_IA };
+static void Pulsar_postprocessing_aa(Pulsar *self) { POST_PROCESSING_AA };
+static void Pulsar_postprocessing_ireva(Pulsar *self) { POST_PROCESSING_IREVA };
+static void Pulsar_postprocessing_areva(Pulsar *self) { POST_PROCESSING_AREVA };
+static void Pulsar_postprocessing_revai(Pulsar *self) { POST_PROCESSING_REVAI };
+static void Pulsar_postprocessing_revaa(Pulsar *self) { POST_PROCESSING_REVAA };
+static void Pulsar_postprocessing_revareva(Pulsar *self) { POST_PROCESSING_REVAREVA };
+
+static void
+Pulsar_setProcMode(Pulsar *self)
 {
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:        
-            self->proc_func_ptr = Fm_readframes_iii;
+        case 0:
+            self->proc_func_ptr = Pulsar_readframes_iii;
             break;
-        case 1:    
-            self->proc_func_ptr = Fm_readframes_aii;
+        case 1:
+            self->proc_func_ptr = Pulsar_readframes_aii;
             break;
-        case 10:    
-            self->proc_func_ptr = Fm_readframes_iai;
+        case 10:
+            self->proc_func_ptr = Pulsar_readframes_iai;
             break;
-        case 11:    
-            self->proc_func_ptr = Fm_readframes_aai;
+        case 11:
+            self->proc_func_ptr = Pulsar_readframes_aai;
             break;
-        case 100:        
-            self->proc_func_ptr = Fm_readframes_iia;
+        case 100:
+            self->proc_func_ptr = Pulsar_readframes_iia;
             break;
-        case 101:    
-            self->proc_func_ptr = Fm_readframes_aia;
+        case 101:
+            self->proc_func_ptr = Pulsar_readframes_aia;
             break;
-        case 110:    
-            self->proc_func_ptr = Fm_readframes_iaa;
+        case 110:
+            self->proc_func_ptr = Pulsar_readframes_iaa;
             break;
-        case 111:    
-            self->proc_func_ptr = Fm_readframes_aaa;
+        case 111:
+            self->proc_func_ptr = Pulsar_readframes_aaa;
             break;
-    } 
-    
+    }
 	switch (muladdmode) {
-        case 0:        
-            self->muladd_func_ptr = Fm_postprocessing_ii;
+        case 0:
+            self->muladd_func_ptr = Pulsar_postprocessing_ii;
             break;
-        case 1:    
-            self->muladd_func_ptr = Fm_postprocessing_ai;
+        case 1:
+            self->muladd_func_ptr = Pulsar_postprocessing_ai;
             break;
-        case 2:    
-            self->muladd_func_ptr = Fm_postprocessing_revai;
+        case 2:
+            self->muladd_func_ptr = Pulsar_postprocessing_revai;
             break;
-        case 10:        
-            self->muladd_func_ptr = Fm_postprocessing_ia;
+        case 10:
+            self->muladd_func_ptr = Pulsar_postprocessing_ia;
             break;
-        case 11:    
-            self->muladd_func_ptr = Fm_postprocessing_aa;
+        case 11:
+            self->muladd_func_ptr = Pulsar_postprocessing_aa;
             break;
-        case 12:    
-            self->muladd_func_ptr = Fm_postprocessing_revaa;
+        case 12:
+            self->muladd_func_ptr = Pulsar_postprocessing_revaa;
             break;
-        case 20:        
-            self->muladd_func_ptr = Fm_postprocessing_ireva;
+        case 20:
+            self->muladd_func_ptr = Pulsar_postprocessing_ireva;
             break;
-        case 21:    
-            self->muladd_func_ptr = Fm_postprocessing_areva;
+        case 21:
+            self->muladd_func_ptr = Pulsar_postprocessing_areva;
             break;
-        case 22:    
-            self->muladd_func_ptr = Fm_postprocessing_revareva;
+        case 22:
+            self->muladd_func_ptr = Pulsar_postprocessing_revareva;
             break;
     }
 }
 
 static void
-Fm_compute_next_data_frame(Fm *self)
+Pulsar_compute_next_data_frame(Pulsar *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
 static int
-Fm_traverse(Fm *self, visitproc visit, void *arg)
+Pulsar_traverse(Pulsar *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->car);    
-    Py_VISIT(self->car_stream);    
-    Py_VISIT(self->ratio);    
-    Py_VISIT(self->ratio_stream);    
-    Py_VISIT(self->index);    
-    Py_VISIT(self->index_stream);    
+    Py_VISIT(self->table);
+    Py_VISIT(self->env);
+    Py_VISIT(self->phase);
+    Py_VISIT(self->phase_stream);
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->frac);
+    Py_VISIT(self->frac_stream);
     return 0;
 }
 
-static int 
-Fm_clear(Fm *self)
+static int
+Pulsar_clear(Pulsar *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->car);    
-    Py_CLEAR(self->car_stream);    
-    Py_CLEAR(self->ratio);    
-    Py_CLEAR(self->ratio_stream);    
-    Py_CLEAR(self->index);    
-    Py_CLEAR(self->index_stream);    
+    Py_CLEAR(self->table);
+    Py_CLEAR(self->env);
+    Py_CLEAR(self->phase);
+    Py_CLEAR(self->phase_stream);
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->frac);
+    Py_CLEAR(self->frac_stream);
     return 0;
 }
 
 static void
-Fm_dealloc(Fm* self)
+Pulsar_dealloc(Pulsar* self)
 {
     pyo_DEALLOC
-    Fm_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Pulsar_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
-Fm_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+Pulsar_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
-    PyObject *cartmp=NULL, *ratiotmp=NULL, *indextmp=NULL, *multmp=NULL, *addtmp=NULL;
-    Fm *self;
-    self = (Fm *)type->tp_alloc(type, 0);
-    
-    self->car = PyFloat_FromDouble(100);
-    self->ratio = PyFloat_FromDouble(0.5);
-    self->index = PyFloat_FromDouble(5);
+    PyObject *tabletmp, *envtmp, *freqtmp=NULL, *phasetmp=NULL, *fractmp=NULL, *multmp=NULL, *addtmp=NULL;
+    Pulsar *self;
+    self = (Pulsar *)type->tp_alloc(type, 0);
+
+    self->freq = PyFloat_FromDouble(100);
+    self->phase = PyFloat_FromDouble(0);
+    self->frac = PyFloat_FromDouble(0.5);
+    self->interp = 2;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
 	self->modebuffer[4] = 0;
-    self->pointerPos_car = self->pointerPos_mod = 0.;
-    
+    self->pointerPos = 0.;
+
     INIT_OBJECT_COMMON
-    Stream_setFunctionPtr(self->stream, Fm_compute_next_data_frame);
-    self->mode_func_ptr = Fm_setProcMode;
+    Stream_setFunctionPtr(self->stream, Pulsar_compute_next_data_frame);
+    self->mode_func_ptr = Pulsar_setProcMode;
 
-    self->scaleFactor = 512.0 / self->sr;
+    static char *kwlist[] = {"table", "env", "freq", "frac", "phase", "interp", "mul", "add", NULL};
 
-    static char *kwlist[] = {"carrier", "ratio", "index", "mul", "add", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOO", kwlist, &cartmp, &ratiotmp, &indextmp, &multmp, &addtmp))
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOOiOO", kwlist, &tabletmp, &envtmp, &freqtmp, &fractmp, &phasetmp, &self->interp, &multmp, &addtmp))
+        Py_RETURN_NONE;
+
+    if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
+        PyErr_SetString(PyExc_TypeError, "\"table\" argument of Pulsar must be a PyoTableObject.\n");
         Py_RETURN_NONE;
-    
-    if (cartmp) {
-        PyObject_CallMethod((PyObject *)self, "setCarrier", "O", cartmp);
     }
-    
-    if (ratiotmp) {
-        PyObject_CallMethod((PyObject *)self, "setRatio", "O", ratiotmp);
+    Py_XDECREF(self->table);
+    self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", "");
+
+    if ( PyObject_HasAttrString((PyObject *)envtmp, "getTableStream") == 0 ) {
+        PyErr_SetString(PyExc_TypeError, "\"env\" argument of Pulsar must be a PyoTableObject.\n");
+        Py_RETURN_NONE;
     }
+    Py_XDECREF(self->env);
+    self->env = PyObject_CallMethod((PyObject *)envtmp, "getTableStream", "");
 
-    if (indextmp) {
-        PyObject_CallMethod((PyObject *)self, "setIndex", "O", indextmp);
+    if (phasetmp) {
+        PyObject_CallMethod((PyObject *)self, "setPhase", "O", phasetmp);
     }
-    
+
+    if (freqtmp) {
+        PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
+    }
+
+    if (fractmp) {
+        PyObject_CallMethod((PyObject *)self, "setFrac", "O", fractmp);
+    }
+
     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);
 
+    SET_INTERP_POINTER
+
     return (PyObject *)self;
 }
 
-static PyObject * Fm_getServer(Fm* self) { GET_SERVER };
-static PyObject * Fm_getStream(Fm* self) { GET_STREAM };
-static PyObject * Fm_setMul(Fm *self, PyObject *arg) { SET_MUL };	
-static PyObject * Fm_setAdd(Fm *self, PyObject *arg) { SET_ADD };	
-static PyObject * Fm_setSub(Fm *self, PyObject *arg) { SET_SUB };	
-static PyObject * Fm_setDiv(Fm *self, PyObject *arg) { SET_DIV };	
+static PyObject * Pulsar_getServer(Pulsar* self) { GET_SERVER };
+static PyObject * Pulsar_getStream(Pulsar* self) { GET_STREAM };
+static PyObject * Pulsar_setMul(Pulsar *self, PyObject *arg) { SET_MUL };
+static PyObject * Pulsar_setAdd(Pulsar *self, PyObject *arg) { SET_ADD };
+static PyObject * Pulsar_setSub(Pulsar *self, PyObject *arg) { SET_SUB };
+static PyObject * Pulsar_setDiv(Pulsar *self, PyObject *arg) { SET_DIV };
 
-static PyObject * Fm_play(Fm *self, PyObject *args, PyObject *kwds) { PLAY };
-static PyObject * Fm_out(Fm *self, PyObject *args, PyObject *kwds) { OUT };
-static PyObject * Fm_stop(Fm *self) { STOP };
+static PyObject * Pulsar_play(Pulsar *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * Pulsar_out(Pulsar *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * Pulsar_stop(Pulsar *self) { STOP };
 
-static PyObject * Fm_multiply(Fm *self, PyObject *arg) { MULTIPLY };
-static PyObject * Fm_inplace_multiply(Fm *self, PyObject *arg) { INPLACE_MULTIPLY };
-static PyObject * Fm_add(Fm *self, PyObject *arg) { ADD };
-static PyObject * Fm_inplace_add(Fm *self, PyObject *arg) { INPLACE_ADD };
-static PyObject * Fm_sub(Fm *self, PyObject *arg) { SUB };
-static PyObject * Fm_inplace_sub(Fm *self, PyObject *arg) { INPLACE_SUB };
-static PyObject * Fm_div(Fm *self, PyObject *arg) { DIV };
-static PyObject * Fm_inplace_div(Fm *self, PyObject *arg) { INPLACE_DIV };
+static PyObject * Pulsar_multiply(Pulsar *self, PyObject *arg) { MULTIPLY };
+static PyObject * Pulsar_inplace_multiply(Pulsar *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * Pulsar_add(Pulsar *self, PyObject *arg) { ADD };
+static PyObject * Pulsar_inplace_add(Pulsar *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * Pulsar_sub(Pulsar *self, PyObject *arg) { SUB };
+static PyObject * Pulsar_inplace_sub(Pulsar *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * Pulsar_div(Pulsar *self, PyObject *arg) { DIV };
+static PyObject * Pulsar_inplace_div(Pulsar *self, PyObject *arg) { INPLACE_DIV };
 
 static PyObject *
-Fm_setCarrier(Fm *self, PyObject *arg)
+Pulsar_getTable(Pulsar* self)
+{
+    Py_INCREF(self->table);
+    return self->table;
+};
+
+static PyObject *
+Pulsar_getEnv(Pulsar* self)
+{
+    Py_INCREF(self->env);
+    return self->env;
+};
+
+static PyObject *
+Pulsar_setTable(Pulsar *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 *
+Pulsar_setEnv(Pulsar *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 PyObject *
+Pulsar_setFreq(Pulsar *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
-	Py_DECREF(self->car);
+	Py_DECREF(self->freq);
 	if (isNumber == 1) {
-		self->car = PyNumber_Float(tmp);
+		self->freq = PyNumber_Float(tmp);
         self->modebuffer[2] = 0;
 	}
 	else {
-		self->car = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->car, "_getStream", NULL);
+		self->freq = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL);
         Py_INCREF(streamtmp);
-        Py_XDECREF(self->car_stream);
-        self->car_stream = (Stream *)streamtmp;
+        Py_XDECREF(self->freq_stream);
+        self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
-Fm_setRatio(Fm *self, PyObject *arg)
+Pulsar_setPhase(Pulsar *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
-	Py_DECREF(self->ratio);
+	Py_DECREF(self->phase);
 	if (isNumber == 1) {
-		self->ratio = PyNumber_Float(tmp);
+		self->phase = PyNumber_Float(tmp);
         self->modebuffer[3] = 0;
 	}
 	else {
-		self->ratio = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->ratio, "_getStream", NULL);
+		self->phase = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->phase, "_getStream", NULL);
         Py_INCREF(streamtmp);
-        Py_XDECREF(self->ratio_stream);
-        self->ratio_stream = (Stream *)streamtmp;
+        Py_XDECREF(self->phase_stream);
+        self->phase_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
-Fm_setIndex(Fm *self, PyObject *arg)
+Pulsar_setFrac(Pulsar *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
-	Py_DECREF(self->index);
+	Py_DECREF(self->frac);
 	if (isNumber == 1) {
-		self->index = PyNumber_Float(tmp);
+		self->frac = PyNumber_Float(tmp);
         self->modebuffer[4] = 0;
 	}
 	else {
-		self->index = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->index, "_getStream", NULL);
+		self->frac = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->frac, "_getStream", NULL);
         Py_INCREF(streamtmp);
-        Py_XDECREF(self->index_stream);
-        self->index_stream = (Stream *)streamtmp;
+        Py_XDECREF(self->frac_stream);
+        self->frac_stream = (Stream *)streamtmp;
 		self->modebuffer[4] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
-static PyMemberDef Fm_members[] = {
-{"server", T_OBJECT_EX, offsetof(Fm, server), 0, "Pyo server."},
-{"stream", T_OBJECT_EX, offsetof(Fm, stream), 0, "Stream object."},
-{"carrier", T_OBJECT_EX, offsetof(Fm, car), 0, "Frequency in cycle per second."},
-{"ratio", T_OBJECT_EX, offsetof(Fm, ratio), 0, "Ratio carrier:modulator (mod freq = car*mod)."},
-{"index", T_OBJECT_EX, offsetof(Fm, index), 0, "Modulation index (mod amp = mod freq*index)."},
-{"mul", T_OBJECT_EX, offsetof(Fm, mul), 0, "Mul factor."},
-{"add", T_OBJECT_EX, offsetof(Fm, add), 0, "Add factor."},
-{NULL}  /* Sentinel */
-};
+static PyObject *
+Pulsar_setInterp(Pulsar *self, PyObject *arg)
+{
+    ASSERT_ARG_NOT_NULL
 
-static PyMethodDef Fm_methods[] = {
-{"getServer", (PyCFunction)Fm_getServer, METH_NOARGS, "Returns server object."},
-{"_getStream", (PyCFunction)Fm_getStream, METH_NOARGS, "Returns stream object."},
-{"play", (PyCFunction)Fm_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
-{"out", (PyCFunction)Fm_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
-{"stop", (PyCFunction)Fm_stop, METH_NOARGS, "Stops computing."},
-{"setCarrier", (PyCFunction)Fm_setCarrier, METH_O, "Sets carrier frequency in cycle per second."},
-{"setRatio", (PyCFunction)Fm_setRatio, METH_O, "Sets car:mod ratio."},
-{"setIndex", (PyCFunction)Fm_setIndex, METH_O, "Sets modulation index."},
-{"setMul", (PyCFunction)Fm_setMul, METH_O, "Sets Fm mul factor."},
-{"setAdd", (PyCFunction)Fm_setAdd, METH_O, "Sets Fm add factor."},
-{"setSub", (PyCFunction)Fm_setSub, METH_O, "Sets inverse add factor."},
-{"setDiv", (PyCFunction)Fm_setDiv, METH_O, "Sets inverse mul factor."},
-{NULL}  /* Sentinel */
-};
+    int isNumber = PyNumber_Check(arg);
 
-static PyNumberMethods Fm_as_number = {
-(binaryfunc)Fm_add,                      /*nb_add*/
-(binaryfunc)Fm_sub,                 /*nb_subtract*/
-(binaryfunc)Fm_multiply,                 /*nb_multiply*/
-(binaryfunc)Fm_div,                   /*nb_divide*/
+	if (isNumber == 1) {
+		self->interp = PyInt_AsLong(PyNumber_Int(arg));
+    }
+
+    SET_INTERP_POINTER
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyMemberDef Pulsar_members[] = {
+{"server", T_OBJECT_EX, offsetof(Pulsar, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(Pulsar, stream), 0, "Stream object."},
+{"table", T_OBJECT_EX, offsetof(Pulsar, table), 0, "Waveform table."},
+{"freq", T_OBJECT_EX, offsetof(Pulsar, freq), 0, "Frequency in cycle per second."},
+{"phase", T_OBJECT_EX, offsetof(Pulsar, phase), 0, "Oscillator phase."},
+{"frac", T_OBJECT_EX, offsetof(Pulsar, frac), 0, "Table width inside whole length."},
+{"mul", T_OBJECT_EX, offsetof(Pulsar, mul), 0, "Mul factor."},
+{"add", T_OBJECT_EX, offsetof(Pulsar, add), 0, "Add factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyMethodDef Pulsar_methods[] = {
+{"getTable", (PyCFunction)Pulsar_getTable, METH_NOARGS, "Returns waveform table object."},
+{"getEnv", (PyCFunction)Pulsar_getEnv, METH_NOARGS, "Returns object envelope."},
+{"getServer", (PyCFunction)Pulsar_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)Pulsar_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)Pulsar_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"out", (PyCFunction)Pulsar_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+{"stop", (PyCFunction)Pulsar_stop, METH_NOARGS, "Stops computing."},
+{"setTable", (PyCFunction)Pulsar_setTable, METH_O, "Sets oscillator table."},
+{"setEnv", (PyCFunction)Pulsar_setEnv, METH_O, "Sets envelope table."},
+{"setFreq", (PyCFunction)Pulsar_setFreq, METH_O, "Sets oscillator frequency in cycle per second."},
+{"setPhase", (PyCFunction)Pulsar_setPhase, METH_O, "Sets oscillator phase."},
+{"setFrac", (PyCFunction)Pulsar_setFrac, METH_O, "Sets waveform width inside whole period length."},
+{"setInterp", (PyCFunction)Pulsar_setInterp, METH_O, "Sets Pulsar interpolation mode."},
+{"setMul", (PyCFunction)Pulsar_setMul, METH_O, "Sets oscillator mul factor."},
+{"setAdd", (PyCFunction)Pulsar_setAdd, METH_O, "Sets oscillator add factor."},
+{"setSub", (PyCFunction)Pulsar_setSub, METH_O, "Sets oscillator inverse add factor."},
+{"setDiv", (PyCFunction)Pulsar_setDiv, METH_O, "Sets inverse mul factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyNumberMethods Pulsar_as_number = {
+(binaryfunc)Pulsar_add,                      /*nb_add*/
+(binaryfunc)Pulsar_sub,                 /*nb_subtract*/
+(binaryfunc)Pulsar_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,                  /*(unaryfunc)array_abs,*/
 0,                    /*nb_nonzero*/
 0,                    /*nb_invert*/
 0,               /*nb_lshift*/
@@ -6103,16 +5732,16 @@ static PyNumberMethods Fm_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
-(binaryfunc)Fm_inplace_add,              /*inplace_add*/
-(binaryfunc)Fm_inplace_sub,         /*inplace_subtract*/
-(binaryfunc)Fm_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)Fm_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
+(binaryfunc)Pulsar_inplace_add,              /*inplace_add*/
+(binaryfunc)Pulsar_inplace_sub,         /*inplace_subtract*/
+(binaryfunc)Pulsar_inplace_multiply,         /*inplace_multiply*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -6121,25 +5750,24 @@ static PyNumberMethods Fm_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)Pulsar_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)Pulsar_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
-PyTypeObject FmType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
-"_pyo.Fm_base",         /*tp_name*/
-sizeof(Fm),         /*tp_basicsize*/
+PyTypeObject PulsarType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.Pulsar_base",         /*tp_name*/
+sizeof(Pulsar),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
-(destructor)Fm_dealloc, /*tp_dealloc*/
+(destructor)Pulsar_dealloc, /*tp_dealloc*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
-&Fm_as_number,             /*tp_as_number*/
+&Pulsar_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
 0,                         /*tp_as_mapping*/
 0,                         /*tp_hash */
@@ -6148,16 +5776,16 @@ sizeof(Fm),         /*tp_basicsize*/
 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*/
-"Fm objects. Generates a frequency modulation synthesis.",           /* tp_doc */
-(traverseproc)Fm_traverse,   /* tp_traverse */
-(inquiry)Fm_clear,           /* tp_clear */
+Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
+"Pulsar objects. Generates pulsar synthesis oscillator.",           /* tp_doc */
+(traverseproc)Pulsar_traverse,   /* tp_traverse */
+(inquiry)Pulsar_clear,           /* tp_clear */
 0,		               /* tp_richcompare */
 0,		               /* tp_weaklistoffset */
 0,		               /* tp_iter */
 0,		               /* tp_iternext */
-Fm_methods,             /* tp_methods */
-Fm_members,             /* tp_members */
+Pulsar_methods,             /* tp_methods */
+Pulsar_members,             /* tp_members */
 0,                      /* tp_getset */
 0,                         /* tp_base */
 0,                         /* tp_dict */
@@ -6166,459 +5794,3404 @@ Fm_members,             /* tp_members */
 0,                         /* tp_dictoffset */
 0,      /* tp_init */
 0,                         /* tp_alloc */
-Fm_new,                 /* tp_new */
+Pulsar_new,                 /* tp_new */
 };
 
-/*************/
-/* CrossFm object */
-/*************/
+/**************/
+/* TableRead object */
+/**************/
 typedef struct {
     pyo_audio_HEAD
-    PyObject *car;
-    Stream *car_stream;
-    PyObject *ratio;
-    Stream *ratio_stream;
-    PyObject *ind1;
-    Stream *ind1_stream;
-    PyObject *ind2;
-    Stream *ind2_stream;
-    int modebuffer[6];
-    MYFLT pointerPos_car;
-    MYFLT pointerPos_mod;
-    MYFLT scaleFactor;
-    MYFLT car_val;
-} CrossFm;
+    PyObject *table;
+    PyObject *freq;
+    Stream *freq_stream;
+    int loop;
+    int go;
+    int modebuffer[3];
+    double pointerPos;
+    MYFLT lastValue;
+    int keepLast;
+    MYFLT *trigsBuffer;
+    TriggerStream *trig_stream;
+    int init;
+    int interp; /* 0 = default to 2, 1 = nointerp, 2 = linear, 3 = cos, 4 = cubic */
+    MYFLT (*interp_func_ptr)(MYFLT *, int, MYFLT, int);
+} TableRead;
 
 static void
-CrossFm_readframes(CrossFm *self) {
-    MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_amp, car_delta, fpart;
+TableRead_readframes_i(TableRead *self) {
+    MYFLT fr, inc, fpart;
     int i, ipart;
-    MYFLT car[self->bufsize];
-    MYFLT rat[self->bufsize];
-    MYFLT ind1[self->bufsize];
-    MYFLT ind2[self->bufsize];
-    
-    if (self->modebuffer[2] == 0) {
-        MYFLT tmpcar = PyFloat_AS_DOUBLE(self->car);
-        for (i=0; i<self->bufsize; i++) {
-            car[i] = tmpcar;
+    MYFLT *tablelist = TableStream_getData(self->table);
+    int size = TableStream_getSize(self->table);
+
+    fr = PyFloat_AS_DOUBLE(self->freq);
+    inc = fr * size / self->sr;
+
+    if (self->go == 0)
+        PyObject_CallMethod((PyObject *)self, "stop", NULL);
+
+    for (i=0; i<self->bufsize; i++) {
+        self->trigsBuffer[i] = 0.0;
+        if (self->pointerPos < 0) {
+            if (self->init == 0) {
+                self->trigsBuffer[i] = 1.0;
+                if (self->loop == 0)
+                    self->go = 0;
+            }
+            else
+                self->init = 0;
+            self->pointerPos = size + self->pointerPos;
         }
-    }
-    else {
-        MYFLT *tmpcar = Stream_getData((Stream *)self->car_stream);
-        for (i=0; i<self->bufsize; i++) {
-            car[i] = tmpcar[i];
+        else if (self->pointerPos >= size && self->go) {
+            self->trigsBuffer[i] = 1.0;
+            if (self->loop == 1)
+                self->pointerPos -= size;
+            else
+                self->go = 0;
         }
-    }
-    
-    if (self->modebuffer[3] == 0) {
-        MYFLT tmprat = PyFloat_AS_DOUBLE(self->ratio);
-        for (i=0; i<self->bufsize; i++) {
-            rat[i] = tmprat;
+        if (self->go == 1) {
+            ipart = (int)self->pointerPos;
+            fpart = self->pointerPos - ipart;
+            self->lastValue = self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
         }
-    }
-    else {
-        MYFLT *tmprat = Stream_getData((Stream *)self->ratio_stream);
-        for (i=0; i<self->bufsize; i++) {
-            rat[i] = tmprat[i];
+        else {
+            if (self->keepLast == 0)
+                self->data[i] = 0.0;
+            else
+                self->data[i] = self->lastValue;
         }
+
+        self->pointerPos += inc;
     }
-    
-    if (self->modebuffer[4] == 0) {
-        MYFLT tmpind1 = PyFloat_AS_DOUBLE(self->ind1);
-        for (i=0; i<self->bufsize; i++) {
-            ind1[i] = tmpind1;
+}
+
+static void
+TableRead_readframes_a(TableRead *self) {
+    MYFLT inc, fpart, sizeOnSr;
+    int i, ipart;
+    MYFLT *tablelist = TableStream_getData(self->table);
+    int size = TableStream_getSize(self->table);
+
+    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
+
+    sizeOnSr = size / self->sr;
+
+    if (self->go == 0)
+        PyObject_CallMethod((PyObject *)self, "stop", NULL);
+
+    for (i=0; i<self->bufsize; i++) {
+        self->trigsBuffer[i] = 0.0;
+        if (self->pointerPos < 0) {
+            if (self->init == 0) {
+                self->trigsBuffer[i] = 1.0;
+                if (self->loop == 0)
+                    self->go = 0;
+            }
+            else
+                self->init = 0;
+            self->pointerPos = size + self->pointerPos;
         }
-    }   
-    else {
-        MYFLT *tmpind1 = Stream_getData((Stream *)self->ind1_stream);
-        for (i=0; i<self->bufsize; i++) {
-            ind1[i] = tmpind1[i];
+        else if (self->pointerPos >= size && self->go) {
+            self->trigsBuffer[i] = 1.0;
+            if (self->loop == 1)
+                self->pointerPos -= size;
+            else
+                self->go = 0;
         }
-    }
-    
-    if (self->modebuffer[5] == 0) {
-        MYFLT tmpind2 = PyFloat_AS_DOUBLE(self->ind2);
-        for (i=0; i<self->bufsize; i++) {
-            ind2[i] = tmpind2;
+        if (self->go == 1) {
+            ipart = (int)self->pointerPos;
+            fpart = self->pointerPos - ipart;
+            self->lastValue = self->data[i] = (*self->interp_func_ptr)(tablelist, ipart, fpart, size);
         }
-    }   
-    else {
-        MYFLT *tmpind2 = Stream_getData((Stream *)self->ind2_stream);
-        for (i=0; i<self->bufsize; i++) {
-            ind2[i] = tmpind2[i];
+        else {
+            if (self->keepLast == 0)
+                self->data[i] = 0.0;
+            else
+                self->data[i] = self->lastValue;
         }
+
+        inc = fr[i] * sizeOnSr;
+        self->pointerPos += inc;
+    }
+}
+
+static void TableRead_postprocessing_ii(TableRead *self) { POST_PROCESSING_II };
+static void TableRead_postprocessing_ai(TableRead *self) { POST_PROCESSING_AI };
+static void TableRead_postprocessing_ia(TableRead *self) { POST_PROCESSING_IA };
+static void TableRead_postprocessing_aa(TableRead *self) { POST_PROCESSING_AA };
+static void TableRead_postprocessing_ireva(TableRead *self) { POST_PROCESSING_IREVA };
+static void TableRead_postprocessing_areva(TableRead *self) { POST_PROCESSING_AREVA };
+static void TableRead_postprocessing_revai(TableRead *self) { POST_PROCESSING_REVAI };
+static void TableRead_postprocessing_revaa(TableRead *self) { POST_PROCESSING_REVAA };
+static void TableRead_postprocessing_revareva(TableRead *self) { POST_PROCESSING_REVAREVA };
+
+static void
+TableRead_setProcMode(TableRead *self)
+{
+    int procmode, muladdmode;
+    procmode = self->modebuffer[2];
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+	switch (procmode) {
+        case 0:
+            self->proc_func_ptr = TableRead_readframes_i;
+            break;
+        case 1:
+            self->proc_func_ptr = TableRead_readframes_a;
+            break;
     }
+	switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = TableRead_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = TableRead_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = TableRead_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = TableRead_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = TableRead_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = TableRead_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = TableRead_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = TableRead_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = TableRead_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+TableRead_compute_next_data_frame(TableRead *self)
+{
+    (*self->proc_func_ptr)(self);
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+TableRead_traverse(TableRead *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->table);
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->trig_stream);
+    return 0;
+}
+
+static int
+TableRead_clear(TableRead *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->table);
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->trig_stream);
+    return 0;
+}
+
+static void
+TableRead_dealloc(TableRead* self)
+{
+    pyo_DEALLOC
+    free(self->trigsBuffer);
+    TableRead_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+TableRead_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    MYFLT *tablelist;
+    PyObject *tabletmp, *freqtmp=NULL, *multmp=NULL, *addtmp=NULL;
+    TableRead *self;
+    self = (TableRead *)type->tp_alloc(type, 0);
+
+    self->freq = PyFloat_FromDouble(1);
+    self->loop = 0;
+    self->init = 1;
+    self->keepLast = 0;
+    self->lastValue = 0.0;
+	self->modebuffer[0] = 0;
+	self->modebuffer[1] = 0;
+	self->modebuffer[2] = 0;
+    self->pointerPos = 0.;
+    self->interp = 2;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, TableRead_compute_next_data_frame);
+    self->mode_func_ptr = TableRead_setProcMode;
+
+    static char *kwlist[] = {"table", "freq", "loop", "interp", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OiiOO", kwlist, &tabletmp, &freqtmp, &self->loop, &self->interp, &multmp, &addtmp))
+        Py_RETURN_NONE;
+
+    if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
+        PyErr_SetString(PyExc_TypeError, "\"table\" argument of TableRead must be a PyoTableObject.\n");
+        Py_RETURN_NONE;
+    }
+    Py_XDECREF(self->table);
+    self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", "");
+
+    if (freqtmp) {
+        PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
+    }
+
+    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->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT));
+
+    tablelist = TableStream_getData(self->table);
+
+    for (i=0; i<self->bufsize; i++) {
+        self->trigsBuffer[i] = 0.0;
+        self->data[i] = tablelist[0];
+    }
+
+    MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL);
+    TriggerStream_setData(self->trig_stream, self->trigsBuffer);
+
+    (*self->mode_func_ptr)(self);
+
+    SET_INTERP_POINTER
+
+    self->init = 1;
+
+    return (PyObject *)self;
+}
+
+static PyObject * TableRead_getServer(TableRead* self) { GET_SERVER };
+static PyObject * TableRead_getStream(TableRead* self) { GET_STREAM };
+static PyObject * TableRead_getTriggerStream(TableRead* self) { GET_TRIGGER_STREAM };
+static PyObject * TableRead_setMul(TableRead *self, PyObject *arg) { SET_MUL };
+static PyObject * TableRead_setAdd(TableRead *self, PyObject *arg) { SET_ADD };
+static PyObject * TableRead_setSub(TableRead *self, PyObject *arg) { SET_SUB };
+static PyObject * TableRead_setDiv(TableRead *self, PyObject *arg) { SET_DIV };
+
+static PyObject * TableRead_play(TableRead *self, PyObject *args, PyObject *kwds)
+{
+    self->pointerPos = 0.0;
+    self->init = 1;
+    self->go = 1;
+    PLAY
+};
+
+static PyObject * TableRead_out(TableRead *self, PyObject *args, PyObject *kwds)
+{
+    self->pointerPos = 0.0;
+    self->init = 1;
+    self->go = 1;
+    OUT
+};
+static PyObject * TableRead_stop(TableRead *self)
+{
+    int i;
+    self->go = 0;
+    Stream_setStreamActive(self->stream, 0);
+    Stream_setStreamChnl(self->stream, 0);
+    Stream_setStreamToDac(self->stream, 0);
+    if (self->keepLast == 0) {
+        for (i=0; i<self->bufsize; i++) {
+            self->data[i] = 0;
+        }
+    }
+    else {
+        for (i=0; i<self->bufsize; i++) {
+            self->data[i] = self->lastValue;
+        }
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
+};
+
+static PyObject * TableRead_multiply(TableRead *self, PyObject *arg) { MULTIPLY };
+static PyObject * TableRead_inplace_multiply(TableRead *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * TableRead_add(TableRead *self, PyObject *arg) { ADD };
+static PyObject * TableRead_inplace_add(TableRead *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * TableRead_sub(TableRead *self, PyObject *arg) { SUB };
+static PyObject * TableRead_inplace_sub(TableRead *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * TableRead_div(TableRead *self, PyObject *arg) { DIV };
+static PyObject * TableRead_inplace_div(TableRead *self, PyObject *arg) { INPLACE_DIV };
+
+static PyObject *
+TableRead_getTable(TableRead* self)
+{
+    Py_INCREF(self->table);
+    return self->table;
+};
+
+static PyObject *
+TableRead_setTable(TableRead *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 *
+TableRead_setFreq(TableRead *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->freq);
+	if (isNumber == 1) {
+		self->freq = PyNumber_Float(tmp);
+        self->modebuffer[2] = 0;
+	}
+	else {
+		self->freq = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->freq_stream);
+        self->freq_stream = (Stream *)streamtmp;
+		self->modebuffer[2] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+TableRead_setLoop(TableRead *self, PyObject *arg)
+{
+    ASSERT_ARG_NOT_NULL
+
+    self->loop = PyInt_AsLong(arg);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *
+TableRead_setInterp(TableRead *self, PyObject *arg)
+{
+    ASSERT_ARG_NOT_NULL
+
+    int isNumber = PyNumber_Check(arg);
+
+	if (isNumber == 1) {
+		self->interp = PyInt_AsLong(PyNumber_Int(arg));
+    }
+
+    SET_INTERP_POINTER
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *
+TableRead_setKeepLast(TableRead *self, PyObject *arg)
+{
+    ASSERT_ARG_NOT_NULL
+
+    self->keepLast = PyInt_AsLong(arg);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *
+TableRead_reset(TableRead *self)
+{
+    self->pointerPos = 0.0;
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyMemberDef TableRead_members[] = {
+{"server", T_OBJECT_EX, offsetof(TableRead, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(TableRead, stream), 0, "Stream object."},
+{"trig_stream", T_OBJECT_EX, offsetof(TableRead, trig_stream), 0, "Trigger Stream object."},
+{"table", T_OBJECT_EX, offsetof(TableRead, table), 0, "Waveform table."},
+{"freq", T_OBJECT_EX, offsetof(TableRead, freq), 0, "Frequency in cycle per second."},
+{"mul", T_OBJECT_EX, offsetof(TableRead, mul), 0, "Mul factor."},
+{"add", T_OBJECT_EX, offsetof(TableRead, add), 0, "Add factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyMethodDef TableRead_methods[] = {
+{"getTable", (PyCFunction)TableRead_getTable, METH_NOARGS, "Returns waveform table object."},
+{"getServer", (PyCFunction)TableRead_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)TableRead_getStream, METH_NOARGS, "Returns stream object."},
+{"_getTriggerStream", (PyCFunction)TableRead_getTriggerStream, METH_NOARGS, "Returns trigger stream object."},
+{"play", (PyCFunction)TableRead_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"out", (PyCFunction)TableRead_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+{"stop", (PyCFunction)TableRead_stop, METH_NOARGS, "Stops computing."},
+{"setTable", (PyCFunction)TableRead_setTable, METH_O, "Sets oscillator table."},
+{"setFreq", (PyCFunction)TableRead_setFreq, METH_O, "Sets oscillator frequency in cycle per second."},
+{"setLoop", (PyCFunction)TableRead_setLoop, METH_O, "Sets the looping mode."},
+{"setInterp", (PyCFunction)TableRead_setInterp, METH_O, "Sets reader interpolation mode."},
+{"setKeepLast", (PyCFunction)TableRead_setKeepLast, METH_O, "Sets keepLast mode."},
+{"reset", (PyCFunction)TableRead_reset, METH_NOARGS, "Resets pointer position to 0."},
+{"setMul", (PyCFunction)TableRead_setMul, METH_O, "Sets oscillator mul factor."},
+{"setAdd", (PyCFunction)TableRead_setAdd, METH_O, "Sets oscillator add factor."},
+{"setSub", (PyCFunction)TableRead_setSub, METH_O, "Sets oscillator inverse add factor."},
+{"setDiv", (PyCFunction)TableRead_setDiv, METH_O, "Sets inverse mul factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyNumberMethods TableRead_as_number = {
+(binaryfunc)TableRead_add,                      /*nb_add*/
+(binaryfunc)TableRead_sub,                 /*nb_subtract*/
+(binaryfunc)TableRead_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)TableRead_inplace_add,              /*inplace_add*/
+(binaryfunc)TableRead_inplace_sub,         /*inplace_subtract*/
+(binaryfunc)TableRead_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)TableRead_div,                       /*nb_true_divide*/
+0,     /*nb_inplace_floor_divide*/
+(binaryfunc)TableRead_inplace_div,                       /*nb_inplace_true_divide*/
+0,                     /* nb_index */
+};
+
+PyTypeObject TableReadType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.TableRead_base",         /*tp_name*/
+sizeof(TableRead),         /*tp_basicsize*/
+0,                         /*tp_itemsize*/
+(destructor)TableRead_dealloc, /*tp_dealloc*/
+0,                         /*tp_print*/
+0,                         /*tp_getattr*/
+0,                         /*tp_setattr*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
+0,                         /*tp_repr*/
+&TableRead_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*/
+"TableRead objects. Generates an oscillatory waveform.",           /* tp_doc */
+(traverseproc)TableRead_traverse,   /* tp_traverse */
+(inquiry)TableRead_clear,           /* tp_clear */
+0,		               /* tp_richcompare */
+0,		               /* tp_weaklistoffset */
+0,		               /* tp_iter */
+0,		               /* tp_iternext */
+TableRead_methods,             /* tp_methods */
+TableRead_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 */
+TableRead_new,                 /* tp_new */
+};
+
+/*************/
+/* Fm object */
+/*************/
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *car;
+    Stream *car_stream;
+    PyObject *ratio;
+    Stream *ratio_stream;
+    PyObject *index;
+    Stream *index_stream;
+    int modebuffer[5];
+    MYFLT pointerPos_car;
+    MYFLT pointerPos_mod;
+    MYFLT scaleFactor;
+} Fm;
+
+static void
+Fm_readframes_iii(Fm *self) {
+    MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_delta, fpart;
+    int i, ipart;
+
+    MYFLT car = PyFloat_AS_DOUBLE(self->car);
+    MYFLT rat = PyFloat_AS_DOUBLE(self->ratio);
+    MYFLT ind = PyFloat_AS_DOUBLE(self->index);
+
+    mod_freq = car * rat;
+    mod_amp = mod_freq * ind;
+    mod_delta = mod_freq * self->scaleFactor;
+
+    for (i=0; i<self->bufsize; i++) {
+        self->pointerPos_mod = Sine_clip(self->pointerPos_mod);
+        ipart = (int)self->pointerPos_mod;
+        fpart = self->pointerPos_mod - ipart;
+        mod_val = mod_amp * (SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart);
+        self->pointerPos_mod += mod_delta;
+
+        car_freq = car + mod_val;
+        car_delta = car_freq * self->scaleFactor;
+        self->pointerPos_car = Sine_clip(self->pointerPos_car);
+        ipart = (int)self->pointerPos_car;
+        fpart = self->pointerPos_car - ipart;
+        self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
+        self->pointerPos_car += car_delta;
+    }
+}
+
+static void
+Fm_readframes_aii(Fm *self) {
+    MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_delta, fpart;
+    int i, ipart;
+
+    MYFLT *car = Stream_getData((Stream *)self->car_stream);
+    MYFLT rat = PyFloat_AS_DOUBLE(self->ratio);
+    MYFLT ind = PyFloat_AS_DOUBLE(self->index);
+
+    for (i=0; i<self->bufsize; i++) {
+        mod_freq = car[i] * rat;
+        mod_amp = mod_freq * ind;
+        mod_delta = mod_freq * self->scaleFactor;
+        self->pointerPos_mod = Sine_clip(self->pointerPos_mod);
+        ipart = (int)self->pointerPos_mod;
+        fpart = self->pointerPos_mod - ipart;
+        mod_val = mod_amp * (SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart);
+        self->pointerPos_mod += mod_delta;
+
+        car_freq = car[i] + mod_val;
+        car_delta = car_freq * self->scaleFactor;
+        self->pointerPos_car = Sine_clip(self->pointerPos_car);
+        ipart = (int)self->pointerPos_car;
+        fpart = self->pointerPos_car - ipart;
+        self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
+        self->pointerPos_car += car_delta;
+    }
+}
+
+static void
+Fm_readframes_iai(Fm *self) {
+    MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_delta, fpart;
+    int i, ipart;
+
+    MYFLT car = PyFloat_AS_DOUBLE(self->car);
+    MYFLT *rat = Stream_getData((Stream *)self->ratio_stream);
+    MYFLT ind = PyFloat_AS_DOUBLE(self->index);
+
+    for (i=0; i<self->bufsize; i++) {
+        mod_freq = car * rat[i];
+        mod_amp = mod_freq * ind;
+        mod_delta = mod_freq * self->scaleFactor;
+        self->pointerPos_mod = Sine_clip(self->pointerPos_mod);
+        ipart = (int)self->pointerPos_mod;
+        fpart = self->pointerPos_mod - ipart;
+        mod_val = mod_amp * (SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart);
+        self->pointerPos_mod += mod_delta;
+
+        car_freq = car + mod_val;
+        car_delta = car_freq * self->scaleFactor;
+        self->pointerPos_car = Sine_clip(self->pointerPos_car);
+        ipart = (int)self->pointerPos_car;
+        fpart = self->pointerPos_car - ipart;
+        self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
+        self->pointerPos_car += car_delta;
+    }
+}
+
+static void
+Fm_readframes_aai(Fm *self) {
+    MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_delta, fpart;
+    int i, ipart;
+
+    MYFLT *car = Stream_getData((Stream *)self->car_stream);
+    MYFLT *rat = Stream_getData((Stream *)self->ratio_stream);
+    MYFLT ind = PyFloat_AS_DOUBLE(self->index);
+
+    for (i=0; i<self->bufsize; i++) {
+        mod_freq = car[i] * rat[i];
+        mod_amp = mod_freq * ind;
+        mod_delta = mod_freq * self->scaleFactor;
+        self->pointerPos_mod = Sine_clip(self->pointerPos_mod);
+        ipart = (int)self->pointerPos_mod;
+        fpart = self->pointerPos_mod - ipart;
+        mod_val = mod_amp * (SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart);
+        self->pointerPos_mod += mod_delta;
+
+        car_freq = car[i] + mod_val;
+        car_delta = car_freq * self->scaleFactor;
+        self->pointerPos_car = Sine_clip(self->pointerPos_car);
+        ipart = (int)self->pointerPos_car;
+        fpart = self->pointerPos_car - ipart;
+        self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
+        self->pointerPos_car += car_delta;
+    }}
+
+static void
+Fm_readframes_iia(Fm *self) {
+    MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_delta, fpart;
+    int i, ipart;
+
+    MYFLT car = PyFloat_AS_DOUBLE(self->car);
+    MYFLT rat = PyFloat_AS_DOUBLE(self->ratio);
+    MYFLT *ind = Stream_getData((Stream *)self->index_stream);
+
+    mod_freq = car * rat;
+    mod_delta = mod_freq * self->scaleFactor;
+
+    for (i=0; i<self->bufsize; i++) {
+        mod_amp = mod_freq * ind[i];
+        self->pointerPos_mod = Sine_clip(self->pointerPos_mod);
+        ipart = (int)self->pointerPos_mod;
+        fpart = self->pointerPos_mod - ipart;
+        mod_val = mod_amp * (SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart);
+        self->pointerPos_mod += mod_delta;
+
+        car_freq = car + mod_val;
+        car_delta = car_freq * self->scaleFactor;
+        self->pointerPos_car = Sine_clip(self->pointerPos_car);
+        ipart = (int)self->pointerPos_car;
+        fpart = self->pointerPos_car - ipart;
+        self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
+        self->pointerPos_car += car_delta;
+    }
+}
+
+static void
+Fm_readframes_aia(Fm *self) {
+    MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_delta, fpart;
+    int i, ipart;
+
+    MYFLT *car = Stream_getData((Stream *)self->car_stream);
+    MYFLT rat = PyFloat_AS_DOUBLE(self->ratio);
+    MYFLT *ind = Stream_getData((Stream *)self->index_stream);
+
+    for (i=0; i<self->bufsize; i++) {
+        mod_freq = car[i] * rat;
+        mod_amp = mod_freq * ind[i];
+        mod_delta = mod_freq * self->scaleFactor;
+        self->pointerPos_mod = Sine_clip(self->pointerPos_mod);
+        ipart = (int)self->pointerPos_mod;
+        fpart = self->pointerPos_mod - ipart;
+        mod_val = mod_amp * (SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart);
+        self->pointerPos_mod += mod_delta;
+
+        car_freq = car[i] + mod_val;
+        car_delta = car_freq * self->scaleFactor;
+        self->pointerPos_car = Sine_clip(self->pointerPos_car);
+        ipart = (int)self->pointerPos_car;
+        fpart = self->pointerPos_car - ipart;
+        self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
+        self->pointerPos_car += car_delta;
+    }
+}
+
+static void
+Fm_readframes_iaa(Fm *self) {
+    MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_delta, fpart;
+    int i, ipart;
+
+    MYFLT car = PyFloat_AS_DOUBLE(self->car);
+    MYFLT *rat = Stream_getData((Stream *)self->ratio_stream);
+    MYFLT *ind = Stream_getData((Stream *)self->index_stream);
+
+    for (i=0; i<self->bufsize; i++) {
+        mod_freq = car * rat[i];
+        mod_amp = mod_freq * ind[i];
+        mod_delta = mod_freq * self->scaleFactor;
+        self->pointerPos_mod = Sine_clip(self->pointerPos_mod);
+        ipart = (int)self->pointerPos_mod;
+        fpart = self->pointerPos_mod - ipart;
+        mod_val = mod_amp * (SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart);
+        self->pointerPos_mod += mod_delta;
+
+        car_freq = car + mod_val;
+        car_delta = car_freq * self->scaleFactor;
+        self->pointerPos_car = Sine_clip(self->pointerPos_car);
+        ipart = (int)self->pointerPos_car;
+        fpart = self->pointerPos_car - ipart;
+        self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
+        self->pointerPos_car += car_delta;
+    }
+}
+
+static void
+Fm_readframes_aaa(Fm *self) {
+    MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_delta, fpart;
+    int i, ipart;
+
+    MYFLT *car = Stream_getData((Stream *)self->car_stream);
+    MYFLT *rat = Stream_getData((Stream *)self->ratio_stream);
+    MYFLT *ind = Stream_getData((Stream *)self->index_stream);
+
+    for (i=0; i<self->bufsize; i++) {
+        mod_freq = car[i] * rat[i];
+        mod_amp = mod_freq * ind[i];
+        mod_delta = mod_freq * self->scaleFactor;
+        self->pointerPos_mod = Sine_clip(self->pointerPos_mod);
+        ipart = (int)self->pointerPos_mod;
+        fpart = self->pointerPos_mod - ipart;
+        mod_val = mod_amp * (SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart);
+        self->pointerPos_mod += mod_delta;
+
+        car_freq = car[i] + mod_val;
+        car_delta = car_freq * self->scaleFactor;
+        self->pointerPos_car = Sine_clip(self->pointerPos_car);
+        ipart = (int)self->pointerPos_car;
+        fpart = self->pointerPos_car - ipart;
+        self->data[i] = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
+        self->pointerPos_car += car_delta;
+    }
+}
+
+static void Fm_postprocessing_ii(Fm *self) { POST_PROCESSING_II };
+static void Fm_postprocessing_ai(Fm *self) { POST_PROCESSING_AI };
+static void Fm_postprocessing_ia(Fm *self) { POST_PROCESSING_IA };
+static void Fm_postprocessing_aa(Fm *self) { POST_PROCESSING_AA };
+static void Fm_postprocessing_ireva(Fm *self) { POST_PROCESSING_IREVA };
+static void Fm_postprocessing_areva(Fm *self) { POST_PROCESSING_AREVA };
+static void Fm_postprocessing_revai(Fm *self) { POST_PROCESSING_REVAI };
+static void Fm_postprocessing_revaa(Fm *self) { POST_PROCESSING_REVAA };
+static void Fm_postprocessing_revareva(Fm *self) { POST_PROCESSING_REVAREVA };
+
+static void
+Fm_setProcMode(Fm *self)
+{
+    int procmode, muladdmode;
+    procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+	switch (procmode) {
+        case 0:
+            self->proc_func_ptr = Fm_readframes_iii;
+            break;
+        case 1:
+            self->proc_func_ptr = Fm_readframes_aii;
+            break;
+        case 10:
+            self->proc_func_ptr = Fm_readframes_iai;
+            break;
+        case 11:
+            self->proc_func_ptr = Fm_readframes_aai;
+            break;
+        case 100:
+            self->proc_func_ptr = Fm_readframes_iia;
+            break;
+        case 101:
+            self->proc_func_ptr = Fm_readframes_aia;
+            break;
+        case 110:
+            self->proc_func_ptr = Fm_readframes_iaa;
+            break;
+        case 111:
+            self->proc_func_ptr = Fm_readframes_aaa;
+            break;
+    }
+
+	switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = Fm_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = Fm_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = Fm_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = Fm_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = Fm_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = Fm_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = Fm_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = Fm_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = Fm_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+Fm_compute_next_data_frame(Fm *self)
+{
+    (*self->proc_func_ptr)(self);
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+Fm_traverse(Fm *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->car);
+    Py_VISIT(self->car_stream);
+    Py_VISIT(self->ratio);
+    Py_VISIT(self->ratio_stream);
+    Py_VISIT(self->index);
+    Py_VISIT(self->index_stream);
+    return 0;
+}
+
+static int
+Fm_clear(Fm *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->car);
+    Py_CLEAR(self->car_stream);
+    Py_CLEAR(self->ratio);
+    Py_CLEAR(self->ratio_stream);
+    Py_CLEAR(self->index);
+    Py_CLEAR(self->index_stream);
+    return 0;
+}
+
+static void
+Fm_dealloc(Fm* self)
+{
+    pyo_DEALLOC
+    Fm_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+Fm_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *cartmp=NULL, *ratiotmp=NULL, *indextmp=NULL, *multmp=NULL, *addtmp=NULL;
+    Fm *self;
+    self = (Fm *)type->tp_alloc(type, 0);
+
+    self->car = PyFloat_FromDouble(100);
+    self->ratio = PyFloat_FromDouble(0.5);
+    self->index = PyFloat_FromDouble(5);
+	self->modebuffer[0] = 0;
+	self->modebuffer[1] = 0;
+	self->modebuffer[2] = 0;
+	self->modebuffer[3] = 0;
+	self->modebuffer[4] = 0;
+    self->pointerPos_car = self->pointerPos_mod = 0.;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, Fm_compute_next_data_frame);
+    self->mode_func_ptr = Fm_setProcMode;
+
+    self->scaleFactor = 512.0 / self->sr;
+
+    static char *kwlist[] = {"carrier", "ratio", "index", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOO", kwlist, &cartmp, &ratiotmp, &indextmp, &multmp, &addtmp))
+        Py_RETURN_NONE;
+
+    if (cartmp) {
+        PyObject_CallMethod((PyObject *)self, "setCarrier", "O", cartmp);
+    }
+
+    if (ratiotmp) {
+        PyObject_CallMethod((PyObject *)self, "setRatio", "O", ratiotmp);
+    }
+
+    if (indextmp) {
+        PyObject_CallMethod((PyObject *)self, "setIndex", "O", indextmp);
+    }
+
+    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 * Fm_getServer(Fm* self) { GET_SERVER };
+static PyObject * Fm_getStream(Fm* self) { GET_STREAM };
+static PyObject * Fm_setMul(Fm *self, PyObject *arg) { SET_MUL };
+static PyObject * Fm_setAdd(Fm *self, PyObject *arg) { SET_ADD };
+static PyObject * Fm_setSub(Fm *self, PyObject *arg) { SET_SUB };
+static PyObject * Fm_setDiv(Fm *self, PyObject *arg) { SET_DIV };
+
+static PyObject * Fm_play(Fm *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * Fm_out(Fm *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * Fm_stop(Fm *self) { STOP };
+
+static PyObject * Fm_multiply(Fm *self, PyObject *arg) { MULTIPLY };
+static PyObject * Fm_inplace_multiply(Fm *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * Fm_add(Fm *self, PyObject *arg) { ADD };
+static PyObject * Fm_inplace_add(Fm *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * Fm_sub(Fm *self, PyObject *arg) { SUB };
+static PyObject * Fm_inplace_sub(Fm *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * Fm_div(Fm *self, PyObject *arg) { DIV };
+static PyObject * Fm_inplace_div(Fm *self, PyObject *arg) { INPLACE_DIV };
+
+static PyObject *
+Fm_setCarrier(Fm *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->car);
+	if (isNumber == 1) {
+		self->car = PyNumber_Float(tmp);
+        self->modebuffer[2] = 0;
+	}
+	else {
+		self->car = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->car, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->car_stream);
+        self->car_stream = (Stream *)streamtmp;
+		self->modebuffer[2] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+Fm_setRatio(Fm *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->ratio);
+	if (isNumber == 1) {
+		self->ratio = PyNumber_Float(tmp);
+        self->modebuffer[3] = 0;
+	}
+	else {
+		self->ratio = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->ratio, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->ratio_stream);
+        self->ratio_stream = (Stream *)streamtmp;
+		self->modebuffer[3] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+Fm_setIndex(Fm *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->index);
+	if (isNumber == 1) {
+		self->index = PyNumber_Float(tmp);
+        self->modebuffer[4] = 0;
+	}
+	else {
+		self->index = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->index, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->index_stream);
+        self->index_stream = (Stream *)streamtmp;
+		self->modebuffer[4] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyMemberDef Fm_members[] = {
+{"server", T_OBJECT_EX, offsetof(Fm, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(Fm, stream), 0, "Stream object."},
+{"carrier", T_OBJECT_EX, offsetof(Fm, car), 0, "Frequency in cycle per second."},
+{"ratio", T_OBJECT_EX, offsetof(Fm, ratio), 0, "Ratio carrier:modulator (mod freq = car*mod)."},
+{"index", T_OBJECT_EX, offsetof(Fm, index), 0, "Modulation index (mod amp = mod freq*index)."},
+{"mul", T_OBJECT_EX, offsetof(Fm, mul), 0, "Mul factor."},
+{"add", T_OBJECT_EX, offsetof(Fm, add), 0, "Add factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyMethodDef Fm_methods[] = {
+{"getServer", (PyCFunction)Fm_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)Fm_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)Fm_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"out", (PyCFunction)Fm_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+{"stop", (PyCFunction)Fm_stop, METH_NOARGS, "Stops computing."},
+{"setCarrier", (PyCFunction)Fm_setCarrier, METH_O, "Sets carrier frequency in cycle per second."},
+{"setRatio", (PyCFunction)Fm_setRatio, METH_O, "Sets car:mod ratio."},
+{"setIndex", (PyCFunction)Fm_setIndex, METH_O, "Sets modulation index."},
+{"setMul", (PyCFunction)Fm_setMul, METH_O, "Sets Fm mul factor."},
+{"setAdd", (PyCFunction)Fm_setAdd, METH_O, "Sets Fm add factor."},
+{"setSub", (PyCFunction)Fm_setSub, METH_O, "Sets inverse add factor."},
+{"setDiv", (PyCFunction)Fm_setDiv, METH_O, "Sets inverse mul factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyNumberMethods Fm_as_number = {
+(binaryfunc)Fm_add,                      /*nb_add*/
+(binaryfunc)Fm_sub,                 /*nb_subtract*/
+(binaryfunc)Fm_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)Fm_inplace_add,              /*inplace_add*/
+(binaryfunc)Fm_inplace_sub,         /*inplace_subtract*/
+(binaryfunc)Fm_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)Fm_div,                       /*nb_true_divide*/
+0,     /*nb_inplace_floor_divide*/
+(binaryfunc)Fm_inplace_div,                       /*nb_inplace_true_divide*/
+0,                     /* nb_index */
+};
+
+PyTypeObject FmType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.Fm_base",         /*tp_name*/
+sizeof(Fm),         /*tp_basicsize*/
+0,                         /*tp_itemsize*/
+(destructor)Fm_dealloc, /*tp_dealloc*/
+0,                         /*tp_print*/
+0,                         /*tp_getattr*/
+0,                         /*tp_setattr*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
+0,                         /*tp_repr*/
+&Fm_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*/
+"Fm objects. Generates a frequency modulation synthesis.",           /* tp_doc */
+(traverseproc)Fm_traverse,   /* tp_traverse */
+(inquiry)Fm_clear,           /* tp_clear */
+0,		               /* tp_richcompare */
+0,		               /* tp_weaklistoffset */
+0,		               /* tp_iter */
+0,		               /* tp_iternext */
+Fm_methods,             /* tp_methods */
+Fm_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 */
+Fm_new,                 /* tp_new */
+};
+
+/*************/
+/* CrossFm object */
+/*************/
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *car;
+    Stream *car_stream;
+    PyObject *ratio;
+    Stream *ratio_stream;
+    PyObject *ind1;
+    Stream *ind1_stream;
+    PyObject *ind2;
+    Stream *ind2_stream;
+    int modebuffer[6];
+    MYFLT pointerPos_car;
+    MYFLT pointerPos_mod;
+    MYFLT scaleFactor;
+    MYFLT car_val;
+} CrossFm;
+
+static void
+CrossFm_readframes(CrossFm *self) {
+    MYFLT mod_freq, mod_amp, mod_delta, mod_val, car_freq, car_amp, car_delta, fpart;
+    int i, ipart;
+    MYFLT car[self->bufsize];
+    MYFLT rat[self->bufsize];
+    MYFLT ind1[self->bufsize];
+    MYFLT ind2[self->bufsize];
+
+    if (self->modebuffer[2] == 0) {
+        MYFLT tmpcar = PyFloat_AS_DOUBLE(self->car);
+        for (i=0; i<self->bufsize; i++) {
+            car[i] = tmpcar;
+        }
+    }
+    else {
+        MYFLT *tmpcar = Stream_getData((Stream *)self->car_stream);
+        for (i=0; i<self->bufsize; i++) {
+            car[i] = tmpcar[i];
+        }
+    }
+
+    if (self->modebuffer[3] == 0) {
+        MYFLT tmprat = PyFloat_AS_DOUBLE(self->ratio);
+        for (i=0; i<self->bufsize; i++) {
+            rat[i] = tmprat;
+        }
+    }
+    else {
+        MYFLT *tmprat = Stream_getData((Stream *)self->ratio_stream);
+        for (i=0; i<self->bufsize; i++) {
+            rat[i] = tmprat[i];
+        }
+    }
+
+    if (self->modebuffer[4] == 0) {
+        MYFLT tmpind1 = PyFloat_AS_DOUBLE(self->ind1);
+        for (i=0; i<self->bufsize; i++) {
+            ind1[i] = tmpind1;
+        }
+    }
+    else {
+        MYFLT *tmpind1 = Stream_getData((Stream *)self->ind1_stream);
+        for (i=0; i<self->bufsize; i++) {
+            ind1[i] = tmpind1[i];
+        }
+    }
+
+    if (self->modebuffer[5] == 0) {
+        MYFLT tmpind2 = PyFloat_AS_DOUBLE(self->ind2);
+        for (i=0; i<self->bufsize; i++) {
+            ind2[i] = tmpind2;
+        }
+    }
+    else {
+        MYFLT *tmpind2 = Stream_getData((Stream *)self->ind2_stream);
+        for (i=0; i<self->bufsize; i++) {
+            ind2[i] = tmpind2[i];
+        }
+    }
+
+    for (i=0; i<self->bufsize; i++) {
+        car_amp = car[i] * ind1[i];
+        mod_freq = car[i] * rat[i];
+        mod_amp = mod_freq * ind2[i];
+        mod_delta = (mod_freq + self->car_val * car_amp) * self->scaleFactor;
+        self->pointerPos_mod = Sine_clip(self->pointerPos_mod);
+        ipart = (int)self->pointerPos_mod;
+        fpart = self->pointerPos_mod - ipart;
+        mod_val = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
+        self->pointerPos_mod += mod_delta;
+
+        car_freq = car[i] + (mod_val * mod_amp);
+        car_delta = car_freq * self->scaleFactor;
+        self->pointerPos_car = Sine_clip(self->pointerPos_car);
+        ipart = (int)self->pointerPos_car;
+        fpart = self->pointerPos_car - ipart;
+        self->car_val = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
+        self->pointerPos_car += car_delta;
+        self->data[i] = (self->car_val + mod_val) * 0.5;
+    }
+}
+
+static void CrossFm_postprocessing_ii(CrossFm *self) { POST_PROCESSING_II };
+static void CrossFm_postprocessing_ai(CrossFm *self) { POST_PROCESSING_AI };
+static void CrossFm_postprocessing_ia(CrossFm *self) { POST_PROCESSING_IA };
+static void CrossFm_postprocessing_aa(CrossFm *self) { POST_PROCESSING_AA };
+static void CrossFm_postprocessing_ireva(CrossFm *self) { POST_PROCESSING_IREVA };
+static void CrossFm_postprocessing_areva(CrossFm *self) { POST_PROCESSING_AREVA };
+static void CrossFm_postprocessing_revai(CrossFm *self) { POST_PROCESSING_REVAI };
+static void CrossFm_postprocessing_revaa(CrossFm *self) { POST_PROCESSING_REVAA };
+static void CrossFm_postprocessing_revareva(CrossFm *self) { POST_PROCESSING_REVAREVA };
+
+static void
+CrossFm_setProcMode(CrossFm *self)
+{
+    int muladdmode;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+    self->proc_func_ptr = CrossFm_readframes;
+
+	switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = CrossFm_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = CrossFm_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = CrossFm_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = CrossFm_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = CrossFm_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = CrossFm_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = CrossFm_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = CrossFm_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = CrossFm_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+CrossFm_compute_next_data_frame(CrossFm *self)
+{
+    (*self->proc_func_ptr)(self);
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+CrossFm_traverse(CrossFm *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->car);
+    Py_VISIT(self->car_stream);
+    Py_VISIT(self->ratio);
+    Py_VISIT(self->ratio_stream);
+    Py_VISIT(self->ind1);
+    Py_VISIT(self->ind1_stream);
+    Py_VISIT(self->ind2);
+    Py_VISIT(self->ind2_stream);
+    return 0;
+}
+
+static int
+CrossFm_clear(CrossFm *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->car);
+    Py_CLEAR(self->car_stream);
+    Py_CLEAR(self->ratio);
+    Py_CLEAR(self->ratio_stream);
+    Py_CLEAR(self->ind1);
+    Py_CLEAR(self->ind1_stream);
+    Py_CLEAR(self->ind2);
+    Py_CLEAR(self->ind2_stream);
+    return 0;
+}
+
+static void
+CrossFm_dealloc(CrossFm* self)
+{
+    pyo_DEALLOC
+    CrossFm_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+CrossFm_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *cartmp=NULL, *ratiotmp=NULL, *ind1tmp=NULL, *ind2tmp=NULL, *multmp=NULL, *addtmp=NULL;
+    CrossFm *self;
+    self = (CrossFm *)type->tp_alloc(type, 0);
+
+    self->car = PyFloat_FromDouble(100);
+    self->ratio = PyFloat_FromDouble(0.5);
+    self->ind1 = PyFloat_FromDouble(2);
+    self->ind2 = PyFloat_FromDouble(2);
+	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->pointerPos_car = self->pointerPos_mod = 0.;
+    self->car_val = 0.;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, CrossFm_compute_next_data_frame);
+    self->mode_func_ptr = CrossFm_setProcMode;
+
+    self->scaleFactor = 512.0 / self->sr;
+
+    static char *kwlist[] = {"carrier", "ratio", "ind1", "ind2", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOOO", kwlist, &cartmp, &ratiotmp, &ind1tmp, &ind2tmp, &multmp, &addtmp))
+        Py_RETURN_NONE;
+
+    if (cartmp) {
+        PyObject_CallMethod((PyObject *)self, "setCarrier", "O", cartmp);
+    }
+
+    if (ratiotmp) {
+        PyObject_CallMethod((PyObject *)self, "setRatio", "O", ratiotmp);
+    }
+
+    if (ind1tmp) {
+        PyObject_CallMethod((PyObject *)self, "setInd1", "O", ind1tmp);
+    }
+
+    if (ind2tmp) {
+        PyObject_CallMethod((PyObject *)self, "setInd2", "O", ind2tmp);
+    }
+
+    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 * CrossFm_getServer(CrossFm* self) { GET_SERVER };
+static PyObject * CrossFm_getStream(CrossFm* self) { GET_STREAM };
+static PyObject * CrossFm_setMul(CrossFm *self, PyObject *arg) { SET_MUL };
+static PyObject * CrossFm_setAdd(CrossFm *self, PyObject *arg) { SET_ADD };
+static PyObject * CrossFm_setSub(CrossFm *self, PyObject *arg) { SET_SUB };
+static PyObject * CrossFm_setDiv(CrossFm *self, PyObject *arg) { SET_DIV };
+
+static PyObject * CrossFm_play(CrossFm *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * CrossFm_out(CrossFm *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * CrossFm_stop(CrossFm *self) { STOP };
+
+static PyObject * CrossFm_multiply(CrossFm *self, PyObject *arg) { MULTIPLY };
+static PyObject * CrossFm_inplace_multiply(CrossFm *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * CrossFm_add(CrossFm *self, PyObject *arg) { ADD };
+static PyObject * CrossFm_inplace_add(CrossFm *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * CrossFm_sub(CrossFm *self, PyObject *arg) { SUB };
+static PyObject * CrossFm_inplace_sub(CrossFm *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * CrossFm_div(CrossFm *self, PyObject *arg) { DIV };
+static PyObject * CrossFm_inplace_div(CrossFm *self, PyObject *arg) { INPLACE_DIV };
+
+static PyObject *
+CrossFm_setCarrier(CrossFm *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->car);
+	if (isNumber == 1) {
+		self->car = PyNumber_Float(tmp);
+        self->modebuffer[2] = 0;
+	}
+	else {
+		self->car = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->car, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->car_stream);
+        self->car_stream = (Stream *)streamtmp;
+		self->modebuffer[2] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+CrossFm_setRatio(CrossFm *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->ratio);
+	if (isNumber == 1) {
+		self->ratio = PyNumber_Float(tmp);
+        self->modebuffer[3] = 0;
+	}
+	else {
+		self->ratio = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->ratio, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->ratio_stream);
+        self->ratio_stream = (Stream *)streamtmp;
+		self->modebuffer[3] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+CrossFm_setInd1(CrossFm *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->ind1);
+	if (isNumber == 1) {
+		self->ind1 = PyNumber_Float(tmp);
+        self->modebuffer[4] = 0;
+	}
+	else {
+		self->ind1 = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->ind1, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->ind1_stream);
+        self->ind1_stream = (Stream *)streamtmp;
+		self->modebuffer[4] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+CrossFm_setInd2(CrossFm *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->ind2);
+	if (isNumber == 1) {
+		self->ind2 = PyNumber_Float(tmp);
+        self->modebuffer[5] = 0;
+	}
+	else {
+		self->ind2 = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->ind2, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->ind2_stream);
+        self->ind2_stream = (Stream *)streamtmp;
+		self->modebuffer[5] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyMemberDef CrossFm_members[] = {
+    {"server", T_OBJECT_EX, offsetof(CrossFm, server), 0, "Pyo server."},
+    {"stream", T_OBJECT_EX, offsetof(CrossFm, stream), 0, "Stream object."},
+    {"carrier", T_OBJECT_EX, offsetof(CrossFm, car), 0, "Frequency in cycle per second."},
+    {"ratio", T_OBJECT_EX, offsetof(CrossFm, ratio), 0, "Ratio carrier:modulator (mod freq = car*mod)."},
+    {"ind1", T_OBJECT_EX, offsetof(CrossFm, ind1), 0, "Modulation ind1 (car amp = car freq*ind1)."},
+    {"ind2", T_OBJECT_EX, offsetof(CrossFm, ind2), 0, "Modulation ind2 (mod amp = mod freq*ind2)."},
+    {"mul", T_OBJECT_EX, offsetof(CrossFm, mul), 0, "Mul factor."},
+    {"add", T_OBJECT_EX, offsetof(CrossFm, add), 0, "Add factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef CrossFm_methods[] = {
+    {"getServer", (PyCFunction)CrossFm_getServer, METH_NOARGS, "Returns server object."},
+    {"_getStream", (PyCFunction)CrossFm_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)CrossFm_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+    {"out", (PyCFunction)CrossFm_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+    {"stop", (PyCFunction)CrossFm_stop, METH_NOARGS, "Stops computing."},
+    {"setCarrier", (PyCFunction)CrossFm_setCarrier, METH_O, "Sets carrier frequency in cycle per second."},
+    {"setRatio", (PyCFunction)CrossFm_setRatio, METH_O, "Sets car:mod ratio."},
+    {"setInd1", (PyCFunction)CrossFm_setInd1, METH_O, "Sets carrier index."},
+    {"setInd2", (PyCFunction)CrossFm_setInd2, METH_O, "Sets modulation index."},
+    {"setMul", (PyCFunction)CrossFm_setMul, METH_O, "Sets CrossFm mul factor."},
+    {"setAdd", (PyCFunction)CrossFm_setAdd, METH_O, "Sets CrossFm add factor."},
+    {"setSub", (PyCFunction)CrossFm_setSub, METH_O, "Sets inverse add factor."},
+    {"setDiv", (PyCFunction)CrossFm_setDiv, METH_O, "Sets inverse mul factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyNumberMethods CrossFm_as_number = {
+    (binaryfunc)CrossFm_add,                      /*nb_add*/
+    (binaryfunc)CrossFm_sub,                 /*nb_subtract*/
+    (binaryfunc)CrossFm_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)CrossFm_inplace_add,              /*inplace_add*/
+    (binaryfunc)CrossFm_inplace_sub,         /*inplace_subtract*/
+    (binaryfunc)CrossFm_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)CrossFm_div,                       /*nb_true_divide*/
+    0,     /*nb_inplace_floor_divide*/
+    (binaryfunc)CrossFm_inplace_div,                       /*nb_inplace_true_divide*/
+    0,                     /* nb_ind1 */
+};
+
+PyTypeObject CrossFmType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.CrossFm_base",         /*tp_name*/
+    sizeof(CrossFm),         /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)CrossFm_dealloc, /*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
+    0,                         /*tp_repr*/
+    &CrossFm_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*/
+    "CrossFm objects. Generates a cross frequency modulation synthesis.",           /* tp_doc */
+    (traverseproc)CrossFm_traverse,   /* tp_traverse */
+    (inquiry)CrossFm_clear,           /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    CrossFm_methods,             /* tp_methods */
+    CrossFm_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 */
+    CrossFm_new,                 /* tp_new */
+};
+
+/*************/
+/* Blit object */
+/*************/
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *freq;
+    Stream *freq_stream;
+    PyObject *harms;
+    Stream *harms_stream;
+    int modebuffer[4];
+    MYFLT phase;
+
+} Blit;
+
+static void
+Blit_readframes_ii(Blit *self) {
+    MYFLT p, m, rate, val;
+    int i, nHarms;
+
+    MYFLT freq = PyFloat_AS_DOUBLE(self->freq);
+    MYFLT hrms = PyFloat_AS_DOUBLE(self->harms);
+
+    nHarms = (int)hrms;
+    m = 2.0 * nHarms + 1.0;
+    p = self->sr / freq;
+    rate = PI / p;
+
+    for (i=0; i<self->bufsize; i++) {
+        if (self->phase <= 0.0)
+            val = 1.0;
+        else {
+            val = MYSIN(m * self->phase);
+            val /= m * MYSIN(self->phase);
+        }
+        self->phase += rate;
+        if (self->phase >= PI)
+            self->phase -= PI;
+
+        self->data[i] = val;
+    }
+}
+
+static void
+Blit_readframes_ai(Blit *self) {
+    MYFLT p, m, rate, val;
+    int i, nHarms;
+
+    MYFLT *freq = Stream_getData((Stream *)self->freq_stream);
+    MYFLT hrms = PyFloat_AS_DOUBLE(self->harms);
+
+    nHarms = (int)hrms;
+    m = 2.0 * nHarms + 1.0;
+
+    for (i=0; i<self->bufsize; i++) {
+        p = self->sr / freq[i];
+        rate = PI / p;
+        if (self->phase <= 0.0)
+            val = 1.0;
+        else {
+            val = MYSIN(m * self->phase);
+            val /= m * MYSIN(self->phase);
+        }
+        self->phase += rate;
+        if (self->phase >= PI)
+            self->phase -= PI;
+
+        self->data[i] = val;
+    }
+}
+
+static void
+Blit_readframes_ia(Blit *self) {
+    MYFLT p, m, rate, val;
+    int i, nHarms;
+
+    MYFLT freq = PyFloat_AS_DOUBLE(self->freq);
+    MYFLT *hrms = Stream_getData((Stream *)self->harms_stream);
+
+    p = self->sr / freq;
+    rate = PI / p;
+
+    for (i=0; i<self->bufsize; i++) {
+        nHarms = (int)hrms[i];
+        m = 2.0 * nHarms + 1.0;
+        if (self->phase <= 0.0)
+            val = 1.0;
+        else {
+            val = MYSIN(m * self->phase);
+            val /= m * MYSIN(self->phase);
+        }
+        self->phase += rate;
+        if (self->phase >= PI)
+            self->phase -= PI;
+
+        self->data[i] = val;
+    }
+}
+
+static void
+Blit_readframes_aa(Blit *self) {
+    MYFLT p, m, rate, val;
+    int i, nHarms;
+
+    MYFLT *freq = Stream_getData((Stream *)self->freq_stream);
+    MYFLT *hrms = Stream_getData((Stream *)self->harms_stream);
+
+    for (i=0; i<self->bufsize; i++) {
+        nHarms = (int)hrms[i];
+        m = 2.0 * nHarms + 1.0;
+        p = self->sr / freq[i];
+        rate = PI / p;
+        if (self->phase <= 0.0)
+            val = 1.0;
+        else {
+            val = MYSIN(m * self->phase);
+            val /= m * MYSIN(self->phase);
+        }
+        self->phase += rate;
+        if (self->phase >= PI)
+            self->phase -= PI;
+
+        self->data[i] = val;
+    }
+}
+
+static void Blit_postprocessing_ii(Blit *self) { POST_PROCESSING_II };
+static void Blit_postprocessing_ai(Blit *self) { POST_PROCESSING_AI };
+static void Blit_postprocessing_ia(Blit *self) { POST_PROCESSING_IA };
+static void Blit_postprocessing_aa(Blit *self) { POST_PROCESSING_AA };
+static void Blit_postprocessing_ireva(Blit *self) { POST_PROCESSING_IREVA };
+static void Blit_postprocessing_areva(Blit *self) { POST_PROCESSING_AREVA };
+static void Blit_postprocessing_revai(Blit *self) { POST_PROCESSING_REVAI };
+static void Blit_postprocessing_revaa(Blit *self) { POST_PROCESSING_REVAA };
+static void Blit_postprocessing_revareva(Blit *self) { POST_PROCESSING_REVAREVA };
+
+static void
+Blit_setProcMode(Blit *self)
+{
+    int procmode, muladdmode;
+    procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+	switch (procmode) {
+        case 0:
+            self->proc_func_ptr = Blit_readframes_ii;
+            break;
+        case 1:
+            self->proc_func_ptr = Blit_readframes_ai;
+            break;
+        case 10:
+            self->proc_func_ptr = Blit_readframes_ia;
+            break;
+        case 11:
+            self->proc_func_ptr = Blit_readframes_aa;
+            break;
+    }
+
+	switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = Blit_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = Blit_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = Blit_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = Blit_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = Blit_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = Blit_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = Blit_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = Blit_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = Blit_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+Blit_compute_next_data_frame(Blit *self)
+{
+    (*self->proc_func_ptr)(self);
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+Blit_traverse(Blit *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->harms);
+    Py_VISIT(self->harms_stream);
+    return 0;
+}
+
+static int
+Blit_clear(Blit *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->harms);
+    Py_CLEAR(self->harms_stream);
+    return 0;
+}
+
+static void
+Blit_dealloc(Blit* self)
+{
+    pyo_DEALLOC
+    Blit_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+Blit_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *freqtmp=NULL, *harmstmp=NULL, *multmp=NULL, *addtmp=NULL;
+    Blit *self;
+    self = (Blit *)type->tp_alloc(type, 0);
+
+    self->freq = PyFloat_FromDouble(100);
+    self->harms = PyFloat_FromDouble(40);
+	self->modebuffer[0] = 0;
+	self->modebuffer[1] = 0;
+	self->modebuffer[2] = 0;
+	self->modebuffer[3] = 0;
+    self->phase = 0.0;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, Blit_compute_next_data_frame);
+    self->mode_func_ptr = Blit_setProcMode;
+
+    static char *kwlist[] = {"freq", "harms", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &freqtmp, &harmstmp, &multmp, &addtmp))
+        Py_RETURN_NONE;
+
+    if (freqtmp) {
+        PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
+    }
+
+    if (harmstmp) {
+        PyObject_CallMethod((PyObject *)self, "setHarms", "O", harmstmp);
+    }
+
+    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 * Blit_getServer(Blit* self) { GET_SERVER };
+static PyObject * Blit_getStream(Blit* self) { GET_STREAM };
+static PyObject * Blit_setMul(Blit *self, PyObject *arg) { SET_MUL };
+static PyObject * Blit_setAdd(Blit *self, PyObject *arg) { SET_ADD };
+static PyObject * Blit_setSub(Blit *self, PyObject *arg) { SET_SUB };
+static PyObject * Blit_setDiv(Blit *self, PyObject *arg) { SET_DIV };
+
+static PyObject * Blit_play(Blit *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * Blit_out(Blit *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * Blit_stop(Blit *self) { STOP };
+
+static PyObject * Blit_multiply(Blit *self, PyObject *arg) { MULTIPLY };
+static PyObject * Blit_inplace_multiply(Blit *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * Blit_add(Blit *self, PyObject *arg) { ADD };
+static PyObject * Blit_inplace_add(Blit *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * Blit_sub(Blit *self, PyObject *arg) { SUB };
+static PyObject * Blit_inplace_sub(Blit *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * Blit_div(Blit *self, PyObject *arg) { DIV };
+static PyObject * Blit_inplace_div(Blit *self, PyObject *arg) { INPLACE_DIV };
+
+static PyObject *
+Blit_setFreq(Blit *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->freq);
+	if (isNumber == 1) {
+		self->freq = PyNumber_Float(tmp);
+        self->modebuffer[2] = 0;
+	}
+	else {
+		self->freq = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->freq_stream);
+        self->freq_stream = (Stream *)streamtmp;
+		self->modebuffer[2] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+Blit_setHarms(Blit *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->harms);
+	if (isNumber == 1) {
+		self->harms = PyNumber_Float(tmp);
+        self->modebuffer[3] = 0;
+	}
+	else {
+		self->harms = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->harms, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->harms_stream);
+        self->harms_stream = (Stream *)streamtmp;
+		self->modebuffer[3] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyMemberDef Blit_members[] = {
+    {"server", T_OBJECT_EX, offsetof(Blit, server), 0, "Pyo server."},
+    {"stream", T_OBJECT_EX, offsetof(Blit, stream), 0, "Stream object."},
+    {"freq", T_OBJECT_EX, offsetof(Blit, freq), 0, "Frequency in cycle per second."},
+    {"harms", T_OBJECT_EX, offsetof(Blit, harms), 0, "Number of harmonics."},
+    {"mul", T_OBJECT_EX, offsetof(Blit, mul), 0, "Mul factor."},
+    {"add", T_OBJECT_EX, offsetof(Blit, add), 0, "Add factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef Blit_methods[] = {
+    {"getServer", (PyCFunction)Blit_getServer, METH_NOARGS, "Returns server object."},
+    {"_getStream", (PyCFunction)Blit_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)Blit_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundfreqd."},
+    {"out", (PyCFunction)Blit_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundfreqd channel speficied by argument."},
+    {"stop", (PyCFunction)Blit_stop, METH_NOARGS, "Stops computing."},
+    {"setFreq", (PyCFunction)Blit_setFreq, METH_O, "Sets frequency in cycle per second."},
+    {"setHarms", (PyCFunction)Blit_setHarms, METH_O, "Sets the number of harmonics."},
+    {"setMul", (PyCFunction)Blit_setMul, METH_O, "Sets Blit mul factor."},
+    {"setAdd", (PyCFunction)Blit_setAdd, METH_O, "Sets Blit add factor."},
+    {"setSub", (PyCFunction)Blit_setSub, METH_O, "Sets inverse add factor."},
+    {"setDiv", (PyCFunction)Blit_setDiv, METH_O, "Sets inverse mul factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyNumberMethods Blit_as_number = {
+    (binaryfunc)Blit_add,                      /*nb_add*/
+    (binaryfunc)Blit_sub,                 /*nb_subtract*/
+    (binaryfunc)Blit_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)Blit_inplace_add,              /*inplace_add*/
+    (binaryfunc)Blit_inplace_sub,         /*inplace_subtract*/
+    (binaryfunc)Blit_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)Blit_div,                       /*nb_true_divide*/
+    0,     /*nb_inplace_floor_divide*/
+    (binaryfunc)Blit_inplace_div,                       /*nb_inplace_true_divide*/
+    0,                     /* nb_cutoff */
+};
+
+PyTypeObject BlitType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.Blit_base",         /*tp_name*/
+    sizeof(Blit),         /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)Blit_dealloc, /*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
+    0,                         /*tp_repr*/
+    &Blit_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*/
+    "Blit objects. Generates a band limited impulse train.",           /* tp_doc */
+    (traverseproc)Blit_traverse,   /* tp_traverse */
+    (inquiry)Blit_clear,           /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    Blit_methods,             /* tp_methods */
+    Blit_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 */
+    Blit_new,                 /* tp_new */
+};
+
+/* Rossler object */
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *pitch;
+    Stream *pitch_stream;
+    PyObject *chaos;
+    Stream *chaos_stream;
+    MYFLT *altBuffer;
+    MYFLT vDX;
+    MYFLT vDY;
+    MYFLT vDZ;
+    MYFLT vX;
+    MYFLT vY;
+    MYFLT vZ;
+    MYFLT pA;
+    MYFLT pB;
+    MYFLT scalePitch;
+    int modebuffer[4];
+} Rossler;
+
+static void
+Rossler_readframes_ii(Rossler *self) {
+    MYFLT delta, pit, chao;
+    int i;
+
+    pit = PyFloat_AS_DOUBLE(self->pitch);
+    chao = PyFloat_AS_DOUBLE(self->chaos);
+    if (pit < 0.0)
+        pit = 1.0;
+    else if (pit > 1.0)
+        pit = 1000.0;
+    else
+        pit = pit * 999.0 + 1.0;
+    delta = self->scalePitch * pit;
+
+    if (chao < 0.0)
+        chao = 3.0;
+    else if (chao > 1.0)
+        chao = 10.0;
+    else
+        chao = chao * 7.0 + 3.0;
+
+    for (i=0; i<self->bufsize; i++) {
+        self->vDX = -self->vY - self->vZ;
+        self->vDY = self->vX + self->pA * self->vY;
+        self->vDZ = self->pB + self->vZ * (self->vX - chao);
+
+        self->vX += self->vDX * delta;
+        self->vY += self->vDY * delta;
+        self->vZ += self->vDZ * delta;
+
+        self->data[i] = self->vX * ROSSLER_SCALE;
+        self->altBuffer[i] = self->vY * ROSSLER_ALT_SCALE;
+    }
+}
+
+static void
+Rossler_readframes_ai(Rossler *self) {
+    MYFLT delta, pit, chao;
+    int i;
+
+    MYFLT *fr = Stream_getData((Stream *)self->pitch_stream);
+    chao = PyFloat_AS_DOUBLE(self->chaos);
+    if (chao < 0.0)
+        chao = 3.0;
+    else if (chao > 1.0)
+        chao = 10.0;
+    else
+        chao = chao * 7.0 + 3.0;
+
+    for (i=0; i<self->bufsize; i++) {
+        pit = fr[i];
+        if (pit < 0.0)
+            pit = 1.0;
+        else if (pit > 1.0)
+            pit = 1000.0;
+        else
+            pit = pit * 999.0 + 1.0;
+        delta = self->scalePitch * pit;
+        self->vDX = -self->vY - self->vZ;
+        self->vDY = self->vX + self->pA * self->vY;
+        self->vDZ = self->pB + self->vZ * (self->vX - chao);
+
+        self->vX += self->vDX * delta;
+        self->vY += self->vDY * delta;
+        self->vZ += self->vDZ * delta;
+
+        self->data[i] = self->vX * ROSSLER_SCALE;
+        self->altBuffer[i] = self->vY * ROSSLER_ALT_SCALE;
+    }
+}
+
+static void
+Rossler_readframes_ia(Rossler *self) {
+    MYFLT delta, pit, chao;
+    int i;
+
+    pit = PyFloat_AS_DOUBLE(self->pitch);
+    MYFLT *ch = Stream_getData((Stream *)self->chaos_stream);
+
+    if (pit < 0.0)
+        pit = 1.0;
+    else if (pit > 1.0)
+        pit = 1000.0;
+    else
+        pit = pit * 999.0 + 1.0;
+    delta = self->scalePitch * pit;
+
+    for (i=0; i<self->bufsize; i++) {
+        chao = ch[i];
+        if (chao < 0.0)
+            chao = 3.0;
+        else if (chao > 1.0)
+            chao = 10.0;
+        else
+            chao = chao * 7.0 + 3.0;
+        self->vDX = -self->vY - self->vZ;
+        self->vDY = self->vX + self->pA * self->vY;
+        self->vDZ = self->pB + self->vZ * (self->vX - chao);
+
+        self->vX += self->vDX * delta;
+        self->vY += self->vDY * delta;
+        self->vZ += self->vDZ * delta;
+
+        self->data[i] = self->vX * ROSSLER_SCALE;
+        self->altBuffer[i] = self->vY * ROSSLER_ALT_SCALE;
+    }
+}
+
+static void
+Rossler_readframes_aa(Rossler *self) {
+    MYFLT delta, pit, chao;
+    int i;
+
+    MYFLT *fr = Stream_getData((Stream *)self->pitch_stream);
+    MYFLT *ch = Stream_getData((Stream *)self->chaos_stream);
+
+    for (i=0; i<self->bufsize; i++) {
+        pit = fr[i];
+        if (pit < 0.0)
+            pit = 1.0;
+        else if (pit > 1.0)
+            pit = 1000.0;
+        else
+            pit = pit * 999.0 + 1.0;
+        delta = self->scalePitch * pit;
+
+        chao = ch[i];
+        if (chao < 0.0)
+            chao = 3.0;
+        else if (chao > 1.0)
+            chao = 10.0;
+        else
+            chao = chao * 7.0 + 3.0;
+        self->vDX = -self->vY - self->vZ;
+        self->vDY = self->vX + self->pA * self->vY;
+        self->vDZ = self->pB + self->vZ * (self->vX - chao);
+
+        self->vX += self->vDX * delta;
+        self->vY += self->vDY * delta;
+        self->vZ += self->vDZ * delta;
+
+        self->data[i] = self->vX * ROSSLER_SCALE;
+        self->altBuffer[i] = self->vY * ROSSLER_ALT_SCALE;
+    }
+}
+
+static void Rossler_postprocessing_ii(Rossler *self) { POST_PROCESSING_II };
+static void Rossler_postprocessing_ai(Rossler *self) { POST_PROCESSING_AI };
+static void Rossler_postprocessing_ia(Rossler *self) { POST_PROCESSING_IA };
+static void Rossler_postprocessing_aa(Rossler *self) { POST_PROCESSING_AA };
+static void Rossler_postprocessing_ireva(Rossler *self) { POST_PROCESSING_IREVA };
+static void Rossler_postprocessing_areva(Rossler *self) { POST_PROCESSING_AREVA };
+static void Rossler_postprocessing_revai(Rossler *self) { POST_PROCESSING_REVAI };
+static void Rossler_postprocessing_revaa(Rossler *self) { POST_PROCESSING_REVAA };
+static void Rossler_postprocessing_revareva(Rossler *self) { POST_PROCESSING_REVAREVA };
+
+static void
+Rossler_setProcMode(Rossler *self)
+{
+    int procmode, muladdmode;
+    procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+	switch (procmode) {
+        case 0:
+            self->proc_func_ptr = Rossler_readframes_ii;
+            break;
+        case 1:
+            self->proc_func_ptr = Rossler_readframes_ai;
+            break;
+        case 10:
+            self->proc_func_ptr = Rossler_readframes_ia;
+            break;
+        case 11:
+            self->proc_func_ptr = Rossler_readframes_aa;
+            break;
+    }
+
+	switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = Rossler_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = Rossler_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = Rossler_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = Rossler_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = Rossler_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = Rossler_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = Rossler_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = Rossler_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = Rossler_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+Rossler_compute_next_data_frame(Rossler *self)
+{
+    (*self->proc_func_ptr)(self);
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+Rossler_traverse(Rossler *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->pitch);
+    Py_VISIT(self->pitch_stream);
+    Py_VISIT(self->chaos);
+    Py_VISIT(self->chaos_stream);
+    return 0;
+}
+
+static int
+Rossler_clear(Rossler *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->pitch);
+    Py_CLEAR(self->pitch_stream);
+    Py_CLEAR(self->chaos);
+    Py_CLEAR(self->chaos_stream);
+    return 0;
+}
+
+static void
+Rossler_dealloc(Rossler* self)
+{
+    pyo_DEALLOC
+    free(self->altBuffer);
+    Rossler_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+Rossler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *pitchtmp=NULL, *chaostmp=NULL, *multmp=NULL, *addtmp=NULL;
+    Rossler *self;
+    self = (Rossler *)type->tp_alloc(type, 0);
+
+    self->pitch = PyFloat_FromDouble(0.25);
+    self->chaos = PyFloat_FromDouble(0.5);
+    self->pA = 0.15;
+    self->pB = 0.20;
+    self->vDX = self->vDY = self->vDZ = 0.0;
+    self->vX = self->vY = self->vZ = 1.0;
+	self->modebuffer[0] = 0;
+	self->modebuffer[1] = 0;
+	self->modebuffer[2] = 0;
+	self->modebuffer[3] = 0;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, Rossler_compute_next_data_frame);
+    self->mode_func_ptr = Rossler_setProcMode;
+
+    self->scalePitch = 2.91 / self->sr;
+
+    static char *kwlist[] = {"pitch", "chaos", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &pitchtmp, &chaostmp, &multmp, &addtmp))
+        Py_RETURN_NONE;
+
+    if (pitchtmp) {
+        PyObject_CallMethod((PyObject *)self, "setPitch", "O", pitchtmp);
+    }
+
+    if (chaostmp) {
+        PyObject_CallMethod((PyObject *)self, "setChaos", "O", chaostmp);
+    }
+
+    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->altBuffer = (MYFLT *)realloc(self->altBuffer, self->bufsize * sizeof(MYFLT));
+
+    for (i=0; i<self->bufsize; i++) {
+        self->altBuffer[i] = 0.0;
+    }
+
+    (*self->mode_func_ptr)(self);
+
+    return (PyObject *)self;
+}
+
+static PyObject * Rossler_getServer(Rossler* self) { GET_SERVER };
+static PyObject * Rossler_getStream(Rossler* self) { GET_STREAM };
+static PyObject * Rossler_setMul(Rossler *self, PyObject *arg) { SET_MUL };
+static PyObject * Rossler_setAdd(Rossler *self, PyObject *arg) { SET_ADD };
+static PyObject * Rossler_setSub(Rossler *self, PyObject *arg) { SET_SUB };
+static PyObject * Rossler_setDiv(Rossler *self, PyObject *arg) { SET_DIV };
+
+static PyObject * Rossler_play(Rossler *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * Rossler_out(Rossler *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * Rossler_stop(Rossler *self) { STOP };
+
+static PyObject * Rossler_multiply(Rossler *self, PyObject *arg) { MULTIPLY };
+static PyObject * Rossler_inplace_multiply(Rossler *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * Rossler_add(Rossler *self, PyObject *arg) { ADD };
+static PyObject * Rossler_inplace_add(Rossler *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * Rossler_sub(Rossler *self, PyObject *arg) { SUB };
+static PyObject * Rossler_inplace_sub(Rossler *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * Rossler_div(Rossler *self, PyObject *arg) { DIV };
+static PyObject * Rossler_inplace_div(Rossler *self, PyObject *arg) { INPLACE_DIV };
+
+static PyObject *
+Rossler_setPitch(Rossler *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[2] = 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[2] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+Rossler_setChaos(Rossler *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->chaos);
+	if (isNumber == 1) {
+		self->chaos = PyNumber_Float(tmp);
+        self->modebuffer[3] = 0;
+	}
+	else {
+		self->chaos = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->chaos, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->chaos_stream);
+        self->chaos_stream = (Stream *)streamtmp;
+		self->modebuffer[3] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+MYFLT *
+Rossler_getAltBuffer(Rossler *self)
+{
+    return (MYFLT *)self->altBuffer;
+}
+
+static PyMemberDef Rossler_members[] = {
+    {"server", T_OBJECT_EX, offsetof(Rossler, server), 0, "Pyo server."},
+    {"stream", T_OBJECT_EX, offsetof(Rossler, stream), 0, "Stream object."},
+    {"pitch", T_OBJECT_EX, offsetof(Rossler, pitch), 0, "Pitch."},
+    {"chaos", T_OBJECT_EX, offsetof(Rossler, chaos), 0, "Chaotic behavior."},
+    {"mul", T_OBJECT_EX, offsetof(Rossler, mul), 0, "Mul factor."},
+    {"add", T_OBJECT_EX, offsetof(Rossler, add), 0, "Add factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef Rossler_methods[] = {
+    {"getServer", (PyCFunction)Rossler_getServer, METH_NOARGS, "Returns server object."},
+    {"_getStream", (PyCFunction)Rossler_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)Rossler_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+    {"out", (PyCFunction)Rossler_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+    {"stop", (PyCFunction)Rossler_stop, METH_NOARGS, "Stops computing."},
+    {"setPitch", (PyCFunction)Rossler_setPitch, METH_O, "Sets oscillator pitch."},
+    {"setChaos", (PyCFunction)Rossler_setChaos, METH_O, "Sets oscillator chaotic behavior."},
+    {"setMul", (PyCFunction)Rossler_setMul, METH_O, "Sets Rossler mul factor."},
+    {"setAdd", (PyCFunction)Rossler_setAdd, METH_O, "Sets Rossler add factor."},
+    {"setSub", (PyCFunction)Rossler_setSub, METH_O, "Sets inverse add factor."},
+    {"setDiv", (PyCFunction)Rossler_setDiv, METH_O, "Sets inverse mul factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyNumberMethods Rossler_as_number = {
+    (binaryfunc)Rossler_add,                      /*nb_add*/
+    (binaryfunc)Rossler_sub,                 /*nb_subtract*/
+    (binaryfunc)Rossler_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)Rossler_inplace_add,              /*inplace_add*/
+    (binaryfunc)Rossler_inplace_sub,         /*inplace_subtract*/
+    (binaryfunc)Rossler_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)Rossler_div,                       /*nb_true_divide*/
+    0,     /*nb_inplace_floor_divide*/
+    (binaryfunc)Rossler_inplace_div,                       /*nb_inplace_true_divide*/
+    0,                     /* nb_index */
+};
+
+PyTypeObject RosslerType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.Rossler_base",         /*tp_name*/
+    sizeof(Rossler),         /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)Rossler_dealloc, /*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
+    0,                         /*tp_repr*/
+    &Rossler_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*/
+    "Rossler objects. Rossler attractor.",           /* tp_doc */
+    (traverseproc)Rossler_traverse,   /* tp_traverse */
+    (inquiry)Rossler_clear,           /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    Rossler_methods,             /* tp_methods */
+    Rossler_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 */
+    Rossler_new,                 /* tp_new */
+};
+
+typedef struct {
+    pyo_audio_HEAD
+    Rossler *mainRossler;
+    int modebuffer[2];
+} RosslerAlt;
+
+static void RosslerAlt_postprocessing_ii(RosslerAlt *self) { POST_PROCESSING_II };
+static void RosslerAlt_postprocessing_ai(RosslerAlt *self) { POST_PROCESSING_AI };
+static void RosslerAlt_postprocessing_ia(RosslerAlt *self) { POST_PROCESSING_IA };
+static void RosslerAlt_postprocessing_aa(RosslerAlt *self) { POST_PROCESSING_AA };
+static void RosslerAlt_postprocessing_ireva(RosslerAlt *self) { POST_PROCESSING_IREVA };
+static void RosslerAlt_postprocessing_areva(RosslerAlt *self) { POST_PROCESSING_AREVA };
+static void RosslerAlt_postprocessing_revai(RosslerAlt *self) { POST_PROCESSING_REVAI };
+static void RosslerAlt_postprocessing_revaa(RosslerAlt *self) { POST_PROCESSING_REVAA };
+static void RosslerAlt_postprocessing_revareva(RosslerAlt *self) { POST_PROCESSING_REVAREVA };
+
+static void
+RosslerAlt_setProcMode(RosslerAlt *self) {
+    int muladdmode;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+    switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = RosslerAlt_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = RosslerAlt_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = RosslerAlt_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = RosslerAlt_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = RosslerAlt_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = RosslerAlt_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = RosslerAlt_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = RosslerAlt_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = RosslerAlt_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+RosslerAlt_compute_next_data_frame(RosslerAlt *self)
+{
+    int i;
+    MYFLT *tmp;
+    tmp = Rossler_getAltBuffer((Rossler *)self->mainRossler);
+    for (i=0; i<self->bufsize; i++) {
+        self->data[i] = tmp[i];
+    }
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+RosslerAlt_traverse(RosslerAlt *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->mainRossler);
+    return 0;
+}
+
+static int
+RosslerAlt_clear(RosslerAlt *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->mainRossler);
+    return 0;
+}
+
+static void
+RosslerAlt_dealloc(RosslerAlt* self)
+{
+    pyo_DEALLOC
+    RosslerAlt_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+RosslerAlt_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL;
+    RosslerAlt *self;
+    self = (RosslerAlt *)type->tp_alloc(type, 0);
+
+    self->modebuffer[0] = 0;
+    self->modebuffer[1] = 0;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, RosslerAlt_compute_next_data_frame);
+    self->mode_func_ptr = RosslerAlt_setProcMode;
+
+    static char *kwlist[] = {"mainRossler", "mul", "alt", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &maintmp, &multmp, &addtmp))
+        Py_RETURN_NONE;
+
+    Py_XDECREF(self->mainRossler);
+    Py_INCREF(maintmp);
+    self->mainRossler = (Rossler *)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 * RosslerAlt_getServer(RosslerAlt* self) { GET_SERVER };
+static PyObject * RosslerAlt_getStream(RosslerAlt* self) { GET_STREAM };
+static PyObject * RosslerAlt_setMul(RosslerAlt *self, PyObject *arg) { SET_MUL };
+static PyObject * RosslerAlt_setAdd(RosslerAlt *self, PyObject *arg) { SET_ADD };
+static PyObject * RosslerAlt_setSub(RosslerAlt *self, PyObject *arg) { SET_SUB };
+static PyObject * RosslerAlt_setDiv(RosslerAlt *self, PyObject *arg) { SET_DIV };
+
+static PyObject * RosslerAlt_play(RosslerAlt *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * RosslerAlt_out(RosslerAlt *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * RosslerAlt_stop(RosslerAlt *self) { STOP };
+
+static PyObject * RosslerAlt_multiply(RosslerAlt *self, PyObject *arg) { MULTIPLY };
+static PyObject * RosslerAlt_inplace_multiply(RosslerAlt *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * RosslerAlt_add(RosslerAlt *self, PyObject *arg) { ADD };
+static PyObject * RosslerAlt_inplace_add(RosslerAlt *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * RosslerAlt_sub(RosslerAlt *self, PyObject *arg) { SUB };
+static PyObject * RosslerAlt_inplace_sub(RosslerAlt *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * RosslerAlt_div(RosslerAlt *self, PyObject *arg) { DIV };
+static PyObject * RosslerAlt_inplace_div(RosslerAlt *self, PyObject *arg) { INPLACE_DIV };
+
+static PyMemberDef RosslerAlt_members[] = {
+    {"server", T_OBJECT_EX, offsetof(RosslerAlt, server), 0, "Pyo server."},
+    {"stream", T_OBJECT_EX, offsetof(RosslerAlt, stream), 0, "Stream object."},
+    {"mul", T_OBJECT_EX, offsetof(RosslerAlt, mul), 0, "Mul factor."},
+    {"add", T_OBJECT_EX, offsetof(RosslerAlt, add), 0, "Add factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef RosslerAlt_methods[] = {
+    {"getServer", (PyCFunction)RosslerAlt_getServer, METH_NOARGS, "Returns server object."},
+    {"_getStream", (PyCFunction)RosslerAlt_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)RosslerAlt_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+    {"out", (PyCFunction)RosslerAlt_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+    {"stop", (PyCFunction)RosslerAlt_stop, METH_NOARGS, "Stops computing."},
+    {"setMul", (PyCFunction)RosslerAlt_setMul, METH_O, "Sets oscillator mul factor."},
+    {"setAdd", (PyCFunction)RosslerAlt_setAdd, METH_O, "Sets oscillator add factor."},
+    {"setSub", (PyCFunction)RosslerAlt_setSub, METH_O, "Sets inverse add factor."},
+    {"setDiv", (PyCFunction)RosslerAlt_setDiv, METH_O, "Sets inverse mul factor."},
+    {NULL}  /* Sentinel */
+};
+static PyNumberMethods RosslerAlt_as_number = {
+    (binaryfunc)RosslerAlt_add,                         /*nb_add*/
+    (binaryfunc)RosslerAlt_sub,                         /*nb_subtract*/
+    (binaryfunc)RosslerAlt_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)RosslerAlt_inplace_add,                 /*inplace_add*/
+    (binaryfunc)RosslerAlt_inplace_sub,                 /*inplace_subtract*/
+    (binaryfunc)RosslerAlt_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)RosslerAlt_div,                       /*nb_true_divide*/
+    0,                                              /*nb_inplace_floor_divide*/
+    (binaryfunc)RosslerAlt_inplace_div,                       /*nb_inplace_true_divide*/
+    0,                                              /* nb_index */
+};
+
+PyTypeObject RosslerAltType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.RosslerAlt_base",         /*tp_name*/
+    sizeof(RosslerAlt),         /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)RosslerAlt_dealloc, /*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
+    0,                         /*tp_repr*/
+    &RosslerAlt_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*/
+    "RosslerAlt objects. Sends the alternate signal of a Rossler attractor.",           /* tp_doc */
+    (traverseproc)RosslerAlt_traverse,   /* tp_traverse */
+    (inquiry)RosslerAlt_clear,           /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    RosslerAlt_methods,             /* tp_methods */
+    RosslerAlt_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 */
+    RosslerAlt_new,                 /* tp_new */
+};
+
+/* Lorenz object */
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *pitch;
+    Stream *pitch_stream;
+    PyObject *chaos;
+    Stream *chaos_stream;
+    MYFLT *altBuffer;
+    MYFLT vDX;
+    MYFLT vDY;
+    MYFLT vDZ;
+    MYFLT vX;
+    MYFLT vY;
+    MYFLT vZ;
+    MYFLT pA;
+    MYFLT pB;
+    MYFLT oneOnSr;
+    int modebuffer[4];
+} Lorenz;
+
+static void
+Lorenz_readframes_ii(Lorenz *self) {
+    MYFLT delta, pit, chao;
+    int i;
+
+    pit = PyFloat_AS_DOUBLE(self->pitch);
+    chao = PyFloat_AS_DOUBLE(self->chaos);
+    if (pit < 0.0)
+        pit = 1.0;
+    else if (pit > 1.0)
+        pit = 750.0;
+    else
+        pit = pit * 749.0 + 1.0;
+    delta = self->oneOnSr * pit;
+
+    if (chao < 0.0)
+        chao = 0.5;
+    else if (chao > 1.0)
+        chao = 3.0;
+    else
+        chao = chao * 2.5 + 0.5;
+
+    for (i=0; i<self->bufsize; i++) {
+        self->vDX = self->pA * (self->vY - self->vX);
+        self->vDY = self->vX * (self->pB - self->vZ) - self->vY;
+        self->vDZ = self->vX * self->vY - chao * self->vZ;
+
+        self->vX += self->vDX * delta;
+        self->vY += self->vDY * delta;
+        self->vZ += self->vDZ * delta;
+
+        self->data[i] = self->vX * LORENZ_SCALE;
+        self->altBuffer[i] = self->vY * LORENZ_ALT_SCALE;
+    }
+}
+
+static void
+Lorenz_readframes_ai(Lorenz *self) {
+    MYFLT delta, pit, chao;
+    int i;
+
+    MYFLT *fr = Stream_getData((Stream *)self->pitch_stream);
+    chao = PyFloat_AS_DOUBLE(self->chaos);
+    if (chao < 0.0)
+        chao = 0.5;
+    else if (chao > 1.0)
+        chao = 3.0;
+    else
+        chao = chao * 2.5 + 0.5;
+
+    for (i=0; i<self->bufsize; i++) {
+        pit = fr[i];
+        if (pit < 0.0)
+            pit = 1.0;
+        else if (pit > 1.0)
+            pit = 750.0;
+        else
+            pit = pit * 749.0 + 1.0;
+        delta = self->oneOnSr * pit;
+        self->vDX = self->pA * (self->vY - self->vX);
+        self->vDY = self->vX * (self->pB - self->vZ) - self->vY;
+        self->vDZ = self->vX * self->vY - chao * self->vZ;
+
+        self->vX += self->vDX * delta;
+        self->vY += self->vDY * delta;
+        self->vZ += self->vDZ * delta;
+
+        self->data[i] = self->vX * LORENZ_SCALE;
+        self->altBuffer[i] = self->vY * LORENZ_ALT_SCALE;
+    }
+}
+
+static void
+Lorenz_readframes_ia(Lorenz *self) {
+    MYFLT delta, pit, chao;
+    int i;
+
+    pit = PyFloat_AS_DOUBLE(self->pitch);
+    MYFLT *ch = Stream_getData((Stream *)self->chaos_stream);
+
+    if (pit < 0.0)
+        pit = 1.0;
+    else if (pit > 1.0)
+        pit = 750.0;
+    else
+        pit = pit * 749.0 + 1.0;
+    delta = self->oneOnSr * pit;
+
+    for (i=0; i<self->bufsize; i++) {
+        chao = ch[i];
+        if (chao < 0.0)
+            chao = 0.5;
+        else if (chao > 1.0)
+            chao = 3.0;
+        else
+            chao = chao * 2.5 + 0.5;
+        self->vDX = self->pA * (self->vY - self->vX);
+        self->vDY = self->vX * (self->pB - self->vZ) - self->vY;
+        self->vDZ = self->vX * self->vY - chao * self->vZ;
+
+        self->vX += self->vDX * delta;
+        self->vY += self->vDY * delta;
+        self->vZ += self->vDZ * delta;
+
+        self->data[i] = self->vX * LORENZ_SCALE;
+        self->altBuffer[i] = self->vY * LORENZ_ALT_SCALE;
+    }
+}
+
+static void
+Lorenz_readframes_aa(Lorenz *self) {
+    MYFLT delta, pit, chao;
+    int i;
+
+    MYFLT *fr = Stream_getData((Stream *)self->pitch_stream);
+    MYFLT *ch = Stream_getData((Stream *)self->chaos_stream);
+
+    for (i=0; i<self->bufsize; i++) {
+        pit = fr[i];
+        if (pit < 0.0)
+            pit = 1.0;
+        else if (pit > 1.0)
+            pit = 750.0;
+        else
+            pit = pit * 749.0 + 1.0;
+        delta = self->oneOnSr * pit;
+
+        chao = ch[i];
+        if (chao < 0.0)
+            chao = 0.5;
+        else if (chao > 1.0)
+            chao = 3.0;
+        else
+            chao = chao * 2.5 + 0.5;
+        self->vDX = self->pA * (self->vY - self->vX);
+        self->vDY = self->vX * (self->pB - self->vZ) - self->vY;
+        self->vDZ = self->vX * self->vY - chao * self->vZ;
 
-    for (i=0; i<self->bufsize; i++) {
-        car_amp = car[i] * ind1[i];
-        mod_freq = car[i] * rat[i];
-        mod_amp = mod_freq * ind2[i];
-        mod_delta = (mod_freq + self->car_val * car_amp) * self->scaleFactor;
-        self->pointerPos_mod = Sine_clip(self->pointerPos_mod);
-        ipart = (int)self->pointerPos_mod;
-        fpart = self->pointerPos_mod - ipart;
-        mod_val = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
-        self->pointerPos_mod += mod_delta;
-        
-        car_freq = car[i] + (mod_val * mod_amp);
-        car_delta = car_freq * self->scaleFactor;
-        self->pointerPos_car = Sine_clip(self->pointerPos_car);
-        ipart = (int)self->pointerPos_car;
-        fpart = self->pointerPos_car - ipart;
-        self->car_val = SINE_ARRAY[ipart] * (1.0 - fpart) + SINE_ARRAY[ipart+1] * fpart;
-        self->pointerPos_car += car_delta;
-        self->data[i] = (self->car_val + mod_val) * 0.5;
+        self->vX += self->vDX * delta;
+        self->vY += self->vDY * delta;
+        self->vZ += self->vDZ * delta;
+
+        self->data[i] = self->vX * LORENZ_SCALE;
+        self->altBuffer[i] = self->vY * LORENZ_ALT_SCALE;
     }
 }
 
-static void CrossFm_postprocessing_ii(CrossFm *self) { POST_PROCESSING_II };
-static void CrossFm_postprocessing_ai(CrossFm *self) { POST_PROCESSING_AI };
-static void CrossFm_postprocessing_ia(CrossFm *self) { POST_PROCESSING_IA };
-static void CrossFm_postprocessing_aa(CrossFm *self) { POST_PROCESSING_AA };
-static void CrossFm_postprocessing_ireva(CrossFm *self) { POST_PROCESSING_IREVA };
-static void CrossFm_postprocessing_areva(CrossFm *self) { POST_PROCESSING_AREVA };
-static void CrossFm_postprocessing_revai(CrossFm *self) { POST_PROCESSING_REVAI };
-static void CrossFm_postprocessing_revaa(CrossFm *self) { POST_PROCESSING_REVAA };
-static void CrossFm_postprocessing_revareva(CrossFm *self) { POST_PROCESSING_REVAREVA };
+static void Lorenz_postprocessing_ii(Lorenz *self) { POST_PROCESSING_II };
+static void Lorenz_postprocessing_ai(Lorenz *self) { POST_PROCESSING_AI };
+static void Lorenz_postprocessing_ia(Lorenz *self) { POST_PROCESSING_IA };
+static void Lorenz_postprocessing_aa(Lorenz *self) { POST_PROCESSING_AA };
+static void Lorenz_postprocessing_ireva(Lorenz *self) { POST_PROCESSING_IREVA };
+static void Lorenz_postprocessing_areva(Lorenz *self) { POST_PROCESSING_AREVA };
+static void Lorenz_postprocessing_revai(Lorenz *self) { POST_PROCESSING_REVAI };
+static void Lorenz_postprocessing_revaa(Lorenz *self) { POST_PROCESSING_REVAA };
+static void Lorenz_postprocessing_revareva(Lorenz *self) { POST_PROCESSING_REVAREVA };
 
 static void
-CrossFm_setProcMode(CrossFm *self)
+Lorenz_setProcMode(Lorenz *self)
 {
-    int muladdmode;
+    int procmode, muladdmode;
+    procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
-    self->proc_func_ptr = CrossFm_readframes;
-    
+	switch (procmode) {
+        case 0:
+            self->proc_func_ptr = Lorenz_readframes_ii;
+            break;
+        case 1:
+            self->proc_func_ptr = Lorenz_readframes_ai;
+            break;
+        case 10:
+            self->proc_func_ptr = Lorenz_readframes_ia;
+            break;
+        case 11:
+            self->proc_func_ptr = Lorenz_readframes_aa;
+            break;
+    }
+
 	switch (muladdmode) {
-        case 0:        
-            self->muladd_func_ptr = CrossFm_postprocessing_ii;
+        case 0:
+            self->muladd_func_ptr = Lorenz_postprocessing_ii;
             break;
-        case 1:    
-            self->muladd_func_ptr = CrossFm_postprocessing_ai;
+        case 1:
+            self->muladd_func_ptr = Lorenz_postprocessing_ai;
             break;
-        case 2:    
-            self->muladd_func_ptr = CrossFm_postprocessing_revai;
+        case 2:
+            self->muladd_func_ptr = Lorenz_postprocessing_revai;
             break;
-        case 10:        
-            self->muladd_func_ptr = CrossFm_postprocessing_ia;
+        case 10:
+            self->muladd_func_ptr = Lorenz_postprocessing_ia;
             break;
-        case 11:    
-            self->muladd_func_ptr = CrossFm_postprocessing_aa;
+        case 11:
+            self->muladd_func_ptr = Lorenz_postprocessing_aa;
             break;
-        case 12:    
-            self->muladd_func_ptr = CrossFm_postprocessing_revaa;
+        case 12:
+            self->muladd_func_ptr = Lorenz_postprocessing_revaa;
             break;
-        case 20:        
-            self->muladd_func_ptr = CrossFm_postprocessing_ireva;
+        case 20:
+            self->muladd_func_ptr = Lorenz_postprocessing_ireva;
             break;
-        case 21:    
-            self->muladd_func_ptr = CrossFm_postprocessing_areva;
+        case 21:
+            self->muladd_func_ptr = Lorenz_postprocessing_areva;
             break;
-        case 22:    
-            self->muladd_func_ptr = CrossFm_postprocessing_revareva;
+        case 22:
+            self->muladd_func_ptr = Lorenz_postprocessing_revareva;
             break;
     }
 }
 
 static void
-CrossFm_compute_next_data_frame(CrossFm *self)
+Lorenz_compute_next_data_frame(Lorenz *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
 static int
-CrossFm_traverse(CrossFm *self, visitproc visit, void *arg)
+Lorenz_traverse(Lorenz *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->car);    
-    Py_VISIT(self->car_stream);    
-    Py_VISIT(self->ratio);    
-    Py_VISIT(self->ratio_stream);    
-    Py_VISIT(self->ind1);    
-    Py_VISIT(self->ind1_stream);    
-    Py_VISIT(self->ind2);    
-    Py_VISIT(self->ind2_stream);    
+    Py_VISIT(self->pitch);
+    Py_VISIT(self->pitch_stream);
+    Py_VISIT(self->chaos);
+    Py_VISIT(self->chaos_stream);
     return 0;
 }
 
-static int 
-CrossFm_clear(CrossFm *self)
+static int
+Lorenz_clear(Lorenz *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->car);    
-    Py_CLEAR(self->car_stream);    
-    Py_CLEAR(self->ratio);    
-    Py_CLEAR(self->ratio_stream);    
-    Py_CLEAR(self->ind1);    
-    Py_CLEAR(self->ind1_stream);    
-    Py_CLEAR(self->ind2);    
-    Py_CLEAR(self->ind2_stream);    
+    Py_CLEAR(self->pitch);
+    Py_CLEAR(self->pitch_stream);
+    Py_CLEAR(self->chaos);
+    Py_CLEAR(self->chaos_stream);
     return 0;
 }
 
 static void
-CrossFm_dealloc(CrossFm* self)
+Lorenz_dealloc(Lorenz* self)
 {
     pyo_DEALLOC
-    CrossFm_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    free(self->altBuffer);
+    Lorenz_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
-CrossFm_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+Lorenz_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
-    PyObject *cartmp=NULL, *ratiotmp=NULL, *ind1tmp=NULL, *ind2tmp=NULL, *multmp=NULL, *addtmp=NULL;
-    CrossFm *self;
-    self = (CrossFm *)type->tp_alloc(type, 0);
-    
-    self->car = PyFloat_FromDouble(100);
-    self->ratio = PyFloat_FromDouble(0.5);
-    self->ind1 = PyFloat_FromDouble(2);
-    self->ind2 = PyFloat_FromDouble(2);
+    PyObject *pitchtmp=NULL, *chaostmp=NULL, *multmp=NULL, *addtmp=NULL;
+    Lorenz *self;
+    self = (Lorenz *)type->tp_alloc(type, 0);
+
+    self->pitch = PyFloat_FromDouble(0.25);
+    self->chaos = PyFloat_FromDouble(0.5);
+    self->pA = 10.0;
+    self->pB = 28.0;
+    self->vDX = self->vDY = self->vDZ = 0.0;
+    self->vX = self->vY = self->vZ = 1.0;
 	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->pointerPos_car = self->pointerPos_mod = 0.;
-    self->car_val = 0.;
-    
+
     INIT_OBJECT_COMMON
-    Stream_setFunctionPtr(self->stream, CrossFm_compute_next_data_frame);
-    self->mode_func_ptr = CrossFm_setProcMode;
-    
-    self->scaleFactor = 512.0 / self->sr;
+    Stream_setFunctionPtr(self->stream, Lorenz_compute_next_data_frame);
+    self->mode_func_ptr = Lorenz_setProcMode;
 
-    static char *kwlist[] = {"carrier", "ratio", "ind1", "ind2", "mul", "add", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOOO", kwlist, &cartmp, &ratiotmp, &ind1tmp, &ind2tmp, &multmp, &addtmp))
+    self->oneOnSr = 1.0 / self->sr;
+
+    static char *kwlist[] = {"pitch", "chaos", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &pitchtmp, &chaostmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
-    if (cartmp) {
-        PyObject_CallMethod((PyObject *)self, "setCarrier", "O", cartmp);
-    }
-    
-    if (ratiotmp) {
-        PyObject_CallMethod((PyObject *)self, "setRatio", "O", ratiotmp);
-    }
-    
-    if (ind1tmp) {
-        PyObject_CallMethod((PyObject *)self, "setInd1", "O", ind1tmp);
+
+    if (pitchtmp) {
+        PyObject_CallMethod((PyObject *)self, "setPitch", "O", pitchtmp);
     }
 
-    if (ind2tmp) {
-        PyObject_CallMethod((PyObject *)self, "setInd2", "O", ind2tmp);
+    if (chaostmp) {
+        PyObject_CallMethod((PyObject *)self, "setChaos", "O", chaostmp);
     }
-    
+
     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->altBuffer = (MYFLT *)realloc(self->altBuffer, self->bufsize * sizeof(MYFLT));
+
+    for (i=0; i<self->bufsize; i++) {
+        self->altBuffer[i] = 0.0;
+    }
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
-static PyObject * CrossFm_getServer(CrossFm* self) { GET_SERVER };
-static PyObject * CrossFm_getStream(CrossFm* self) { GET_STREAM };
-static PyObject * CrossFm_setMul(CrossFm *self, PyObject *arg) { SET_MUL };	
-static PyObject * CrossFm_setAdd(CrossFm *self, PyObject *arg) { SET_ADD };	
-static PyObject * CrossFm_setSub(CrossFm *self, PyObject *arg) { SET_SUB };	
-static PyObject * CrossFm_setDiv(CrossFm *self, PyObject *arg) { SET_DIV };	
+static PyObject * Lorenz_getServer(Lorenz* self) { GET_SERVER };
+static PyObject * Lorenz_getStream(Lorenz* self) { GET_STREAM };
+static PyObject * Lorenz_setMul(Lorenz *self, PyObject *arg) { SET_MUL };
+static PyObject * Lorenz_setAdd(Lorenz *self, PyObject *arg) { SET_ADD };
+static PyObject * Lorenz_setSub(Lorenz *self, PyObject *arg) { SET_SUB };
+static PyObject * Lorenz_setDiv(Lorenz *self, PyObject *arg) { SET_DIV };
 
-static PyObject * CrossFm_play(CrossFm *self, PyObject *args, PyObject *kwds) { PLAY };
-static PyObject * CrossFm_out(CrossFm *self, PyObject *args, PyObject *kwds) { OUT };
-static PyObject * CrossFm_stop(CrossFm *self) { STOP };
+static PyObject * Lorenz_play(Lorenz *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * Lorenz_out(Lorenz *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * Lorenz_stop(Lorenz *self) { STOP };
 
-static PyObject * CrossFm_multiply(CrossFm *self, PyObject *arg) { MULTIPLY };
-static PyObject * CrossFm_inplace_multiply(CrossFm *self, PyObject *arg) { INPLACE_MULTIPLY };
-static PyObject * CrossFm_add(CrossFm *self, PyObject *arg) { ADD };
-static PyObject * CrossFm_inplace_add(CrossFm *self, PyObject *arg) { INPLACE_ADD };
-static PyObject * CrossFm_sub(CrossFm *self, PyObject *arg) { SUB };
-static PyObject * CrossFm_inplace_sub(CrossFm *self, PyObject *arg) { INPLACE_SUB };
-static PyObject * CrossFm_div(CrossFm *self, PyObject *arg) { DIV };
-static PyObject * CrossFm_inplace_div(CrossFm *self, PyObject *arg) { INPLACE_DIV };
+static PyObject * Lorenz_multiply(Lorenz *self, PyObject *arg) { MULTIPLY };
+static PyObject * Lorenz_inplace_multiply(Lorenz *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * Lorenz_add(Lorenz *self, PyObject *arg) { ADD };
+static PyObject * Lorenz_inplace_add(Lorenz *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * Lorenz_sub(Lorenz *self, PyObject *arg) { SUB };
+static PyObject * Lorenz_inplace_sub(Lorenz *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * Lorenz_div(Lorenz *self, PyObject *arg) { DIV };
+static PyObject * Lorenz_inplace_div(Lorenz *self, PyObject *arg) { INPLACE_DIV };
 
 static PyObject *
-CrossFm_setCarrier(CrossFm *self, PyObject *arg)
+Lorenz_setPitch(Lorenz *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	int isNumber = PyNumber_Check(arg);
-	
-	tmp = arg;
-	Py_INCREF(tmp);
-	Py_DECREF(self->car);
-	if (isNumber == 1) {
-		self->car = PyNumber_Float(tmp);
-        self->modebuffer[2] = 0;
-	}
-	else {
-		self->car = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->car, "_getStream", NULL);
-        Py_INCREF(streamtmp);
-        Py_XDECREF(self->car_stream);
-        self->car_stream = (Stream *)streamtmp;
-		self->modebuffer[2] = 1;
-	}
-    
-    (*self->mode_func_ptr)(self);
-    
-	Py_INCREF(Py_None);
-	return Py_None;
-}	
 
-static PyObject *
-CrossFm_setRatio(CrossFm *self, PyObject *arg)
-{
-	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	int isNumber = PyNumber_Check(arg);
-	
-	tmp = arg;
-	Py_INCREF(tmp);
-	Py_DECREF(self->ratio);
-	if (isNumber == 1) {
-		self->ratio = PyNumber_Float(tmp);
-        self->modebuffer[3] = 0;
-	}
-	else {
-		self->ratio = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->ratio, "_getStream", NULL);
-        Py_INCREF(streamtmp);
-        Py_XDECREF(self->ratio_stream);
-        self->ratio_stream = (Stream *)streamtmp;
-		self->modebuffer[3] = 1;
-	}
-    
-    (*self->mode_func_ptr)(self);
-    
-	Py_INCREF(Py_None);
-	return Py_None;
-}	
+    ASSERT_ARG_NOT_NULL
 
-static PyObject *
-CrossFm_setInd1(CrossFm *self, PyObject *arg)
-{
-	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
-	Py_DECREF(self->ind1);
+	Py_DECREF(self->pitch);
 	if (isNumber == 1) {
-		self->ind1 = PyNumber_Float(tmp);
-        self->modebuffer[4] = 0;
+		self->pitch = PyNumber_Float(tmp);
+        self->modebuffer[2] = 0;
 	}
 	else {
-		self->ind1 = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->ind1, "_getStream", NULL);
+		self->pitch = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->pitch, "_getStream", NULL);
         Py_INCREF(streamtmp);
-        Py_XDECREF(self->ind1_stream);
-        self->ind1_stream = (Stream *)streamtmp;
-		self->modebuffer[4] = 1;
+        Py_XDECREF(self->pitch_stream);
+        self->pitch_stream = (Stream *)streamtmp;
+		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
-CrossFm_setInd2(CrossFm *self, PyObject *arg)
+Lorenz_setChaos(Lorenz *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
-	Py_DECREF(self->ind2);
+	Py_DECREF(self->chaos);
 	if (isNumber == 1) {
-		self->ind2 = PyNumber_Float(tmp);
-        self->modebuffer[5] = 0;
+		self->chaos = PyNumber_Float(tmp);
+        self->modebuffer[3] = 0;
 	}
 	else {
-		self->ind2 = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->ind2, "_getStream", NULL);
+		self->chaos = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->chaos, "_getStream", NULL);
         Py_INCREF(streamtmp);
-        Py_XDECREF(self->ind2_stream);
-        self->ind2_stream = (Stream *)streamtmp;
-		self->modebuffer[5] = 1;
+        Py_XDECREF(self->chaos_stream);
+        self->chaos_stream = (Stream *)streamtmp;
+		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
-static PyMemberDef CrossFm_members[] = {
-    {"server", T_OBJECT_EX, offsetof(CrossFm, server), 0, "Pyo server."},
-    {"stream", T_OBJECT_EX, offsetof(CrossFm, stream), 0, "Stream object."},
-    {"carrier", T_OBJECT_EX, offsetof(CrossFm, car), 0, "Frequency in cycle per second."},
-    {"ratio", T_OBJECT_EX, offsetof(CrossFm, ratio), 0, "Ratio carrier:modulator (mod freq = car*mod)."},
-    {"ind1", T_OBJECT_EX, offsetof(CrossFm, ind1), 0, "Modulation ind1 (car amp = car freq*ind1)."},
-    {"ind2", T_OBJECT_EX, offsetof(CrossFm, ind2), 0, "Modulation ind2 (mod amp = mod freq*ind2)."},
-    {"mul", T_OBJECT_EX, offsetof(CrossFm, mul), 0, "Mul factor."},
-    {"add", T_OBJECT_EX, offsetof(CrossFm, add), 0, "Add factor."},
+MYFLT *
+Lorenz_getAltBuffer(Lorenz *self)
+{
+    return (MYFLT *)self->altBuffer;
+}
+
+static PyMemberDef Lorenz_members[] = {
+    {"server", T_OBJECT_EX, offsetof(Lorenz, server), 0, "Pyo server."},
+    {"stream", T_OBJECT_EX, offsetof(Lorenz, stream), 0, "Stream object."},
+    {"pitch", T_OBJECT_EX, offsetof(Lorenz, pitch), 0, "Pitch."},
+    {"chaos", T_OBJECT_EX, offsetof(Lorenz, chaos), 0, "Chaotic behavior."},
+    {"mul", T_OBJECT_EX, offsetof(Lorenz, mul), 0, "Mul factor."},
+    {"add", T_OBJECT_EX, offsetof(Lorenz, add), 0, "Add factor."},
     {NULL}  /* Sentinel */
 };
 
-static PyMethodDef CrossFm_methods[] = {
-    {"getServer", (PyCFunction)CrossFm_getServer, METH_NOARGS, "Returns server object."},
-    {"_getStream", (PyCFunction)CrossFm_getStream, METH_NOARGS, "Returns stream object."},
-    {"play", (PyCFunction)CrossFm_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
-    {"out", (PyCFunction)CrossFm_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
-    {"stop", (PyCFunction)CrossFm_stop, METH_NOARGS, "Stops computing."},
-    {"setCarrier", (PyCFunction)CrossFm_setCarrier, METH_O, "Sets carrier frequency in cycle per second."},
-    {"setRatio", (PyCFunction)CrossFm_setRatio, METH_O, "Sets car:mod ratio."},
-    {"setInd1", (PyCFunction)CrossFm_setInd1, METH_O, "Sets carrier index."},
-    {"setInd2", (PyCFunction)CrossFm_setInd2, METH_O, "Sets modulation index."},
-    {"setMul", (PyCFunction)CrossFm_setMul, METH_O, "Sets CrossFm mul factor."},
-    {"setAdd", (PyCFunction)CrossFm_setAdd, METH_O, "Sets CrossFm add factor."},
-    {"setSub", (PyCFunction)CrossFm_setSub, METH_O, "Sets inverse add factor."},
-    {"setDiv", (PyCFunction)CrossFm_setDiv, METH_O, "Sets inverse mul factor."},
+static PyMethodDef Lorenz_methods[] = {
+    {"getServer", (PyCFunction)Lorenz_getServer, METH_NOARGS, "Returns server object."},
+    {"_getStream", (PyCFunction)Lorenz_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)Lorenz_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+    {"out", (PyCFunction)Lorenz_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+    {"stop", (PyCFunction)Lorenz_stop, METH_NOARGS, "Stops computing."},
+    {"setPitch", (PyCFunction)Lorenz_setPitch, METH_O, "Sets oscillator pitch."},
+    {"setChaos", (PyCFunction)Lorenz_setChaos, METH_O, "Sets oscillator chaotic behavior."},
+    {"setMul", (PyCFunction)Lorenz_setMul, METH_O, "Sets Lorenz mul factor."},
+    {"setAdd", (PyCFunction)Lorenz_setAdd, METH_O, "Sets Lorenz add factor."},
+    {"setSub", (PyCFunction)Lorenz_setSub, METH_O, "Sets inverse add factor."},
+    {"setDiv", (PyCFunction)Lorenz_setDiv, METH_O, "Sets inverse mul factor."},
     {NULL}  /* Sentinel */
 };
 
-static PyNumberMethods CrossFm_as_number = {
-    (binaryfunc)CrossFm_add,                      /*nb_add*/
-    (binaryfunc)CrossFm_sub,                 /*nb_subtract*/
-    (binaryfunc)CrossFm_multiply,                 /*nb_multiply*/
-    (binaryfunc)CrossFm_div,                   /*nb_divide*/
+static PyNumberMethods Lorenz_as_number = {
+    (binaryfunc)Lorenz_add,                      /*nb_add*/
+    (binaryfunc)Lorenz_sub,                 /*nb_subtract*/
+    (binaryfunc)Lorenz_multiply,                 /*nb_multiply*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -6632,513 +9205,292 @@ static PyNumberMethods CrossFm_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
-    0,                      /*nb_long*/
-    0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
-    (binaryfunc)CrossFm_inplace_add,              /*inplace_add*/
-    (binaryfunc)CrossFm_inplace_sub,         /*inplace_subtract*/
-    (binaryfunc)CrossFm_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)CrossFm_inplace_div,           /*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*/
-    0,              /*nb_true_divide*/
-    0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
-    0,                     /* nb_ind1 */
-};
-
-PyTypeObject CrossFmType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
-    "_pyo.CrossFm_base",         /*tp_name*/
-    sizeof(CrossFm),         /*tp_basicsize*/
-    0,                         /*tp_itemsize*/
-    (destructor)CrossFm_dealloc, /*tp_dealloc*/
-    0,                         /*tp_print*/
-    0,                         /*tp_getattr*/
-    0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
-    0,                         /*tp_repr*/
-    &CrossFm_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*/
-    "CrossFm objects. Generates a cross frequency modulation synthesis.",           /* tp_doc */
-    (traverseproc)CrossFm_traverse,   /* tp_traverse */
-    (inquiry)CrossFm_clear,           /* tp_clear */
-    0,		               /* tp_richcompare */
-    0,		               /* tp_weaklistoffset */
-    0,		               /* tp_iter */
-    0,		               /* tp_iternext */
-    CrossFm_methods,             /* tp_methods */
-    CrossFm_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 */
-    CrossFm_new,                 /* tp_new */
-};
-
-/*************/
-/* Blit object */
-/*************/
-typedef struct {
-    pyo_audio_HEAD
-    PyObject *freq;
-    Stream *freq_stream;
-    PyObject *harms;
-    Stream *harms_stream;
-    int modebuffer[4];
-    MYFLT phase;
-    
-} Blit;
-
-static void
-Blit_readframes_ii(Blit *self) {
-    MYFLT p, m, rate, val;
-    int i, nHarms;
-    
-    MYFLT freq = PyFloat_AS_DOUBLE(self->freq);
-    MYFLT hrms = PyFloat_AS_DOUBLE(self->harms);
-
-    nHarms = (int)hrms;
-    m = 2.0 * nHarms + 1.0;
-    p = self->sr / freq;
-    rate = PI / p;
-
-    for (i=0; i<self->bufsize; i++) {
-        if (self->phase <= 0.0)
-            val = 1.0;
-        else {
-            val = MYSIN(m * self->phase);
-            val /= m * MYSIN(self->phase);
-        }
-        self->phase += rate;
-        if (self->phase >= PI)
-            self->phase -= PI;
-
-        self->data[i] = val;
-    }
-}
-
-static void
-Blit_readframes_ai(Blit *self) {
-    MYFLT p, m, rate, val;
-    int i, nHarms;
-    
-    MYFLT *freq = Stream_getData((Stream *)self->freq_stream);
-    MYFLT hrms = PyFloat_AS_DOUBLE(self->harms);
-
-    nHarms = (int)hrms;
-    m = 2.0 * nHarms + 1.0;
-    
-    for (i=0; i<self->bufsize; i++) {
-        p = self->sr / freq[i];
-        rate = PI / p;
-        if (self->phase <= 0.0)
-            val = 1.0;
-        else {
-            val = MYSIN(m * self->phase);
-            val /= m * MYSIN(self->phase);
-        }
-        self->phase += rate;
-        if (self->phase >= PI)
-            self->phase -= PI;
-        
-        self->data[i] = val;
-    }
-}
-
-static void
-Blit_readframes_ia(Blit *self) {
-    MYFLT p, m, rate, val;
-    int i, nHarms;
-    
-    MYFLT freq = PyFloat_AS_DOUBLE(self->freq);
-    MYFLT *hrms = Stream_getData((Stream *)self->harms_stream);
-
-    p = self->sr / freq;
-    rate = PI / p;
-    
-    for (i=0; i<self->bufsize; i++) {
-        nHarms = (int)hrms[i];
-        m = 2.0 * nHarms + 1.0;
-        if (self->phase <= 0.0)
-            val = 1.0;
-        else {
-            val = MYSIN(m * self->phase);
-            val /= m * MYSIN(self->phase);
-        }
-        self->phase += rate;
-        if (self->phase >= PI)
-            self->phase -= PI;
-        
-        self->data[i] = val;
-    }
-}
+    0,                      /*nb_long*/
+    0,                     /*nb_float*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
+    (binaryfunc)Lorenz_inplace_add,              /*inplace_add*/
+    (binaryfunc)Lorenz_inplace_sub,         /*inplace_subtract*/
+    (binaryfunc)Lorenz_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)Lorenz_div,                       /*nb_true_divide*/
+    0,     /*nb_inplace_floor_divide*/
+    (binaryfunc)Lorenz_inplace_div,                       /*nb_inplace_true_divide*/
+    0,                     /* nb_index */
+};
 
-static void
-Blit_readframes_aa(Blit *self) {
-    MYFLT p, m, rate, val;
-    int i, nHarms;
-    
-    MYFLT *freq = Stream_getData((Stream *)self->freq_stream);
-    MYFLT *hrms = Stream_getData((Stream *)self->harms_stream);
-    
-    for (i=0; i<self->bufsize; i++) {
-        nHarms = (int)hrms[i];
-        m = 2.0 * nHarms + 1.0;
-        p = self->sr / freq[i];
-        rate = PI / p;
-        if (self->phase <= 0.0)
-            val = 1.0;
-        else {
-            val = MYSIN(m * self->phase);
-            val /= m * MYSIN(self->phase);
-        }
-        self->phase += rate;
-        if (self->phase >= PI)
-            self->phase -= PI;
-        
-        self->data[i] = val;
-    }
-}
+PyTypeObject LorenzType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.Lorenz_base",         /*tp_name*/
+    sizeof(Lorenz),         /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)Lorenz_dealloc, /*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
+    0,                         /*tp_repr*/
+    &Lorenz_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*/
+    "Lorenz objects. Lorenz attractor.",           /* tp_doc */
+    (traverseproc)Lorenz_traverse,   /* tp_traverse */
+    (inquiry)Lorenz_clear,           /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    Lorenz_methods,             /* tp_methods */
+    Lorenz_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 */
+    Lorenz_new,                 /* tp_new */
+};
 
-static void Blit_postprocessing_ii(Blit *self) { POST_PROCESSING_II };
-static void Blit_postprocessing_ai(Blit *self) { POST_PROCESSING_AI };
-static void Blit_postprocessing_ia(Blit *self) { POST_PROCESSING_IA };
-static void Blit_postprocessing_aa(Blit *self) { POST_PROCESSING_AA };
-static void Blit_postprocessing_ireva(Blit *self) { POST_PROCESSING_IREVA };
-static void Blit_postprocessing_areva(Blit *self) { POST_PROCESSING_AREVA };
-static void Blit_postprocessing_revai(Blit *self) { POST_PROCESSING_REVAI };
-static void Blit_postprocessing_revaa(Blit *self) { POST_PROCESSING_REVAA };
-static void Blit_postprocessing_revareva(Blit *self) { POST_PROCESSING_REVAREVA };
+typedef struct {
+    pyo_audio_HEAD
+    Lorenz *mainLorenz;
+    int modebuffer[2];
+} LorenzAlt;
+
+static void LorenzAlt_postprocessing_ii(LorenzAlt *self) { POST_PROCESSING_II };
+static void LorenzAlt_postprocessing_ai(LorenzAlt *self) { POST_PROCESSING_AI };
+static void LorenzAlt_postprocessing_ia(LorenzAlt *self) { POST_PROCESSING_IA };
+static void LorenzAlt_postprocessing_aa(LorenzAlt *self) { POST_PROCESSING_AA };
+static void LorenzAlt_postprocessing_ireva(LorenzAlt *self) { POST_PROCESSING_IREVA };
+static void LorenzAlt_postprocessing_areva(LorenzAlt *self) { POST_PROCESSING_AREVA };
+static void LorenzAlt_postprocessing_revai(LorenzAlt *self) { POST_PROCESSING_REVAI };
+static void LorenzAlt_postprocessing_revaa(LorenzAlt *self) { POST_PROCESSING_REVAA };
+static void LorenzAlt_postprocessing_revareva(LorenzAlt *self) { POST_PROCESSING_REVAREVA };
 
 static void
-Blit_setProcMode(Blit *self)
-{
-    int procmode, muladdmode;
-    procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
+LorenzAlt_setProcMode(LorenzAlt *self) {
+    int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
-	switch (procmode) {
-        case 0:        
-            self->proc_func_ptr = Blit_readframes_ii;
-            break;
-        case 1:    
-            self->proc_func_ptr = Blit_readframes_ai;
-            break;
-        case 10:    
-            self->proc_func_ptr = Blit_readframes_ia;
-            break;
-        case 11:    
-            self->proc_func_ptr = Blit_readframes_aa;
-            break;
-    } 
-    
-	switch (muladdmode) {
-        case 0:        
-            self->muladd_func_ptr = Blit_postprocessing_ii;
+
+    switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = LorenzAlt_postprocessing_ii;
             break;
-        case 1:    
-            self->muladd_func_ptr = Blit_postprocessing_ai;
+        case 1:
+            self->muladd_func_ptr = LorenzAlt_postprocessing_ai;
             break;
-        case 2:    
-            self->muladd_func_ptr = Blit_postprocessing_revai;
+        case 2:
+            self->muladd_func_ptr = LorenzAlt_postprocessing_revai;
             break;
-        case 10:        
-            self->muladd_func_ptr = Blit_postprocessing_ia;
+        case 10:
+            self->muladd_func_ptr = LorenzAlt_postprocessing_ia;
             break;
-        case 11:    
-            self->muladd_func_ptr = Blit_postprocessing_aa;
+        case 11:
+            self->muladd_func_ptr = LorenzAlt_postprocessing_aa;
             break;
-        case 12:    
-            self->muladd_func_ptr = Blit_postprocessing_revaa;
+        case 12:
+            self->muladd_func_ptr = LorenzAlt_postprocessing_revaa;
             break;
-        case 20:        
-            self->muladd_func_ptr = Blit_postprocessing_ireva;
+        case 20:
+            self->muladd_func_ptr = LorenzAlt_postprocessing_ireva;
             break;
-        case 21:    
-            self->muladd_func_ptr = Blit_postprocessing_areva;
+        case 21:
+            self->muladd_func_ptr = LorenzAlt_postprocessing_areva;
             break;
-        case 22:    
-            self->muladd_func_ptr = Blit_postprocessing_revareva;
+        case 22:
+            self->muladd_func_ptr = LorenzAlt_postprocessing_revareva;
             break;
     }
 }
 
 static void
-Blit_compute_next_data_frame(Blit *self)
+LorenzAlt_compute_next_data_frame(LorenzAlt *self)
 {
-    (*self->proc_func_ptr)(self); 
+    int i;
+    MYFLT *tmp;
+    tmp = Lorenz_getAltBuffer((Lorenz *)self->mainLorenz);
+    for (i=0; i<self->bufsize; i++) {
+        self->data[i] = tmp[i];
+    }
     (*self->muladd_func_ptr)(self);
 }
 
 static int
-Blit_traverse(Blit *self, visitproc visit, void *arg)
+LorenzAlt_traverse(LorenzAlt *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
-    Py_VISIT(self->harms);    
-    Py_VISIT(self->harms_stream);    
+    Py_VISIT(self->mainLorenz);
     return 0;
 }
 
-static int 
-Blit_clear(Blit *self)
+static int
+LorenzAlt_clear(LorenzAlt *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
-    Py_CLEAR(self->harms);    
-    Py_CLEAR(self->harms_stream);    
+    Py_CLEAR(self->mainLorenz);
     return 0;
 }
 
 static void
-Blit_dealloc(Blit* self)
+LorenzAlt_dealloc(LorenzAlt* self)
 {
     pyo_DEALLOC
-    Blit_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    LorenzAlt_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
-Blit_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+LorenzAlt_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
-    PyObject *freqtmp=NULL, *harmstmp=NULL, *multmp=NULL, *addtmp=NULL;
-    Blit *self;
-    self = (Blit *)type->tp_alloc(type, 0);
-    
-    self->freq = PyFloat_FromDouble(100);
-    self->harms = PyFloat_FromDouble(40);
-	self->modebuffer[0] = 0;
-	self->modebuffer[1] = 0;
-	self->modebuffer[2] = 0;
-	self->modebuffer[3] = 0;
-    self->phase = 0.0;
-    
+    PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL;
+    LorenzAlt *self;
+    self = (LorenzAlt *)type->tp_alloc(type, 0);
+
+    self->modebuffer[0] = 0;
+    self->modebuffer[1] = 0;
+
     INIT_OBJECT_COMMON
-    Stream_setFunctionPtr(self->stream, Blit_compute_next_data_frame);
-    self->mode_func_ptr = Blit_setProcMode;
+    Stream_setFunctionPtr(self->stream, LorenzAlt_compute_next_data_frame);
+    self->mode_func_ptr = LorenzAlt_setProcMode;
 
-    static char *kwlist[] = {"freq", "harms", "mul", "add", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &freqtmp, &harmstmp, &multmp, &addtmp))
+    static char *kwlist[] = {"mainLorenz", "mul", "alt", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &maintmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
-    if (freqtmp) {
-        PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
-    }
-    
-    if (harmstmp) {
-        PyObject_CallMethod((PyObject *)self, "setHarms", "O", harmstmp);
-    }
+
+    Py_XDECREF(self->mainLorenz);
+    Py_INCREF(maintmp);
+    self->mainLorenz = (Lorenz *)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 * Blit_getServer(Blit* self) { GET_SERVER };
-static PyObject * Blit_getStream(Blit* self) { GET_STREAM };
-static PyObject * Blit_setMul(Blit *self, PyObject *arg) { SET_MUL };	
-static PyObject * Blit_setAdd(Blit *self, PyObject *arg) { SET_ADD };	
-static PyObject * Blit_setSub(Blit *self, PyObject *arg) { SET_SUB };	
-static PyObject * Blit_setDiv(Blit *self, PyObject *arg) { SET_DIV };	
-
-static PyObject * Blit_play(Blit *self, PyObject *args, PyObject *kwds) { PLAY };
-static PyObject * Blit_out(Blit *self, PyObject *args, PyObject *kwds) { OUT };
-static PyObject * Blit_stop(Blit *self) { STOP };
-
-static PyObject * Blit_multiply(Blit *self, PyObject *arg) { MULTIPLY };
-static PyObject * Blit_inplace_multiply(Blit *self, PyObject *arg) { INPLACE_MULTIPLY };
-static PyObject * Blit_add(Blit *self, PyObject *arg) { ADD };
-static PyObject * Blit_inplace_add(Blit *self, PyObject *arg) { INPLACE_ADD };
-static PyObject * Blit_sub(Blit *self, PyObject *arg) { SUB };
-static PyObject * Blit_inplace_sub(Blit *self, PyObject *arg) { INPLACE_SUB };
-static PyObject * Blit_div(Blit *self, PyObject *arg) { DIV };
-static PyObject * Blit_inplace_div(Blit *self, PyObject *arg) { INPLACE_DIV };
-
-static PyObject *
-Blit_setFreq(Blit *self, PyObject *arg)
-{
-	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	int isNumber = PyNumber_Check(arg);
-	
-	tmp = arg;
-	Py_INCREF(tmp);
-	Py_DECREF(self->freq);
-	if (isNumber == 1) {
-		self->freq = PyNumber_Float(tmp);
-        self->modebuffer[2] = 0;
-	}
-	else {
-		self->freq = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL);
-        Py_INCREF(streamtmp);
-        Py_XDECREF(self->freq_stream);
-        self->freq_stream = (Stream *)streamtmp;
-		self->modebuffer[2] = 1;
-	}
-    
-    (*self->mode_func_ptr)(self);
-    
-	Py_INCREF(Py_None);
-	return Py_None;
-}	
+    }
+
+    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
-static PyObject *
-Blit_setHarms(Blit *self, PyObject *arg)
-{
-	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	int isNumber = PyNumber_Check(arg);
-	
-	tmp = arg;
-	Py_INCREF(tmp);
-	Py_DECREF(self->harms);
-	if (isNumber == 1) {
-		self->harms = PyNumber_Float(tmp);
-        self->modebuffer[3] = 0;
-	}
-	else {
-		self->harms = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->harms, "_getStream", NULL);
-        Py_INCREF(streamtmp);
-        Py_XDECREF(self->harms_stream);
-        self->harms_stream = (Stream *)streamtmp;
-		self->modebuffer[3] = 1;
-	}
-    
     (*self->mode_func_ptr)(self);
-    
-	Py_INCREF(Py_None);
-	return Py_None;
-}	
 
-static PyMemberDef Blit_members[] = {
-    {"server", T_OBJECT_EX, offsetof(Blit, server), 0, "Pyo server."},
-    {"stream", T_OBJECT_EX, offsetof(Blit, stream), 0, "Stream object."},
-    {"freq", T_OBJECT_EX, offsetof(Blit, freq), 0, "Frequency in cycle per second."},
-    {"harms", T_OBJECT_EX, offsetof(Blit, harms), 0, "Number of harmonics."},
-    {"mul", T_OBJECT_EX, offsetof(Blit, mul), 0, "Mul factor."},
-    {"add", T_OBJECT_EX, offsetof(Blit, add), 0, "Add factor."},
+    return (PyObject *)self;
+}
+
+static PyObject * LorenzAlt_getServer(LorenzAlt* self) { GET_SERVER };
+static PyObject * LorenzAlt_getStream(LorenzAlt* self) { GET_STREAM };
+static PyObject * LorenzAlt_setMul(LorenzAlt *self, PyObject *arg) { SET_MUL };
+static PyObject * LorenzAlt_setAdd(LorenzAlt *self, PyObject *arg) { SET_ADD };
+static PyObject * LorenzAlt_setSub(LorenzAlt *self, PyObject *arg) { SET_SUB };
+static PyObject * LorenzAlt_setDiv(LorenzAlt *self, PyObject *arg) { SET_DIV };
+
+static PyObject * LorenzAlt_play(LorenzAlt *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * LorenzAlt_out(LorenzAlt *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * LorenzAlt_stop(LorenzAlt *self) { STOP };
+
+static PyObject * LorenzAlt_multiply(LorenzAlt *self, PyObject *arg) { MULTIPLY };
+static PyObject * LorenzAlt_inplace_multiply(LorenzAlt *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * LorenzAlt_add(LorenzAlt *self, PyObject *arg) { ADD };
+static PyObject * LorenzAlt_inplace_add(LorenzAlt *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * LorenzAlt_sub(LorenzAlt *self, PyObject *arg) { SUB };
+static PyObject * LorenzAlt_inplace_sub(LorenzAlt *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * LorenzAlt_div(LorenzAlt *self, PyObject *arg) { DIV };
+static PyObject * LorenzAlt_inplace_div(LorenzAlt *self, PyObject *arg) { INPLACE_DIV };
+
+static PyMemberDef LorenzAlt_members[] = {
+    {"server", T_OBJECT_EX, offsetof(LorenzAlt, server), 0, "Pyo server."},
+    {"stream", T_OBJECT_EX, offsetof(LorenzAlt, stream), 0, "Stream object."},
+    {"mul", T_OBJECT_EX, offsetof(LorenzAlt, mul), 0, "Mul factor."},
+    {"add", T_OBJECT_EX, offsetof(LorenzAlt, add), 0, "Add factor."},
     {NULL}  /* Sentinel */
 };
 
-static PyMethodDef Blit_methods[] = {
-    {"getServer", (PyCFunction)Blit_getServer, METH_NOARGS, "Returns server object."},
-    {"_getStream", (PyCFunction)Blit_getStream, METH_NOARGS, "Returns stream object."},
-    {"play", (PyCFunction)Blit_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundfreqd."},
-    {"out", (PyCFunction)Blit_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundfreqd channel speficied by argument."},
-    {"stop", (PyCFunction)Blit_stop, METH_NOARGS, "Stops computing."},
-    {"setFreq", (PyCFunction)Blit_setFreq, METH_O, "Sets frequency in cycle per second."},
-    {"setHarms", (PyCFunction)Blit_setHarms, METH_O, "Sets the number of harmonics."},
-    {"setMul", (PyCFunction)Blit_setMul, METH_O, "Sets Blit mul factor."},
-    {"setAdd", (PyCFunction)Blit_setAdd, METH_O, "Sets Blit add factor."},
-    {"setSub", (PyCFunction)Blit_setSub, METH_O, "Sets inverse add factor."},
-    {"setDiv", (PyCFunction)Blit_setDiv, METH_O, "Sets inverse mul factor."},
+static PyMethodDef LorenzAlt_methods[] = {
+    {"getServer", (PyCFunction)LorenzAlt_getServer, METH_NOARGS, "Returns server object."},
+    {"_getStream", (PyCFunction)LorenzAlt_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)LorenzAlt_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+    {"out", (PyCFunction)LorenzAlt_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+    {"stop", (PyCFunction)LorenzAlt_stop, METH_NOARGS, "Stops computing."},
+    {"setMul", (PyCFunction)LorenzAlt_setMul, METH_O, "Sets oscillator mul factor."},
+    {"setAdd", (PyCFunction)LorenzAlt_setAdd, METH_O, "Sets oscillator add factor."},
+    {"setSub", (PyCFunction)LorenzAlt_setSub, METH_O, "Sets inverse add factor."},
+    {"setDiv", (PyCFunction)LorenzAlt_setDiv, METH_O, "Sets inverse mul factor."},
     {NULL}  /* Sentinel */
 };
-
-static PyNumberMethods Blit_as_number = {
-    (binaryfunc)Blit_add,                      /*nb_add*/
-    (binaryfunc)Blit_sub,                 /*nb_subtract*/
-    (binaryfunc)Blit_multiply,                 /*nb_multiply*/
-    (binaryfunc)Blit_div,                   /*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*/
-    0,                                          /*nb_coerce*/
-    0,                       /*nb_int*/
-    0,                      /*nb_long*/
-    0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
-    (binaryfunc)Blit_inplace_add,              /*inplace_add*/
-    (binaryfunc)Blit_inplace_sub,         /*inplace_subtract*/
-    (binaryfunc)Blit_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)Blit_inplace_div,           /*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*/
-    0,              /*nb_true_divide*/
-    0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
-    0,                     /* nb_cutoff */
+static PyNumberMethods LorenzAlt_as_number = {
+    (binaryfunc)LorenzAlt_add,                         /*nb_add*/
+    (binaryfunc)LorenzAlt_sub,                         /*nb_subtract*/
+    (binaryfunc)LorenzAlt_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)LorenzAlt_inplace_add,                 /*inplace_add*/
+    (binaryfunc)LorenzAlt_inplace_sub,                 /*inplace_subtract*/
+    (binaryfunc)LorenzAlt_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)LorenzAlt_div,                       /*nb_true_divide*/
+    0,                                              /*nb_inplace_floor_divide*/
+    (binaryfunc)LorenzAlt_inplace_div,                       /*nb_inplace_true_divide*/
+    0,                                              /* nb_index */
 };
 
-PyTypeObject BlitType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
-    "_pyo.Blit_base",         /*tp_name*/
-    sizeof(Blit),         /*tp_basicsize*/
+PyTypeObject LorenzAltType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.LorenzAlt_base",         /*tp_name*/
+    sizeof(LorenzAlt),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
-    (destructor)Blit_dealloc, /*tp_dealloc*/
+    (destructor)LorenzAlt_dealloc, /*tp_dealloc*/
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
-    &Blit_as_number,             /*tp_as_number*/
+    &LorenzAlt_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
     0,                         /*tp_as_mapping*/
     0,                         /*tp_hash */
@@ -7148,15 +9500,15 @@ PyTypeObject BlitType = {
     0,                         /*tp_setattro*/
     0,                         /*tp_as_buffer*/
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES,  /*tp_flags*/
-    "Blit objects. Generates a band limited impulse train.",           /* tp_doc */
-    (traverseproc)Blit_traverse,   /* tp_traverse */
-    (inquiry)Blit_clear,           /* tp_clear */
+    "LorenzAlt objects. Sends the alternate signal of a Lorenz attractor.",           /* tp_doc */
+    (traverseproc)LorenzAlt_traverse,   /* tp_traverse */
+    (inquiry)LorenzAlt_clear,           /* tp_clear */
     0,		               /* tp_richcompare */
     0,		               /* tp_weaklistoffset */
     0,		               /* tp_iter */
     0,		               /* tp_iternext */
-    Blit_methods,             /* tp_methods */
-    Blit_members,             /* tp_members */
+    LorenzAlt_methods,             /* tp_methods */
+    LorenzAlt_members,             /* tp_members */
     0,                      /* tp_getset */
     0,                         /* tp_base */
     0,                         /* tp_dict */
@@ -7165,10 +9517,10 @@ PyTypeObject BlitType = {
     0,                         /* tp_dictoffset */
     0,      /* tp_init */
     0,                         /* tp_alloc */
-    Blit_new,                 /* tp_new */
+    LorenzAlt_new,                 /* tp_new */
 };
 
-/* Rossler object */
+/* ChenLee object */
 typedef struct {
     pyo_audio_HEAD
     PyObject *pitch;
@@ -7184,124 +9536,130 @@ typedef struct {
     MYFLT vZ;
     MYFLT pA;
     MYFLT pB;
-    MYFLT scalePitch;
+    MYFLT oneOnSr;
     int modebuffer[4];
-} Rossler;
+} ChenLee;
 
 static void
-Rossler_readframes_ii(Rossler *self) {
+ChenLee_readframes_ii(ChenLee *self) {
     MYFLT delta, pit, chao;
     int i;
-    
+
     pit = PyFloat_AS_DOUBLE(self->pitch);
     chao = PyFloat_AS_DOUBLE(self->chaos);
     if (pit < 0.0)
         pit = 1.0;
     else if (pit > 1.0)
-        pit = 1000.0;
+        pit = 125.0;
     else
-        pit = pit * 999.0 + 1.0;
-    delta = self->scalePitch * pit;
+        pit = pit * 124.0 + 1.0;
+    delta = self->oneOnSr * pit;
 
     if (chao < 0.0)
-        chao = 3.0;
+        chao = 4.0;
     else if (chao > 1.0)
-        chao = 10.0;
+        chao = 2.51;
     else
-        chao = chao * 7.0 + 3.0;
-    
+        chao = (1.0 - chao) * 1.49 + 2.51;
+
     for (i=0; i<self->bufsize; i++) {
-        self->vDX = -self->vY - self->vZ;
-        self->vDY = self->vX + self->pA * self->vY;
-        self->vDZ = self->pB + self->vZ * (self->vX - chao);
-        
+        self->vDX = -self->vY * self->vZ + self->pA * self->vX;
+        self->vDY = self->vX * self->vZ - self->pB * self->vY;
+        self->vDZ = self->vX * self->vY / 3.0 - chao * self->vZ;
+
         self->vX += self->vDX * delta;
+        self->vX = (self->vX > 50.0) ? 50.0 : (self->vX < -50.0) ? -50.0 : self->vX;
         self->vY += self->vDY * delta;
+        self->vY = (self->vY > 50.0) ? 50.0 : (self->vY < -50.0) ? -50.0 : self->vY;
         self->vZ += self->vDZ * delta;
-        
-        self->data[i] = self->vX * ROSSLER_SCALE;
-        self->altBuffer[i] = self->vY * ROSSLER_ALT_SCALE;
+
+        self->data[i] = self->vX * CHENLEE_SCALE;
+        self->altBuffer[i] = self->vY * CHENLEE_ALT_SCALE;
     }
 }
 
 static void
-Rossler_readframes_ai(Rossler *self) {
+ChenLee_readframes_ai(ChenLee *self) {
     MYFLT delta, pit, chao;
     int i;
-    
+
     MYFLT *fr = Stream_getData((Stream *)self->pitch_stream);
     chao = PyFloat_AS_DOUBLE(self->chaos);
     if (chao < 0.0)
-        chao = 3.0;
+        chao = 4.0;
     else if (chao > 1.0)
-        chao = 10.0;
+        chao = 2.51;
     else
-        chao = chao * 7.0 + 3.0;
-    
+        chao = (1.0 - chao) * 1.49 + 2.51;
+
     for (i=0; i<self->bufsize; i++) {
         pit = fr[i];
         if (pit < 0.0)
             pit = 1.0;
         else if (pit > 1.0)
-            pit = 1000.0;
+            pit = 125.0;
         else
-            pit = pit * 999.0 + 1.0;
-        delta = self->scalePitch * pit;
-        self->vDX = -self->vY - self->vZ;
-        self->vDY = self->vX + self->pA * self->vY;
-        self->vDZ = self->pB + self->vZ * (self->vX - chao);
-        
+            pit = pit * 124.0 + 1.0;
+        delta = self->oneOnSr * pit;
+        self->vDX = -self->vY * self->vZ + self->pA * self->vX;
+        self->vDY = self->vX * self->vZ - self->pB * self->vY;
+        self->vDZ = self->vX * self->vY / 3.0 - chao * self->vZ;
+
         self->vX += self->vDX * delta;
+        self->vX = (self->vX > 50.0) ? 50.0 : (self->vX < -50.0) ? -50.0 : self->vX;
         self->vY += self->vDY * delta;
+        self->vY = (self->vY > 50.0) ? 50.0 : (self->vY < -50.0) ? -50.0 : self->vY;
         self->vZ += self->vDZ * delta;
-        
-        self->data[i] = self->vX * ROSSLER_SCALE;
-        self->altBuffer[i] = self->vY * ROSSLER_ALT_SCALE;
+
+        self->data[i] = self->vX * CHENLEE_SCALE;
+        self->altBuffer[i] = self->vY * CHENLEE_ALT_SCALE;
     }
 }
 
 static void
-Rossler_readframes_ia(Rossler *self) {
+ChenLee_readframes_ia(ChenLee *self) {
     MYFLT delta, pit, chao;
     int i;
-    
+
     pit = PyFloat_AS_DOUBLE(self->pitch);
     MYFLT *ch = Stream_getData((Stream *)self->chaos_stream);
 
     if (pit < 0.0)
         pit = 1.0;
     else if (pit > 1.0)
-        pit = 1000.0;
+        pit = 125.0;
     else
-        pit = pit * 999.0 + 1.0;
-    delta = self->scalePitch * pit;
-    
+        pit = pit * 124.0 + 1.0;
+    delta = self->oneOnSr * pit;
+
     for (i=0; i<self->bufsize; i++) {
         chao = ch[i];
         if (chao < 0.0)
-            chao = 3.0;
+            chao = 4.0;
         else if (chao > 1.0)
-            chao = 10.0;
+            chao = 2.51;
         else
-            chao = chao * 7.0 + 3.0;        
-        self->vDX = -self->vY - self->vZ;
-        self->vDY = self->vX + self->pA * self->vY;
-        self->vDZ = self->pB + self->vZ * (self->vX - chao);
-        
+            chao = (1.0 - chao) * 1.49 + 2.51;
+        self->vDX = -self->vY * self->vZ + self->pA * self->vX;
+        self->vDY = self->vX * self->vZ - self->pB * self->vY;
+        self->vDZ = self->vX * self->vY / 3.0 - chao * self->vZ;
+
         self->vX += self->vDX * delta;
+        self->vX = (self->vX > 50.0) ? 50.0 : (self->vX < -50.0) ? -50.0 : self->vX;
         self->vY += self->vDY * delta;
+        self->vY = (self->vY > 50.0) ? 50.0 : (self->vY < -50.0) ? -50.0 : self->vY;
         self->vZ += self->vDZ * delta;
-        
-        self->data[i] = self->vX * ROSSLER_SCALE;
-        self->altBuffer[i] = self->vY * ROSSLER_ALT_SCALE;
+
+        self->data[i] = self->vX * CHENLEE_SCALE;
+        self->altBuffer[i] = self->vY * CHENLEE_ALT_SCALE;
     }
 }
 
 static void
-Rossler_readframes_aa(Rossler *self) {
+ChenLee_readframes_aa(ChenLee *self) {
     MYFLT delta, pit, chao;
     int i;
-    
+
     MYFLT *fr = Stream_getData((Stream *)self->pitch_stream);
     MYFLT *ch = Stream_getData((Stream *)self->chaos_stream);
 
@@ -7310,162 +9668,164 @@ Rossler_readframes_aa(Rossler *self) {
         if (pit < 0.0)
             pit = 1.0;
         else if (pit > 1.0)
-            pit = 1000.0;
+            pit = 125.0;
         else
-            pit = pit * 999.0 + 1.0;
-        delta = self->scalePitch * pit;
-        
+            pit = pit * 124.0 + 1.0;
+        delta = self->oneOnSr * pit;
+
         chao = ch[i];
         if (chao < 0.0)
-            chao = 3.0;
+            chao = 4.0;
         else if (chao > 1.0)
-            chao = 10.0;
+            chao = 2.51;
         else
-            chao = chao * 7.0 + 3.0;        
-        self->vDX = -self->vY - self->vZ;
-        self->vDY = self->vX + self->pA * self->vY;
-        self->vDZ = self->pB + self->vZ * (self->vX - chao);
-        
+            chao = (1.0 - chao) * 1.49 + 2.51;
+        self->vDX = -self->vY * self->vZ + self->pA * self->vX;
+        self->vDY = self->vX * self->vZ - self->pB * self->vY;
+        self->vDZ = self->vX * self->vY / 3.0 - chao * self->vZ;
+
         self->vX += self->vDX * delta;
+        self->vX = (self->vX > 50.0) ? 50.0 : (self->vX < -50.0) ? -50.0 : self->vX;
         self->vY += self->vDY * delta;
+        self->vY = (self->vY > 50.0) ? 50.0 : (self->vY < -50.0) ? -50.0 : self->vY;
         self->vZ += self->vDZ * delta;
-        
-        self->data[i] = self->vX * ROSSLER_SCALE;
-        self->altBuffer[i] = self->vY * ROSSLER_ALT_SCALE;
+
+        self->data[i] = self->vX * CHENLEE_SCALE;
+        self->altBuffer[i] = self->vY * CHENLEE_ALT_SCALE;
     }
 }
 
-static void Rossler_postprocessing_ii(Rossler *self) { POST_PROCESSING_II };
-static void Rossler_postprocessing_ai(Rossler *self) { POST_PROCESSING_AI };
-static void Rossler_postprocessing_ia(Rossler *self) { POST_PROCESSING_IA };
-static void Rossler_postprocessing_aa(Rossler *self) { POST_PROCESSING_AA };
-static void Rossler_postprocessing_ireva(Rossler *self) { POST_PROCESSING_IREVA };
-static void Rossler_postprocessing_areva(Rossler *self) { POST_PROCESSING_AREVA };
-static void Rossler_postprocessing_revai(Rossler *self) { POST_PROCESSING_REVAI };
-static void Rossler_postprocessing_revaa(Rossler *self) { POST_PROCESSING_REVAA };
-static void Rossler_postprocessing_revareva(Rossler *self) { POST_PROCESSING_REVAREVA };
+static void ChenLee_postprocessing_ii(ChenLee *self) { POST_PROCESSING_II };
+static void ChenLee_postprocessing_ai(ChenLee *self) { POST_PROCESSING_AI };
+static void ChenLee_postprocessing_ia(ChenLee *self) { POST_PROCESSING_IA };
+static void ChenLee_postprocessing_aa(ChenLee *self) { POST_PROCESSING_AA };
+static void ChenLee_postprocessing_ireva(ChenLee *self) { POST_PROCESSING_IREVA };
+static void ChenLee_postprocessing_areva(ChenLee *self) { POST_PROCESSING_AREVA };
+static void ChenLee_postprocessing_revai(ChenLee *self) { POST_PROCESSING_REVAI };
+static void ChenLee_postprocessing_revaa(ChenLee *self) { POST_PROCESSING_REVAA };
+static void ChenLee_postprocessing_revareva(ChenLee *self) { POST_PROCESSING_REVAREVA };
 
 static void
-Rossler_setProcMode(Rossler *self)
+ChenLee_setProcMode(ChenLee *self)
 {
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:        
-            self->proc_func_ptr = Rossler_readframes_ii;
+        case 0:
+            self->proc_func_ptr = ChenLee_readframes_ii;
             break;
-        case 1:    
-            self->proc_func_ptr = Rossler_readframes_ai;
+        case 1:
+            self->proc_func_ptr = ChenLee_readframes_ai;
             break;
-        case 10:        
-            self->proc_func_ptr = Rossler_readframes_ia;
+        case 10:
+            self->proc_func_ptr = ChenLee_readframes_ia;
             break;
-        case 11:    
-            self->proc_func_ptr = Rossler_readframes_aa;
+        case 11:
+            self->proc_func_ptr = ChenLee_readframes_aa;
             break;
-    } 
-    
+    }
+
 	switch (muladdmode) {
-        case 0:        
-            self->muladd_func_ptr = Rossler_postprocessing_ii;
+        case 0:
+            self->muladd_func_ptr = ChenLee_postprocessing_ii;
             break;
-        case 1:    
-            self->muladd_func_ptr = Rossler_postprocessing_ai;
+        case 1:
+            self->muladd_func_ptr = ChenLee_postprocessing_ai;
             break;
-        case 2:    
-            self->muladd_func_ptr = Rossler_postprocessing_revai;
+        case 2:
+            self->muladd_func_ptr = ChenLee_postprocessing_revai;
             break;
-        case 10:        
-            self->muladd_func_ptr = Rossler_postprocessing_ia;
+        case 10:
+            self->muladd_func_ptr = ChenLee_postprocessing_ia;
             break;
-        case 11:    
-            self->muladd_func_ptr = Rossler_postprocessing_aa;
+        case 11:
+            self->muladd_func_ptr = ChenLee_postprocessing_aa;
             break;
-        case 12:    
-            self->muladd_func_ptr = Rossler_postprocessing_revaa;
+        case 12:
+            self->muladd_func_ptr = ChenLee_postprocessing_revaa;
             break;
-        case 20:        
-            self->muladd_func_ptr = Rossler_postprocessing_ireva;
+        case 20:
+            self->muladd_func_ptr = ChenLee_postprocessing_ireva;
             break;
-        case 21:    
-            self->muladd_func_ptr = Rossler_postprocessing_areva;
+        case 21:
+            self->muladd_func_ptr = ChenLee_postprocessing_areva;
             break;
-        case 22:    
-            self->muladd_func_ptr = Rossler_postprocessing_revareva;
+        case 22:
+            self->muladd_func_ptr = ChenLee_postprocessing_revareva;
             break;
     }
 }
 
 static void
-Rossler_compute_next_data_frame(Rossler *self)
+ChenLee_compute_next_data_frame(ChenLee *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
 static int
-Rossler_traverse(Rossler *self, visitproc visit, void *arg)
+ChenLee_traverse(ChenLee *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->pitch);    
-    Py_VISIT(self->pitch_stream);    
-    Py_VISIT(self->chaos);    
-    Py_VISIT(self->chaos_stream);    
+    Py_VISIT(self->pitch);
+    Py_VISIT(self->pitch_stream);
+    Py_VISIT(self->chaos);
+    Py_VISIT(self->chaos_stream);
     return 0;
 }
 
-static int 
-Rossler_clear(Rossler *self)
+static int
+ChenLee_clear(ChenLee *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->pitch);    
-    Py_CLEAR(self->pitch_stream);    
-    Py_CLEAR(self->chaos);    
-    Py_CLEAR(self->chaos_stream);    
+    Py_CLEAR(self->pitch);
+    Py_CLEAR(self->pitch_stream);
+    Py_CLEAR(self->chaos);
+    Py_CLEAR(self->chaos_stream);
     return 0;
 }
 
 static void
-Rossler_dealloc(Rossler* self)
+ChenLee_dealloc(ChenLee* self)
 {
     pyo_DEALLOC
     free(self->altBuffer);
-    Rossler_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    ChenLee_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
-Rossler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+ChenLee_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
     PyObject *pitchtmp=NULL, *chaostmp=NULL, *multmp=NULL, *addtmp=NULL;
-    Rossler *self;
-    self = (Rossler *)type->tp_alloc(type, 0);
-    
-    self->pitch = PyFloat_FromDouble(0.25);    
-    self->chaos = PyFloat_FromDouble(0.5);    
-    self->pA = 0.15;
-    self->pB = 0.20;
+    ChenLee *self;
+    self = (ChenLee *)type->tp_alloc(type, 0);
+
+    self->pitch = PyFloat_FromDouble(0.25);
+    self->chaos = PyFloat_FromDouble(0.5);
+    self->pA = 5.0;
+    self->pB = 10.0;
     self->vDX = self->vDY = self->vDZ = 0.0;
     self->vX = self->vY = self->vZ = 1.0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
-    
+
     INIT_OBJECT_COMMON
-    Stream_setFunctionPtr(self->stream, Rossler_compute_next_data_frame);
-    self->mode_func_ptr = Rossler_setProcMode;
-    
-    self->scalePitch = 2.91 / self->sr;
+    Stream_setFunctionPtr(self->stream, ChenLee_compute_next_data_frame);
+    self->mode_func_ptr = ChenLee_setProcMode;
+
+    self->oneOnSr = 1.0 / self->sr;
 
     static char *kwlist[] = {"pitch", "chaos", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &pitchtmp, &chaostmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     if (pitchtmp) {
         PyObject_CallMethod((PyObject *)self, "setPitch", "O", pitchtmp);
     }
@@ -7473,60 +9833,57 @@ Rossler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (chaostmp) {
         PyObject_CallMethod((PyObject *)self, "setChaos", "O", chaostmp);
     }
-    
+
     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->altBuffer = (MYFLT *)realloc(self->altBuffer, self->bufsize * sizeof(MYFLT));
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->altBuffer[i] = 0.0;
-    }    
-    
+    }
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
 }
 
-static PyObject * Rossler_getServer(Rossler* self) { GET_SERVER };
-static PyObject * Rossler_getStream(Rossler* self) { GET_STREAM };
-static PyObject * Rossler_setMul(Rossler *self, PyObject *arg) { SET_MUL };	
-static PyObject * Rossler_setAdd(Rossler *self, PyObject *arg) { SET_ADD };	
-static PyObject * Rossler_setSub(Rossler *self, PyObject *arg) { SET_SUB };	
-static PyObject * Rossler_setDiv(Rossler *self, PyObject *arg) { SET_DIV };	
+static PyObject * ChenLee_getServer(ChenLee* self) { GET_SERVER };
+static PyObject * ChenLee_getStream(ChenLee* self) { GET_STREAM };
+static PyObject * ChenLee_setMul(ChenLee *self, PyObject *arg) { SET_MUL };
+static PyObject * ChenLee_setAdd(ChenLee *self, PyObject *arg) { SET_ADD };
+static PyObject * ChenLee_setSub(ChenLee *self, PyObject *arg) { SET_SUB };
+static PyObject * ChenLee_setDiv(ChenLee *self, PyObject *arg) { SET_DIV };
 
-static PyObject * Rossler_play(Rossler *self, PyObject *args, PyObject *kwds) { PLAY };
-static PyObject * Rossler_out(Rossler *self, PyObject *args, PyObject *kwds) { OUT };
-static PyObject * Rossler_stop(Rossler *self) { STOP };
+static PyObject * ChenLee_play(ChenLee *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * ChenLee_out(ChenLee *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * ChenLee_stop(ChenLee *self) { STOP };
 
-static PyObject * Rossler_multiply(Rossler *self, PyObject *arg) { MULTIPLY };
-static PyObject * Rossler_inplace_multiply(Rossler *self, PyObject *arg) { INPLACE_MULTIPLY };
-static PyObject * Rossler_add(Rossler *self, PyObject *arg) { ADD };
-static PyObject * Rossler_inplace_add(Rossler *self, PyObject *arg) { INPLACE_ADD };
-static PyObject * Rossler_sub(Rossler *self, PyObject *arg) { SUB };
-static PyObject * Rossler_inplace_sub(Rossler *self, PyObject *arg) { INPLACE_SUB };
-static PyObject * Rossler_div(Rossler *self, PyObject *arg) { DIV };
-static PyObject * Rossler_inplace_div(Rossler *self, PyObject *arg) { INPLACE_DIV };
+static PyObject * ChenLee_multiply(ChenLee *self, PyObject *arg) { MULTIPLY };
+static PyObject * ChenLee_inplace_multiply(ChenLee *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * ChenLee_add(ChenLee *self, PyObject *arg) { ADD };
+static PyObject * ChenLee_inplace_add(ChenLee *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * ChenLee_sub(ChenLee *self, PyObject *arg) { SUB };
+static PyObject * ChenLee_inplace_sub(ChenLee *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * ChenLee_div(ChenLee *self, PyObject *arg) { DIV };
+static PyObject * ChenLee_inplace_div(ChenLee *self, PyObject *arg) { INPLACE_DIV };
 
 static PyObject *
-Rossler_setPitch(Rossler *self, PyObject *arg)
+ChenLee_setPitch(ChenLee *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->pitch);
@@ -7542,25 +9899,22 @@ Rossler_setPitch(Rossler *self, PyObject *arg)
         self->pitch_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
-Rossler_setChaos(Rossler *self, PyObject *arg)
+ChenLee_setChaos(ChenLee *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->chaos);
@@ -7576,49 +9930,49 @@ Rossler_setChaos(Rossler *self, PyObject *arg)
         self->chaos_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 MYFLT *
-Rossler_getAltBuffer(Rossler *self)
+ChenLee_getAltBuffer(ChenLee *self)
 {
     return (MYFLT *)self->altBuffer;
-}    
+}
 
-static PyMemberDef Rossler_members[] = {
-    {"server", T_OBJECT_EX, offsetof(Rossler, server), 0, "Pyo server."},
-    {"stream", T_OBJECT_EX, offsetof(Rossler, stream), 0, "Stream object."},
-    {"pitch", T_OBJECT_EX, offsetof(Rossler, pitch), 0, "Pitch."},
-    {"chaos", T_OBJECT_EX, offsetof(Rossler, chaos), 0, "Chaotic behavior."},
-    {"mul", T_OBJECT_EX, offsetof(Rossler, mul), 0, "Mul factor."},
-    {"add", T_OBJECT_EX, offsetof(Rossler, add), 0, "Add factor."},
+static PyMemberDef ChenLee_members[] = {
+    {"server", T_OBJECT_EX, offsetof(ChenLee, server), 0, "Pyo server."},
+    {"stream", T_OBJECT_EX, offsetof(ChenLee, stream), 0, "Stream object."},
+    {"pitch", T_OBJECT_EX, offsetof(ChenLee, pitch), 0, "Pitch."},
+    {"chaos", T_OBJECT_EX, offsetof(ChenLee, chaos), 0, "Chaotic behavior."},
+    {"mul", T_OBJECT_EX, offsetof(ChenLee, mul), 0, "Mul factor."},
+    {"add", T_OBJECT_EX, offsetof(ChenLee, add), 0, "Add factor."},
     {NULL}  /* Sentinel */
 };
 
-static PyMethodDef Rossler_methods[] = {
-    {"getServer", (PyCFunction)Rossler_getServer, METH_NOARGS, "Returns server object."},
-    {"_getStream", (PyCFunction)Rossler_getStream, METH_NOARGS, "Returns stream object."},
-    {"play", (PyCFunction)Rossler_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
-    {"out", (PyCFunction)Rossler_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
-    {"stop", (PyCFunction)Rossler_stop, METH_NOARGS, "Stops computing."},
-    {"setPitch", (PyCFunction)Rossler_setPitch, METH_O, "Sets oscillator pitch."},
-    {"setChaos", (PyCFunction)Rossler_setChaos, METH_O, "Sets oscillator chaotic behavior."},
-    {"setMul", (PyCFunction)Rossler_setMul, METH_O, "Sets Rossler mul factor."},
-    {"setAdd", (PyCFunction)Rossler_setAdd, METH_O, "Sets Rossler add factor."},
-    {"setSub", (PyCFunction)Rossler_setSub, METH_O, "Sets inverse add factor."},
-    {"setDiv", (PyCFunction)Rossler_setDiv, METH_O, "Sets inverse mul factor."},
+static PyMethodDef ChenLee_methods[] = {
+    {"getServer", (PyCFunction)ChenLee_getServer, METH_NOARGS, "Returns server object."},
+    {"_getStream", (PyCFunction)ChenLee_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)ChenLee_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+    {"out", (PyCFunction)ChenLee_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+    {"stop", (PyCFunction)ChenLee_stop, METH_NOARGS, "Stops computing."},
+    {"setPitch", (PyCFunction)ChenLee_setPitch, METH_O, "Sets oscillator pitch."},
+    {"setChaos", (PyCFunction)ChenLee_setChaos, METH_O, "Sets oscillator chaotic behavior."},
+    {"setMul", (PyCFunction)ChenLee_setMul, METH_O, "Sets ChenLee mul factor."},
+    {"setAdd", (PyCFunction)ChenLee_setAdd, METH_O, "Sets ChenLee add factor."},
+    {"setSub", (PyCFunction)ChenLee_setSub, METH_O, "Sets inverse add factor."},
+    {"setDiv", (PyCFunction)ChenLee_setDiv, METH_O, "Sets inverse mul factor."},
     {NULL}  /* Sentinel */
 };
 
-static PyNumberMethods Rossler_as_number = {
-    (binaryfunc)Rossler_add,                      /*nb_add*/
-    (binaryfunc)Rossler_sub,                 /*nb_subtract*/
-    (binaryfunc)Rossler_multiply,                 /*nb_multiply*/
-    (binaryfunc)Rossler_div,                   /*nb_divide*/
+static PyNumberMethods ChenLee_as_number = {
+    (binaryfunc)ChenLee_add,                      /*nb_add*/
+    (binaryfunc)ChenLee_sub,                 /*nb_subtract*/
+    (binaryfunc)ChenLee_multiply,                 /*nb_multiply*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -7632,16 +9986,16 @@ static PyNumberMethods Rossler_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
-    (binaryfunc)Rossler_inplace_add,              /*inplace_add*/
-    (binaryfunc)Rossler_inplace_sub,         /*inplace_subtract*/
-    (binaryfunc)Rossler_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)Rossler_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
+    (binaryfunc)ChenLee_inplace_add,              /*inplace_add*/
+    (binaryfunc)ChenLee_inplace_sub,         /*inplace_subtract*/
+    (binaryfunc)ChenLee_inplace_multiply,         /*inplace_multiply*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -7650,25 +10004,274 @@ static PyNumberMethods Rossler_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)ChenLee_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)ChenLee_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
-PyTypeObject RosslerType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
-    "_pyo.Rossler_base",         /*tp_name*/
-    sizeof(Rossler),         /*tp_basicsize*/
+PyTypeObject ChenLeeType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.ChenLee_base",         /*tp_name*/
+    sizeof(ChenLee),         /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)ChenLee_dealloc, /*tp_dealloc*/
+    0,                         /*tp_print*/
+    0,                         /*tp_getattr*/
+    0,                         /*tp_setattr*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
+    0,                         /*tp_repr*/
+    &ChenLee_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*/
+    "ChenLee objects. ChenLee attractor.",           /* tp_doc */
+    (traverseproc)ChenLee_traverse,   /* tp_traverse */
+    (inquiry)ChenLee_clear,           /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    ChenLee_methods,             /* tp_methods */
+    ChenLee_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 */
+    ChenLee_new,                 /* tp_new */
+};
+
+typedef struct {
+    pyo_audio_HEAD
+    ChenLee *mainChenLee;
+    int modebuffer[2];
+} ChenLeeAlt;
+
+static void ChenLeeAlt_postprocessing_ii(ChenLeeAlt *self) { POST_PROCESSING_II };
+static void ChenLeeAlt_postprocessing_ai(ChenLeeAlt *self) { POST_PROCESSING_AI };
+static void ChenLeeAlt_postprocessing_ia(ChenLeeAlt *self) { POST_PROCESSING_IA };
+static void ChenLeeAlt_postprocessing_aa(ChenLeeAlt *self) { POST_PROCESSING_AA };
+static void ChenLeeAlt_postprocessing_ireva(ChenLeeAlt *self) { POST_PROCESSING_IREVA };
+static void ChenLeeAlt_postprocessing_areva(ChenLeeAlt *self) { POST_PROCESSING_AREVA };
+static void ChenLeeAlt_postprocessing_revai(ChenLeeAlt *self) { POST_PROCESSING_REVAI };
+static void ChenLeeAlt_postprocessing_revaa(ChenLeeAlt *self) { POST_PROCESSING_REVAA };
+static void ChenLeeAlt_postprocessing_revareva(ChenLeeAlt *self) { POST_PROCESSING_REVAREVA };
+
+static void
+ChenLeeAlt_setProcMode(ChenLeeAlt *self) {
+    int muladdmode;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+    switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = ChenLeeAlt_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = ChenLeeAlt_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = ChenLeeAlt_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = ChenLeeAlt_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = ChenLeeAlt_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = ChenLeeAlt_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = ChenLeeAlt_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = ChenLeeAlt_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = ChenLeeAlt_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+ChenLeeAlt_compute_next_data_frame(ChenLeeAlt *self)
+{
+    int i;
+    MYFLT *tmp;
+    tmp = ChenLee_getAltBuffer((ChenLee *)self->mainChenLee);
+    for (i=0; i<self->bufsize; i++) {
+        self->data[i] = tmp[i];
+    }
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+ChenLeeAlt_traverse(ChenLeeAlt *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->mainChenLee);
+    return 0;
+}
+
+static int
+ChenLeeAlt_clear(ChenLeeAlt *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->mainChenLee);
+    return 0;
+}
+
+static void
+ChenLeeAlt_dealloc(ChenLeeAlt* self)
+{
+    pyo_DEALLOC
+    ChenLeeAlt_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+ChenLeeAlt_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL;
+    ChenLeeAlt *self;
+    self = (ChenLeeAlt *)type->tp_alloc(type, 0);
+
+    self->modebuffer[0] = 0;
+    self->modebuffer[1] = 0;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, ChenLeeAlt_compute_next_data_frame);
+    self->mode_func_ptr = ChenLeeAlt_setProcMode;
+
+    static char *kwlist[] = {"mainChenLee", "mul", "alt", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &maintmp, &multmp, &addtmp))
+        Py_RETURN_NONE;
+
+    Py_XDECREF(self->mainChenLee);
+    Py_INCREF(maintmp);
+    self->mainChenLee = (ChenLee *)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 * ChenLeeAlt_getServer(ChenLeeAlt* self) { GET_SERVER };
+static PyObject * ChenLeeAlt_getStream(ChenLeeAlt* self) { GET_STREAM };
+static PyObject * ChenLeeAlt_setMul(ChenLeeAlt *self, PyObject *arg) { SET_MUL };
+static PyObject * ChenLeeAlt_setAdd(ChenLeeAlt *self, PyObject *arg) { SET_ADD };
+static PyObject * ChenLeeAlt_setSub(ChenLeeAlt *self, PyObject *arg) { SET_SUB };
+static PyObject * ChenLeeAlt_setDiv(ChenLeeAlt *self, PyObject *arg) { SET_DIV };
+
+static PyObject * ChenLeeAlt_play(ChenLeeAlt *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * ChenLeeAlt_out(ChenLeeAlt *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * ChenLeeAlt_stop(ChenLeeAlt *self) { STOP };
+
+static PyObject * ChenLeeAlt_multiply(ChenLeeAlt *self, PyObject *arg) { MULTIPLY };
+static PyObject * ChenLeeAlt_inplace_multiply(ChenLeeAlt *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * ChenLeeAlt_add(ChenLeeAlt *self, PyObject *arg) { ADD };
+static PyObject * ChenLeeAlt_inplace_add(ChenLeeAlt *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * ChenLeeAlt_sub(ChenLeeAlt *self, PyObject *arg) { SUB };
+static PyObject * ChenLeeAlt_inplace_sub(ChenLeeAlt *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * ChenLeeAlt_div(ChenLeeAlt *self, PyObject *arg) { DIV };
+static PyObject * ChenLeeAlt_inplace_div(ChenLeeAlt *self, PyObject *arg) { INPLACE_DIV };
+
+static PyMemberDef ChenLeeAlt_members[] = {
+    {"server", T_OBJECT_EX, offsetof(ChenLeeAlt, server), 0, "Pyo server."},
+    {"stream", T_OBJECT_EX, offsetof(ChenLeeAlt, stream), 0, "Stream object."},
+    {"mul", T_OBJECT_EX, offsetof(ChenLeeAlt, mul), 0, "Mul factor."},
+    {"add", T_OBJECT_EX, offsetof(ChenLeeAlt, add), 0, "Add factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef ChenLeeAlt_methods[] = {
+    {"getServer", (PyCFunction)ChenLeeAlt_getServer, METH_NOARGS, "Returns server object."},
+    {"_getStream", (PyCFunction)ChenLeeAlt_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)ChenLeeAlt_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+    {"out", (PyCFunction)ChenLeeAlt_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+    {"stop", (PyCFunction)ChenLeeAlt_stop, METH_NOARGS, "Stops computing."},
+    {"setMul", (PyCFunction)ChenLeeAlt_setMul, METH_O, "Sets oscillator mul factor."},
+    {"setAdd", (PyCFunction)ChenLeeAlt_setAdd, METH_O, "Sets oscillator add factor."},
+    {"setSub", (PyCFunction)ChenLeeAlt_setSub, METH_O, "Sets inverse add factor."},
+    {"setDiv", (PyCFunction)ChenLeeAlt_setDiv, METH_O, "Sets inverse mul factor."},
+    {NULL}  /* Sentinel */
+};
+static PyNumberMethods ChenLeeAlt_as_number = {
+    (binaryfunc)ChenLeeAlt_add,                         /*nb_add*/
+    (binaryfunc)ChenLeeAlt_sub,                         /*nb_subtract*/
+    (binaryfunc)ChenLeeAlt_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)ChenLeeAlt_inplace_add,                 /*inplace_add*/
+    (binaryfunc)ChenLeeAlt_inplace_sub,                 /*inplace_subtract*/
+    (binaryfunc)ChenLeeAlt_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)ChenLeeAlt_div,                       /*nb_true_divide*/
+    0,                                              /*nb_inplace_floor_divide*/
+    (binaryfunc)ChenLeeAlt_inplace_div,                       /*nb_inplace_true_divide*/
+    0,                                              /* nb_index */
+};
+
+PyTypeObject ChenLeeAltType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.ChenLeeAlt_base",         /*tp_name*/
+    sizeof(ChenLeeAlt),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
-    (destructor)Rossler_dealloc, /*tp_dealloc*/
+    (destructor)ChenLeeAlt_dealloc, /*tp_dealloc*/
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
-    &Rossler_as_number,             /*tp_as_number*/
+    &ChenLeeAlt_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
     0,                         /*tp_as_mapping*/
     0,                         /*tp_hash */
@@ -7678,15 +10281,15 @@ PyTypeObject RosslerType = {
     0,                         /*tp_setattro*/
     0,                         /*tp_as_buffer*/
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES,  /*tp_flags*/
-    "Rossler objects. Rossler attractor.",           /* tp_doc */
-    (traverseproc)Rossler_traverse,   /* tp_traverse */
-    (inquiry)Rossler_clear,           /* tp_clear */
+    "ChenLeeAlt objects. Sends the alternate signal of a ChenLee attractor.",           /* tp_doc */
+    (traverseproc)ChenLeeAlt_traverse,   /* tp_traverse */
+    (inquiry)ChenLeeAlt_clear,           /* tp_clear */
     0,		               /* tp_richcompare */
     0,		               /* tp_weaklistoffset */
     0,		               /* tp_iter */
     0,		               /* tp_iternext */
-    Rossler_methods,             /* tp_methods */
-    Rossler_members,             /* tp_members */
+    ChenLeeAlt_methods,             /* tp_methods */
+    ChenLeeAlt_members,             /* tp_members */
     0,                      /* tp_getset */
     0,                         /* tp_base */
     0,                         /* tp_dict */
@@ -7695,1588 +10298,1405 @@ PyTypeObject RosslerType = {
     0,                         /* tp_dictoffset */
     0,      /* tp_init */
     0,                         /* tp_alloc */
-    Rossler_new,                 /* tp_new */
+    ChenLeeAlt_new,                 /* tp_new */
 };
 
+/*************/
+/* SumOsc object */
+/*************/
 typedef struct {
     pyo_audio_HEAD
-    Rossler *mainRossler;
-    int modebuffer[2];
-} RosslerAlt;
-
-static void RosslerAlt_postprocessing_ii(RosslerAlt *self) { POST_PROCESSING_II };
-static void RosslerAlt_postprocessing_ai(RosslerAlt *self) { POST_PROCESSING_AI };
-static void RosslerAlt_postprocessing_ia(RosslerAlt *self) { POST_PROCESSING_IA };
-static void RosslerAlt_postprocessing_aa(RosslerAlt *self) { POST_PROCESSING_AA };
-static void RosslerAlt_postprocessing_ireva(RosslerAlt *self) { POST_PROCESSING_IREVA };
-static void RosslerAlt_postprocessing_areva(RosslerAlt *self) { POST_PROCESSING_AREVA };
-static void RosslerAlt_postprocessing_revai(RosslerAlt *self) { POST_PROCESSING_REVAI };
-static void RosslerAlt_postprocessing_revaa(RosslerAlt *self) { POST_PROCESSING_REVAA };
-static void RosslerAlt_postprocessing_revareva(RosslerAlt *self) { POST_PROCESSING_REVAREVA };
+    PyObject *freq;
+    Stream *freq_stream;
+    PyObject *ratio;
+    Stream *ratio_stream;
+    PyObject *index;
+    Stream *index_stream;
+    int modebuffer[5];
+    MYFLT theta;
+    MYFLT beta;
+    MYFLT scaleFactor;
+    MYFLT xn1; // dc block input delay
+    MYFLT yn1; // dc block output delay
+} SumOsc;
 
 static void
-RosslerAlt_setProcMode(RosslerAlt *self) {
-    int muladdmode;
-    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
-    switch (muladdmode) {
-        case 0:        
-            self->muladd_func_ptr = RosslerAlt_postprocessing_ii;
-            break;
-        case 1:    
-            self->muladd_func_ptr = RosslerAlt_postprocessing_ai;
-            break;
-        case 2:    
-            self->muladd_func_ptr = RosslerAlt_postprocessing_revai;
-            break;
-        case 10:        
-            self->muladd_func_ptr = RosslerAlt_postprocessing_ia;
-            break;
-        case 11:    
-            self->muladd_func_ptr = RosslerAlt_postprocessing_aa;
-            break;
-        case 12:    
-            self->muladd_func_ptr = RosslerAlt_postprocessing_revaa;
-            break;
-        case 20:        
-            self->muladd_func_ptr = RosslerAlt_postprocessing_ireva;
-            break;
-        case 21:    
-            self->muladd_func_ptr = RosslerAlt_postprocessing_areva;
-            break;
-        case 22:    
-            self->muladd_func_ptr = RosslerAlt_postprocessing_revareva;
-            break;
-    }  
+SumOsc_readframes_iii(SumOsc *self) {
+    MYFLT mod_freq, mod_delta, freq_delta, x, y, ind2, theta_minus_beta, sin1, sin2, cos1;
+    int i, ipart;
+
+    MYFLT freq = PyFloat_AS_DOUBLE(self->freq);
+    MYFLT rat = PyFloat_AS_DOUBLE(self->ratio);
+    MYFLT ind = PyFloat_AS_DOUBLE(self->index);
+
+    freq_delta = freq * self->scaleFactor;
+    mod_freq = freq * rat;
+    mod_delta = mod_freq * self->scaleFactor;
+    if (ind < 0)
+        ind = 0;
+    else if (ind > 0.999)
+        ind = 0.999;
+
+    ind2 = ind * ind;
+    for (i=0; i<self->bufsize; i++) {
+        ipart = (int)self->theta;
+        sin1 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (self->theta - ipart);
+        theta_minus_beta = Sine_clip(self->theta - self->beta);
+        ipart = (int)theta_minus_beta;
+        sin2 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (theta_minus_beta - ipart);
+        ipart = (int)self->beta;
+        cos1 = COSINE_ARRAY[ipart] + (COSINE_ARRAY[ipart+1] - COSINE_ARRAY[ipart]) * (self->beta - ipart);
+        x = (sin1 - ind * sin2) / (1 + ind2 - 2 * ind * cos1);
+        self->theta += freq_delta;
+        self->beta += mod_delta;
+        self->theta = Sine_clip(self->theta);
+        self->beta = Sine_clip(self->beta);
+
+        /* DC filtering */
+        y = x - self->xn1 + 0.995 * self->yn1;
+        self->xn1 = x; self->yn1 = y;
+
+        self->data[i] = y * (1 - ind2);
+    }
 }
 
 static void
-RosslerAlt_compute_next_data_frame(RosslerAlt *self)
-{
-    int i;
-    MYFLT *tmp;
-    tmp = Rossler_getAltBuffer((Rossler *)self->mainRossler);
+SumOsc_readframes_aii(SumOsc *self) {
+    MYFLT freq, mod_freq, mod_delta, freq_delta, x, y, ind2, theta_minus_beta, sin1, sin2, cos1;
+    int i, ipart;
+
+    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
+    MYFLT rat = PyFloat_AS_DOUBLE(self->ratio);
+    MYFLT ind = PyFloat_AS_DOUBLE(self->index);
+
+    if (ind < 0)
+        ind = 0;
+    else if (ind > 0.999)
+        ind = 0.999;
+
+    ind2 = ind * ind;
     for (i=0; i<self->bufsize; i++) {
-        self->data[i] = tmp[i];
-    }    
-    (*self->muladd_func_ptr)(self);
-}
+        freq = fr[i];
+        freq_delta = freq * self->scaleFactor;
+        mod_freq = freq * rat;
+        mod_delta = mod_freq * self->scaleFactor;
+        ipart = (int)self->theta;
+        sin1 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (self->theta - ipart);
+        theta_minus_beta = Sine_clip(self->theta - self->beta);
+        ipart = (int)theta_minus_beta;
+        sin2 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (theta_minus_beta - ipart);
+        ipart = (int)self->beta;
+        cos1 = COSINE_ARRAY[ipart] + (COSINE_ARRAY[ipart+1] - COSINE_ARRAY[ipart]) * (self->beta - ipart);
+        x = (sin1 - ind * sin2) / (1 + ind2 - 2 * ind * cos1);
+        self->theta += freq_delta;
+        self->beta += mod_delta;
+        self->theta = Sine_clip(self->theta);
+        self->beta = Sine_clip(self->beta);
 
-static int
-RosslerAlt_traverse(RosslerAlt *self, visitproc visit, void *arg)
-{
-    pyo_VISIT
-    Py_VISIT(self->mainRossler);
-    return 0;
-}
+        y = x - self->xn1 + 0.995 * self->yn1;
+        self->xn1 = x; self->yn1 = y;
 
-static int 
-RosslerAlt_clear(RosslerAlt *self)
-{
-    pyo_CLEAR
-    Py_CLEAR(self->mainRossler);    
-    return 0;
+        self->data[i] = y * (1 - ind2);
+    }
 }
 
 static void
-RosslerAlt_dealloc(RosslerAlt* self)
-{
-    pyo_DEALLOC
-    RosslerAlt_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
-}
+SumOsc_readframes_iai(SumOsc *self) {
+    MYFLT ratio, mod_freq, mod_delta, freq_delta, x, y, ind2, theta_minus_beta, sin1, sin2, cos1;
+    int i, ipart;
 
-static PyObject *
-RosslerAlt_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
-    int i;
-    PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL;
-    RosslerAlt *self;
-    self = (RosslerAlt *)type->tp_alloc(type, 0);
-    
-    self->modebuffer[0] = 0;
-    self->modebuffer[1] = 0;
-    
-    INIT_OBJECT_COMMON
-    Stream_setFunctionPtr(self->stream, RosslerAlt_compute_next_data_frame);
-    self->mode_func_ptr = RosslerAlt_setProcMode;
+    MYFLT freq = PyFloat_AS_DOUBLE(self->freq);
+    MYFLT *rat = Stream_getData((Stream *)self->ratio_stream);
+    MYFLT ind = PyFloat_AS_DOUBLE(self->index);
 
-    static char *kwlist[] = {"mainRossler", "mul", "alt", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &maintmp, &multmp, &addtmp))
-        Py_RETURN_NONE;
-    
-    Py_XDECREF(self->mainRossler);
-    Py_INCREF(maintmp);
-    self->mainRossler = (Rossler *)maintmp;
+    freq_delta = freq * self->scaleFactor;
+    if (ind < 0)
+        ind = 0;
+    else if (ind > 0.999)
+        ind = 0.999;
 
-    if (multmp) {
-        PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
-    }
-    
-    if (addtmp) {
-        PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
+    ind2 = ind * ind;
+    for (i=0; i<self->bufsize; i++) {
+        ratio = rat[i];
+        mod_freq = freq * ratio;
+        mod_delta = mod_freq * self->scaleFactor;
+        ipart = (int)self->theta;
+        sin1 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (self->theta - ipart);
+        theta_minus_beta = Sine_clip(self->theta - self->beta);
+        ipart = (int)theta_minus_beta;
+        sin2 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (theta_minus_beta - ipart);
+        ipart = (int)self->beta;
+        cos1 = COSINE_ARRAY[ipart] + (COSINE_ARRAY[ipart+1] - COSINE_ARRAY[ipart]) * (self->beta - ipart);
+        x = (sin1 - ind * sin2) / (1 + ind2 - 2 * ind * cos1);
+        self->theta += freq_delta;
+        self->beta += mod_delta;
+        self->theta = Sine_clip(self->theta);
+        self->beta = Sine_clip(self->beta);
+
+        y = x - self->xn1 + 0.995 * self->yn1;
+        self->xn1 = x; self->yn1 = y;
+
+        self->data[i] = y * (1 - ind2);
     }
-    
-    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
-    (*self->mode_func_ptr)(self);
-    
-    return (PyObject *)self;
 }
 
-static PyObject * RosslerAlt_getServer(RosslerAlt* self) { GET_SERVER };
-static PyObject * RosslerAlt_getStream(RosslerAlt* self) { GET_STREAM };
-static PyObject * RosslerAlt_setMul(RosslerAlt *self, PyObject *arg) { SET_MUL };	
-static PyObject * RosslerAlt_setAdd(RosslerAlt *self, PyObject *arg) { SET_ADD };	
-static PyObject * RosslerAlt_setSub(RosslerAlt *self, PyObject *arg) { SET_SUB };	
-static PyObject * RosslerAlt_setDiv(RosslerAlt *self, PyObject *arg) { SET_DIV };	
+static void
+SumOsc_readframes_aai(SumOsc *self) {
+    MYFLT freq, ratio, mod_freq, mod_delta, freq_delta, x, y, ind2, theta_minus_beta, sin1, sin2, cos1;
+    int i, ipart;
+
+    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
+    MYFLT *rat = Stream_getData((Stream *)self->ratio_stream);
+    MYFLT ind = PyFloat_AS_DOUBLE(self->index);
+
+    if (ind < 0)
+        ind = 0;
+    else if (ind > 0.999)
+        ind = 0.999;
+
+    ind2 = ind * ind;
+    for (i=0; i<self->bufsize; i++) {
+        freq = fr[i];
+        ratio = rat[i];
+        freq_delta = freq * self->scaleFactor;
+        mod_freq = freq * ratio;
+        mod_delta = mod_freq * self->scaleFactor;
+        ipart = (int)self->theta;
+        sin1 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (self->theta - ipart);
+        theta_minus_beta = Sine_clip(self->theta - self->beta);
+        ipart = (int)theta_minus_beta;
+        sin2 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (theta_minus_beta - ipart);
+        ipart = (int)self->beta;
+        cos1 = COSINE_ARRAY[ipart] + (COSINE_ARRAY[ipart+1] - COSINE_ARRAY[ipart]) * (self->beta - ipart);
+        x = (sin1 - ind * sin2) / (1 + ind2 - 2 * ind * cos1);
+        self->theta += freq_delta;
+        self->beta += mod_delta;
+        self->theta = Sine_clip(self->theta);
+        self->beta = Sine_clip(self->beta);
+
+        y = x - self->xn1 + 0.995 * self->yn1;
+        self->xn1 = x; self->yn1 = y;
 
-static PyObject * RosslerAlt_play(RosslerAlt *self, PyObject *args, PyObject *kwds) { PLAY };
-static PyObject * RosslerAlt_out(RosslerAlt *self, PyObject *args, PyObject *kwds) { OUT };
-static PyObject * RosslerAlt_stop(RosslerAlt *self) { STOP };
+        self->data[i] = y * (1 - ind2);
+    }
+}
 
-static PyObject * RosslerAlt_multiply(RosslerAlt *self, PyObject *arg) { MULTIPLY };
-static PyObject * RosslerAlt_inplace_multiply(RosslerAlt *self, PyObject *arg) { INPLACE_MULTIPLY };
-static PyObject * RosslerAlt_add(RosslerAlt *self, PyObject *arg) { ADD };
-static PyObject * RosslerAlt_inplace_add(RosslerAlt *self, PyObject *arg) { INPLACE_ADD };
-static PyObject * RosslerAlt_sub(RosslerAlt *self, PyObject *arg) { SUB };
-static PyObject * RosslerAlt_inplace_sub(RosslerAlt *self, PyObject *arg) { INPLACE_SUB };
-static PyObject * RosslerAlt_div(RosslerAlt *self, PyObject *arg) { DIV };
-static PyObject * RosslerAlt_inplace_div(RosslerAlt *self, PyObject *arg) { INPLACE_DIV };
+static void
+SumOsc_readframes_iia(SumOsc *self) {
+    MYFLT ind, mod_freq, mod_delta, freq_delta, x, y, ind2, theta_minus_beta, sin1, sin2, cos1;
+    int i, ipart;
 
-static PyMemberDef RosslerAlt_members[] = {
-    {"server", T_OBJECT_EX, offsetof(RosslerAlt, server), 0, "Pyo server."},
-    {"stream", T_OBJECT_EX, offsetof(RosslerAlt, stream), 0, "Stream object."},
-    {"mul", T_OBJECT_EX, offsetof(RosslerAlt, mul), 0, "Mul factor."},
-    {"add", T_OBJECT_EX, offsetof(RosslerAlt, add), 0, "Add factor."},
-    {NULL}  /* Sentinel */
-};
+    MYFLT freq = PyFloat_AS_DOUBLE(self->freq);
+    MYFLT rat = PyFloat_AS_DOUBLE(self->ratio);
+    MYFLT *index = Stream_getData((Stream *)self->index_stream);
 
-static PyMethodDef RosslerAlt_methods[] = {
-    {"getServer", (PyCFunction)RosslerAlt_getServer, METH_NOARGS, "Returns server object."},
-    {"_getStream", (PyCFunction)RosslerAlt_getStream, METH_NOARGS, "Returns stream object."},
-    {"play", (PyCFunction)RosslerAlt_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
-    {"out", (PyCFunction)RosslerAlt_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
-    {"stop", (PyCFunction)RosslerAlt_stop, METH_NOARGS, "Stops computing."},
-    {"setMul", (PyCFunction)RosslerAlt_setMul, METH_O, "Sets oscillator mul factor."},
-    {"setAdd", (PyCFunction)RosslerAlt_setAdd, METH_O, "Sets oscillator add factor."},
-    {"setSub", (PyCFunction)RosslerAlt_setSub, METH_O, "Sets inverse add factor."},
-    {"setDiv", (PyCFunction)RosslerAlt_setDiv, METH_O, "Sets inverse mul factor."},        
-    {NULL}  /* Sentinel */
-};
-static PyNumberMethods RosslerAlt_as_number = {
-    (binaryfunc)RosslerAlt_add,                         /*nb_add*/
-    (binaryfunc)RosslerAlt_sub,                         /*nb_subtract*/
-    (binaryfunc)RosslerAlt_multiply,                    /*nb_multiply*/
-    (binaryfunc)RosslerAlt_div,                                              /*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*/
-    0,                                              /*nb_coerce*/
-    0,                                              /*nb_int*/
-    0,                                              /*nb_long*/
-    0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
-    (binaryfunc)RosslerAlt_inplace_add,                 /*inplace_add*/
-    (binaryfunc)RosslerAlt_inplace_sub,                 /*inplace_subtract*/
-    (binaryfunc)RosslerAlt_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)RosslerAlt_inplace_div,                                              /*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*/
-    0,                                              /*nb_true_divide*/
-    0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
-    0,                                              /* nb_index */
-};
+    freq_delta = freq * self->scaleFactor;
+    mod_freq = freq * rat;
+    mod_delta = mod_freq * self->scaleFactor;
 
-PyTypeObject RosslerAltType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
-    "_pyo.RosslerAlt_base",         /*tp_name*/
-    sizeof(RosslerAlt),         /*tp_basicsize*/
-    0,                         /*tp_itemsize*/
-    (destructor)RosslerAlt_dealloc, /*tp_dealloc*/
-    0,                         /*tp_print*/
-    0,                         /*tp_getattr*/
-    0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
-    0,                         /*tp_repr*/
-    &RosslerAlt_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*/
-    "RosslerAlt objects. Sends the alternate signal of a Rossler attractor.",           /* tp_doc */
-    (traverseproc)RosslerAlt_traverse,   /* tp_traverse */
-    (inquiry)RosslerAlt_clear,           /* tp_clear */
-    0,		               /* tp_richcompare */
-    0,		               /* tp_weaklistoffset */
-    0,		               /* tp_iter */
-    0,		               /* tp_iternext */
-    RosslerAlt_methods,             /* tp_methods */
-    RosslerAlt_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 */
-    RosslerAlt_new,                 /* tp_new */
-};
+    for (i=0; i<self->bufsize; i++) {
+        ind = index[i];
+        if (ind < 0)
+            ind = 0;
+        else if (ind > 0.999)
+            ind = 0.999;
+        ind2 = ind * ind;
+        ipart = (int)self->theta;
+        sin1 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (self->theta - ipart);
+        theta_minus_beta = Sine_clip(self->theta - self->beta);
+        ipart = (int)theta_minus_beta;
+        sin2 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (theta_minus_beta - ipart);
+        ipart = (int)self->beta;
+        cos1 = COSINE_ARRAY[ipart] + (COSINE_ARRAY[ipart+1] - COSINE_ARRAY[ipart]) * (self->beta - ipart);
+        x = (sin1 - ind * sin2) / (1 + ind2 - 2 * ind * cos1);
+        self->theta += freq_delta;
+        self->beta += mod_delta;
+        self->theta = Sine_clip(self->theta);
+        self->beta = Sine_clip(self->beta);
 
-/* Lorenz object */
-typedef struct {
-    pyo_audio_HEAD
-    PyObject *pitch;
-    Stream *pitch_stream;
-    PyObject *chaos;
-    Stream *chaos_stream;
-    MYFLT *altBuffer;
-    MYFLT vDX;
-    MYFLT vDY;
-    MYFLT vDZ;
-    MYFLT vX;
-    MYFLT vY;
-    MYFLT vZ;
-    MYFLT pA;
-    MYFLT pB;
-    MYFLT oneOnSr;
-    int modebuffer[4];
-} Lorenz;
+        y = x - self->xn1 + 0.995 * self->yn1;
+        self->xn1 = x; self->yn1 = y;
 
-static void
-Lorenz_readframes_ii(Lorenz *self) {
-    MYFLT delta, pit, chao;
-    int i;
-    
-    pit = PyFloat_AS_DOUBLE(self->pitch);
-    chao = PyFloat_AS_DOUBLE(self->chaos);
-    if (pit < 0.0)
-        pit = 1.0;
-    else if (pit > 1.0)
-        pit = 750.0;
-    else
-        pit = pit * 749.0 + 1.0;
-    delta = self->oneOnSr * pit;
-    
-    if (chao < 0.0)
-        chao = 0.5;
-    else if (chao > 1.0)
-        chao = 3.0;
-    else
-        chao = chao * 2.5 + 0.5;
-    
-    for (i=0; i<self->bufsize; i++) {
-        self->vDX = self->pA * (self->vY - self->vX);
-        self->vDY = self->vX * (self->pB - self->vZ) - self->vY;
-        self->vDZ = self->vX * self->vY - chao * self->vZ;
-        
-        self->vX += self->vDX * delta;
-        self->vY += self->vDY * delta;
-        self->vZ += self->vDZ * delta;
-        
-        self->data[i] = self->vX * LORENZ_SCALE;
-        self->altBuffer[i] = self->vY * LORENZ_ALT_SCALE;
+        self->data[i] = y * (1 - ind2);
     }
 }
 
 static void
-Lorenz_readframes_ai(Lorenz *self) {
-    MYFLT delta, pit, chao;
-    int i;
-    
-    MYFLT *fr = Stream_getData((Stream *)self->pitch_stream);
-    chao = PyFloat_AS_DOUBLE(self->chaos);
-    if (chao < 0.0)
-        chao = 0.5;
-    else if (chao > 1.0)
-        chao = 3.0;
-    else
-        chao = chao * 2.5 + 0.5;
-    
+SumOsc_readframes_aia(SumOsc *self) {
+    MYFLT freq, ind, mod_freq, mod_delta, freq_delta, x, y, ind2, theta_minus_beta, sin1, sin2, cos1;
+    int i, ipart;
+
+    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
+    MYFLT rat = PyFloat_AS_DOUBLE(self->ratio);
+    MYFLT *index = Stream_getData((Stream *)self->index_stream);
+
     for (i=0; i<self->bufsize; i++) {
-        pit = fr[i];
-        if (pit < 0.0)
-            pit = 1.0;
-        else if (pit > 1.0)
-            pit = 750.0;
-        else
-            pit = pit * 749.0 + 1.0;
-        delta = self->oneOnSr * pit;
-        self->vDX = self->pA * (self->vY - self->vX);
-        self->vDY = self->vX * (self->pB - self->vZ) - self->vY;
-        self->vDZ = self->vX * self->vY - chao * self->vZ;
-        
-        self->vX += self->vDX * delta;
-        self->vY += self->vDY * delta;
-        self->vZ += self->vDZ * delta;
-        
-        self->data[i] = self->vX * LORENZ_SCALE;
-        self->altBuffer[i] = self->vY * LORENZ_ALT_SCALE;
+        freq = fr[i];
+        ind = index[i];
+        freq_delta = freq * self->scaleFactor;
+        mod_freq = freq * rat;
+        mod_delta = mod_freq * self->scaleFactor;
+        if (ind < 0)
+            ind = 0;
+        else if (ind > 0.999)
+            ind = 0.999;
+        ind2 = ind * ind;
+        ipart = (int)self->theta;
+        sin1 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (self->theta - ipart);
+        theta_minus_beta = Sine_clip(self->theta - self->beta);
+        ipart = (int)theta_minus_beta;
+        sin2 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (theta_minus_beta - ipart);
+        ipart = (int)self->beta;
+        cos1 = COSINE_ARRAY[ipart] + (COSINE_ARRAY[ipart+1] - COSINE_ARRAY[ipart]) * (self->beta - ipart);
+        x = (sin1 - ind * sin2) / (1 + ind2 - 2 * ind * cos1);
+        self->theta += freq_delta;
+        self->beta += mod_delta;
+        self->theta = Sine_clip(self->theta);
+        self->beta = Sine_clip(self->beta);
+
+        y = x - self->xn1 + 0.995 * self->yn1;
+        self->xn1 = x; self->yn1 = y;
+
+        self->data[i] = y * (1 - ind2);
     }
 }
 
 static void
-Lorenz_readframes_ia(Lorenz *self) {
-    MYFLT delta, pit, chao;
-    int i;
-    
-    pit = PyFloat_AS_DOUBLE(self->pitch);
-    MYFLT *ch = Stream_getData((Stream *)self->chaos_stream);
-    
-    if (pit < 0.0)
-        pit = 1.0;
-    else if (pit > 1.0)
-        pit = 750.0;
-    else
-        pit = pit * 749.0 + 1.0;
-    delta = self->oneOnSr * pit;
-    
+SumOsc_readframes_iaa(SumOsc *self) {
+    MYFLT ratio, ind, mod_freq, mod_delta, freq_delta, x, y, ind2, theta_minus_beta, sin1, sin2, cos1;
+    int i, ipart;
+
+    MYFLT freq = PyFloat_AS_DOUBLE(self->freq);
+    MYFLT *rat = Stream_getData((Stream *)self->ratio_stream);
+    MYFLT *index = Stream_getData((Stream *)self->index_stream);
+
+    freq_delta = freq * self->scaleFactor;
+
     for (i=0; i<self->bufsize; i++) {
-        chao = ch[i];
-        if (chao < 0.0)
-            chao = 0.5;
-        else if (chao > 1.0)
-            chao = 3.0;
-        else
-            chao = chao * 2.5 + 0.5;        
-        self->vDX = self->pA * (self->vY - self->vX);
-        self->vDY = self->vX * (self->pB - self->vZ) - self->vY;
-        self->vDZ = self->vX * self->vY - chao * self->vZ;
-        
-        self->vX += self->vDX * delta;
-        self->vY += self->vDY * delta;
-        self->vZ += self->vDZ * delta;
-        
-        self->data[i] = self->vX * LORENZ_SCALE;
-        self->altBuffer[i] = self->vY * LORENZ_ALT_SCALE;
+        ind = index[i];
+        ratio = rat[i];
+        mod_freq = freq * ratio;
+        mod_delta = mod_freq * self->scaleFactor;
+        if (ind < 0)
+            ind = 0;
+        else if (ind > 0.999)
+            ind = 0.999;
+        ind2 = ind * ind;
+        ipart = (int)self->theta;
+        sin1 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (self->theta - ipart);
+        theta_minus_beta = Sine_clip(self->theta - self->beta);
+        ipart = (int)theta_minus_beta;
+        sin2 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (theta_minus_beta - ipart);
+        ipart = (int)self->beta;
+        cos1 = COSINE_ARRAY[ipart] + (COSINE_ARRAY[ipart+1] - COSINE_ARRAY[ipart]) * (self->beta - ipart);
+        x = (sin1 - ind * sin2) / (1 + ind2 - 2 * ind * cos1);
+        self->theta += freq_delta;
+        self->beta += mod_delta;
+        self->theta = Sine_clip(self->theta);
+        self->beta = Sine_clip(self->beta);
+
+        y = x - self->xn1 + 0.995 * self->yn1;
+        self->xn1 = x; self->yn1 = y;
+
+        self->data[i] = y * (1 - ind2);
     }
 }
 
 static void
-Lorenz_readframes_aa(Lorenz *self) {
-    MYFLT delta, pit, chao;
-    int i;
-    
-    MYFLT *fr = Stream_getData((Stream *)self->pitch_stream);
-    MYFLT *ch = Stream_getData((Stream *)self->chaos_stream);
-    
+SumOsc_readframes_aaa(SumOsc *self) {
+    MYFLT freq, ratio, ind, mod_freq, mod_delta, freq_delta, x, y, ind2, theta_minus_beta, sin1, sin2, cos1;
+    int i, ipart;
+
+    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
+    MYFLT *rat = Stream_getData((Stream *)self->ratio_stream);
+    MYFLT *index = Stream_getData((Stream *)self->index_stream);
+
     for (i=0; i<self->bufsize; i++) {
-        pit = fr[i];
-        if (pit < 0.0)
-            pit = 1.0;
-        else if (pit > 1.0)
-            pit = 750.0;
-        else
-            pit = pit * 749.0 + 1.0;
-        delta = self->oneOnSr * pit;
-        
-        chao = ch[i];
-        if (chao < 0.0)
-            chao = 0.5;
-        else if (chao > 1.0)
-            chao = 3.0;
-        else
-            chao = chao * 2.5 + 0.5;        
-        self->vDX = self->pA * (self->vY - self->vX);
-        self->vDY = self->vX * (self->pB - self->vZ) - self->vY;
-        self->vDZ = self->vX * self->vY - chao * self->vZ;
-        
-        self->vX += self->vDX * delta;
-        self->vY += self->vDY * delta;
-        self->vZ += self->vDZ * delta;
-        
-        self->data[i] = self->vX * LORENZ_SCALE;
-        self->altBuffer[i] = self->vY * LORENZ_ALT_SCALE;
+        freq = fr[i];
+        ind = index[i];
+        ratio = rat[i];
+        freq_delta = freq * self->scaleFactor;
+        mod_freq = freq * ratio;
+        mod_delta = mod_freq * self->scaleFactor;
+        if (ind < 0)
+            ind = 0;
+        else if (ind > 0.999)
+            ind = 0.999;
+        ind2 = ind * ind;
+        ipart = (int)self->theta;
+        sin1 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (self->theta - ipart);
+        theta_minus_beta = Sine_clip(self->theta - self->beta);
+        ipart = (int)theta_minus_beta;
+        sin2 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (theta_minus_beta - ipart);
+        ipart = (int)self->beta;
+        cos1 = COSINE_ARRAY[ipart] + (COSINE_ARRAY[ipart+1] - COSINE_ARRAY[ipart]) * (self->beta - ipart);
+        x = (sin1 - ind * sin2) / (1 + ind2 - 2 * ind * cos1);
+        self->theta += freq_delta;
+        self->beta += mod_delta;
+        self->theta = Sine_clip(self->theta);
+        self->beta = Sine_clip(self->beta);
+
+        y = x - self->xn1 + 0.995 * self->yn1;
+        self->xn1 = x; self->yn1 = y;
+
+        self->data[i] = y * (1 - ind2);
     }
 }
 
-static void Lorenz_postprocessing_ii(Lorenz *self) { POST_PROCESSING_II };
-static void Lorenz_postprocessing_ai(Lorenz *self) { POST_PROCESSING_AI };
-static void Lorenz_postprocessing_ia(Lorenz *self) { POST_PROCESSING_IA };
-static void Lorenz_postprocessing_aa(Lorenz *self) { POST_PROCESSING_AA };
-static void Lorenz_postprocessing_ireva(Lorenz *self) { POST_PROCESSING_IREVA };
-static void Lorenz_postprocessing_areva(Lorenz *self) { POST_PROCESSING_AREVA };
-static void Lorenz_postprocessing_revai(Lorenz *self) { POST_PROCESSING_REVAI };
-static void Lorenz_postprocessing_revaa(Lorenz *self) { POST_PROCESSING_REVAA };
-static void Lorenz_postprocessing_revareva(Lorenz *self) { POST_PROCESSING_REVAREVA };
+static void SumOsc_postprocessing_ii(SumOsc *self) { POST_PROCESSING_II };
+static void SumOsc_postprocessing_ai(SumOsc *self) { POST_PROCESSING_AI };
+static void SumOsc_postprocessing_ia(SumOsc *self) { POST_PROCESSING_IA };
+static void SumOsc_postprocessing_aa(SumOsc *self) { POST_PROCESSING_AA };
+static void SumOsc_postprocessing_ireva(SumOsc *self) { POST_PROCESSING_IREVA };
+static void SumOsc_postprocessing_areva(SumOsc *self) { POST_PROCESSING_AREVA };
+static void SumOsc_postprocessing_revai(SumOsc *self) { POST_PROCESSING_REVAI };
+static void SumOsc_postprocessing_revaa(SumOsc *self) { POST_PROCESSING_REVAA };
+static void SumOsc_postprocessing_revareva(SumOsc *self) { POST_PROCESSING_REVAREVA };
 
 static void
-Lorenz_setProcMode(Lorenz *self)
+SumOsc_setProcMode(SumOsc *self)
 {
     int procmode, muladdmode;
-    procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
+    procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:        
-            self->proc_func_ptr = Lorenz_readframes_ii;
+        case 0:
+            self->proc_func_ptr = SumOsc_readframes_iii;
             break;
-        case 1:    
-            self->proc_func_ptr = Lorenz_readframes_ai;
+        case 1:
+            self->proc_func_ptr = SumOsc_readframes_aii;
             break;
-        case 10:        
-            self->proc_func_ptr = Lorenz_readframes_ia;
+        case 10:
+            self->proc_func_ptr = SumOsc_readframes_iai;
             break;
-        case 11:    
-            self->proc_func_ptr = Lorenz_readframes_aa;
+        case 11:
+            self->proc_func_ptr = SumOsc_readframes_aai;
             break;
-    } 
-    
+        case 100:
+            self->proc_func_ptr = SumOsc_readframes_iia;
+            break;
+        case 101:
+            self->proc_func_ptr = SumOsc_readframes_aia;
+            break;
+        case 110:
+            self->proc_func_ptr = SumOsc_readframes_iaa;
+            break;
+        case 111:
+            self->proc_func_ptr = SumOsc_readframes_aaa;
+            break;
+    }
+
 	switch (muladdmode) {
-        case 0:        
-            self->muladd_func_ptr = Lorenz_postprocessing_ii;
+        case 0:
+            self->muladd_func_ptr = SumOsc_postprocessing_ii;
             break;
-        case 1:    
-            self->muladd_func_ptr = Lorenz_postprocessing_ai;
+        case 1:
+            self->muladd_func_ptr = SumOsc_postprocessing_ai;
             break;
-        case 2:    
-            self->muladd_func_ptr = Lorenz_postprocessing_revai;
+        case 2:
+            self->muladd_func_ptr = SumOsc_postprocessing_revai;
             break;
-        case 10:        
-            self->muladd_func_ptr = Lorenz_postprocessing_ia;
+        case 10:
+            self->muladd_func_ptr = SumOsc_postprocessing_ia;
             break;
-        case 11:    
-            self->muladd_func_ptr = Lorenz_postprocessing_aa;
+        case 11:
+            self->muladd_func_ptr = SumOsc_postprocessing_aa;
             break;
-        case 12:    
-            self->muladd_func_ptr = Lorenz_postprocessing_revaa;
+        case 12:
+            self->muladd_func_ptr = SumOsc_postprocessing_revaa;
             break;
-        case 20:        
-            self->muladd_func_ptr = Lorenz_postprocessing_ireva;
+        case 20:
+            self->muladd_func_ptr = SumOsc_postprocessing_ireva;
             break;
-        case 21:    
-            self->muladd_func_ptr = Lorenz_postprocessing_areva;
+        case 21:
+            self->muladd_func_ptr = SumOsc_postprocessing_areva;
             break;
-        case 22:    
-            self->muladd_func_ptr = Lorenz_postprocessing_revareva;
+        case 22:
+            self->muladd_func_ptr = SumOsc_postprocessing_revareva;
             break;
     }
 }
 
 static void
-Lorenz_compute_next_data_frame(Lorenz *self)
+SumOsc_compute_next_data_frame(SumOsc *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
 static int
-Lorenz_traverse(Lorenz *self, visitproc visit, void *arg)
+SumOsc_traverse(SumOsc *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->pitch);    
-    Py_VISIT(self->pitch_stream);    
-    Py_VISIT(self->chaos);    
-    Py_VISIT(self->chaos_stream);    
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->ratio);
+    Py_VISIT(self->ratio_stream);
+    Py_VISIT(self->index);
+    Py_VISIT(self->index_stream);
     return 0;
 }
 
-static int 
-Lorenz_clear(Lorenz *self)
+static int
+SumOsc_clear(SumOsc *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->pitch);    
-    Py_CLEAR(self->pitch_stream);    
-    Py_CLEAR(self->chaos);    
-    Py_CLEAR(self->chaos_stream);    
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->ratio);
+    Py_CLEAR(self->ratio_stream);
+    Py_CLEAR(self->index);
+    Py_CLEAR(self->index_stream);
     return 0;
 }
 
 static void
-Lorenz_dealloc(Lorenz* self)
+SumOsc_dealloc(SumOsc* self)
 {
     pyo_DEALLOC
-    free(self->altBuffer);
-    Lorenz_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    SumOsc_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
-Lorenz_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+SumOsc_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
-    PyObject *pitchtmp=NULL, *chaostmp=NULL, *multmp=NULL, *addtmp=NULL;
-    Lorenz *self;
-    self = (Lorenz *)type->tp_alloc(type, 0);
-    
-    self->pitch = PyFloat_FromDouble(0.25);    
-    self->chaos = PyFloat_FromDouble(0.5);    
-    self->pA = 10.0;
-    self->pB = 28.0;
-    self->vDX = self->vDY = self->vDZ = 0.0;
-    self->vX = self->vY = self->vZ = 1.0;
+    PyObject *freqtmp=NULL, *ratiotmp=NULL, *indextmp=NULL, *multmp=NULL, *addtmp=NULL;
+    SumOsc *self;
+    self = (SumOsc *)type->tp_alloc(type, 0);
+
+    self->freq = PyFloat_FromDouble(100);
+    self->ratio = PyFloat_FromDouble(0.5);
+    self->index = PyFloat_FromDouble(0.5);
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
-    
+	self->modebuffer[4] = 0;
+    self->theta = self->beta = 0.;
+    self->xn1 = self->yn1 = 0.0;
+
     INIT_OBJECT_COMMON
-    Stream_setFunctionPtr(self->stream, Lorenz_compute_next_data_frame);
-    self->mode_func_ptr = Lorenz_setProcMode;
-    
-    self->oneOnSr = 1.0 / self->sr;
- 
-    static char *kwlist[] = {"pitch", "chaos", "mul", "add", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &pitchtmp, &chaostmp, &multmp, &addtmp))
+    Stream_setFunctionPtr(self->stream, SumOsc_compute_next_data_frame);
+    self->mode_func_ptr = SumOsc_setProcMode;
+
+    self->scaleFactor = 512.0 / self->sr;
+
+    static char *kwlist[] = {"freq", "ratio", "index", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOO", kwlist, &freqtmp, &ratiotmp, &indextmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
-    if (pitchtmp) {
-        PyObject_CallMethod((PyObject *)self, "setPitch", "O", pitchtmp);
+
+    if (freqtmp) {
+        PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    
-    if (chaostmp) {
-        PyObject_CallMethod((PyObject *)self, "setChaos", "O", chaostmp);
+
+    if (ratiotmp) {
+        PyObject_CallMethod((PyObject *)self, "setRatio", "O", ratiotmp);
     }
-    
+
+    if (indextmp) {
+        PyObject_CallMethod((PyObject *)self, "setIndex", "O", indextmp);
+    }
+
     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->altBuffer = (MYFLT *)realloc(self->altBuffer, self->bufsize * sizeof(MYFLT));
-    
-    for (i=0; i<self->bufsize; i++) {
-        self->altBuffer[i] = 0.0;
-    }    
-    
+
     (*self->mode_func_ptr)(self);
-   
+
     return (PyObject *)self;
 }
 
-static PyObject * Lorenz_getServer(Lorenz* self) { GET_SERVER };
-static PyObject * Lorenz_getStream(Lorenz* self) { GET_STREAM };
-static PyObject * Lorenz_setMul(Lorenz *self, PyObject *arg) { SET_MUL };	
-static PyObject * Lorenz_setAdd(Lorenz *self, PyObject *arg) { SET_ADD };	
-static PyObject * Lorenz_setSub(Lorenz *self, PyObject *arg) { SET_SUB };	
-static PyObject * Lorenz_setDiv(Lorenz *self, PyObject *arg) { SET_DIV };	
+static PyObject * SumOsc_getServer(SumOsc* self) { GET_SERVER };
+static PyObject * SumOsc_getStream(SumOsc* self) { GET_STREAM };
+static PyObject * SumOsc_setMul(SumOsc *self, PyObject *arg) { SET_MUL };
+static PyObject * SumOsc_setAdd(SumOsc *self, PyObject *arg) { SET_ADD };
+static PyObject * SumOsc_setSub(SumOsc *self, PyObject *arg) { SET_SUB };
+static PyObject * SumOsc_setDiv(SumOsc *self, PyObject *arg) { SET_DIV };
 
-static PyObject * Lorenz_play(Lorenz *self, PyObject *args, PyObject *kwds) { PLAY };
-static PyObject * Lorenz_out(Lorenz *self, PyObject *args, PyObject *kwds) { OUT };
-static PyObject * Lorenz_stop(Lorenz *self) { STOP };
+static PyObject * SumOsc_play(SumOsc *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * SumOsc_out(SumOsc *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * SumOsc_stop(SumOsc *self) { STOP };
 
-static PyObject * Lorenz_multiply(Lorenz *self, PyObject *arg) { MULTIPLY };
-static PyObject * Lorenz_inplace_multiply(Lorenz *self, PyObject *arg) { INPLACE_MULTIPLY };
-static PyObject * Lorenz_add(Lorenz *self, PyObject *arg) { ADD };
-static PyObject * Lorenz_inplace_add(Lorenz *self, PyObject *arg) { INPLACE_ADD };
-static PyObject * Lorenz_sub(Lorenz *self, PyObject *arg) { SUB };
-static PyObject * Lorenz_inplace_sub(Lorenz *self, PyObject *arg) { INPLACE_SUB };
-static PyObject * Lorenz_div(Lorenz *self, PyObject *arg) { DIV };
-static PyObject * Lorenz_inplace_div(Lorenz *self, PyObject *arg) { INPLACE_DIV };
+static PyObject * SumOsc_multiply(SumOsc *self, PyObject *arg) { MULTIPLY };
+static PyObject * SumOsc_inplace_multiply(SumOsc *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * SumOsc_add(SumOsc *self, PyObject *arg) { ADD };
+static PyObject * SumOsc_inplace_add(SumOsc *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * SumOsc_sub(SumOsc *self, PyObject *arg) { SUB };
+static PyObject * SumOsc_inplace_sub(SumOsc *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * SumOsc_div(SumOsc *self, PyObject *arg) { DIV };
+static PyObject * SumOsc_inplace_div(SumOsc *self, PyObject *arg) { INPLACE_DIV };
 
 static PyObject *
-Lorenz_setPitch(Lorenz *self, PyObject *arg)
+SumOsc_setFreq(SumOsc *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
-	Py_DECREF(self->pitch);
+	Py_DECREF(self->freq);
 	if (isNumber == 1) {
-		self->pitch = PyNumber_Float(tmp);
+		self->freq = PyNumber_Float(tmp);
         self->modebuffer[2] = 0;
 	}
 	else {
-		self->pitch = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->pitch, "_getStream", NULL);
+		self->freq = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL);
         Py_INCREF(streamtmp);
-        Py_XDECREF(self->pitch_stream);
-        self->pitch_stream = (Stream *)streamtmp;
+        Py_XDECREF(self->freq_stream);
+        self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
-Lorenz_setChaos(Lorenz *self, PyObject *arg)
+SumOsc_setRatio(SumOsc *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
-	Py_DECREF(self->chaos);
+	Py_DECREF(self->ratio);
 	if (isNumber == 1) {
-		self->chaos = PyNumber_Float(tmp);
+		self->ratio = PyNumber_Float(tmp);
         self->modebuffer[3] = 0;
 	}
 	else {
-		self->chaos = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->chaos, "_getStream", NULL);
-        Py_INCREF(streamtmp);
-        Py_XDECREF(self->chaos_stream);
-        self->chaos_stream = (Stream *)streamtmp;
-		self->modebuffer[3] = 1;
-	}
-    
-    (*self->mode_func_ptr)(self);
-    
-	Py_INCREF(Py_None);
-	return Py_None;
-}	
-
-MYFLT *
-Lorenz_getAltBuffer(Lorenz *self)
-{
-    return (MYFLT *)self->altBuffer;
-}    
-
-static PyMemberDef Lorenz_members[] = {
-    {"server", T_OBJECT_EX, offsetof(Lorenz, server), 0, "Pyo server."},
-    {"stream", T_OBJECT_EX, offsetof(Lorenz, stream), 0, "Stream object."},
-    {"pitch", T_OBJECT_EX, offsetof(Lorenz, pitch), 0, "Pitch."},
-    {"chaos", T_OBJECT_EX, offsetof(Lorenz, chaos), 0, "Chaotic behavior."},
-    {"mul", T_OBJECT_EX, offsetof(Lorenz, mul), 0, "Mul factor."},
-    {"add", T_OBJECT_EX, offsetof(Lorenz, add), 0, "Add factor."},
-    {NULL}  /* Sentinel */
-};
-
-static PyMethodDef Lorenz_methods[] = {
-    {"getServer", (PyCFunction)Lorenz_getServer, METH_NOARGS, "Returns server object."},
-    {"_getStream", (PyCFunction)Lorenz_getStream, METH_NOARGS, "Returns stream object."},
-    {"play", (PyCFunction)Lorenz_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
-    {"out", (PyCFunction)Lorenz_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
-    {"stop", (PyCFunction)Lorenz_stop, METH_NOARGS, "Stops computing."},
-    {"setPitch", (PyCFunction)Lorenz_setPitch, METH_O, "Sets oscillator pitch."},
-    {"setChaos", (PyCFunction)Lorenz_setChaos, METH_O, "Sets oscillator chaotic behavior."},
-    {"setMul", (PyCFunction)Lorenz_setMul, METH_O, "Sets Lorenz mul factor."},
-    {"setAdd", (PyCFunction)Lorenz_setAdd, METH_O, "Sets Lorenz add factor."},
-    {"setSub", (PyCFunction)Lorenz_setSub, METH_O, "Sets inverse add factor."},
-    {"setDiv", (PyCFunction)Lorenz_setDiv, METH_O, "Sets inverse mul factor."},
-    {NULL}  /* Sentinel */
-};
-
-static PyNumberMethods Lorenz_as_number = {
-    (binaryfunc)Lorenz_add,                      /*nb_add*/
-    (binaryfunc)Lorenz_sub,                 /*nb_subtract*/
-    (binaryfunc)Lorenz_multiply,                 /*nb_multiply*/
-    (binaryfunc)Lorenz_div,                   /*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*/
-    0,                                          /*nb_coerce*/
-    0,                       /*nb_int*/
-    0,                      /*nb_long*/
-    0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
-    (binaryfunc)Lorenz_inplace_add,              /*inplace_add*/
-    (binaryfunc)Lorenz_inplace_sub,         /*inplace_subtract*/
-    (binaryfunc)Lorenz_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)Lorenz_inplace_div,           /*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*/
-    0,              /*nb_true_divide*/
-    0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
-    0,                     /* nb_index */
-};
-
-PyTypeObject LorenzType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
-    "_pyo.Lorenz_base",         /*tp_name*/
-    sizeof(Lorenz),         /*tp_basicsize*/
-    0,                         /*tp_itemsize*/
-    (destructor)Lorenz_dealloc, /*tp_dealloc*/
-    0,                         /*tp_print*/
-    0,                         /*tp_getattr*/
-    0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
-    0,                         /*tp_repr*/
-    &Lorenz_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*/
-    "Lorenz objects. Lorenz attractor.",           /* tp_doc */
-    (traverseproc)Lorenz_traverse,   /* tp_traverse */
-    (inquiry)Lorenz_clear,           /* tp_clear */
-    0,		               /* tp_richcompare */
-    0,		               /* tp_weaklistoffset */
-    0,		               /* tp_iter */
-    0,		               /* tp_iternext */
-    Lorenz_methods,             /* tp_methods */
-    Lorenz_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 */
-    Lorenz_new,                 /* tp_new */
-};
-
-typedef struct {
-    pyo_audio_HEAD
-    Lorenz *mainLorenz;
-    int modebuffer[2];
-} LorenzAlt;
-
-static void LorenzAlt_postprocessing_ii(LorenzAlt *self) { POST_PROCESSING_II };
-static void LorenzAlt_postprocessing_ai(LorenzAlt *self) { POST_PROCESSING_AI };
-static void LorenzAlt_postprocessing_ia(LorenzAlt *self) { POST_PROCESSING_IA };
-static void LorenzAlt_postprocessing_aa(LorenzAlt *self) { POST_PROCESSING_AA };
-static void LorenzAlt_postprocessing_ireva(LorenzAlt *self) { POST_PROCESSING_IREVA };
-static void LorenzAlt_postprocessing_areva(LorenzAlt *self) { POST_PROCESSING_AREVA };
-static void LorenzAlt_postprocessing_revai(LorenzAlt *self) { POST_PROCESSING_REVAI };
-static void LorenzAlt_postprocessing_revaa(LorenzAlt *self) { POST_PROCESSING_REVAA };
-static void LorenzAlt_postprocessing_revareva(LorenzAlt *self) { POST_PROCESSING_REVAREVA };
-
-static void
-LorenzAlt_setProcMode(LorenzAlt *self) {
-    int muladdmode;
-    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
-    switch (muladdmode) {
-        case 0:        
-            self->muladd_func_ptr = LorenzAlt_postprocessing_ii;
-            break;
-        case 1:    
-            self->muladd_func_ptr = LorenzAlt_postprocessing_ai;
-            break;
-        case 2:    
-            self->muladd_func_ptr = LorenzAlt_postprocessing_revai;
-            break;
-        case 10:        
-            self->muladd_func_ptr = LorenzAlt_postprocessing_ia;
-            break;
-        case 11:    
-            self->muladd_func_ptr = LorenzAlt_postprocessing_aa;
-            break;
-        case 12:    
-            self->muladd_func_ptr = LorenzAlt_postprocessing_revaa;
-            break;
-        case 20:        
-            self->muladd_func_ptr = LorenzAlt_postprocessing_ireva;
-            break;
-        case 21:    
-            self->muladd_func_ptr = LorenzAlt_postprocessing_areva;
-            break;
-        case 22:    
-            self->muladd_func_ptr = LorenzAlt_postprocessing_revareva;
-            break;
-    }  
-}
-
-static void
-LorenzAlt_compute_next_data_frame(LorenzAlt *self)
-{
-    int i;
-    MYFLT *tmp;
-    tmp = Lorenz_getAltBuffer((Lorenz *)self->mainLorenz);
-    for (i=0; i<self->bufsize; i++) {
-        self->data[i] = tmp[i];
-    }    
-    (*self->muladd_func_ptr)(self);
-}
-
-static int
-LorenzAlt_traverse(LorenzAlt *self, visitproc visit, void *arg)
-{
-    pyo_VISIT
-    Py_VISIT(self->mainLorenz);
-    return 0;
-}
+		self->ratio = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->ratio, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->ratio_stream);
+        self->ratio_stream = (Stream *)streamtmp;
+		self->modebuffer[3] = 1;
+	}
 
-static int 
-LorenzAlt_clear(LorenzAlt *self)
-{
-    pyo_CLEAR
-    Py_CLEAR(self->mainLorenz);    
-    return 0;
-}
+    (*self->mode_func_ptr)(self);
 
-static void
-LorenzAlt_dealloc(LorenzAlt* self)
-{
-    pyo_DEALLOC
-    LorenzAlt_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+	Py_INCREF(Py_None);
+	return Py_None;
 }
 
 static PyObject *
-LorenzAlt_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+SumOsc_setIndex(SumOsc *self, PyObject *arg)
 {
-    int i;
-    PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL;
-    LorenzAlt *self;
-    self = (LorenzAlt *)type->tp_alloc(type, 0);
-    
-    self->modebuffer[0] = 0;
-    self->modebuffer[1] = 0;
-    
-    INIT_OBJECT_COMMON
-    Stream_setFunctionPtr(self->stream, LorenzAlt_compute_next_data_frame);
-    self->mode_func_ptr = LorenzAlt_setProcMode;
+	PyObject *tmp, *streamtmp;
 
-    static char *kwlist[] = {"mainLorenz", "mul", "alt", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &maintmp, &multmp, &addtmp))
-        Py_RETURN_NONE;
-    
-    Py_XDECREF(self->mainLorenz);
-    Py_INCREF(maintmp);
-    self->mainLorenz = (Lorenz *)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;
-}
+    ASSERT_ARG_NOT_NULL
 
-static PyObject * LorenzAlt_getServer(LorenzAlt* self) { GET_SERVER };
-static PyObject * LorenzAlt_getStream(LorenzAlt* self) { GET_STREAM };
-static PyObject * LorenzAlt_setMul(LorenzAlt *self, PyObject *arg) { SET_MUL };	
-static PyObject * LorenzAlt_setAdd(LorenzAlt *self, PyObject *arg) { SET_ADD };	
-static PyObject * LorenzAlt_setSub(LorenzAlt *self, PyObject *arg) { SET_SUB };	
-static PyObject * LorenzAlt_setDiv(LorenzAlt *self, PyObject *arg) { SET_DIV };	
+	int isNumber = PyNumber_Check(arg);
 
-static PyObject * LorenzAlt_play(LorenzAlt *self, PyObject *args, PyObject *kwds) { PLAY };
-static PyObject * LorenzAlt_out(LorenzAlt *self, PyObject *args, PyObject *kwds) { OUT };
-static PyObject * LorenzAlt_stop(LorenzAlt *self) { STOP };
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->index);
+	if (isNumber == 1) {
+		self->index = PyNumber_Float(tmp);
+        self->modebuffer[4] = 0;
+	}
+	else {
+		self->index = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->index, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->index_stream);
+        self->index_stream = (Stream *)streamtmp;
+		self->modebuffer[4] = 1;
+	}
 
-static PyObject * LorenzAlt_multiply(LorenzAlt *self, PyObject *arg) { MULTIPLY };
-static PyObject * LorenzAlt_inplace_multiply(LorenzAlt *self, PyObject *arg) { INPLACE_MULTIPLY };
-static PyObject * LorenzAlt_add(LorenzAlt *self, PyObject *arg) { ADD };
-static PyObject * LorenzAlt_inplace_add(LorenzAlt *self, PyObject *arg) { INPLACE_ADD };
-static PyObject * LorenzAlt_sub(LorenzAlt *self, PyObject *arg) { SUB };
-static PyObject * LorenzAlt_inplace_sub(LorenzAlt *self, PyObject *arg) { INPLACE_SUB };
-static PyObject * LorenzAlt_div(LorenzAlt *self, PyObject *arg) { DIV };
-static PyObject * LorenzAlt_inplace_div(LorenzAlt *self, PyObject *arg) { INPLACE_DIV };
+    (*self->mode_func_ptr)(self);
 
-static PyMemberDef LorenzAlt_members[] = {
-    {"server", T_OBJECT_EX, offsetof(LorenzAlt, server), 0, "Pyo server."},
-    {"stream", T_OBJECT_EX, offsetof(LorenzAlt, stream), 0, "Stream object."},
-    {"mul", T_OBJECT_EX, offsetof(LorenzAlt, mul), 0, "Mul factor."},
-    {"add", T_OBJECT_EX, offsetof(LorenzAlt, add), 0, "Add factor."},
-    {NULL}  /* Sentinel */
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyMemberDef SumOsc_members[] = {
+{"server", T_OBJECT_EX, offsetof(SumOsc, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(SumOsc, stream), 0, "Stream object."},
+{"freq", T_OBJECT_EX, offsetof(SumOsc, freq), 0, "Frequency in cycle per second."},
+{"ratio", T_OBJECT_EX, offsetof(SumOsc, ratio), 0, "Ratio freq:modulator (mod freq = freq*ratio)."},
+{"index", T_OBJECT_EX, offsetof(SumOsc, index), 0, "Index, high frequency damping."},
+{"mul", T_OBJECT_EX, offsetof(SumOsc, mul), 0, "Mul factor."},
+{"add", T_OBJECT_EX, offsetof(SumOsc, add), 0, "Add factor."},
+{NULL}  /* Sentinel */
 };
 
-static PyMethodDef LorenzAlt_methods[] = {
-    {"getServer", (PyCFunction)LorenzAlt_getServer, METH_NOARGS, "Returns server object."},
-    {"_getStream", (PyCFunction)LorenzAlt_getStream, METH_NOARGS, "Returns stream object."},
-    {"play", (PyCFunction)LorenzAlt_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
-    {"out", (PyCFunction)LorenzAlt_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
-    {"stop", (PyCFunction)LorenzAlt_stop, METH_NOARGS, "Stops computing."},
-    {"setMul", (PyCFunction)LorenzAlt_setMul, METH_O, "Sets oscillator mul factor."},
-    {"setAdd", (PyCFunction)LorenzAlt_setAdd, METH_O, "Sets oscillator add factor."},
-    {"setSub", (PyCFunction)LorenzAlt_setSub, METH_O, "Sets inverse add factor."},
-    {"setDiv", (PyCFunction)LorenzAlt_setDiv, METH_O, "Sets inverse mul factor."},        
-    {NULL}  /* Sentinel */
+static PyMethodDef SumOsc_methods[] = {
+{"getServer", (PyCFunction)SumOsc_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)SumOsc_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)SumOsc_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundfreqd."},
+{"out", (PyCFunction)SumOsc_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundfreqd channel speficied by argument."},
+{"stop", (PyCFunction)SumOsc_stop, METH_NOARGS, "Stops computing."},
+{"setFreq", (PyCFunction)SumOsc_setFreq, METH_O, "Sets oscillator frequency in cycle per second."},
+{"setRatio", (PyCFunction)SumOsc_setRatio, METH_O, "Sets freq:mod ratio."},
+{"setIndex", (PyCFunction)SumOsc_setIndex, METH_O, "Sets high frequency damping."},
+{"setMul", (PyCFunction)SumOsc_setMul, METH_O, "Sets SumOsc mul factor."},
+{"setAdd", (PyCFunction)SumOsc_setAdd, METH_O, "Sets SumOsc add factor."},
+{"setSub", (PyCFunction)SumOsc_setSub, METH_O, "Sets inverse add factor."},
+{"setDiv", (PyCFunction)SumOsc_setDiv, METH_O, "Sets inverse mul factor."},
+{NULL}  /* Sentinel */
 };
-static PyNumberMethods LorenzAlt_as_number = {
-    (binaryfunc)LorenzAlt_add,                         /*nb_add*/
-    (binaryfunc)LorenzAlt_sub,                         /*nb_subtract*/
-    (binaryfunc)LorenzAlt_multiply,                    /*nb_multiply*/
-    (binaryfunc)LorenzAlt_div,                                              /*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*/
-    0,                                              /*nb_coerce*/
-    0,                                              /*nb_int*/
-    0,                                              /*nb_long*/
-    0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
-    (binaryfunc)LorenzAlt_inplace_add,                 /*inplace_add*/
-    (binaryfunc)LorenzAlt_inplace_sub,                 /*inplace_subtract*/
-    (binaryfunc)LorenzAlt_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)LorenzAlt_inplace_div,                                              /*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*/
-    0,                                              /*nb_true_divide*/
-    0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
-    0,                                              /* nb_index */
+
+static PyNumberMethods SumOsc_as_number = {
+(binaryfunc)SumOsc_add,                      /*nb_add*/
+(binaryfunc)SumOsc_sub,                 /*nb_subtract*/
+(binaryfunc)SumOsc_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)SumOsc_inplace_add,              /*inplace_add*/
+(binaryfunc)SumOsc_inplace_sub,         /*inplace_subtract*/
+(binaryfunc)SumOsc_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)SumOsc_div,                       /*nb_true_divide*/
+0,     /*nb_inplace_floor_divide*/
+(binaryfunc)SumOsc_inplace_div,                       /*nb_inplace_true_divide*/
+0,                     /* nb_index */
 };
 
-PyTypeObject LorenzAltType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
-    "_pyo.LorenzAlt_base",         /*tp_name*/
-    sizeof(LorenzAlt),         /*tp_basicsize*/
-    0,                         /*tp_itemsize*/
-    (destructor)LorenzAlt_dealloc, /*tp_dealloc*/
-    0,                         /*tp_print*/
-    0,                         /*tp_getattr*/
-    0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
-    0,                         /*tp_repr*/
-    &LorenzAlt_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*/
-    "LorenzAlt objects. Sends the alternate signal of a Lorenz attractor.",           /* tp_doc */
-    (traverseproc)LorenzAlt_traverse,   /* tp_traverse */
-    (inquiry)LorenzAlt_clear,           /* tp_clear */
-    0,		               /* tp_richcompare */
-    0,		               /* tp_weaklistoffset */
-    0,		               /* tp_iter */
-    0,		               /* tp_iternext */
-    LorenzAlt_methods,             /* tp_methods */
-    LorenzAlt_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 */
-    LorenzAlt_new,                 /* tp_new */
+PyTypeObject SumOscType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.SumOsc_base",         /*tp_name*/
+sizeof(SumOsc),         /*tp_basicsize*/
+0,                         /*tp_itemsize*/
+(destructor)SumOsc_dealloc, /*tp_dealloc*/
+0,                         /*tp_print*/
+0,                         /*tp_getattr*/
+0,                         /*tp_setattr*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
+0,                         /*tp_repr*/
+&SumOsc_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*/
+"SumOsc objects. Infite summation oscillator.",           /* tp_doc */
+(traverseproc)SumOsc_traverse,   /* tp_traverse */
+(inquiry)SumOsc_clear,           /* tp_clear */
+0,		               /* tp_richcompare */
+0,		               /* tp_weaklistoffset */
+0,		               /* tp_iter */
+0,		               /* tp_iternext */
+SumOsc_methods,             /* tp_methods */
+SumOsc_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 */
+SumOsc_new,                 /* tp_new */
 };
 
-/*************/
-/* SumOsc object */
-/*************/
+static MYFLT SUPERSAW_DETUNES[7][128] = {{1.0, 0.9999999999999738, 0.9999999999983218, 0.9999999999808844, 0.9999999998925958, 0.9999999995902856, 0.9999999987765995, 0.999999996915041, 0.9999999931261337, 0.9999999860647035, 0.9999999737782811, 0.9999999535466255, 0.999999921702367, 0.9999998734327713, 0.9999998025626238, 0.9999997013182335, 0.9999995600725585, 0.9999993670714514, 0.999999108141024, 0.9999987663761343, 0.999998321809992, 0.9999977510648862, 0.9999970269840314, 0.9999961182445354, 0.9999949889514873, 0.9999935982131656, 0.999991899697366, 0.9999898411688514, 0.9999873640079204, 0.999984402710097, 0.9999808843669409, 0.9999767281279772, 0.9999718446437478, 0.9999661354899821, 0.9999594925728883, 0.9999517975155655, 0.9999429210255355, 0.9999327222433956, 0.9999210480725913, 0.9999077324903094, 0.9998925958394921, 0.9998754441019703, 0.9998560681527183, 0.9998342429952286, 0.9998097269780065, 0.9997822609921857, 0.9997515676502643, 0.9997173504459607, 0.99967929289519, 0.9996370576581611, 0.9995902856425938, 0.9995385950880562, 0.999481580631423, 0.9994188123534535, 0.9993498348064905, 0.9992741660232791, 0.999191296506906, 0.9991006882018598, 0.9990017734462106, 0.9988939539049104, 0.9987765994842147, 0.9986490472272227, 0.9985106001905395, 0.9983605263020577, 0.9981980571998603, 0.9980223870522424, 0.9978326713588549, 0.9976280257329677, 0.9974075246648535, 0.9971702002662917, 0.996915040996193, 0.9966409903673441, 0.9963469456342734, 0.9960317564622357, 0.995694223577319, 0.9953330973976697, 0.9949470766458405, 0.9945348069422566, 0.994094879379803, 0.9936258290795327, 0.9931261337274945, 0.9925942120926815, 0.9920284225260998, 0.9914270614409579, 0.9907883617739762, 0.9901104914278165, 0.9893915516946329, 0.988629575660742, 0.9878225265924139, 0.9869682963027838, 0.9860647034998833, 0.985109492115793, 0.9841003296169146, 0.9830348052953636, 0.9819104285414826, 0.9807246270974751, 0.9794747452921589, 0.9781580422568408, 0.9767716901223106, 0.9753127721969568, 0.9737782811260014, 0.9721651170318559, 0.9704700856355972, 0.9686898963595642, 0.9668211604110741, 0.9648603888472602, 0.9628039906210292, 0.9606482706081385, 0.9583894276153956, 0.9560235523699754, 0.9535466254898602, 0.9509545154353983, 0.9482429764419842, 0.9454076464338582, 0.9424440449190272, 0.9393475708653054, 0.9361135005574749, 0.9327369854355683, 0.9292130499142693, 0.9255365891834358, 0.9217023669897422, 0.9177050133994422, 0.9135390225422524, 0.9091987503363557, 0.9046784121945255, 0.8999720807113701, 0.8950736833316975, 0.889977},
+{1.0, 0.999999999999985, 0.9999999999990408, 0.9999999999890743, 0.9999999999386124, 0.999999999765825, 0.999999999300757, 0.9999999982367705, 0.9999999960711946, 0.9999999920351857, 0.9999999850127967, 0.9999999734492553, 0.999999955248451, 0.9999999276596326, 0.9999998871533139, 0.9999998292863885, 0.9999997485564546, 0.9999996382453485, 0.9999994902518874, 0.9999992949138214, 0.9999990408189948, 0.9999987146057163, 0.9999983007523392, 0.9999977813560498, 0.9999971359008654, 0.9999963410148422, 0.9999953702164914, 0.9999941936504051, 0.9999927778120908, 0.9999910852620164, 0.9999890743288626, 0.9999866988019865, 0.9999839076130926, 0.9999806445071142, 0.9999768477023036, 0.9999724495395311, 0.9999673761207947, 0.9999615469369367, 0.999954874484572, 0.9999472638722232, 0.9999386124156673, 0.9999288092224893, 0.9999177347658472, 0.9999052604474442, 0.9998912481497119, 0.9998755497772012, 0.9998580067871834, 0.9998384497094605, 0.9998166976553837, 0.9997925578160827, 0.9997658249499025, 0.999736280859051, 0.9997036938554544, 0.9996678182158232, 0.9996283936259261, 0.9995851446140742, 0.9995377799738134, 0.9994859921758271, 0.9994294567690473, 0.9993678317709748, 0.9993007570472097, 0.9992278536801902, 0.9991487233271403, 0.9990629475672279, 0.9989700872379311, 0.998869681760614, 0.9987612484553119, 0.9986442818447255, 0.9985182529474248, 0.998382608560261, 0.9982367705299892, 0.998080135014099, 0.9979120717308554, 0.9977319231985478, 0.9975390039639489, 0.9973325998199832, 0.9971119670126036, 0.996876331436878, 0.9966248878222852, 0.9963567989072191, 0.9960711946027035, 0.9957671711453152, 0.9954437902393161, 0.9951000781879951, 0.9947350250142191, 0.9943475835701934, 0.9939366686364304, 0.9935011560099285, 0.9930398815815602, 0.9925516404026683, 0.9920351857408729, 0.9914892281250863, 0.9909124343797379, 0.9903034266482077, 0.9896607814054699, 0.9889830284599445, 0.9882686499445592, 0.9875160792970205, 0.9867237002292923, 0.9858898456862866, 0.9850127967937606, 0.984090781795425, 0.9831219749792602, 0.982104495593043, 0.9810364067490811, 0.9799157143181576, 0.978740365812685, 0.9775082492590679, 0.9762171920592747, 0.9748649598416194, 0.9734492553007513, 0.9719677170268558, 0.9704179183240623, 0.9687973660180627, 0.9671034992529387, 0.9653336882771985, 0.9634852332190221, 0.9615553628507172, 0.9595412333423818, 0.9574399270047795, 0.9552484510214205, 0.9529637361698543, 0.9505826355321707, 0.9481019231947095, 0.9455182929369806, 0.9428283569097924, 0.9400286443025894, 0.9371156},
+{1.0, 0.9999999999999953, 0.9999999999997022, 0.9999999999966079, 0.9999999999809411, 0.9999999999272962, 0.9999999997829073, 0.9999999994525735, 0.9999999987802313, 0.9999999975271793, 0.9999999953469515, 0.9999999917568408, 0.9999999861060718, 0.9999999775406239, 0.9999999649647041, 0.9999999469988698, 0.9999999219348009, 0.9999998876867218, 0.9999998417394735, 0.999999781093236, 0.9999997022048986, 0.9999996009260829, 0.9999994724378124, 0.9999993111818348, 0.999999110788592, 0.999998864001841, 0.9999985625999245, 0.9999981973136907, 0.9999977577410636, 0.9999972322582629, 0.9999966079276733, 0.9999958704023647, 0.9999950038272605, 0.9999939907369569, 0.9999928119501926, 0.9999914464609663, 0.9999898713263058, 0.9999880615506863, 0.9999859899670982, 0.9999836271147652, 0.9999809411135118, 0.9999778975347812, 0.999974459269302, 0.9999705863914059, 0.999966236019994, 0.9999613621761544, 0.9999559156374276, 0.9999498437887238, 0.9999430904698884, 0.9999355958199183, 0.9999272961178276, 0.9999181236201629, 0.9999080063951687, 0.9998968681536032, 0.9998846280762023, 0.9998712006377948, 0.9998564954280671, 0.9998404169689776, 0.9998228645288206, 0.9998037319329405, 0.9997829073710953, 0.9997602732014707, 0.9997357057513431, 0.999709075114393, 0.9996802449446679, 0.9996490722471952, 0.9996154071652449, 0.9995790927642417, 0.9995399648123278, 0.9994978515575741, 0.999452573501843, 0.9994039431712994, 0.9993517648835726, 0.9992958345115667, 0.9992359392439231, 0.9991718573421298, 0.9991033578942833, 0.9990302005654985, 0.998952135344969, 0.9988689022896773, 0.9987802312647548, 0.9986858416804911, 0.9985854422259942, 0.9984787305994991, 0.9983653932353271, 0.9982451050274953, 0.9981175290499744, 0.9979823162735979, 0.9978391052796202, 0.9976875219699247, 0.997527179273882, 0.9973576768518573, 0.9971786007953681, 0.9969895233238919, 0.9967900024783226, 0.9965795818110783, 0.9963577900728574, 0.9961241408960458, 0.995878132474773, 0.9956192472416178, 0.9953469515409651, 0.9950606952990115, 0.9947599116904207, 0.9944440168016286, 0.9941124092907996, 0.9937644700444305, 0.9933995618306056, 0.9930170289489021, 0.9926161968769434, 0.992196371913604, 0.9917568408188636, 0.9912968704503108, 0.9908157073962964, 0.9903125776057377, 0.9897866860145708, 0.9892372161688545, 0.9886633298445227, 0.9880641666637873, 0.9874388437081904, 0.9867864551283071, 0.9861060717500971, 0.985396740677907, 0.9846574848941214, 0.9838873028554654, 0.9830851680859551, 0.9822500287664989, 0.9813808073211485, 0.9804764},
+{1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0},
+{1.0, 1.0000000000000047, 1.0000000000003038, 1.0000000000034597, 1.0000000000194382, 1.000000000074151, 1.0000000002214138, 1.0000000005583225, 1.000000001244047, 1.0000000025220401, 1.0000000047456632, 1.000000008407232, 1.0000000141704746, 1.00000002290641, 1.0000000357326424, 1.0000000540560707, 1.0000000796190178, 1.0000001145487747, 1.0000001614105622, 1.0000002232639098, 1.0000003037224496, 1.0000004070171307, 1.0000005380628465, 1.0000007025284818, 1.000000906910375, 1.0000011586091981, 1.0000014660102534, 1.000001838567187, 1.0000022868891185, 1.00000282283119, 1.0000034595885279, 1.0000042117936259, 1.0000050956171416, 1.000006128872112, 1.000007331121585, 1.0000087237896673, 1.0000103302759908, 1.0000121760735943, 1.0000142888902226, 1.0000166987730426, 1.0000194382367766, 1.0000225423952513, 1.0000260490963657, 1.0000299990604729, 1.000034436022182, 1.0000394068755751, 1.0000449618228406, 1.0000511545263258, 1.0000580422640029, 1.0000656860883557, 1.0000741509886801, 1.0000835060568027, 1.0000938246562172, 1.0001051845946354, 1.0001176682999573, 1.000131362999657, 1.0001463609035854, 1.0001627593901905, 1.0001806611961532, 1.000200174609442, 1.0002214136657828, 1.0002444983485461, 1.000269554792052, 1.0002967154882902, 1.0003261194970592, 1.0003579126595197, 1.000392247815168, 1.0004292850222227, 1.0004691917814321, 1.0005121432632953, 1.000558322538702, 1.0006079208129879, 1.0006611376634087, 1.0007181812800294, 1.0007792687100308, 1.0008446261054336, 1.000914488974239, 1.0009891024349855, 1.0010687214747234, 1.0011536112104062, 1.0012440471536985, 1.0013403154792009, 1.0014427132960908, 1.001551548923183, 1.0016671421674035, 1.0017898246056827, 1.0019199398702647, 1.0020578439374328, 1.0022039054196534, 1.0023585058611355, 1.0025220400368071, 1.0026949162547094, 1.0028775566618078, 1.0030703975532176, 1.0032738896848503, 1.0034884985894736, 1.0037147048961896, 1.00395300465333, 1.004203909654768, 1.0044679477696459, 1.0047456632755227, 1.0050376171949345, 1.005344387635375, 1.0056665701326912, 1.006004777997897, 1.0063596426674022, 1.0067318140566603, 1.0071219609172322, 1.0075307711972652, 1.0079589524053931, 1.0084072319780484, 1.0088763576501938, 1.0093670978294713, 1.0098802419737667, 1.0104166009721909, 1.010977007529479, 1.0115623165538064, 1.0121734055480207, 1.0128111750042907, 1.013476548802174, 1.0141704746100983, 1.0148939242902633, 1.0156478943069556, 1.016433406138284, 1.0172515066913297, 1.0181032687207134, 1.01898979125058, 1.0199122},
+{1.0, 1.0000000000000149, 1.0000000000009481, 1.0000000000108007, 1.0000000000606857, 1.0000000002314975, 1.000000000691248, 1.0000000017430692, 1.0000000038838848, 1.0000000078737472, 1.0000000148158443, 1.000000026247172, 1.0000000442398742, 1.0000000715132509, 1.0000001115564334, 1.000000168761727, 1.0000002485686208, 1.0000003576184653, 1.0000005039198165, 1.00000069702445, 1.0000009482140382, 1.000001270697499, 1.0000016798190097, 1.0000021932766892, 1.0000028313519465, 1.0000036171494986, 1.0000045768480532, 1.0000057399616615, 1.000007139611736, 1.0000088128097373, 1.0000108007505284, 1.0000131491163944, 1.0000159083917324, 1.0000191341884066, 1.0000228875817727, 1.0000272354573667, 1.0000322508682655, 1.0000380134031104, 1.0000446095648012, 1.0000521331598566, 1.0000606856984415, 1.0000703768050623, 1.0000813246399298, 1.000093656330989, 1.0001075084166169, 1.0001230272989865, 1.0001403697080997, 1.0001597031764875, 1.0001812065245754, 1.0002050703567196, 1.0002314975679076, 1.0002607038611286, 1.000292918275409, 1.0003283837245178, 1.0003673575463365, 1.0004101120629, 1.000456935151101, 1.000508130824065, 1.000564019823191, 1.00062494022086, 1.000691248033811, 1.0007633178471849, 1.0008415434492337, 1.0009263384767009, 1.0010181370708653, 1.0011173945442546, 1.0012245880580264, 1.0013402173100148, 1.0014648052334467, 1.0015988987063238, 1.0017430692714728, 1.0018979138672632, 1.0020640555689915, 1.0022421443409335, 1.002432857799065, 1.0026369019844479, 1.0028550121472843, 1.00308795354164, 1.0033365222308317, 1.0036015459034857, 1.003883884700261, 1.0041844320512403, 1.0045041155239904, 1.004843897682287, 1.00520477695551, 1.0055877885187026, 1.0059940051833023, 1.0064245382985348, 1.006880538663479, 1.0073631974497963, 1.0078737471351296, 1.008413462447169, 1.008983661318385, 1.0095857058514275, 1.0102210032951957, 1.0108910070315718, 1.011597217572824, 1.0123411835696772, 1.0131245028300493, 1.0139488233484573, 1.0148158443460882, 1.0157273173215406, 1.0166850471122297, 1.017690892966463, 1.018746769626182, 1.0198546484203714, 1.0210165583691362, 1.022234587298445, 1.0235108829655426, 1.0248476541950278, 1.0262471720256006, 1.027711770867476, 1.0292438496704641, 1.0308458731027206, 1.0325203727401608, 1.0342699482665438, 1.0360972686842238, 1.0380050735355673, 1.0399961741350399, 1.042073454811958, 1.04423987416391, 1.0464984663208448, 1.0488523422198255, 1.051304690890453, 1.053858780750956, 1.0565179609149487, 1.0592856625088545, 1.0621654},
+{1.0, 1.0000000000000255, 1.000000000001639, 1.0000000000186688, 1.0000000001048943, 1.0000000004001401, 1.0000000011948122, 1.0000000030128702, 1.0000000067132389, 1.0000000136096587, 1.0000000256089738, 1.0000000453678595, 1.0000000764679864, 1.0000001236096256, 1.000000192823691, 1.0000002917022184, 1.0000004296472869, 1.0000006181383747, 1.000000871018157, 1.000001204796739, 1.0000016389743303, 1.000002196382355, 1.0000029035430034, 1.000003791047219, 1.0000048939511264, 1.000006252190896, 1.0000079110160478, 1.0000099214411948, 1.0000123407162225, 1.0000152328149083, 1.00001866894198, 1.0000227280586114, 1.0000274974263563, 1.000033073169523, 1.0000395608559847, 1.0000470760964295, 1.0000557451620493, 1.000065705620667, 1.000077106991301, 1.0000901114171699, 1.0001048943571336, 1.0001216452955755, 1.0001405684707207, 1.0001618836213946, 1.0001858267522177, 1.0002126509172415, 1.0002426270220208, 1.0002760446441257, 1.0003132128720909, 1.0003544611628048, 1.0004001402173366, 1.0004506228752006, 1.000506305027061, 1.0005676065458742, 1.0006349722364685, 1.000708872803565, 1.0007898058382332, 1.0008782968227894, 1.0009749001541295, 1.0010802001855026, 1.0011948122867234, 1.0013193839228205, 1.001454595751126, 1.001601162736803, 1.0017598352868091, 1.0019314004023019, 1.0021166828494799, 1.0023165463488648, 1.0025318947830195, 1.0027636734227063, 1.003012870171483, 1.003280516828737, 1.0035676903711592, 1.0038755142526548, 1.0042051597226938, 1.0045578471630987, 1.0049348474432722, 1.0053374832938626, 1.0057671306988667, 1.0062252203061728, 1.0067132388565414, 1.0072327306310243, 1.0077852989168221, 1.0083726074915806, 1.0089963821261256, 1.009658412105635, 1.010360551769251, 1.0111047220681308, 1.0118929121419333, 1.012727180913748, 1.0136096587034578, 1.0145425488595459, 1.0155281294093352, 1.0165687547276714, 1.0176668572240406, 1.0188249490481271, 1.0200456238138111, 1.0213315583416007, 1.0226855144195075, 1.0241103405823564, 1.0256089739095362, 1.027184441841188, 1.028839864012832, 1.0305784541084329, 1.0324035217319039, 1.0343184742970488, 1.0363268189359423, 1.0384321644257501, 1.0406382231339857, 1.0429488129822073, 1.0453678594281517, 1.0478993974663078, 1.0505475736469276, 1.053316648113477, 1.0562109966585231, 1.0592351127980624, 1.0623936098642848, 1.0656912231167786, 1.0691328118721717, 1.0727233616522132, 1.0764679863502924, 1.080371930416396, 1.0844405710605045, 1.0886794204744272, 1.0930941280720745, 1.0976904827481695, 1.102474415155399, 1.107452}
+};
+static MYFLT SUPERSAW_BALANCES[7][128] = {{0.044372, 0.0540113055986112, 0.0635591436542873, 0.07301551416702834, 0.08238041713683428, 0.09165385256370512, 0.10083582044764089, 0.10992632078864159, 0.11892535358670717, 0.12783291884183767, 0.1366490165540331, 0.14537364672329345, 0.1540068093496187, 0.16254850443300886, 0.17099873197346394, 0.17935749197098394, 0.18762478442556885, 0.19580060933721868, 0.2038849667059334, 0.21187785653171307, 0.2197792788145576, 0.2275892335544671, 0.2353077207514415, 0.24293474040548083, 0.25047029251658504, 0.2579143770847542, 0.2652669941099882, 0.2725281435922872, 0.27969782553165107, 0.2867760399280799, 0.2937627867815736, 0.30065806609213225, 0.3074618778597557, 0.3141742220844442, 0.32079509876619755, 0.3273245079050158, 0.333762449500899, 0.34010892355384714, 0.3463639300638601, 0.35252746903093807, 0.3585995404550809, 0.36458014433628866, 0.3704692806745614, 0.37626694946989897, 0.3819731507223015, 0.3875878844317689, 0.39311115059830126, 0.3985429492218985, 0.40388328030256065, 0.4091321438402877, 0.4142895398350797, 0.4193554682869366, 0.4243299291958584, 0.4292129225618452, 0.4340044483848969, 0.4387045066650134, 0.4433130974021948, 0.4478302205964412, 0.4522558762477525, 0.45659006435612876, 0.4608327849215699, 0.4649840379440759, 0.4690438234236469, 0.47301214136028275, 0.4768889917539835, 0.4806743746047492, 0.4843682899125799, 0.4879707376774754, 0.4914817178994358, 0.4949012305784613, 0.4982292757145515, 0.5014658533077067, 0.5046109633579267, 0.5076646058652117, 0.5106267808295617, 0.5134974882509765, 0.5162767281294562, 0.518964500465001, 0.5215608052576105, 0.524065642507285, 0.5264790122140244, 0.5288009143778287, 0.531031348998698, 0.5331703160766321, 0.5352178156116313, 0.5371738476036952, 0.5390384120528241, 0.5408115089590179, 0.5424931383222766, 0.5440833001426003, 0.5455819944199888, 0.5469892211544423, 0.5483049803459606, 0.549529271994544, 0.5506620961001921, 0.5517034526629053, 0.5526533416826834, 0.5535117631595262, 0.5542787170934341, 0.5549542034844069, 0.5555382223324447, 0.5560307736375473, 0.5564318573997148, 0.5567414736189472, 0.5569596222952445, 0.557086303428607, 0.5571215170190341, 0.5570652630665262, 0.5569175415710832, 0.5566783525327051, 0.556347695951392, 0.5559255718271436, 0.5554119801599603, 0.5548069209498419, 0.5541103941967883, 0.5533223999007997, 0.552442938061876, 0.5514720086800173, 0.5504096117552235, 0.5492557472874944, 0.5480104152768307, 0.5466736157232315, 0.5452453486266973, 0.543725613987228, 0.5421144118048237, 0.5404117420794842, 0.5386176048112096, 0.536732},
+{0.044372, 0.0540113055986112, 0.0635591436542873, 0.07301551416702834, 0.08238041713683428, 0.09165385256370512, 0.10083582044764089, 0.10992632078864159, 0.11892535358670717, 0.12783291884183767, 0.1366490165540331, 0.14537364672329345, 0.1540068093496187, 0.16254850443300886, 0.17099873197346394, 0.17935749197098394, 0.18762478442556885, 0.19580060933721868, 0.2038849667059334, 0.21187785653171307, 0.2197792788145576, 0.2275892335544671, 0.2353077207514415, 0.24293474040548083, 0.25047029251658504, 0.2579143770847542, 0.2652669941099882, 0.2725281435922872, 0.27969782553165107, 0.2867760399280799, 0.2937627867815736, 0.30065806609213225, 0.3074618778597557, 0.3141742220844442, 0.32079509876619755, 0.3273245079050158, 0.333762449500899, 0.34010892355384714, 0.3463639300638601, 0.35252746903093807, 0.3585995404550809, 0.36458014433628866, 0.3704692806745614, 0.37626694946989897, 0.3819731507223015, 0.3875878844317689, 0.39311115059830126, 0.3985429492218985, 0.40388328030256065, 0.4091321438402877, 0.4142895398350797, 0.4193554682869366, 0.4243299291958584, 0.4292129225618452, 0.4340044483848969, 0.4387045066650134, 0.4433130974021948, 0.4478302205964412, 0.4522558762477525, 0.45659006435612876, 0.4608327849215699, 0.4649840379440759, 0.4690438234236469, 0.47301214136028275, 0.4768889917539835, 0.4806743746047492, 0.4843682899125799, 0.4879707376774754, 0.4914817178994358, 0.4949012305784613, 0.4982292757145515, 0.5014658533077067, 0.5046109633579267, 0.5076646058652117, 0.5106267808295617, 0.5134974882509765, 0.5162767281294562, 0.518964500465001, 0.5215608052576105, 0.524065642507285, 0.5264790122140244, 0.5288009143778287, 0.531031348998698, 0.5331703160766321, 0.5352178156116313, 0.5371738476036952, 0.5390384120528241, 0.5408115089590179, 0.5424931383222766, 0.5440833001426003, 0.5455819944199888, 0.5469892211544423, 0.5483049803459606, 0.549529271994544, 0.5506620961001921, 0.5517034526629053, 0.5526533416826834, 0.5535117631595262, 0.5542787170934341, 0.5549542034844069, 0.5555382223324447, 0.5560307736375473, 0.5564318573997148, 0.5567414736189472, 0.5569596222952445, 0.557086303428607, 0.5571215170190341, 0.5570652630665262, 0.5569175415710832, 0.5566783525327051, 0.556347695951392, 0.5559255718271436, 0.5554119801599603, 0.5548069209498419, 0.5541103941967883, 0.5533223999007997, 0.552442938061876, 0.5514720086800173, 0.5504096117552235, 0.5492557472874944, 0.5480104152768307, 0.5466736157232315, 0.5452453486266973, 0.543725613987228, 0.5421144118048237, 0.5404117420794842, 0.5386176048112096, 0.536732},
+{0.044372, 0.0540113055986112, 0.0635591436542873, 0.07301551416702834, 0.08238041713683428, 0.09165385256370512, 0.10083582044764089, 0.10992632078864159, 0.11892535358670717, 0.12783291884183767, 0.1366490165540331, 0.14537364672329345, 0.1540068093496187, 0.16254850443300886, 0.17099873197346394, 0.17935749197098394, 0.18762478442556885, 0.19580060933721868, 0.2038849667059334, 0.21187785653171307, 0.2197792788145576, 0.2275892335544671, 0.2353077207514415, 0.24293474040548083, 0.25047029251658504, 0.2579143770847542, 0.2652669941099882, 0.2725281435922872, 0.27969782553165107, 0.2867760399280799, 0.2937627867815736, 0.30065806609213225, 0.3074618778597557, 0.3141742220844442, 0.32079509876619755, 0.3273245079050158, 0.333762449500899, 0.34010892355384714, 0.3463639300638601, 0.35252746903093807, 0.3585995404550809, 0.36458014433628866, 0.3704692806745614, 0.37626694946989897, 0.3819731507223015, 0.3875878844317689, 0.39311115059830126, 0.3985429492218985, 0.40388328030256065, 0.4091321438402877, 0.4142895398350797, 0.4193554682869366, 0.4243299291958584, 0.4292129225618452, 0.4340044483848969, 0.4387045066650134, 0.4433130974021948, 0.4478302205964412, 0.4522558762477525, 0.45659006435612876, 0.4608327849215699, 0.4649840379440759, 0.4690438234236469, 0.47301214136028275, 0.4768889917539835, 0.4806743746047492, 0.4843682899125799, 0.4879707376774754, 0.4914817178994358, 0.4949012305784613, 0.4982292757145515, 0.5014658533077067, 0.5046109633579267, 0.5076646058652117, 0.5106267808295617, 0.5134974882509765, 0.5162767281294562, 0.518964500465001, 0.5215608052576105, 0.524065642507285, 0.5264790122140244, 0.5288009143778287, 0.531031348998698, 0.5331703160766321, 0.5352178156116313, 0.5371738476036952, 0.5390384120528241, 0.5408115089590179, 0.5424931383222766, 0.5440833001426003, 0.5455819944199888, 0.5469892211544423, 0.5483049803459606, 0.549529271994544, 0.5506620961001921, 0.5517034526629053, 0.5526533416826834, 0.5535117631595262, 0.5542787170934341, 0.5549542034844069, 0.5555382223324447, 0.5560307736375473, 0.5564318573997148, 0.5567414736189472, 0.5569596222952445, 0.557086303428607, 0.5571215170190341, 0.5570652630665262, 0.5569175415710832, 0.5566783525327051, 0.556347695951392, 0.5559255718271436, 0.5554119801599603, 0.5548069209498419, 0.5541103941967883, 0.5533223999007997, 0.552442938061876, 0.5514720086800173, 0.5504096117552235, 0.5492557472874944, 0.5480104152768307, 0.5466736157232315, 0.5452453486266973, 0.543725613987228, 0.5421144118048237, 0.5404117420794842, 0.5386176048112096, 0.536732},
+{0.99785, 0.9934904251968504, 0.9891308503937009, 0.9847712755905512, 0.9804117007874016, 0.976052125984252, 0.9716925511811024, 0.9673329763779528, 0.9629734015748032, 0.9586138267716535, 0.954254251968504, 0.9498946771653544, 0.9455351023622047, 0.9411755275590551, 0.9368159527559056, 0.9324563779527559, 0.9280968031496063, 0.9237372283464567, 0.9193776535433071, 0.9150180787401575, 0.9106585039370079, 0.9062989291338582, 0.9019393543307087, 0.8975797795275591, 0.8932202047244094, 0.8888606299212598, 0.8845010551181103, 0.8801414803149606, 0.875781905511811, 0.8714223307086615, 0.8670627559055119, 0.8627031811023622, 0.8583436062992126, 0.8539840314960631, 0.8496244566929134, 0.8452648818897638, 0.8409053070866142, 0.8365457322834646, 0.832186157480315, 0.8278265826771654, 0.8234670078740158, 0.8191074330708662, 0.8147478582677166, 0.8103882834645669, 0.8060287086614173, 0.8016691338582678, 0.7973095590551181, 0.7929499842519685, 0.788590409448819, 0.7842308346456693, 0.7798712598425197, 0.7755116850393701, 0.7711521102362204, 0.7667925354330709, 0.7624329606299213, 0.7580733858267716, 0.7537138110236221, 0.7493542362204725, 0.7449946614173228, 0.7406350866141733, 0.7362755118110236, 0.731915937007874, 0.7275563622047244, 0.7231967874015748, 0.7188372125984253, 0.7144776377952756, 0.710118062992126, 0.7057584881889765, 0.7013989133858267, 0.6970393385826772, 0.6926797637795276, 0.6883201889763779, 0.6839606141732284, 0.6796010393700788, 0.6752414645669291, 0.6708818897637796, 0.6665223149606299, 0.6621627401574803, 0.6578031653543307, 0.6534435905511811, 0.6490840157480315, 0.6447244409448819, 0.6403648661417323, 0.6360052913385827, 0.631645716535433, 0.6272861417322835, 0.622926566929134, 0.6185669921259842, 0.6142074173228347, 0.609847842519685, 0.6054882677165354, 0.6011286929133859, 0.5967691181102361, 0.5924095433070866, 0.5880499685039371, 0.5836903937007873, 0.5793308188976378, 0.5749712440944883, 0.5706116692913386, 0.566252094488189, 0.5618925196850394, 0.5575329448818898, 0.5531733700787402, 0.5488137952755906, 0.544454220472441, 0.5400946456692914, 0.5357350708661417, 0.5313754960629922, 0.5270159212598425, 0.5226563464566929, 0.5182967716535434, 0.5139371968503937, 0.5095776220472441, 0.5052180472440946, 0.500858472440945, 0.4964988976377953, 0.4921393228346457, 0.48777974803149604, 0.4834201732283465, 0.4790605984251969, 0.47470102362204725, 0.4703414488188977, 0.4659818740157481, 0.46162229921259845, 0.4572627244094488, 0.4529031496062992, 0.44854357480314966, 0.444184},
+{0.044372, 0.054437289850579704, 0.06441111215822432, 0.07429346692293384, 0.08408435414470829, 0.09378377382354765, 0.10339172595945192, 0.11290821055242112, 0.12233322760245521, 0.1316667771095542, 0.14090885907371814, 0.150059473494947, 0.15911862037324073, 0.16808629970859942, 0.176962511501023, 0.1857472557505115, 0.1944405324570649, 0.20304234162068327, 0.21155268324136647, 0.21997155731911466, 0.2282989638539277, 0.23653490284580572, 0.2446793742947486, 0.25273237820075645, 0.2606939145638291, 0.26856398338396675, 0.27634258466116934, 0.2840297183954368, 0.2916253845867692, 0.2991295832351665, 0.3065423143406287, 0.31386357790315583, 0.3210933739227479, 0.3282317023994048, 0.3352785633331267, 0.3422339567239135, 0.34909788257176516, 0.3558703408766818, 0.3625513316386633, 0.3691408548577098, 0.3756389105338211, 0.3820454986669974, 0.3883606192572386, 0.3945842723045447, 0.4007164578089156, 0.4067571757703516, 0.41270642618885245, 0.4185642090644182, 0.4243305243970488, 0.4300053721867444, 0.43558875243350487, 0.44108066513733035, 0.44648111029822063, 0.4517900879161758, 0.457007597991196, 0.46213364052328115, 0.46716821551243104, 0.4721113229586459, 0.4769629628619257, 0.48172313522227056, 0.4863918400396801, 0.4909690773141547, 0.4954548470456941, 0.4998491492342985, 0.5041519838799677, 0.508363350982702, 0.5124832505425011, 0.5165116825593651, 0.5204486470332941, 0.524294143964288, 0.5280481733523468, 0.5317107351974705, 0.535281829499659, 0.5387614562589126, 0.542149615475231, 0.5454463071486143, 0.5486515312790626, 0.5517652878665756, 0.5547875769111539, 0.5577183984127968, 0.5605577523715047, 0.5633056387872776, 0.5659620576601153, 0.568527008990018, 0.5710004927769856, 0.5733825090210181, 0.5756730577221155, 0.5778721388802778, 0.5799797524955049, 0.5819958985677972, 0.5839205770971542, 0.5857537880835761, 0.587495531527063, 0.5891458074276149, 0.5907046157852317, 0.5921719565999132, 0.5935478298716598, 0.5948322356004713, 0.5960251737863476, 0.597126644429289, 0.598136647529295, 0.5990551830863663, 0.5998822511005023, 0.6006178515717031, 0.601261984499969, 0.6018146498852998, 0.6022758477276954, 0.6026455780271561, 0.6029238407836814, 0.6031106359972721, 0.6032059636679274, 0.6032098237956476, 0.6031222163804327, 0.6029431414222828, 0.6026725989211977, 0.6023105888771778, 0.6018571112902225, 0.6013121661603325, 0.6006757534875071, 0.5999478732717465, 0.5991285255130511, 0.5982177102114203, 0.5972154273668548, 0.596121676979354, 0.594936459048918, 0.5936597735755472, 0.5922916205592411, 0.590832},
+{0.044372, 0.054437289850579704, 0.06441111215822432, 0.07429346692293384, 0.08408435414470829, 0.09378377382354765, 0.10339172595945192, 0.11290821055242112, 0.12233322760245521, 0.1316667771095542, 0.14090885907371814, 0.150059473494947, 0.15911862037324073, 0.16808629970859942, 0.176962511501023, 0.1857472557505115, 0.1944405324570649, 0.20304234162068327, 0.21155268324136647, 0.21997155731911466, 0.2282989638539277, 0.23653490284580572, 0.2446793742947486, 0.25273237820075645, 0.2606939145638291, 0.26856398338396675, 0.27634258466116934, 0.2840297183954368, 0.2916253845867692, 0.2991295832351665, 0.3065423143406287, 0.31386357790315583, 0.3210933739227479, 0.3282317023994048, 0.3352785633331267, 0.3422339567239135, 0.34909788257176516, 0.3558703408766818, 0.3625513316386633, 0.3691408548577098, 0.3756389105338211, 0.3820454986669974, 0.3883606192572386, 0.3945842723045447, 0.4007164578089156, 0.4067571757703516, 0.41270642618885245, 0.4185642090644182, 0.4243305243970488, 0.4300053721867444, 0.43558875243350487, 0.44108066513733035, 0.44648111029822063, 0.4517900879161758, 0.457007597991196, 0.46213364052328115, 0.46716821551243104, 0.4721113229586459, 0.4769629628619257, 0.48172313522227056, 0.4863918400396801, 0.4909690773141547, 0.4954548470456941, 0.4998491492342985, 0.5041519838799677, 0.508363350982702, 0.5124832505425011, 0.5165116825593651, 0.5204486470332941, 0.524294143964288, 0.5280481733523468, 0.5317107351974705, 0.535281829499659, 0.5387614562589126, 0.542149615475231, 0.5454463071486143, 0.5486515312790626, 0.5517652878665756, 0.5547875769111539, 0.5577183984127968, 0.5605577523715047, 0.5633056387872776, 0.5659620576601153, 0.568527008990018, 0.5710004927769856, 0.5733825090210181, 0.5756730577221155, 0.5778721388802778, 0.5799797524955049, 0.5819958985677972, 0.5839205770971542, 0.5857537880835761, 0.587495531527063, 0.5891458074276149, 0.5907046157852317, 0.5921719565999132, 0.5935478298716598, 0.5948322356004713, 0.5960251737863476, 0.597126644429289, 0.598136647529295, 0.5990551830863663, 0.5998822511005023, 0.6006178515717031, 0.601261984499969, 0.6018146498852998, 0.6022758477276954, 0.6026455780271561, 0.6029238407836814, 0.6031106359972721, 0.6032059636679274, 0.6032098237956476, 0.6031222163804327, 0.6029431414222828, 0.6026725989211977, 0.6023105888771778, 0.6018571112902225, 0.6013121661603325, 0.6006757534875071, 0.5999478732717465, 0.5991285255130511, 0.5982177102114203, 0.5972154273668548, 0.596121676979354, 0.594936459048918, 0.5936597735755472, 0.5922916205592411, 0.590832},
+{0.044372, 0.054437289850579704, 0.06441111215822432, 0.07429346692293384, 0.08408435414470829, 0.09378377382354765, 0.10339172595945192, 0.11290821055242112, 0.12233322760245521, 0.1316667771095542, 0.14090885907371814, 0.150059473494947, 0.15911862037324073, 0.16808629970859942, 0.176962511501023, 0.1857472557505115, 0.1944405324570649, 0.20304234162068327, 0.21155268324136647, 0.21997155731911466, 0.2282989638539277, 0.23653490284580572, 0.2446793742947486, 0.25273237820075645, 0.2606939145638291, 0.26856398338396675, 0.27634258466116934, 0.2840297183954368, 0.2916253845867692, 0.2991295832351665, 0.3065423143406287, 0.31386357790315583, 0.3210933739227479, 0.3282317023994048, 0.3352785633331267, 0.3422339567239135, 0.34909788257176516, 0.3558703408766818, 0.3625513316386633, 0.3691408548577098, 0.3756389105338211, 0.3820454986669974, 0.3883606192572386, 0.3945842723045447, 0.4007164578089156, 0.4067571757703516, 0.41270642618885245, 0.4185642090644182, 0.4243305243970488, 0.4300053721867444, 0.43558875243350487, 0.44108066513733035, 0.44648111029822063, 0.4517900879161758, 0.457007597991196, 0.46213364052328115, 0.46716821551243104, 0.4721113229586459, 0.4769629628619257, 0.48172313522227056, 0.4863918400396801, 0.4909690773141547, 0.4954548470456941, 0.4998491492342985, 0.5041519838799677, 0.508363350982702, 0.5124832505425011, 0.5165116825593651, 0.5204486470332941, 0.524294143964288, 0.5280481733523468, 0.5317107351974705, 0.535281829499659, 0.5387614562589126, 0.542149615475231, 0.5454463071486143, 0.5486515312790626, 0.5517652878665756, 0.5547875769111539, 0.5577183984127968, 0.5605577523715047, 0.5633056387872776, 0.5659620576601153, 0.568527008990018, 0.5710004927769856, 0.5733825090210181, 0.5756730577221155, 0.5778721388802778, 0.5799797524955049, 0.5819958985677972, 0.5839205770971542, 0.5857537880835761, 0.587495531527063, 0.5891458074276149, 0.5907046157852317, 0.5921719565999132, 0.5935478298716598, 0.5948322356004713, 0.5960251737863476, 0.597126644429289, 0.598136647529295, 0.5990551830863663, 0.5998822511005023, 0.6006178515717031, 0.601261984499969, 0.6018146498852998, 0.6022758477276954, 0.6026455780271561, 0.6029238407836814, 0.6031106359972721, 0.6032059636679274, 0.6032098237956476, 0.6031222163804327, 0.6029431414222828, 0.6026725989211977, 0.6023105888771778, 0.6018571112902225, 0.6013121661603325, 0.6006757534875071, 0.5999478732717465, 0.5991285255130511, 0.5982177102114203, 0.5972154273668548, 0.596121676979354, 0.594936459048918, 0.5936597735755472, 0.5922916205592411, 0.590832}
+};
+
+/**************/
+/* SuperSaw object */
+/**************/
 typedef struct {
     pyo_audio_HEAD
     PyObject *freq;
     Stream *freq_stream;
-    PyObject *ratio;
-    Stream *ratio_stream;
-    PyObject *index;
-    Stream *index_stream;
+    PyObject *detune;
+    Stream *detune_stream;
+    PyObject *bal;
+    Stream *bal_stream;
     int modebuffer[5];
-    MYFLT theta;
-    MYFLT beta;
-    MYFLT scaleFactor;
-    MYFLT xn1; // dc block input delay
-    MYFLT yn1; // dc block output delay
-} SumOsc;
+    double pointerPos[7];
+    // sample memories
+    MYFLT x1;
+    MYFLT x2;
+    MYFLT y1;
+    MYFLT y2;
+    // variables
+    MYFLT c;
+    MYFLT w0;
+    MYFLT alpha;
+    // coefficients
+    MYFLT b0;
+    MYFLT b1;
+    MYFLT b2;
+    MYFLT a0;
+    MYFLT a1;
+    MYFLT a2;
+    MYFLT lastFilterFreq;
+    MYFLT nyquist;
+} SuperSaw;
 
 static void
-SumOsc_readframes_iii(SumOsc *self) {
-    MYFLT mod_freq, mod_delta, freq_delta, x, y, ind2, theta_minus_beta, sin1, sin2, cos1;
-    int i, ipart;
-    
-    MYFLT freq = PyFloat_AS_DOUBLE(self->freq);
-    MYFLT rat = PyFloat_AS_DOUBLE(self->ratio);
-    MYFLT ind = PyFloat_AS_DOUBLE(self->index);
-    
-    freq_delta = freq * self->scaleFactor;
-    mod_freq = freq * rat;
-    mod_delta = mod_freq * self->scaleFactor;
-    if (ind < 0)
-        ind = 0;
-    else if (ind > 0.999)
-        ind = 0.999;
+SuperSaw_readframes_iii(SuperSaw *self) {
+    MYFLT fr, det, bal, twoOnSr, val;
+    int i, j, det_ind, bal_ind;
+    MYFLT inc[7];
+    MYFLT amp[7];
 
-    ind2 = ind * ind;
-    for (i=0; i<self->bufsize; i++) {
-        ipart = (int)self->theta;
-        sin1 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (self->theta - ipart);
-        theta_minus_beta = Sine_clip(self->theta - self->beta);
-        ipart = (int)theta_minus_beta;
-        sin2 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (theta_minus_beta - ipart);
-        ipart = (int)self->beta;
-        cos1 = COSINE_ARRAY[ipart] + (COSINE_ARRAY[ipart+1] - COSINE_ARRAY[ipart]) * (self->beta - ipart);
-        x = (sin1 - ind * sin2) / (1 + ind2 - 2 * ind * cos1);
-        self->theta += freq_delta;
-        self->beta += mod_delta;
-        self->theta = Sine_clip(self->theta);
-        self->beta = Sine_clip(self->beta);
-        
-        /* DC filtering */
-        y = x - self->xn1 + 0.995 * self->yn1;
-        self->xn1 = x; self->yn1 = y;
+    fr = PyFloat_AS_DOUBLE(self->freq);
+    det = _clip(PyFloat_AS_DOUBLE(self->detune));
+    bal = _clip(PyFloat_AS_DOUBLE(self->bal));
+    twoOnSr = 2.0 / self->sr;
 
-        self->data[i] = y * (1 - ind2);
+    if (fr <= 1.0)
+        fr = 1.0;
+    else if (fr >= self->nyquist)
+        fr = self->nyquist;
+
+    det_ind = (int)(det * 126);
+    bal_ind = (int)(bal * 126);
+
+    if (fr != self->lastFilterFreq) {
+        self->lastFilterFreq = fr;
+        self->w0 = TWOPI * fr / self->sr;
+        self->c = MYCOS(self->w0);
+        self->alpha = MYSIN(self->w0) * 0.5;
+        self->b0 = self->b2 = (1 + self->c) * 0.5;
+        self->b1 = -(1 + self->c);
+        self->a0 = 1 + self->alpha;
+        self->a1 = -2 * self->c;
+        self->a2 = 1 - self->alpha;
+    }
+
+    for (j=0; j<7; j++) {
+        inc[j] = fr * SUPERSAW_DETUNES[j][det_ind] * twoOnSr;
+        amp[j] = SUPERSAW_BALANCES[j][bal_ind];
+    }
+
+    for (i=0; i<self->bufsize; i++) {
+        val = 0.0;
+        for (j=0; j<7; j++) {
+            val += self->pointerPos[j] * amp[j];
+            self->pointerPos[j] += inc[j];
+            if (self->pointerPos[j] < -1.0)
+                self->pointerPos[j] += 2.0;
+            else if (self->pointerPos[j] >= 1.0)
+                self->pointerPos[j] -= 2.0;
+        }
+        self->data[i] = ( (self->b0 * val) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
+        self->y2 = self->y1;
+        self->y1 = self->data[i];
+        self->x2 = self->x1;
+        self->x1 = val;
+        self->data[i] *= 0.2;
     }
 }
 
 static void
-SumOsc_readframes_aii(SumOsc *self) {
-    MYFLT freq, mod_freq, mod_delta, freq_delta, x, y, ind2, theta_minus_beta, sin1, sin2, cos1;
-    int i, ipart;
-    
-    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    MYFLT rat = PyFloat_AS_DOUBLE(self->ratio);
-    MYFLT ind = PyFloat_AS_DOUBLE(self->index);
+SuperSaw_readframes_aii(SuperSaw *self) {
+    MYFLT fr, det, bal, twoOnSr, val;
+    int i, j, det_ind, bal_ind;
 
-    if (ind < 0)
-        ind = 0;
-    else if (ind > 0.999)
-        ind = 0.999;
+    MYFLT *freq = Stream_getData((Stream *)self->freq_stream);
+    det = _clip(PyFloat_AS_DOUBLE(self->detune));
+    bal = _clip(PyFloat_AS_DOUBLE(self->bal));
+    twoOnSr = 2.0 / self->sr;
+
+    det_ind = (int)(det * 126);
+    bal_ind = (int)(bal * 126);
 
-    ind2 = ind * ind;
     for (i=0; i<self->bufsize; i++) {
-        freq = fr[i];
-        freq_delta = freq * self->scaleFactor;
-        mod_freq = freq * rat;
-        mod_delta = mod_freq * self->scaleFactor;
-        ipart = (int)self->theta;
-        sin1 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (self->theta - ipart);
-        theta_minus_beta = Sine_clip(self->theta - self->beta);
-        ipart = (int)theta_minus_beta;
-        sin2 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (theta_minus_beta - ipart);
-        ipart = (int)self->beta;
-        cos1 = COSINE_ARRAY[ipart] + (COSINE_ARRAY[ipart+1] - COSINE_ARRAY[ipart]) * (self->beta - ipart);
-        x = (sin1 - ind * sin2) / (1 + ind2 - 2 * ind * cos1);
-        self->theta += freq_delta;
-        self->beta += mod_delta;
-        self->theta = Sine_clip(self->theta);
-        self->beta = Sine_clip(self->beta);
-        
-        y = x - self->xn1 + 0.995 * self->yn1;
-        self->xn1 = x; self->yn1 = y;
+        fr = freq[i];
+        if (fr <= 1.0)
+            fr = 1.0;
+        else if (fr >= self->nyquist)
+            fr = self->nyquist;
+        if (fr != self->lastFilterFreq) {
+            self->lastFilterFreq = fr;
+            self->w0 = TWOPI * fr / self->sr;
+            self->c = MYCOS(self->w0);
+            self->alpha = MYSIN(self->w0) * 0.5;
+            self->b0 = self->b2 = (1 + self->c) * 0.5;
+            self->b1 = -(1 + self->c);
+            self->a0 = 1 + self->alpha;
+            self->a1 = -2 * self->c;
+            self->a2 = 1 - self->alpha;
+        }
+        val = 0.0;
+        for (j=0; j<7; j++) {
+            val += self->pointerPos[j] * SUPERSAW_BALANCES[j][bal_ind];
+            self->pointerPos[j] += fr * SUPERSAW_DETUNES[j][det_ind] * twoOnSr;
+            if (self->pointerPos[j] < -1.0)
+                self->pointerPos[j] += 2.0;
+            else if (self->pointerPos[j] >= 1.0)
+                self->pointerPos[j] -= 2.0;
+        }
+        self->data[i] = ( (self->b0 * val) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
+        self->y2 = self->y1;
+        self->y1 = self->data[i];
+        self->x2 = self->x1;
+        self->x1 = val;
+        self->data[i] *= 0.2;
+    }
+}
 
-        self->data[i] = y * (1 - ind2);
+static void
+SuperSaw_readframes_iai(SuperSaw *self) {
+    MYFLT fr, bal, twoOnSr, val;
+    int i, j, det_ind, bal_ind;
+
+    fr = PyFloat_AS_DOUBLE(self->freq);
+    MYFLT *detune = Stream_getData((Stream *)self->detune_stream);
+    bal = _clip(PyFloat_AS_DOUBLE(self->bal));
+    twoOnSr = 2.0 / self->sr;
+
+    if (fr <= 1.0)
+        fr = 1.0;
+    else if (fr >= self->nyquist)
+        fr = self->nyquist;
+
+    bal_ind = (int)(bal * 126);
+
+    if (fr != self->lastFilterFreq) {
+        self->lastFilterFreq = fr;
+        self->w0 = TWOPI * fr / self->sr;
+        self->c = MYCOS(self->w0);
+        self->alpha = MYSIN(self->w0) * 0.5;
+        self->b0 = self->b2 = (1 + self->c) * 0.5;
+        self->b1 = -(1 + self->c);
+        self->a0 = 1 + self->alpha;
+        self->a1 = -2 * self->c;
+        self->a2 = 1 - self->alpha;
+    }
+
+    for (i=0; i<self->bufsize; i++) {
+        det_ind = (int)(_clip(detune[i]) * 126);
+        val = 0.0;
+        for (j=0; j<7; j++) {
+            val += self->pointerPos[j] * SUPERSAW_BALANCES[j][bal_ind];
+            self->pointerPos[j] += fr * SUPERSAW_DETUNES[j][det_ind] * twoOnSr;
+            if (self->pointerPos[j] < -1.0)
+                self->pointerPos[j] += 2.0;
+            else if (self->pointerPos[j] >= 1.0)
+                self->pointerPos[j] -= 2.0;
+        }
+        self->data[i] = ( (self->b0 * val) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
+        self->y2 = self->y1;
+        self->y1 = self->data[i];
+        self->x2 = self->x1;
+        self->x1 = val;
+        self->data[i] *= 0.2;
     }
 }
 
 static void
-SumOsc_readframes_iai(SumOsc *self) {
-    MYFLT ratio, mod_freq, mod_delta, freq_delta, x, y, ind2, theta_minus_beta, sin1, sin2, cos1;
-    int i, ipart;
-    
-    MYFLT freq = PyFloat_AS_DOUBLE(self->freq);
-    MYFLT *rat = Stream_getData((Stream *)self->ratio_stream);
-    MYFLT ind = PyFloat_AS_DOUBLE(self->index);
+SuperSaw_readframes_aai(SuperSaw *self) {
+    MYFLT fr, bal, twoOnSr, val;
+    int i, j, det_ind, bal_ind;
 
-    freq_delta = freq * self->scaleFactor;
-    if (ind < 0)
-        ind = 0;
-    else if (ind > 0.999)
-        ind = 0.999;
+    MYFLT *freq = Stream_getData((Stream *)self->freq_stream);
+    MYFLT *detune = Stream_getData((Stream *)self->detune_stream);
+    bal = _clip(PyFloat_AS_DOUBLE(self->bal));
+    twoOnSr = 2.0 / self->sr;
 
-    ind2 = ind * ind;
-    for (i=0; i<self->bufsize; i++) {
-        ratio = rat[i];
-        mod_freq = freq * ratio;
-        mod_delta = mod_freq * self->scaleFactor;
-        ipart = (int)self->theta;
-        sin1 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (self->theta - ipart);
-        theta_minus_beta = Sine_clip(self->theta - self->beta);
-        ipart = (int)theta_minus_beta;
-        sin2 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (theta_minus_beta - ipart);
-        ipart = (int)self->beta;
-        cos1 = COSINE_ARRAY[ipart] + (COSINE_ARRAY[ipart+1] - COSINE_ARRAY[ipart]) * (self->beta - ipart);
-        x = (sin1 - ind * sin2) / (1 + ind2 - 2 * ind * cos1);
-        self->theta += freq_delta;
-        self->beta += mod_delta;
-        self->theta = Sine_clip(self->theta);
-        self->beta = Sine_clip(self->beta);
-        
-        y = x - self->xn1 + 0.995 * self->yn1;
-        self->xn1 = x; self->yn1 = y;
+    bal_ind = (int)(bal * 126);
 
-        self->data[i] = y * (1 - ind2);
+    for (i=0; i<self->bufsize; i++) {
+        fr = freq[i];
+        if (fr <= 1.0)
+            fr = 1.0;
+        else if (fr >= self->nyquist)
+            fr = self->nyquist;
+        if (fr != self->lastFilterFreq) {
+            self->lastFilterFreq = fr;
+            self->w0 = TWOPI * fr / self->sr;
+            self->c = MYCOS(self->w0);
+            self->alpha = MYSIN(self->w0) * 0.5;
+            self->b0 = self->b2 = (1 + self->c) * 0.5;
+            self->b1 = -(1 + self->c);
+            self->a0 = 1 + self->alpha;
+            self->a1 = -2 * self->c;
+            self->a2 = 1 - self->alpha;
+        }
+        det_ind = (int)(_clip(detune[i]) * 126);
+        val = 0.0;
+        for (j=0; j<7; j++) {
+            val += self->pointerPos[j] * SUPERSAW_BALANCES[j][bal_ind];
+            self->pointerPos[j] += fr * SUPERSAW_DETUNES[j][det_ind] * twoOnSr;
+            if (self->pointerPos[j] < -1.0)
+                self->pointerPos[j] += 2.0;
+            else if (self->pointerPos[j] >= 1.0)
+                self->pointerPos[j] -= 2.0;
+        }
+        self->data[i] = ( (self->b0 * val) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
+        self->y2 = self->y1;
+        self->y1 = self->data[i];
+        self->x2 = self->x1;
+        self->x1 = val;
+        self->data[i] *= 0.2;
     }
 }
 
 static void
-SumOsc_readframes_aai(SumOsc *self) {
-    MYFLT freq, ratio, mod_freq, mod_delta, freq_delta, x, y, ind2, theta_minus_beta, sin1, sin2, cos1;
-    int i, ipart;
-    
-    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    MYFLT *rat = Stream_getData((Stream *)self->ratio_stream);
-    MYFLT ind = PyFloat_AS_DOUBLE(self->index);
+SuperSaw_readframes_iia(SuperSaw *self) {
+    MYFLT fr, det, twoOnSr, val;
+    int i, j, det_ind, bal_ind;
+    MYFLT inc[7];
 
-    if (ind < 0)
-        ind = 0;
-    else if (ind > 0.999)
-        ind = 0.999;
+    fr = PyFloat_AS_DOUBLE(self->freq);
+    det = _clip(PyFloat_AS_DOUBLE(self->detune));
+    MYFLT *balance = Stream_getData((Stream *)self->bal_stream);
+    twoOnSr = 2.0 / self->sr;
 
-    ind2 = ind * ind;
-    for (i=0; i<self->bufsize; i++) {
-        freq = fr[i];
-        ratio = rat[i];
-        freq_delta = freq * self->scaleFactor;
-        mod_freq = freq * ratio;
-        mod_delta = mod_freq * self->scaleFactor;
-        ipart = (int)self->theta;
-        sin1 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (self->theta - ipart);
-        theta_minus_beta = Sine_clip(self->theta - self->beta);
-        ipart = (int)theta_minus_beta;
-        sin2 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (theta_minus_beta - ipart);
-        ipart = (int)self->beta;
-        cos1 = COSINE_ARRAY[ipart] + (COSINE_ARRAY[ipart+1] - COSINE_ARRAY[ipart]) * (self->beta - ipart);
-        x = (sin1 - ind * sin2) / (1 + ind2 - 2 * ind * cos1);
-        self->theta += freq_delta;
-        self->beta += mod_delta;
-        self->theta = Sine_clip(self->theta);
-        self->beta = Sine_clip(self->beta);
-        
-        y = x - self->xn1 + 0.995 * self->yn1;
-        self->xn1 = x; self->yn1 = y;
+    if (fr <= 1.0)
+        fr = 1.0;
+    else if (fr >= self->nyquist)
+        fr = self->nyquist;
 
-        self->data[i] = y * (1 - ind2);
-    }
-}
+    det_ind = (int)(det * 126);
 
-static void
-SumOsc_readframes_iia(SumOsc *self) {
-    MYFLT ind, mod_freq, mod_delta, freq_delta, x, y, ind2, theta_minus_beta, sin1, sin2, cos1;
-    int i, ipart;
-    
-    MYFLT freq = PyFloat_AS_DOUBLE(self->freq);
-    MYFLT rat = PyFloat_AS_DOUBLE(self->ratio);
-    MYFLT *index = Stream_getData((Stream *)self->index_stream);
+    if (fr != self->lastFilterFreq) {
+        self->lastFilterFreq = fr;
+        self->w0 = TWOPI * fr / self->sr;
+        self->c = MYCOS(self->w0);
+        self->alpha = MYSIN(self->w0) * 0.5;
+        self->b0 = self->b2 = (1 + self->c) * 0.5;
+        self->b1 = -(1 + self->c);
+        self->a0 = 1 + self->alpha;
+        self->a1 = -2 * self->c;
+        self->a2 = 1 - self->alpha;
+    }
 
-    freq_delta = freq * self->scaleFactor;
-    mod_freq = freq * rat;
-    mod_delta = mod_freq * self->scaleFactor;
+    for (j=0; j<7; j++) {
+        inc[j] = fr * SUPERSAW_DETUNES[j][det_ind] * twoOnSr;
+    }
 
     for (i=0; i<self->bufsize; i++) {
-        ind = index[i];
-        if (ind < 0)
-            ind = 0;
-        else if (ind > 0.999)
-            ind = 0.999;
-        ind2 = ind * ind;
-        ipart = (int)self->theta;
-        sin1 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (self->theta - ipart);
-        theta_minus_beta = Sine_clip(self->theta - self->beta);
-        ipart = (int)theta_minus_beta;
-        sin2 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (theta_minus_beta - ipart);
-        ipart = (int)self->beta;
-        cos1 = COSINE_ARRAY[ipart] + (COSINE_ARRAY[ipart+1] - COSINE_ARRAY[ipart]) * (self->beta - ipart);
-        x = (sin1 - ind * sin2) / (1 + ind2 - 2 * ind * cos1);
-        self->theta += freq_delta;
-        self->beta += mod_delta;
-        self->theta = Sine_clip(self->theta);
-        self->beta = Sine_clip(self->beta);
-        
-        y = x - self->xn1 + 0.995 * self->yn1;
-        self->xn1 = x; self->yn1 = y;
-
-        self->data[i] = y * (1 - ind2);
-    }    
+        bal_ind = (int)(_clip(balance[i]) * 126);
+        val = 0.0;
+        for (j=0; j<7; j++) {
+            val += self->pointerPos[j] * SUPERSAW_BALANCES[j][bal_ind];
+            self->pointerPos[j] += inc[j];
+            if (self->pointerPos[j] < -1.0)
+                self->pointerPos[j] += 2.0;
+            else if (self->pointerPos[j] >= 1.0)
+                self->pointerPos[j] -= 2.0;
+        }
+        self->data[i] = ( (self->b0 * val) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
+        self->y2 = self->y1;
+        self->y1 = self->data[i];
+        self->x2 = self->x1;
+        self->x1 = val;
+        self->data[i] *= 0.2;
+    }
 }
 
 static void
-SumOsc_readframes_aia(SumOsc *self) {
-    MYFLT freq, ind, mod_freq, mod_delta, freq_delta, x, y, ind2, theta_minus_beta, sin1, sin2, cos1;
-    int i, ipart;
-    
-    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    MYFLT rat = PyFloat_AS_DOUBLE(self->ratio);
-    MYFLT *index = Stream_getData((Stream *)self->index_stream);
+SuperSaw_readframes_aia(SuperSaw *self) {
+    MYFLT fr, det, twoOnSr, val;
+    int i, j, det_ind, bal_ind;
 
-    for (i=0; i<self->bufsize; i++) {
-        freq = fr[i];
-        ind = index[i];
-        freq_delta = freq * self->scaleFactor;
-        mod_freq = freq * rat;
-        mod_delta = mod_freq * self->scaleFactor;
-        if (ind < 0)
-            ind = 0;
-        else if (ind > 0.999)
-            ind = 0.999;
-        ind2 = ind * ind;
-        ipart = (int)self->theta;
-        sin1 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (self->theta - ipart);
-        theta_minus_beta = Sine_clip(self->theta - self->beta);
-        ipart = (int)theta_minus_beta;
-        sin2 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (theta_minus_beta - ipart);
-        ipart = (int)self->beta;
-        cos1 = COSINE_ARRAY[ipart] + (COSINE_ARRAY[ipart+1] - COSINE_ARRAY[ipart]) * (self->beta - ipart);
-        x = (sin1 - ind * sin2) / (1 + ind2 - 2 * ind * cos1);
-        self->theta += freq_delta;
-        self->beta += mod_delta;
-        self->theta = Sine_clip(self->theta);
-        self->beta = Sine_clip(self->beta);
-        
-        y = x - self->xn1 + 0.995 * self->yn1;
-        self->xn1 = x; self->yn1 = y;
+    MYFLT *freq = Stream_getData((Stream *)self->freq_stream);
+    det = _clip(PyFloat_AS_DOUBLE(self->detune));
+    MYFLT *balance = Stream_getData((Stream *)self->bal_stream);
+    twoOnSr = 2.0 / self->sr;
 
-        self->data[i] = y * (1 - ind2);
-    }    
+    det_ind = (int)(det * 126);
+
+    for (i=0; i<self->bufsize; i++) {
+        fr = freq[i];
+        if (fr <= 1.0)
+            fr = 1.0;
+        else if (fr >= self->nyquist)
+            fr = self->nyquist;
+        if (fr != self->lastFilterFreq) {
+            self->lastFilterFreq = fr;
+            self->w0 = TWOPI * fr / self->sr;
+            self->c = MYCOS(self->w0);
+            self->alpha = MYSIN(self->w0) * 0.5;
+            self->b0 = self->b2 = (1 + self->c) * 0.5;
+            self->b1 = -(1 + self->c);
+            self->a0 = 1 + self->alpha;
+            self->a1 = -2 * self->c;
+            self->a2 = 1 - self->alpha;
+        }
+        bal_ind = (int)(_clip(balance[i]) * 126);
+        val = 0.0;
+        for (j=0; j<7; j++) {
+            val += self->pointerPos[j] * SUPERSAW_BALANCES[j][bal_ind];
+            self->pointerPos[j] += fr * SUPERSAW_DETUNES[j][det_ind] * twoOnSr;
+            if (self->pointerPos[j] < -1.0)
+                self->pointerPos[j] += 2.0;
+            else if (self->pointerPos[j] >= 1.0)
+                self->pointerPos[j] -= 2.0;
+        }
+        self->data[i] = ( (self->b0 * val) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
+        self->y2 = self->y1;
+        self->y1 = self->data[i];
+        self->x2 = self->x1;
+        self->x1 = val;
+        self->data[i] *= 0.2;
+    }
 }
 
 static void
-SumOsc_readframes_iaa(SumOsc *self) {
-    MYFLT ratio, ind, mod_freq, mod_delta, freq_delta, x, y, ind2, theta_minus_beta, sin1, sin2, cos1;
-    int i, ipart;
-    
-    MYFLT freq = PyFloat_AS_DOUBLE(self->freq);
-    MYFLT *rat = Stream_getData((Stream *)self->ratio_stream);
-    MYFLT *index = Stream_getData((Stream *)self->index_stream);
+SuperSaw_readframes_iaa(SuperSaw *self) {
+    MYFLT fr, twoOnSr, val;
+    int i, j, det_ind, bal_ind;
 
-    freq_delta = freq * self->scaleFactor;
+    fr = PyFloat_AS_DOUBLE(self->freq);
+    MYFLT *detune = Stream_getData((Stream *)self->detune_stream);
+    MYFLT *balance = Stream_getData((Stream *)self->bal_stream);
+    twoOnSr = 2.0 / self->sr;
 
-    for (i=0; i<self->bufsize; i++) {
-        ind = index[i];
-        ratio = rat[i];
-        mod_freq = freq * ratio;
-        mod_delta = mod_freq * self->scaleFactor;
-        if (ind < 0)
-            ind = 0;
-        else if (ind > 0.999)
-            ind = 0.999;
-        ind2 = ind * ind;
-        ipart = (int)self->theta;
-        sin1 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (self->theta - ipart);
-        theta_minus_beta = Sine_clip(self->theta - self->beta);
-        ipart = (int)theta_minus_beta;
-        sin2 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (theta_minus_beta - ipart);
-        ipart = (int)self->beta;
-        cos1 = COSINE_ARRAY[ipart] + (COSINE_ARRAY[ipart+1] - COSINE_ARRAY[ipart]) * (self->beta - ipart);
-        x = (sin1 - ind * sin2) / (1 + ind2 - 2 * ind * cos1);
-        self->theta += freq_delta;
-        self->beta += mod_delta;
-        self->theta = Sine_clip(self->theta);
-        self->beta = Sine_clip(self->beta);
-        
-        y = x - self->xn1 + 0.995 * self->yn1;
-        self->xn1 = x; self->yn1 = y;
+    if (fr <= 1.0)
+        fr = 1.0;
+    else if (fr >= self->nyquist)
+        fr = self->nyquist;
 
-        self->data[i] = y * (1 - ind2);
-    } 
+    if (fr != self->lastFilterFreq) {
+        self->lastFilterFreq = fr;
+        self->w0 = TWOPI * fr / self->sr;
+        self->c = MYCOS(self->w0);
+        self->alpha = MYSIN(self->w0) * 0.5;
+        self->b0 = self->b2 = (1 + self->c) * 0.5;
+        self->b1 = -(1 + self->c);
+        self->a0 = 1 + self->alpha;
+        self->a1 = -2 * self->c;
+        self->a2 = 1 - self->alpha;
+    }
+
+    for (i=0; i<self->bufsize; i++) {
+        det_ind = (int)(_clip(detune[i]) * 126);
+        bal_ind = (int)(_clip(balance[i]) * 126);
+        val = 0.0;
+        for (j=0; j<7; j++) {
+            val += self->pointerPos[j] * SUPERSAW_BALANCES[j][bal_ind];
+            self->pointerPos[j] += fr * SUPERSAW_DETUNES[j][det_ind] * twoOnSr;
+            if (self->pointerPos[j] < -1.0)
+                self->pointerPos[j] += 2.0;
+            else if (self->pointerPos[j] >= 1.0)
+                self->pointerPos[j] -= 2.0;
+        }
+        self->data[i] = ( (self->b0 * val) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
+        self->y2 = self->y1;
+        self->y1 = self->data[i];
+        self->x2 = self->x1;
+        self->x1 = val;
+        self->data[i] *= 0.2;
+    }
 }
 
 static void
-SumOsc_readframes_aaa(SumOsc *self) {
-    MYFLT freq, ratio, ind, mod_freq, mod_delta, freq_delta, x, y, ind2, theta_minus_beta, sin1, sin2, cos1;
-    int i, ipart;
-    
-    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    MYFLT *rat = Stream_getData((Stream *)self->ratio_stream);
-    MYFLT *index = Stream_getData((Stream *)self->index_stream);
+SuperSaw_readframes_aaa(SuperSaw *self) {
+    MYFLT fr, twoOnSr, val;
+    int i, j, det_ind, bal_ind;
+
+    MYFLT *freq = Stream_getData((Stream *)self->freq_stream);
+    MYFLT *detune = Stream_getData((Stream *)self->detune_stream);
+    MYFLT *balance = Stream_getData((Stream *)self->bal_stream);
+    twoOnSr = 2.0 / self->sr;
 
     for (i=0; i<self->bufsize; i++) {
-        freq = fr[i];
-        ind = index[i];
-        ratio = rat[i];
-        freq_delta = freq * self->scaleFactor;
-        mod_freq = freq * ratio;
-        mod_delta = mod_freq * self->scaleFactor;
-        if (ind < 0)
-            ind = 0;
-        else if (ind > 0.999)
-            ind = 0.999;
-        ind2 = ind * ind;
-        ipart = (int)self->theta;
-        sin1 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (self->theta - ipart);
-        theta_minus_beta = Sine_clip(self->theta - self->beta);
-        ipart = (int)theta_minus_beta;
-        sin2 = SINE_ARRAY[ipart] + (SINE_ARRAY[ipart+1] - SINE_ARRAY[ipart]) * (theta_minus_beta - ipart);
-        ipart = (int)self->beta;
-        cos1 = COSINE_ARRAY[ipart] + (COSINE_ARRAY[ipart+1] - COSINE_ARRAY[ipart]) * (self->beta - ipart);
-        x = (sin1 - ind * sin2) / (1 + ind2 - 2 * ind * cos1);
-        self->theta += freq_delta;
-        self->beta += mod_delta;
-        self->theta = Sine_clip(self->theta);
-        self->beta = Sine_clip(self->beta);
-        
-        y = x - self->xn1 + 0.995 * self->yn1;
-        self->xn1 = x; self->yn1 = y;
+        fr = freq[i];
+        if (fr <= 1.0)
+            fr = 1.0;
+        else if (fr >= self->nyquist)
+            fr = self->nyquist;
+        if (fr != self->lastFilterFreq) {
+            self->lastFilterFreq = fr;
+            self->w0 = TWOPI * fr / self->sr;
+            self->c = MYCOS(self->w0);
+            self->alpha = MYSIN(self->w0) * 0.5;
+            self->b0 = self->b2 = (1 + self->c) * 0.5;
+            self->b1 = -(1 + self->c);
+            self->a0 = 1 + self->alpha;
+            self->a1 = -2 * self->c;
+            self->a2 = 1 - self->alpha;
+        }
+        det_ind = (int)(_clip(detune[i]) * 126);
+        bal_ind = (int)(_clip(balance[i]) * 126);
 
-        self->data[i] = y * (1 - ind2);
-    } 
+        val = 0.0;
+        for (j=0; j<7; j++) {
+            val += self->pointerPos[j] * SUPERSAW_BALANCES[j][bal_ind];
+            self->pointerPos[j] += fr * SUPERSAW_DETUNES[j][det_ind] * twoOnSr;
+            if (self->pointerPos[j] < -1.0)
+                self->pointerPos[j] += 2.0;
+            else if (self->pointerPos[j] >= 1.0)
+                self->pointerPos[j] -= 2.0;
+        }
+        self->data[i] = ( (self->b0 * val) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
+        self->y2 = self->y1;
+        self->y1 = self->data[i];
+        self->x2 = self->x1;
+        self->x1 = val;
+        self->data[i] *= 0.2;
+    }
 }
 
-static void SumOsc_postprocessing_ii(SumOsc *self) { POST_PROCESSING_II };
-static void SumOsc_postprocessing_ai(SumOsc *self) { POST_PROCESSING_AI };
-static void SumOsc_postprocessing_ia(SumOsc *self) { POST_PROCESSING_IA };
-static void SumOsc_postprocessing_aa(SumOsc *self) { POST_PROCESSING_AA };
-static void SumOsc_postprocessing_ireva(SumOsc *self) { POST_PROCESSING_IREVA };
-static void SumOsc_postprocessing_areva(SumOsc *self) { POST_PROCESSING_AREVA };
-static void SumOsc_postprocessing_revai(SumOsc *self) { POST_PROCESSING_REVAI };
-static void SumOsc_postprocessing_revaa(SumOsc *self) { POST_PROCESSING_REVAA };
-static void SumOsc_postprocessing_revareva(SumOsc *self) { POST_PROCESSING_REVAREVA };
+static void SuperSaw_postprocessing_ii(SuperSaw *self) { POST_PROCESSING_II };
+static void SuperSaw_postprocessing_ai(SuperSaw *self) { POST_PROCESSING_AI };
+static void SuperSaw_postprocessing_ia(SuperSaw *self) { POST_PROCESSING_IA };
+static void SuperSaw_postprocessing_aa(SuperSaw *self) { POST_PROCESSING_AA };
+static void SuperSaw_postprocessing_ireva(SuperSaw *self) { POST_PROCESSING_IREVA };
+static void SuperSaw_postprocessing_areva(SuperSaw *self) { POST_PROCESSING_AREVA };
+static void SuperSaw_postprocessing_revai(SuperSaw *self) { POST_PROCESSING_REVAI };
+static void SuperSaw_postprocessing_revaa(SuperSaw *self) { POST_PROCESSING_REVAA };
+static void SuperSaw_postprocessing_revareva(SuperSaw *self) { POST_PROCESSING_REVAREVA };
 
 static void
-SumOsc_setProcMode(SumOsc *self)
+SuperSaw_setProcMode(SuperSaw *self)
 {
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:        
-            self->proc_func_ptr = SumOsc_readframes_iii;
+        case 0:
+            self->proc_func_ptr = SuperSaw_readframes_iii;
             break;
-        case 1:    
-            self->proc_func_ptr = SumOsc_readframes_aii;
+        case 1:
+            self->proc_func_ptr = SuperSaw_readframes_aii;
             break;
-        case 10:    
-            self->proc_func_ptr = SumOsc_readframes_iai;
+        case 10:
+            self->proc_func_ptr = SuperSaw_readframes_iai;
             break;
-        case 11:    
-            self->proc_func_ptr = SumOsc_readframes_aai;
+        case 11:
+            self->proc_func_ptr = SuperSaw_readframes_aai;
             break;
-        case 100:        
-            self->proc_func_ptr = SumOsc_readframes_iia;
+        case 100:
+            self->proc_func_ptr = SuperSaw_readframes_iia;
             break;
-        case 101:    
-            self->proc_func_ptr = SumOsc_readframes_aia;
+        case 101:
+            self->proc_func_ptr = SuperSaw_readframes_aia;
             break;
-        case 110:    
-            self->proc_func_ptr = SumOsc_readframes_iaa;
+        case 110:
+            self->proc_func_ptr = SuperSaw_readframes_iaa;
             break;
-        case 111:    
-            self->proc_func_ptr = SumOsc_readframes_aaa;
+        case 111:
+            self->proc_func_ptr = SuperSaw_readframes_aaa;
             break;
-    } 
-    
+    }
 	switch (muladdmode) {
-        case 0:        
-            self->muladd_func_ptr = SumOsc_postprocessing_ii;
+        case 0:
+            self->muladd_func_ptr = SuperSaw_postprocessing_ii;
             break;
-        case 1:    
-            self->muladd_func_ptr = SumOsc_postprocessing_ai;
+        case 1:
+            self->muladd_func_ptr = SuperSaw_postprocessing_ai;
             break;
-        case 2:    
-            self->muladd_func_ptr = SumOsc_postprocessing_revai;
+        case 2:
+            self->muladd_func_ptr = SuperSaw_postprocessing_revai;
             break;
-        case 10:        
-            self->muladd_func_ptr = SumOsc_postprocessing_ia;
+        case 10:
+            self->muladd_func_ptr = SuperSaw_postprocessing_ia;
             break;
-        case 11:    
-            self->muladd_func_ptr = SumOsc_postprocessing_aa;
+        case 11:
+            self->muladd_func_ptr = SuperSaw_postprocessing_aa;
             break;
-        case 12:    
-            self->muladd_func_ptr = SumOsc_postprocessing_revaa;
+        case 12:
+            self->muladd_func_ptr = SuperSaw_postprocessing_revaa;
             break;
-        case 20:        
-            self->muladd_func_ptr = SumOsc_postprocessing_ireva;
+        case 20:
+            self->muladd_func_ptr = SuperSaw_postprocessing_ireva;
             break;
-        case 21:    
-            self->muladd_func_ptr = SumOsc_postprocessing_areva;
+        case 21:
+            self->muladd_func_ptr = SuperSaw_postprocessing_areva;
             break;
-        case 22:    
-            self->muladd_func_ptr = SumOsc_postprocessing_revareva;
+        case 22:
+            self->muladd_func_ptr = SuperSaw_postprocessing_revareva;
             break;
     }
 }
 
 static void
-SumOsc_compute_next_data_frame(SumOsc *self)
+SuperSaw_compute_next_data_frame(SuperSaw *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
 static int
-SumOsc_traverse(SumOsc *self, visitproc visit, void *arg)
+SuperSaw_traverse(SuperSaw *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
-    Py_VISIT(self->ratio);    
-    Py_VISIT(self->ratio_stream);    
-    Py_VISIT(self->index);    
-    Py_VISIT(self->index_stream);    
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->detune);
+    Py_VISIT(self->detune_stream);
+    Py_VISIT(self->bal);
+    Py_VISIT(self->bal_stream);
     return 0;
 }
 
-static int 
-SumOsc_clear(SumOsc *self)
+static int
+SuperSaw_clear(SuperSaw *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
-    Py_CLEAR(self->ratio);    
-    Py_CLEAR(self->ratio_stream);    
-    Py_CLEAR(self->index);    
-    Py_CLEAR(self->index_stream);    
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->detune);
+    Py_CLEAR(self->detune_stream);
+    Py_CLEAR(self->bal);
+    Py_CLEAR(self->bal_stream);
     return 0;
 }
 
 static void
-SumOsc_dealloc(SumOsc* self)
+SuperSaw_dealloc(SuperSaw* self)
 {
     pyo_DEALLOC
-    SumOsc_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    SuperSaw_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
-SumOsc_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+SuperSaw_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
-    PyObject *freqtmp=NULL, *ratiotmp=NULL, *indextmp=NULL, *multmp=NULL, *addtmp=NULL;
-    SumOsc *self;
-    self = (SumOsc *)type->tp_alloc(type, 0);
-    
+    PyObject *freqtmp=NULL, *detunetmp=NULL, *baltmp=NULL, *multmp=NULL, *addtmp=NULL;
+    SuperSaw *self;
+    self = (SuperSaw *)type->tp_alloc(type, 0);
+
     self->freq = PyFloat_FromDouble(100);
-    self->ratio = PyFloat_FromDouble(0.5);
-    self->index = PyFloat_FromDouble(0.5);
+    self->detune = PyFloat_FromDouble(0.5);
+    self->bal = PyFloat_FromDouble(0.7);
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
 	self->modebuffer[4] = 0;
-    self->theta = self->beta = 0.;
-    self->xn1 = self->yn1 = 0.0;
-    
+    self->pointerPos[0] = -0.75;
+    self->pointerPos[1] = -0.5;
+    self->pointerPos[2] = -0.25;
+    self->pointerPos[3] = 0.0;
+    self->pointerPos[4] = 0.25;
+    self->pointerPos[5] = 0.5;
+    self->pointerPos[6] = 0.75;
+    self->lastFilterFreq = -1.0;
+    self->x1 = self->x2 = self->y1 = self->y2 = 0.0;
+
     INIT_OBJECT_COMMON
-    Stream_setFunctionPtr(self->stream, SumOsc_compute_next_data_frame);
-    self->mode_func_ptr = SumOsc_setProcMode;
 
-    self->scaleFactor = 512.0 / self->sr;
+    self->nyquist = (MYFLT)self->sr * 0.49;
 
-    static char *kwlist[] = {"freq", "ratio", "index", "mul", "add", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOO", kwlist, &freqtmp, &ratiotmp, &indextmp, &multmp, &addtmp))
+    Stream_setFunctionPtr(self->stream, SuperSaw_compute_next_data_frame);
+    self->mode_func_ptr = SuperSaw_setProcMode;
+
+    static char *kwlist[] = {"freq", "detune", "bal", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOO", kwlist, &freqtmp, &detunetmp, &baltmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    
-    if (ratiotmp) {
-        PyObject_CallMethod((PyObject *)self, "setRatio", "O", ratiotmp);
+
+    if (detunetmp) {
+        PyObject_CallMethod((PyObject *)self, "setDetune", "O", detunetmp);
     }
 
-    if (indextmp) {
-        PyObject_CallMethod((PyObject *)self, "setIndex", "O", indextmp);
+    if (baltmp) {
+        PyObject_CallMethod((PyObject *)self, "setBal", "O", baltmp);
     }
-    
+
     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 * SumOsc_getServer(SumOsc* self) { GET_SERVER };
-static PyObject * SumOsc_getStream(SumOsc* self) { GET_STREAM };
-static PyObject * SumOsc_setMul(SumOsc *self, PyObject *arg) { SET_MUL };	
-static PyObject * SumOsc_setAdd(SumOsc *self, PyObject *arg) { SET_ADD };	
-static PyObject * SumOsc_setSub(SumOsc *self, PyObject *arg) { SET_SUB };	
-static PyObject * SumOsc_setDiv(SumOsc *self, PyObject *arg) { SET_DIV };	
+static PyObject * SuperSaw_getServer(SuperSaw* self) { GET_SERVER };
+static PyObject * SuperSaw_getStream(SuperSaw* self) { GET_STREAM };
+static PyObject * SuperSaw_setMul(SuperSaw *self, PyObject *arg) { SET_MUL };
+static PyObject * SuperSaw_setAdd(SuperSaw *self, PyObject *arg) { SET_ADD };
+static PyObject * SuperSaw_setSub(SuperSaw *self, PyObject *arg) { SET_SUB };
+static PyObject * SuperSaw_setDiv(SuperSaw *self, PyObject *arg) { SET_DIV };
 
-static PyObject * SumOsc_play(SumOsc *self, PyObject *args, PyObject *kwds) { PLAY };
-static PyObject * SumOsc_out(SumOsc *self, PyObject *args, PyObject *kwds) { OUT };
-static PyObject * SumOsc_stop(SumOsc *self) { STOP };
+static PyObject * SuperSaw_play(SuperSaw *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * SuperSaw_out(SuperSaw *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * SuperSaw_stop(SuperSaw *self) { STOP };
 
-static PyObject * SumOsc_multiply(SumOsc *self, PyObject *arg) { MULTIPLY };
-static PyObject * SumOsc_inplace_multiply(SumOsc *self, PyObject *arg) { INPLACE_MULTIPLY };
-static PyObject * SumOsc_add(SumOsc *self, PyObject *arg) { ADD };
-static PyObject * SumOsc_inplace_add(SumOsc *self, PyObject *arg) { INPLACE_ADD };
-static PyObject * SumOsc_sub(SumOsc *self, PyObject *arg) { SUB };
-static PyObject * SumOsc_inplace_sub(SumOsc *self, PyObject *arg) { INPLACE_SUB };
-static PyObject * SumOsc_div(SumOsc *self, PyObject *arg) { DIV };
-static PyObject * SumOsc_inplace_div(SumOsc *self, PyObject *arg) { INPLACE_DIV };
+static PyObject * SuperSaw_multiply(SuperSaw *self, PyObject *arg) { MULTIPLY };
+static PyObject * SuperSaw_inplace_multiply(SuperSaw *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * SuperSaw_add(SuperSaw *self, PyObject *arg) { ADD };
+static PyObject * SuperSaw_inplace_add(SuperSaw *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * SuperSaw_sub(SuperSaw *self, PyObject *arg) { SUB };
+static PyObject * SuperSaw_inplace_sub(SuperSaw *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * SuperSaw_div(SuperSaw *self, PyObject *arg) { DIV };
+static PyObject * SuperSaw_inplace_div(SuperSaw *self, PyObject *arg) { INPLACE_DIV };
 
 static PyObject *
-SumOsc_setFreq(SumOsc *self, PyObject *arg)
+SuperSaw_setFreq(SuperSaw *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -9292,119 +11712,113 @@ SumOsc_setFreq(SumOsc *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
-SumOsc_setRatio(SumOsc *self, PyObject *arg)
+SuperSaw_setDetune(SuperSaw *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
-	Py_DECREF(self->ratio);
+	Py_DECREF(self->detune);
 	if (isNumber == 1) {
-		self->ratio = PyNumber_Float(tmp);
+		self->detune = PyNumber_Float(tmp);
         self->modebuffer[3] = 0;
 	}
 	else {
-		self->ratio = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->ratio, "_getStream", NULL);
+		self->detune = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->detune, "_getStream", NULL);
         Py_INCREF(streamtmp);
-        Py_XDECREF(self->ratio_stream);
-        self->ratio_stream = (Stream *)streamtmp;
+        Py_XDECREF(self->detune_stream);
+        self->detune_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
-SumOsc_setIndex(SumOsc *self, PyObject *arg)
+SuperSaw_setBal(SuperSaw *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
-	Py_DECREF(self->index);
+	Py_DECREF(self->bal);
 	if (isNumber == 1) {
-		self->index = PyNumber_Float(tmp);
+		self->bal = PyNumber_Float(tmp);
         self->modebuffer[4] = 0;
 	}
 	else {
-		self->index = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->index, "_getStream", NULL);
+		self->bal = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->bal, "_getStream", NULL);
         Py_INCREF(streamtmp);
-        Py_XDECREF(self->index_stream);
-        self->index_stream = (Stream *)streamtmp;
+        Py_XDECREF(self->bal_stream);
+        self->bal_stream = (Stream *)streamtmp;
 		self->modebuffer[4] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
-static PyMemberDef SumOsc_members[] = {
-{"server", T_OBJECT_EX, offsetof(SumOsc, server), 0, "Pyo server."},
-{"stream", T_OBJECT_EX, offsetof(SumOsc, stream), 0, "Stream object."},
-{"freq", T_OBJECT_EX, offsetof(SumOsc, freq), 0, "Frequency in cycle per second."},
-{"ratio", T_OBJECT_EX, offsetof(SumOsc, ratio), 0, "Ratio freq:modulator (mod freq = freq*ratio)."},
-{"index", T_OBJECT_EX, offsetof(SumOsc, index), 0, "Index, high frequency damping."},
-{"mul", T_OBJECT_EX, offsetof(SumOsc, mul), 0, "Mul factor."},
-{"add", T_OBJECT_EX, offsetof(SumOsc, add), 0, "Add factor."},
+static PyMemberDef SuperSaw_members[] = {
+{"server", T_OBJECT_EX, offsetof(SuperSaw, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(SuperSaw, stream), 0, "Stream object."},
+{"freq", T_OBJECT_EX, offsetof(SuperSaw, freq), 0, "Frequency in cycle per second."},
+{"detune", T_OBJECT_EX, offsetof(SuperSaw, detune), 0, "Detune factor."},
+{"bal", T_OBJECT_EX, offsetof(SuperSaw, bal), 0, "Mix factor."},
+{"mul", T_OBJECT_EX, offsetof(SuperSaw, mul), 0, "Mul factor."},
+{"add", T_OBJECT_EX, offsetof(SuperSaw, add), 0, "Add factor."},
 {NULL}  /* Sentinel */
 };
 
-static PyMethodDef SumOsc_methods[] = {
-{"getServer", (PyCFunction)SumOsc_getServer, METH_NOARGS, "Returns server object."},
-{"_getStream", (PyCFunction)SumOsc_getStream, METH_NOARGS, "Returns stream object."},
-{"play", (PyCFunction)SumOsc_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundfreqd."},
-{"out", (PyCFunction)SumOsc_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundfreqd channel speficied by argument."},
-{"stop", (PyCFunction)SumOsc_stop, METH_NOARGS, "Stops computing."},
-{"setFreq", (PyCFunction)SumOsc_setFreq, METH_O, "Sets oscillator frequency in cycle per second."},
-{"setRatio", (PyCFunction)SumOsc_setRatio, METH_O, "Sets freq:mod ratio."},
-{"setIndex", (PyCFunction)SumOsc_setIndex, METH_O, "Sets high frequency damping."},
-{"setMul", (PyCFunction)SumOsc_setMul, METH_O, "Sets SumOsc mul factor."},
-{"setAdd", (PyCFunction)SumOsc_setAdd, METH_O, "Sets SumOsc add factor."},
-{"setSub", (PyCFunction)SumOsc_setSub, METH_O, "Sets inverse add factor."},
-{"setDiv", (PyCFunction)SumOsc_setDiv, METH_O, "Sets inverse mul factor."},
+static PyMethodDef SuperSaw_methods[] = {
+{"getServer", (PyCFunction)SuperSaw_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)SuperSaw_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)SuperSaw_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"out", (PyCFunction)SuperSaw_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+{"stop", (PyCFunction)SuperSaw_stop, METH_NOARGS, "Stops computing."},
+{"setFreq", (PyCFunction)SuperSaw_setFreq, METH_O, "Sets oscillator frequency in cycle per second."},
+{"setDetune", (PyCFunction)SuperSaw_setDetune, METH_O, "Sets oscillator detune factor."},
+{"setBal", (PyCFunction)SuperSaw_setBal, METH_O, "Sets oscillator mix factor."},
+{"setMul", (PyCFunction)SuperSaw_setMul, METH_O, "Sets oscillator mul factor."},
+{"setAdd", (PyCFunction)SuperSaw_setAdd, METH_O, "Sets oscillator add factor."},
+{"setSub", (PyCFunction)SuperSaw_setSub, METH_O, "Sets oscillator inverse add factor."},
+{"setDiv", (PyCFunction)SuperSaw_setDiv, METH_O, "Sets inverse mul factor."},
 {NULL}  /* Sentinel */
 };
 
-static PyNumberMethods SumOsc_as_number = {
-(binaryfunc)SumOsc_add,                      /*nb_add*/
-(binaryfunc)SumOsc_sub,                 /*nb_subtract*/
-(binaryfunc)SumOsc_multiply,                 /*nb_multiply*/
-(binaryfunc)SumOsc_div,                   /*nb_divide*/
+static PyNumberMethods SuperSaw_as_number = {
+(binaryfunc)SuperSaw_add,                      /*nb_add*/
+(binaryfunc)SuperSaw_sub,                 /*nb_subtract*/
+(binaryfunc)SuperSaw_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,                  /*(unaryfunc)array_abs,*/
 0,                    /*nb_nonzero*/
 0,                    /*nb_invert*/
 0,               /*nb_lshift*/
@@ -9412,16 +11826,16 @@ static PyNumberMethods SumOsc_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
-(binaryfunc)SumOsc_inplace_add,              /*inplace_add*/
-(binaryfunc)SumOsc_inplace_sub,         /*inplace_subtract*/
-(binaryfunc)SumOsc_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)SumOsc_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
+(binaryfunc)SuperSaw_inplace_add,              /*inplace_add*/
+(binaryfunc)SuperSaw_inplace_sub,         /*inplace_subtract*/
+(binaryfunc)SuperSaw_inplace_multiply,         /*inplace_multiply*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -9430,25 +11844,24 @@ static PyNumberMethods SumOsc_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)SuperSaw_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)SuperSaw_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
-PyTypeObject SumOscType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
-"_pyo.SumOsc_base",         /*tp_name*/
-sizeof(SumOsc),         /*tp_basicsize*/
+PyTypeObject SuperSawType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.SuperSaw_base",         /*tp_name*/
+sizeof(SuperSaw),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
-(destructor)SumOsc_dealloc, /*tp_dealloc*/
+(destructor)SuperSaw_dealloc, /*tp_dealloc*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
-&SumOsc_as_number,             /*tp_as_number*/
+&SuperSaw_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
 0,                         /*tp_as_mapping*/
 0,                         /*tp_hash */
@@ -9457,810 +11870,780 @@ sizeof(SumOsc),         /*tp_basicsize*/
 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*/
-"SumOsc objects. Infite summation oscillator.",           /* tp_doc */
-(traverseproc)SumOsc_traverse,   /* tp_traverse */
-(inquiry)SumOsc_clear,           /* tp_clear */
+Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
+"SuperSaw objects. detune incrementor from 0 to 1.",           /* tp_doc */
+(traverseproc)SuperSaw_traverse,   /* tp_traverse */
+(inquiry)SuperSaw_clear,           /* tp_clear */
 0,		               /* tp_richcompare */
 0,		               /* tp_weaklistoffset */
 0,		               /* tp_iter */
 0,		               /* tp_iternext */
-SumOsc_methods,             /* tp_methods */
-SumOsc_members,             /* tp_members */
+SuperSaw_methods,             /* tp_methods */
+SuperSaw_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 */
-SumOsc_new,                 /* tp_new */
-};
-
-static MYFLT SUPERSAW_DETUNES[7][128] = {{1.0, 0.9999999999999738, 0.9999999999983218, 0.9999999999808844, 0.9999999998925958, 0.9999999995902856, 0.9999999987765995, 0.999999996915041, 0.9999999931261337, 0.9999999860647035, 0.9999999737782811, 0.9999999535466255, 0.999999921702367, 0.9999998734327713, 0.9999998025626238, 0.9999997013182335, 0.9999995600725585, 0.9999993670714514, 0.999999108141024, 0.9999987663761343, 0.999998321809992, 0.9999977510648862, 0.9999970269840314, 0.9999961182445354, 0.9999949889514873, 0.9999935982131656, 0.999991899697366, 0.9999898411688514, 0.9999873640079204, 0.999984402710097, 0.9999808843669409, 0.9999767281279772, 0.9999718446437478, 0.9999661354899821, 0.9999594925728883, 0.9999517975155655, 0.9999429210255355, 0.9999327222433956, 0.9999210480725913, 0.9999077324903094, 0.9998925958394921, 0.9998754441019703, 0.9998560681527183, 0.9998342429952286, 0.9998097269780065, 0.9997822609921857, 0.9997515676502643, 0.9997173504459607, 0.99967929289519, 0.9996370576581611, 0.9995902856425938, 0.9995385950880562, 0.999481580631423, 0.9994188123534535, 0.9993498348064905, 0.9992741660232791, 0.999191296506906, 0.9991006882018598, 0.9990017734462106, 0.9988939539049104, 0.9987765994842147, 0.9986490472272227, 0.9985106001905395, 0.9983605263020577, 0.9981980571998603, 0.9980223870522424, 0.9978326713588549, 0.9976280257329677, 0.9974075246648535, 0.9971702002662917, 0.996915040996193, 0.9966409903673441, 0.9963469456342734, 0.9960317564622357, 0.995694223577319, 0.9953330973976697, 0.9949470766458405, 0.9945348069422566, 0.994094879379803, 0.9936258290795327, 0.9931261337274945, 0.9925942120926815, 0.9920284225260998, 0.9914270614409579, 0.9907883617739762, 0.9901104914278165, 0.9893915516946329, 0.988629575660742, 0.9878225265924139, 0.9869682963027838, 0.9860647034998833, 0.985109492115793, 0.9841003296169146, 0.9830348052953636, 0.9819104285414826, 0.9807246270974751, 0.9794747452921589, 0.9781580422568408, 0.9767716901223106, 0.9753127721969568, 0.9737782811260014, 0.9721651170318559, 0.9704700856355972, 0.9686898963595642, 0.9668211604110741, 0.9648603888472602, 0.9628039906210292, 0.9606482706081385, 0.9583894276153956, 0.9560235523699754, 0.9535466254898602, 0.9509545154353983, 0.9482429764419842, 0.9454076464338582, 0.9424440449190272, 0.9393475708653054, 0.9361135005574749, 0.9327369854355683, 0.9292130499142693, 0.9255365891834358, 0.9217023669897422, 0.9177050133994422, 0.9135390225422524, 0.9091987503363557, 0.9046784121945255, 0.8999720807113701, 0.8950736833316975, 0.889977},
-{1.0, 0.999999999999985, 0.9999999999990408, 0.9999999999890743, 0.9999999999386124, 0.999999999765825, 0.999999999300757, 0.9999999982367705, 0.9999999960711946, 0.9999999920351857, 0.9999999850127967, 0.9999999734492553, 0.999999955248451, 0.9999999276596326, 0.9999998871533139, 0.9999998292863885, 0.9999997485564546, 0.9999996382453485, 0.9999994902518874, 0.9999992949138214, 0.9999990408189948, 0.9999987146057163, 0.9999983007523392, 0.9999977813560498, 0.9999971359008654, 0.9999963410148422, 0.9999953702164914, 0.9999941936504051, 0.9999927778120908, 0.9999910852620164, 0.9999890743288626, 0.9999866988019865, 0.9999839076130926, 0.9999806445071142, 0.9999768477023036, 0.9999724495395311, 0.9999673761207947, 0.9999615469369367, 0.999954874484572, 0.9999472638722232, 0.9999386124156673, 0.9999288092224893, 0.9999177347658472, 0.9999052604474442, 0.9998912481497119, 0.9998755497772012, 0.9998580067871834, 0.9998384497094605, 0.9998166976553837, 0.9997925578160827, 0.9997658249499025, 0.999736280859051, 0.9997036938554544, 0.9996678182158232, 0.9996283936259261, 0.9995851446140742, 0.9995377799738134, 0.9994859921758271, 0.9994294567690473, 0.9993678317709748, 0.9993007570472097, 0.9992278536801902, 0.9991487233271403, 0.9990629475672279, 0.9989700872379311, 0.998869681760614, 0.9987612484553119, 0.9986442818447255, 0.9985182529474248, 0.998382608560261, 0.9982367705299892, 0.998080135014099, 0.9979120717308554, 0.9977319231985478, 0.9975390039639489, 0.9973325998199832, 0.9971119670126036, 0.996876331436878, 0.9966248878222852, 0.9963567989072191, 0.9960711946027035, 0.9957671711453152, 0.9954437902393161, 0.9951000781879951, 0.9947350250142191, 0.9943475835701934, 0.9939366686364304, 0.9935011560099285, 0.9930398815815602, 0.9925516404026683, 0.9920351857408729, 0.9914892281250863, 0.9909124343797379, 0.9903034266482077, 0.9896607814054699, 0.9889830284599445, 0.9882686499445592, 0.9875160792970205, 0.9867237002292923, 0.9858898456862866, 0.9850127967937606, 0.984090781795425, 0.9831219749792602, 0.982104495593043, 0.9810364067490811, 0.9799157143181576, 0.978740365812685, 0.9775082492590679, 0.9762171920592747, 0.9748649598416194, 0.9734492553007513, 0.9719677170268558, 0.9704179183240623, 0.9687973660180627, 0.9671034992529387, 0.9653336882771985, 0.9634852332190221, 0.9615553628507172, 0.9595412333423818, 0.9574399270047795, 0.9552484510214205, 0.9529637361698543, 0.9505826355321707, 0.9481019231947095, 0.9455182929369806, 0.9428283569097924, 0.9400286443025894, 0.9371156},
-{1.0, 0.9999999999999953, 0.9999999999997022, 0.9999999999966079, 0.9999999999809411, 0.9999999999272962, 0.9999999997829073, 0.9999999994525735, 0.9999999987802313, 0.9999999975271793, 0.9999999953469515, 0.9999999917568408, 0.9999999861060718, 0.9999999775406239, 0.9999999649647041, 0.9999999469988698, 0.9999999219348009, 0.9999998876867218, 0.9999998417394735, 0.999999781093236, 0.9999997022048986, 0.9999996009260829, 0.9999994724378124, 0.9999993111818348, 0.999999110788592, 0.999998864001841, 0.9999985625999245, 0.9999981973136907, 0.9999977577410636, 0.9999972322582629, 0.9999966079276733, 0.9999958704023647, 0.9999950038272605, 0.9999939907369569, 0.9999928119501926, 0.9999914464609663, 0.9999898713263058, 0.9999880615506863, 0.9999859899670982, 0.9999836271147652, 0.9999809411135118, 0.9999778975347812, 0.999974459269302, 0.9999705863914059, 0.999966236019994, 0.9999613621761544, 0.9999559156374276, 0.9999498437887238, 0.9999430904698884, 0.9999355958199183, 0.9999272961178276, 0.9999181236201629, 0.9999080063951687, 0.9998968681536032, 0.9998846280762023, 0.9998712006377948, 0.9998564954280671, 0.9998404169689776, 0.9998228645288206, 0.9998037319329405, 0.9997829073710953, 0.9997602732014707, 0.9997357057513431, 0.999709075114393, 0.9996802449446679, 0.9996490722471952, 0.9996154071652449, 0.9995790927642417, 0.9995399648123278, 0.9994978515575741, 0.999452573501843, 0.9994039431712994, 0.9993517648835726, 0.9992958345115667, 0.9992359392439231, 0.9991718573421298, 0.9991033578942833, 0.9990302005654985, 0.998952135344969, 0.9988689022896773, 0.9987802312647548, 0.9986858416804911, 0.9985854422259942, 0.9984787305994991, 0.9983653932353271, 0.9982451050274953, 0.9981175290499744, 0.9979823162735979, 0.9978391052796202, 0.9976875219699247, 0.997527179273882, 0.9973576768518573, 0.9971786007953681, 0.9969895233238919, 0.9967900024783226, 0.9965795818110783, 0.9963577900728574, 0.9961241408960458, 0.995878132474773, 0.9956192472416178, 0.9953469515409651, 0.9950606952990115, 0.9947599116904207, 0.9944440168016286, 0.9941124092907996, 0.9937644700444305, 0.9933995618306056, 0.9930170289489021, 0.9926161968769434, 0.992196371913604, 0.9917568408188636, 0.9912968704503108, 0.9908157073962964, 0.9903125776057377, 0.9897866860145708, 0.9892372161688545, 0.9886633298445227, 0.9880641666637873, 0.9874388437081904, 0.9867864551283071, 0.9861060717500971, 0.985396740677907, 0.9846574848941214, 0.9838873028554654, 0.9830851680859551, 0.9822500287664989, 0.9813808073211485, 0.9804764},
-{1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0},
-{1.0, 1.0000000000000047, 1.0000000000003038, 1.0000000000034597, 1.0000000000194382, 1.000000000074151, 1.0000000002214138, 1.0000000005583225, 1.000000001244047, 1.0000000025220401, 1.0000000047456632, 1.000000008407232, 1.0000000141704746, 1.00000002290641, 1.0000000357326424, 1.0000000540560707, 1.0000000796190178, 1.0000001145487747, 1.0000001614105622, 1.0000002232639098, 1.0000003037224496, 1.0000004070171307, 1.0000005380628465, 1.0000007025284818, 1.000000906910375, 1.0000011586091981, 1.0000014660102534, 1.000001838567187, 1.0000022868891185, 1.00000282283119, 1.0000034595885279, 1.0000042117936259, 1.0000050956171416, 1.000006128872112, 1.000007331121585, 1.0000087237896673, 1.0000103302759908, 1.0000121760735943, 1.0000142888902226, 1.0000166987730426, 1.0000194382367766, 1.0000225423952513, 1.0000260490963657, 1.0000299990604729, 1.000034436022182, 1.0000394068755751, 1.0000449618228406, 1.0000511545263258, 1.0000580422640029, 1.0000656860883557, 1.0000741509886801, 1.0000835060568027, 1.0000938246562172, 1.0001051845946354, 1.0001176682999573, 1.000131362999657, 1.0001463609035854, 1.0001627593901905, 1.0001806611961532, 1.000200174609442, 1.0002214136657828, 1.0002444983485461, 1.000269554792052, 1.0002967154882902, 1.0003261194970592, 1.0003579126595197, 1.000392247815168, 1.0004292850222227, 1.0004691917814321, 1.0005121432632953, 1.000558322538702, 1.0006079208129879, 1.0006611376634087, 1.0007181812800294, 1.0007792687100308, 1.0008446261054336, 1.000914488974239, 1.0009891024349855, 1.0010687214747234, 1.0011536112104062, 1.0012440471536985, 1.0013403154792009, 1.0014427132960908, 1.001551548923183, 1.0016671421674035, 1.0017898246056827, 1.0019199398702647, 1.0020578439374328, 1.0022039054196534, 1.0023585058611355, 1.0025220400368071, 1.0026949162547094, 1.0028775566618078, 1.0030703975532176, 1.0032738896848503, 1.0034884985894736, 1.0037147048961896, 1.00395300465333, 1.004203909654768, 1.0044679477696459, 1.0047456632755227, 1.0050376171949345, 1.005344387635375, 1.0056665701326912, 1.006004777997897, 1.0063596426674022, 1.0067318140566603, 1.0071219609172322, 1.0075307711972652, 1.0079589524053931, 1.0084072319780484, 1.0088763576501938, 1.0093670978294713, 1.0098802419737667, 1.0104166009721909, 1.010977007529479, 1.0115623165538064, 1.0121734055480207, 1.0128111750042907, 1.013476548802174, 1.0141704746100983, 1.0148939242902633, 1.0156478943069556, 1.016433406138284, 1.0172515066913297, 1.0181032687207134, 1.01898979125058, 1.0199122},
-{1.0, 1.0000000000000149, 1.0000000000009481, 1.0000000000108007, 1.0000000000606857, 1.0000000002314975, 1.000000000691248, 1.0000000017430692, 1.0000000038838848, 1.0000000078737472, 1.0000000148158443, 1.000000026247172, 1.0000000442398742, 1.0000000715132509, 1.0000001115564334, 1.000000168761727, 1.0000002485686208, 1.0000003576184653, 1.0000005039198165, 1.00000069702445, 1.0000009482140382, 1.000001270697499, 1.0000016798190097, 1.0000021932766892, 1.0000028313519465, 1.0000036171494986, 1.0000045768480532, 1.0000057399616615, 1.000007139611736, 1.0000088128097373, 1.0000108007505284, 1.0000131491163944, 1.0000159083917324, 1.0000191341884066, 1.0000228875817727, 1.0000272354573667, 1.0000322508682655, 1.0000380134031104, 1.0000446095648012, 1.0000521331598566, 1.0000606856984415, 1.0000703768050623, 1.0000813246399298, 1.000093656330989, 1.0001075084166169, 1.0001230272989865, 1.0001403697080997, 1.0001597031764875, 1.0001812065245754, 1.0002050703567196, 1.0002314975679076, 1.0002607038611286, 1.000292918275409, 1.0003283837245178, 1.0003673575463365, 1.0004101120629, 1.000456935151101, 1.000508130824065, 1.000564019823191, 1.00062494022086, 1.000691248033811, 1.0007633178471849, 1.0008415434492337, 1.0009263384767009, 1.0010181370708653, 1.0011173945442546, 1.0012245880580264, 1.0013402173100148, 1.0014648052334467, 1.0015988987063238, 1.0017430692714728, 1.0018979138672632, 1.0020640555689915, 1.0022421443409335, 1.002432857799065, 1.0026369019844479, 1.0028550121472843, 1.00308795354164, 1.0033365222308317, 1.0036015459034857, 1.003883884700261, 1.0041844320512403, 1.0045041155239904, 1.004843897682287, 1.00520477695551, 1.0055877885187026, 1.0059940051833023, 1.0064245382985348, 1.006880538663479, 1.0073631974497963, 1.0078737471351296, 1.008413462447169, 1.008983661318385, 1.0095857058514275, 1.0102210032951957, 1.0108910070315718, 1.011597217572824, 1.0123411835696772, 1.0131245028300493, 1.0139488233484573, 1.0148158443460882, 1.0157273173215406, 1.0166850471122297, 1.017690892966463, 1.018746769626182, 1.0198546484203714, 1.0210165583691362, 1.022234587298445, 1.0235108829655426, 1.0248476541950278, 1.0262471720256006, 1.027711770867476, 1.0292438496704641, 1.0308458731027206, 1.0325203727401608, 1.0342699482665438, 1.0360972686842238, 1.0380050735355673, 1.0399961741350399, 1.042073454811958, 1.04423987416391, 1.0464984663208448, 1.0488523422198255, 1.051304690890453, 1.053858780750956, 1.0565179609149487, 1.0592856625088545, 1.0621654},
-{1.0, 1.0000000000000255, 1.000000000001639, 1.0000000000186688, 1.0000000001048943, 1.0000000004001401, 1.0000000011948122, 1.0000000030128702, 1.0000000067132389, 1.0000000136096587, 1.0000000256089738, 1.0000000453678595, 1.0000000764679864, 1.0000001236096256, 1.000000192823691, 1.0000002917022184, 1.0000004296472869, 1.0000006181383747, 1.000000871018157, 1.000001204796739, 1.0000016389743303, 1.000002196382355, 1.0000029035430034, 1.000003791047219, 1.0000048939511264, 1.000006252190896, 1.0000079110160478, 1.0000099214411948, 1.0000123407162225, 1.0000152328149083, 1.00001866894198, 1.0000227280586114, 1.0000274974263563, 1.000033073169523, 1.0000395608559847, 1.0000470760964295, 1.0000557451620493, 1.000065705620667, 1.000077106991301, 1.0000901114171699, 1.0001048943571336, 1.0001216452955755, 1.0001405684707207, 1.0001618836213946, 1.0001858267522177, 1.0002126509172415, 1.0002426270220208, 1.0002760446441257, 1.0003132128720909, 1.0003544611628048, 1.0004001402173366, 1.0004506228752006, 1.000506305027061, 1.0005676065458742, 1.0006349722364685, 1.000708872803565, 1.0007898058382332, 1.0008782968227894, 1.0009749001541295, 1.0010802001855026, 1.0011948122867234, 1.0013193839228205, 1.001454595751126, 1.001601162736803, 1.0017598352868091, 1.0019314004023019, 1.0021166828494799, 1.0023165463488648, 1.0025318947830195, 1.0027636734227063, 1.003012870171483, 1.003280516828737, 1.0035676903711592, 1.0038755142526548, 1.0042051597226938, 1.0045578471630987, 1.0049348474432722, 1.0053374832938626, 1.0057671306988667, 1.0062252203061728, 1.0067132388565414, 1.0072327306310243, 1.0077852989168221, 1.0083726074915806, 1.0089963821261256, 1.009658412105635, 1.010360551769251, 1.0111047220681308, 1.0118929121419333, 1.012727180913748, 1.0136096587034578, 1.0145425488595459, 1.0155281294093352, 1.0165687547276714, 1.0176668572240406, 1.0188249490481271, 1.0200456238138111, 1.0213315583416007, 1.0226855144195075, 1.0241103405823564, 1.0256089739095362, 1.027184441841188, 1.028839864012832, 1.0305784541084329, 1.0324035217319039, 1.0343184742970488, 1.0363268189359423, 1.0384321644257501, 1.0406382231339857, 1.0429488129822073, 1.0453678594281517, 1.0478993974663078, 1.0505475736469276, 1.053316648113477, 1.0562109966585231, 1.0592351127980624, 1.0623936098642848, 1.0656912231167786, 1.0691328118721717, 1.0727233616522132, 1.0764679863502924, 1.080371930416396, 1.0844405710605045, 1.0886794204744272, 1.0930941280720745, 1.0976904827481695, 1.102474415155399, 1.107452}
-};
-static MYFLT SUPERSAW_BALANCES[7][128] = {{0.044372, 0.0540113055986112, 0.0635591436542873, 0.07301551416702834, 0.08238041713683428, 0.09165385256370512, 0.10083582044764089, 0.10992632078864159, 0.11892535358670717, 0.12783291884183767, 0.1366490165540331, 0.14537364672329345, 0.1540068093496187, 0.16254850443300886, 0.17099873197346394, 0.17935749197098394, 0.18762478442556885, 0.19580060933721868, 0.2038849667059334, 0.21187785653171307, 0.2197792788145576, 0.2275892335544671, 0.2353077207514415, 0.24293474040548083, 0.25047029251658504, 0.2579143770847542, 0.2652669941099882, 0.2725281435922872, 0.27969782553165107, 0.2867760399280799, 0.2937627867815736, 0.30065806609213225, 0.3074618778597557, 0.3141742220844442, 0.32079509876619755, 0.3273245079050158, 0.333762449500899, 0.34010892355384714, 0.3463639300638601, 0.35252746903093807, 0.3585995404550809, 0.36458014433628866, 0.3704692806745614, 0.37626694946989897, 0.3819731507223015, 0.3875878844317689, 0.39311115059830126, 0.3985429492218985, 0.40388328030256065, 0.4091321438402877, 0.4142895398350797, 0.4193554682869366, 0.4243299291958584, 0.4292129225618452, 0.4340044483848969, 0.4387045066650134, 0.4433130974021948, 0.4478302205964412, 0.4522558762477525, 0.45659006435612876, 0.4608327849215699, 0.4649840379440759, 0.4690438234236469, 0.47301214136028275, 0.4768889917539835, 0.4806743746047492, 0.4843682899125799, 0.4879707376774754, 0.4914817178994358, 0.4949012305784613, 0.4982292757145515, 0.5014658533077067, 0.5046109633579267, 0.5076646058652117, 0.5106267808295617, 0.5134974882509765, 0.5162767281294562, 0.518964500465001, 0.5215608052576105, 0.524065642507285, 0.5264790122140244, 0.5288009143778287, 0.531031348998698, 0.5331703160766321, 0.5352178156116313, 0.5371738476036952, 0.5390384120528241, 0.5408115089590179, 0.5424931383222766, 0.5440833001426003, 0.5455819944199888, 0.5469892211544423, 0.5483049803459606, 0.549529271994544, 0.5506620961001921, 0.5517034526629053, 0.5526533416826834, 0.5535117631595262, 0.5542787170934341, 0.5549542034844069, 0.5555382223324447, 0.5560307736375473, 0.5564318573997148, 0.5567414736189472, 0.5569596222952445, 0.557086303428607, 0.5571215170190341, 0.5570652630665262, 0.5569175415710832, 0.5566783525327051, 0.556347695951392, 0.5559255718271436, 0.5554119801599603, 0.5548069209498419, 0.5541103941967883, 0.5533223999007997, 0.552442938061876, 0.5514720086800173, 0.5504096117552235, 0.5492557472874944, 0.5480104152768307, 0.5466736157232315, 0.5452453486266973, 0.543725613987228, 0.5421144118048237, 0.5404117420794842, 0.5386176048112096, 0.536732},
-{0.044372, 0.0540113055986112, 0.0635591436542873, 0.07301551416702834, 0.08238041713683428, 0.09165385256370512, 0.10083582044764089, 0.10992632078864159, 0.11892535358670717, 0.12783291884183767, 0.1366490165540331, 0.14537364672329345, 0.1540068093496187, 0.16254850443300886, 0.17099873197346394, 0.17935749197098394, 0.18762478442556885, 0.19580060933721868, 0.2038849667059334, 0.21187785653171307, 0.2197792788145576, 0.2275892335544671, 0.2353077207514415, 0.24293474040548083, 0.25047029251658504, 0.2579143770847542, 0.2652669941099882, 0.2725281435922872, 0.27969782553165107, 0.2867760399280799, 0.2937627867815736, 0.30065806609213225, 0.3074618778597557, 0.3141742220844442, 0.32079509876619755, 0.3273245079050158, 0.333762449500899, 0.34010892355384714, 0.3463639300638601, 0.35252746903093807, 0.3585995404550809, 0.36458014433628866, 0.3704692806745614, 0.37626694946989897, 0.3819731507223015, 0.3875878844317689, 0.39311115059830126, 0.3985429492218985, 0.40388328030256065, 0.4091321438402877, 0.4142895398350797, 0.4193554682869366, 0.4243299291958584, 0.4292129225618452, 0.4340044483848969, 0.4387045066650134, 0.4433130974021948, 0.4478302205964412, 0.4522558762477525, 0.45659006435612876, 0.4608327849215699, 0.4649840379440759, 0.4690438234236469, 0.47301214136028275, 0.4768889917539835, 0.4806743746047492, 0.4843682899125799, 0.4879707376774754, 0.4914817178994358, 0.4949012305784613, 0.4982292757145515, 0.5014658533077067, 0.5046109633579267, 0.5076646058652117, 0.5106267808295617, 0.5134974882509765, 0.5162767281294562, 0.518964500465001, 0.5215608052576105, 0.524065642507285, 0.5264790122140244, 0.5288009143778287, 0.531031348998698, 0.5331703160766321, 0.5352178156116313, 0.5371738476036952, 0.5390384120528241, 0.5408115089590179, 0.5424931383222766, 0.5440833001426003, 0.5455819944199888, 0.5469892211544423, 0.5483049803459606, 0.549529271994544, 0.5506620961001921, 0.5517034526629053, 0.5526533416826834, 0.5535117631595262, 0.5542787170934341, 0.5549542034844069, 0.5555382223324447, 0.5560307736375473, 0.5564318573997148, 0.5567414736189472, 0.5569596222952445, 0.557086303428607, 0.5571215170190341, 0.5570652630665262, 0.5569175415710832, 0.5566783525327051, 0.556347695951392, 0.5559255718271436, 0.5554119801599603, 0.5548069209498419, 0.5541103941967883, 0.5533223999007997, 0.552442938061876, 0.5514720086800173, 0.5504096117552235, 0.5492557472874944, 0.5480104152768307, 0.5466736157232315, 0.5452453486266973, 0.543725613987228, 0.5421144118048237, 0.5404117420794842, 0.5386176048112096, 0.536732},
-{0.044372, 0.0540113055986112, 0.0635591436542873, 0.07301551416702834, 0.08238041713683428, 0.09165385256370512, 0.10083582044764089, 0.10992632078864159, 0.11892535358670717, 0.12783291884183767, 0.1366490165540331, 0.14537364672329345, 0.1540068093496187, 0.16254850443300886, 0.17099873197346394, 0.17935749197098394, 0.18762478442556885, 0.19580060933721868, 0.2038849667059334, 0.21187785653171307, 0.2197792788145576, 0.2275892335544671, 0.2353077207514415, 0.24293474040548083, 0.25047029251658504, 0.2579143770847542, 0.2652669941099882, 0.2725281435922872, 0.27969782553165107, 0.2867760399280799, 0.2937627867815736, 0.30065806609213225, 0.3074618778597557, 0.3141742220844442, 0.32079509876619755, 0.3273245079050158, 0.333762449500899, 0.34010892355384714, 0.3463639300638601, 0.35252746903093807, 0.3585995404550809, 0.36458014433628866, 0.3704692806745614, 0.37626694946989897, 0.3819731507223015, 0.3875878844317689, 0.39311115059830126, 0.3985429492218985, 0.40388328030256065, 0.4091321438402877, 0.4142895398350797, 0.4193554682869366, 0.4243299291958584, 0.4292129225618452, 0.4340044483848969, 0.4387045066650134, 0.4433130974021948, 0.4478302205964412, 0.4522558762477525, 0.45659006435612876, 0.4608327849215699, 0.4649840379440759, 0.4690438234236469, 0.47301214136028275, 0.4768889917539835, 0.4806743746047492, 0.4843682899125799, 0.4879707376774754, 0.4914817178994358, 0.4949012305784613, 0.4982292757145515, 0.5014658533077067, 0.5046109633579267, 0.5076646058652117, 0.5106267808295617, 0.5134974882509765, 0.5162767281294562, 0.518964500465001, 0.5215608052576105, 0.524065642507285, 0.5264790122140244, 0.5288009143778287, 0.531031348998698, 0.5331703160766321, 0.5352178156116313, 0.5371738476036952, 0.5390384120528241, 0.5408115089590179, 0.5424931383222766, 0.5440833001426003, 0.5455819944199888, 0.5469892211544423, 0.5483049803459606, 0.549529271994544, 0.5506620961001921, 0.5517034526629053, 0.5526533416826834, 0.5535117631595262, 0.5542787170934341, 0.5549542034844069, 0.5555382223324447, 0.5560307736375473, 0.5564318573997148, 0.5567414736189472, 0.5569596222952445, 0.557086303428607, 0.5571215170190341, 0.5570652630665262, 0.5569175415710832, 0.5566783525327051, 0.556347695951392, 0.5559255718271436, 0.5554119801599603, 0.5548069209498419, 0.5541103941967883, 0.5533223999007997, 0.552442938061876, 0.5514720086800173, 0.5504096117552235, 0.5492557472874944, 0.5480104152768307, 0.5466736157232315, 0.5452453486266973, 0.543725613987228, 0.5421144118048237, 0.5404117420794842, 0.5386176048112096, 0.536732},
-{0.99785, 0.9934904251968504, 0.9891308503937009, 0.9847712755905512, 0.9804117007874016, 0.976052125984252, 0.9716925511811024, 0.9673329763779528, 0.9629734015748032, 0.9586138267716535, 0.954254251968504, 0.9498946771653544, 0.9455351023622047, 0.9411755275590551, 0.9368159527559056, 0.9324563779527559, 0.9280968031496063, 0.9237372283464567, 0.9193776535433071, 0.9150180787401575, 0.9106585039370079, 0.9062989291338582, 0.9019393543307087, 0.8975797795275591, 0.8932202047244094, 0.8888606299212598, 0.8845010551181103, 0.8801414803149606, 0.875781905511811, 0.8714223307086615, 0.8670627559055119, 0.8627031811023622, 0.8583436062992126, 0.8539840314960631, 0.8496244566929134, 0.8452648818897638, 0.8409053070866142, 0.8365457322834646, 0.832186157480315, 0.8278265826771654, 0.8234670078740158, 0.8191074330708662, 0.8147478582677166, 0.8103882834645669, 0.8060287086614173, 0.8016691338582678, 0.7973095590551181, 0.7929499842519685, 0.788590409448819, 0.7842308346456693, 0.7798712598425197, 0.7755116850393701, 0.7711521102362204, 0.7667925354330709, 0.7624329606299213, 0.7580733858267716, 0.7537138110236221, 0.7493542362204725, 0.7449946614173228, 0.7406350866141733, 0.7362755118110236, 0.731915937007874, 0.7275563622047244, 0.7231967874015748, 0.7188372125984253, 0.7144776377952756, 0.710118062992126, 0.7057584881889765, 0.7013989133858267, 0.6970393385826772, 0.6926797637795276, 0.6883201889763779, 0.6839606141732284, 0.6796010393700788, 0.6752414645669291, 0.6708818897637796, 0.6665223149606299, 0.6621627401574803, 0.6578031653543307, 0.6534435905511811, 0.6490840157480315, 0.6447244409448819, 0.6403648661417323, 0.6360052913385827, 0.631645716535433, 0.6272861417322835, 0.622926566929134, 0.6185669921259842, 0.6142074173228347, 0.609847842519685, 0.6054882677165354, 0.6011286929133859, 0.5967691181102361, 0.5924095433070866, 0.5880499685039371, 0.5836903937007873, 0.5793308188976378, 0.5749712440944883, 0.5706116692913386, 0.566252094488189, 0.5618925196850394, 0.5575329448818898, 0.5531733700787402, 0.5488137952755906, 0.544454220472441, 0.5400946456692914, 0.5357350708661417, 0.5313754960629922, 0.5270159212598425, 0.5226563464566929, 0.5182967716535434, 0.5139371968503937, 0.5095776220472441, 0.5052180472440946, 0.500858472440945, 0.4964988976377953, 0.4921393228346457, 0.48777974803149604, 0.4834201732283465, 0.4790605984251969, 0.47470102362204725, 0.4703414488188977, 0.4659818740157481, 0.46162229921259845, 0.4572627244094488, 0.4529031496062992, 0.44854357480314966, 0.444184},
-{0.044372, 0.054437289850579704, 0.06441111215822432, 0.07429346692293384, 0.08408435414470829, 0.09378377382354765, 0.10339172595945192, 0.11290821055242112, 0.12233322760245521, 0.1316667771095542, 0.14090885907371814, 0.150059473494947, 0.15911862037324073, 0.16808629970859942, 0.176962511501023, 0.1857472557505115, 0.1944405324570649, 0.20304234162068327, 0.21155268324136647, 0.21997155731911466, 0.2282989638539277, 0.23653490284580572, 0.2446793742947486, 0.25273237820075645, 0.2606939145638291, 0.26856398338396675, 0.27634258466116934, 0.2840297183954368, 0.2916253845867692, 0.2991295832351665, 0.3065423143406287, 0.31386357790315583, 0.3210933739227479, 0.3282317023994048, 0.3352785633331267, 0.3422339567239135, 0.34909788257176516, 0.3558703408766818, 0.3625513316386633, 0.3691408548577098, 0.3756389105338211, 0.3820454986669974, 0.3883606192572386, 0.3945842723045447, 0.4007164578089156, 0.4067571757703516, 0.41270642618885245, 0.4185642090644182, 0.4243305243970488, 0.4300053721867444, 0.43558875243350487, 0.44108066513733035, 0.44648111029822063, 0.4517900879161758, 0.457007597991196, 0.46213364052328115, 0.46716821551243104, 0.4721113229586459, 0.4769629628619257, 0.48172313522227056, 0.4863918400396801, 0.4909690773141547, 0.4954548470456941, 0.4998491492342985, 0.5041519838799677, 0.508363350982702, 0.5124832505425011, 0.5165116825593651, 0.5204486470332941, 0.524294143964288, 0.5280481733523468, 0.5317107351974705, 0.535281829499659, 0.5387614562589126, 0.542149615475231, 0.5454463071486143, 0.5486515312790626, 0.5517652878665756, 0.5547875769111539, 0.5577183984127968, 0.5605577523715047, 0.5633056387872776, 0.5659620576601153, 0.568527008990018, 0.5710004927769856, 0.5733825090210181, 0.5756730577221155, 0.5778721388802778, 0.5799797524955049, 0.5819958985677972, 0.5839205770971542, 0.5857537880835761, 0.587495531527063, 0.5891458074276149, 0.5907046157852317, 0.5921719565999132, 0.5935478298716598, 0.5948322356004713, 0.5960251737863476, 0.597126644429289, 0.598136647529295, 0.5990551830863663, 0.5998822511005023, 0.6006178515717031, 0.601261984499969, 0.6018146498852998, 0.6022758477276954, 0.6026455780271561, 0.6029238407836814, 0.6031106359972721, 0.6032059636679274, 0.6032098237956476, 0.6031222163804327, 0.6029431414222828, 0.6026725989211977, 0.6023105888771778, 0.6018571112902225, 0.6013121661603325, 0.6006757534875071, 0.5999478732717465, 0.5991285255130511, 0.5982177102114203, 0.5972154273668548, 0.596121676979354, 0.594936459048918, 0.5936597735755472, 0.5922916205592411, 0.590832},
-{0.044372, 0.054437289850579704, 0.06441111215822432, 0.07429346692293384, 0.08408435414470829, 0.09378377382354765, 0.10339172595945192, 0.11290821055242112, 0.12233322760245521, 0.1316667771095542, 0.14090885907371814, 0.150059473494947, 0.15911862037324073, 0.16808629970859942, 0.176962511501023, 0.1857472557505115, 0.1944405324570649, 0.20304234162068327, 0.21155268324136647, 0.21997155731911466, 0.2282989638539277, 0.23653490284580572, 0.2446793742947486, 0.25273237820075645, 0.2606939145638291, 0.26856398338396675, 0.27634258466116934, 0.2840297183954368, 0.2916253845867692, 0.2991295832351665, 0.3065423143406287, 0.31386357790315583, 0.3210933739227479, 0.3282317023994048, 0.3352785633331267, 0.3422339567239135, 0.34909788257176516, 0.3558703408766818, 0.3625513316386633, 0.3691408548577098, 0.3756389105338211, 0.3820454986669974, 0.3883606192572386, 0.3945842723045447, 0.4007164578089156, 0.4067571757703516, 0.41270642618885245, 0.4185642090644182, 0.4243305243970488, 0.4300053721867444, 0.43558875243350487, 0.44108066513733035, 0.44648111029822063, 0.4517900879161758, 0.457007597991196, 0.46213364052328115, 0.46716821551243104, 0.4721113229586459, 0.4769629628619257, 0.48172313522227056, 0.4863918400396801, 0.4909690773141547, 0.4954548470456941, 0.4998491492342985, 0.5041519838799677, 0.508363350982702, 0.5124832505425011, 0.5165116825593651, 0.5204486470332941, 0.524294143964288, 0.5280481733523468, 0.5317107351974705, 0.535281829499659, 0.5387614562589126, 0.542149615475231, 0.5454463071486143, 0.5486515312790626, 0.5517652878665756, 0.5547875769111539, 0.5577183984127968, 0.5605577523715047, 0.5633056387872776, 0.5659620576601153, 0.568527008990018, 0.5710004927769856, 0.5733825090210181, 0.5756730577221155, 0.5778721388802778, 0.5799797524955049, 0.5819958985677972, 0.5839205770971542, 0.5857537880835761, 0.587495531527063, 0.5891458074276149, 0.5907046157852317, 0.5921719565999132, 0.5935478298716598, 0.5948322356004713, 0.5960251737863476, 0.597126644429289, 0.598136647529295, 0.5990551830863663, 0.5998822511005023, 0.6006178515717031, 0.601261984499969, 0.6018146498852998, 0.6022758477276954, 0.6026455780271561, 0.6029238407836814, 0.6031106359972721, 0.6032059636679274, 0.6032098237956476, 0.6031222163804327, 0.6029431414222828, 0.6026725989211977, 0.6023105888771778, 0.6018571112902225, 0.6013121661603325, 0.6006757534875071, 0.5999478732717465, 0.5991285255130511, 0.5982177102114203, 0.5972154273668548, 0.596121676979354, 0.594936459048918, 0.5936597735755472, 0.5922916205592411, 0.590832},
-{0.044372, 0.054437289850579704, 0.06441111215822432, 0.07429346692293384, 0.08408435414470829, 0.09378377382354765, 0.10339172595945192, 0.11290821055242112, 0.12233322760245521, 0.1316667771095542, 0.14090885907371814, 0.150059473494947, 0.15911862037324073, 0.16808629970859942, 0.176962511501023, 0.1857472557505115, 0.1944405324570649, 0.20304234162068327, 0.21155268324136647, 0.21997155731911466, 0.2282989638539277, 0.23653490284580572, 0.2446793742947486, 0.25273237820075645, 0.2606939145638291, 0.26856398338396675, 0.27634258466116934, 0.2840297183954368, 0.2916253845867692, 0.2991295832351665, 0.3065423143406287, 0.31386357790315583, 0.3210933739227479, 0.3282317023994048, 0.3352785633331267, 0.3422339567239135, 0.34909788257176516, 0.3558703408766818, 0.3625513316386633, 0.3691408548577098, 0.3756389105338211, 0.3820454986669974, 0.3883606192572386, 0.3945842723045447, 0.4007164578089156, 0.4067571757703516, 0.41270642618885245, 0.4185642090644182, 0.4243305243970488, 0.4300053721867444, 0.43558875243350487, 0.44108066513733035, 0.44648111029822063, 0.4517900879161758, 0.457007597991196, 0.46213364052328115, 0.46716821551243104, 0.4721113229586459, 0.4769629628619257, 0.48172313522227056, 0.4863918400396801, 0.4909690773141547, 0.4954548470456941, 0.4998491492342985, 0.5041519838799677, 0.508363350982702, 0.5124832505425011, 0.5165116825593651, 0.5204486470332941, 0.524294143964288, 0.5280481733523468, 0.5317107351974705, 0.535281829499659, 0.5387614562589126, 0.542149615475231, 0.5454463071486143, 0.5486515312790626, 0.5517652878665756, 0.5547875769111539, 0.5577183984127968, 0.5605577523715047, 0.5633056387872776, 0.5659620576601153, 0.568527008990018, 0.5710004927769856, 0.5733825090210181, 0.5756730577221155, 0.5778721388802778, 0.5799797524955049, 0.5819958985677972, 0.5839205770971542, 0.5857537880835761, 0.587495531527063, 0.5891458074276149, 0.5907046157852317, 0.5921719565999132, 0.5935478298716598, 0.5948322356004713, 0.5960251737863476, 0.597126644429289, 0.598136647529295, 0.5990551830863663, 0.5998822511005023, 0.6006178515717031, 0.601261984499969, 0.6018146498852998, 0.6022758477276954, 0.6026455780271561, 0.6029238407836814, 0.6031106359972721, 0.6032059636679274, 0.6032098237956476, 0.6031222163804327, 0.6029431414222828, 0.6026725989211977, 0.6023105888771778, 0.6018571112902225, 0.6013121661603325, 0.6006757534875071, 0.5999478732717465, 0.5991285255130511, 0.5982177102114203, 0.5972154273668548, 0.596121676979354, 0.594936459048918, 0.5936597735755472, 0.5922916205592411, 0.590832}
-};
-
-/**************/
-/* SuperSaw object */
-/**************/
-typedef struct {
-    pyo_audio_HEAD
-    PyObject *freq;
-    Stream *freq_stream;
-    PyObject *detune;
-    Stream *detune_stream;
-    PyObject *bal;
-    Stream *bal_stream;
-    int modebuffer[5];
-    double pointerPos[7];
-    // sample memories
-    MYFLT x1;
-    MYFLT x2;
-    MYFLT y1;
-    MYFLT y2;
-    // variables
-    MYFLT c;
-    MYFLT w0;
-    MYFLT alpha;
-    // coefficients
-    MYFLT b0;
-    MYFLT b1;
-    MYFLT b2;
-    MYFLT a0;
-    MYFLT a1;
-    MYFLT a2;
-    MYFLT lastFilterFreq;
-    MYFLT nyquist;
-} SuperSaw;
+0,                         /* tp_base */
+0,                         /* tp_dict */
+0,                         /* tp_descr_get */
+0,                         /* tp_descr_set */
+0,                         /* tp_dictoffset */
+0,      /* tp_init */
+0,                         /* tp_alloc */
+SuperSaw_new,                 /* tp_new */
+};
+
+/**************/
+/* RCOsc object */
+/**************/
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *freq;
+    Stream *freq_stream;
+    PyObject *sharp;
+    Stream *sharp_stream;
+    int modebuffer[4];
+    MYFLT pointerPos;
+} RCOsc;
 
 static void
-SuperSaw_readframes_iii(SuperSaw *self) {
-    MYFLT fr, det, bal, twoOnSr, val;
-    int i, j, det_ind, bal_ind;
-    MYFLT inc[7];
-    MYFLT amp[7];
+RCOsc_readframes_ii(RCOsc *self) {
+    MYFLT fr, sh, inc, down_phase, up_phase;
+    int i;
 
     fr = PyFloat_AS_DOUBLE(self->freq);
-    det = _clip(PyFloat_AS_DOUBLE(self->detune));
-    bal = _clip(PyFloat_AS_DOUBLE(self->bal));
-    twoOnSr = 2.0 / self->sr;
+    sh = _clip(PyFloat_AS_DOUBLE(self->sharp));
+    sh = sh * sh * 99.0 + 1.0;
+    inc = fr * 2 / self->sr;
 
-    if (fr <= 1.0)
-        fr = 1.0;
-    else if (fr >= self->nyquist)
-        fr = self->nyquist; 
+    for (i=0; i<self->bufsize; i++) {
+        if (self->pointerPos < 1) {
+            down_phase = 1.0 - self->pointerPos;
+            up_phase = 1.0;
+        }
+        else {
+            down_phase = 0.0;
+            up_phase = 2.0 - self->pointerPos;
+        }
+        self->data[i] = ( (1.0 - MYPOW(down_phase, sh)) + (MYPOW(up_phase, sh)) ) * 2.0 - 3.0;
+        self->pointerPos += inc;
+        if (self->pointerPos < 0)
+            self->pointerPos += 2.0;
+        else if (self->pointerPos >= 2)
+            self->pointerPos -= 2.0;
+    }
+}
 
-    det_ind = (int)(det * 126);
-    bal_ind = (int)(bal * 126);
-    
-    if (fr != self->lastFilterFreq) {       
-        self->lastFilterFreq = fr;
-        self->w0 = TWOPI * fr / self->sr;
-        self->c = MYCOS(self->w0);
-        self->alpha = MYSIN(self->w0) * 0.5;
-        self->b0 = self->b2 = (1 + self->c) * 0.5;
-        self->b1 = -(1 + self->c);
-        self->a0 = 1 + self->alpha;
-        self->a1 = -2 * self->c;
-        self->a2 = 1 - self->alpha;
+static void
+RCOsc_readframes_ai(RCOsc *self) {
+    MYFLT sh, down_phase, up_phase, twoOverSr;
+    int i;
+
+    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
+    sh = _clip(PyFloat_AS_DOUBLE(self->sharp));
+    sh = sh * sh * 99.0 + 1.0;
+
+    twoOverSr = 2.0 / self->sr;
+    for (i=0; i<self->bufsize; i++) {
+        if (self->pointerPos < 1) {
+            down_phase = 1.0 - self->pointerPos;
+            up_phase = 1.0;
+        }
+        else {
+            down_phase = 0.0;
+            up_phase = 2.0 - self->pointerPos;
+        }
+        self->data[i] = ( (1.0 - MYPOW(down_phase, sh)) + (MYPOW(up_phase, sh)) ) * 2.0 - 3.0;
+        self->pointerPos += fr[i] * twoOverSr;
+        if (self->pointerPos < 0)
+            self->pointerPos += 2.0;
+        else if (self->pointerPos >= 2)
+            self->pointerPos -= 2.0;
     }
+}
 
-    for (j=0; j<7; j++) {
-        inc[j] = fr * SUPERSAW_DETUNES[j][det_ind] * twoOnSr;
-        amp[j] = SUPERSAW_BALANCES[j][bal_ind];
+static void
+RCOsc_readframes_ia(RCOsc *self) {
+    MYFLT fr, sh, inc, down_phase, up_phase;
+    int i;
+
+    fr = PyFloat_AS_DOUBLE(self->freq);
+    MYFLT *sharp = Stream_getData((Stream *)self->sharp_stream);
+    inc = fr * 2 / self->sr;
+
+    for (i=0; i<self->bufsize; i++) {
+        sh = _clip(sharp[i]);
+        sh = sh * sh * 99.0 + 1.0;
+        if (self->pointerPos < 1) {
+            down_phase = 1.0 - self->pointerPos;
+            up_phase = 1.0;
+        }
+        else {
+            down_phase = 0.0;
+            up_phase = 2.0 - self->pointerPos;
+        }
+        self->data[i] = ( (1.0 - MYPOW(down_phase, sh)) + (MYPOW(up_phase, sh)) ) * 2.0 - 3.0;
+        self->pointerPos += inc;
+        if (self->pointerPos < 0)
+            self->pointerPos += 2.0;
+        else if (self->pointerPos >= 2)
+            self->pointerPos -= 2.0;
     }
+}
+
+static void
+RCOsc_readframes_aa(RCOsc *self) {
+    MYFLT sh, down_phase, up_phase, twoOverSr;
+    int i;
 
+    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
+    MYFLT *sharp = Stream_getData((Stream *)self->sharp_stream);
+
+    twoOverSr = 2.0 / self->sr;
     for (i=0; i<self->bufsize; i++) {
-        val = 0.0;
-        for (j=0; j<7; j++) {
-            val += self->pointerPos[j] * amp[j];
-            self->pointerPos[j] += inc[j];
-            if (self->pointerPos[j] < -1.0)
-                self->pointerPos[j] += 2.0;
-            else if (self->pointerPos[j] >= 1.0)
-                self->pointerPos[j] -= 2.0;
+        sh = _clip(sharp[i]);
+        sh = sh * sh * 99.0 + 1.0;
+        if (self->pointerPos < 1) {
+            down_phase = 1.0 - self->pointerPos;
+            up_phase = 1.0;
         }
-        self->data[i] = ( (self->b0 * val) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
-        self->y2 = self->y1;
-        self->y1 = self->data[i];
-        self->x2 = self->x1;
-        self->x1 = val;
-        self->data[i] *= 0.2;
+        else {
+            down_phase = 0.0;
+            up_phase = 2.0 - self->pointerPos;
+        }
+        self->data[i] = ( (1.0 - MYPOW(down_phase, sh)) + (MYPOW(up_phase, sh)) ) * 2.0 - 3.0;
+        self->pointerPos += fr[i] * twoOverSr;
+        if (self->pointerPos < 0)
+            self->pointerPos += 2.0;
+        else if (self->pointerPos >= 2)
+            self->pointerPos -= 2.0;
+    }
+}
+
+static void RCOsc_postprocessing_ii(RCOsc *self) { POST_PROCESSING_II };
+static void RCOsc_postprocessing_ai(RCOsc *self) { POST_PROCESSING_AI };
+static void RCOsc_postprocessing_ia(RCOsc *self) { POST_PROCESSING_IA };
+static void RCOsc_postprocessing_aa(RCOsc *self) { POST_PROCESSING_AA };
+static void RCOsc_postprocessing_ireva(RCOsc *self) { POST_PROCESSING_IREVA };
+static void RCOsc_postprocessing_areva(RCOsc *self) { POST_PROCESSING_AREVA };
+static void RCOsc_postprocessing_revai(RCOsc *self) { POST_PROCESSING_REVAI };
+static void RCOsc_postprocessing_revaa(RCOsc *self) { POST_PROCESSING_REVAA };
+static void RCOsc_postprocessing_revareva(RCOsc *self) { POST_PROCESSING_REVAREVA };
+
+static void
+RCOsc_setProcMode(RCOsc *self)
+{
+    int procmode, muladdmode;
+    procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+	switch (procmode) {
+        case 0:
+            self->proc_func_ptr = RCOsc_readframes_ii;
+            break;
+        case 1:
+            self->proc_func_ptr = RCOsc_readframes_ai;
+            break;
+        case 10:
+            self->proc_func_ptr = RCOsc_readframes_ia;
+            break;
+        case 11:
+            self->proc_func_ptr = RCOsc_readframes_aa;
+            break;
+    }
+	switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = RCOsc_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = RCOsc_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = RCOsc_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = RCOsc_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = RCOsc_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = RCOsc_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = RCOsc_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = RCOsc_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = RCOsc_postprocessing_revareva;
+            break;
     }
 }
 
-static void
-SuperSaw_readframes_aii(SuperSaw *self) {
-    MYFLT fr, det, bal, twoOnSr, val;
-    int i, j, det_ind, bal_ind;
+static void
+RCOsc_compute_next_data_frame(RCOsc *self)
+{
+    (*self->proc_func_ptr)(self);
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+RCOsc_traverse(RCOsc *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->sharp);
+    Py_VISIT(self->sharp_stream);
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    return 0;
+}
+
+static int
+RCOsc_clear(RCOsc *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->sharp);
+    Py_CLEAR(self->sharp_stream);
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    return 0;
+}
+
+static void
+RCOsc_dealloc(RCOsc* self)
+{
+    pyo_DEALLOC
+    RCOsc_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+RCOsc_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *freqtmp=NULL, *sharptmp=NULL, *multmp=NULL, *addtmp=NULL;
+    RCOsc *self;
+    self = (RCOsc *)type->tp_alloc(type, 0);
+
+    self->freq = PyFloat_FromDouble(100);
+    self->sharp = PyFloat_FromDouble(0.25);
+	self->modebuffer[0] = 0;
+	self->modebuffer[1] = 0;
+	self->modebuffer[2] = 0;
+	self->modebuffer[3] = 0;
+    self->pointerPos = 0.;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, RCOsc_compute_next_data_frame);
+    self->mode_func_ptr = RCOsc_setProcMode;
+
+    static char *kwlist[] = {"freq", "sharp", "mul", "add", NULL};
 
-    MYFLT *freq = Stream_getData((Stream *)self->freq_stream);
-    det = _clip(PyFloat_AS_DOUBLE(self->detune));
-    bal = _clip(PyFloat_AS_DOUBLE(self->bal));
-    twoOnSr = 2.0 / self->sr;
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &freqtmp, &sharptmp, &multmp, &addtmp))
+        Py_RETURN_NONE;
 
-    det_ind = (int)(det * 126);
-    bal_ind = (int)(bal * 126);
+    if (freqtmp) {
+        PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
+    }
 
-    for (i=0; i<self->bufsize; i++) {
-        fr = freq[i];
-        if (fr <= 1.0)
-            fr = 1.0;
-        else if (fr >= self->nyquist)
-            fr = self->nyquist; 
-        if (fr != self->lastFilterFreq) {       
-            self->lastFilterFreq = fr;
-            self->w0 = TWOPI * fr / self->sr;
-            self->c = MYCOS(self->w0);
-            self->alpha = MYSIN(self->w0) * 0.5;
-            self->b0 = self->b2 = (1 + self->c) * 0.5;
-            self->b1 = -(1 + self->c);
-            self->a0 = 1 + self->alpha;
-            self->a1 = -2 * self->c;
-            self->a2 = 1 - self->alpha;
-        }
-        val = 0.0;
-        for (j=0; j<7; j++) {
-            val += self->pointerPos[j] * SUPERSAW_BALANCES[j][bal_ind];
-            self->pointerPos[j] += fr * SUPERSAW_DETUNES[j][det_ind] * twoOnSr;
-            if (self->pointerPos[j] < -1.0)
-                self->pointerPos[j] += 2.0;
-            else if (self->pointerPos[j] >= 1.0)
-                self->pointerPos[j] -= 2.0;
-        }
-        self->data[i] = ( (self->b0 * val) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
-        self->y2 = self->y1;
-        self->y1 = self->data[i];
-        self->x2 = self->x1;
-        self->x1 = val;
-        self->data[i] *= 0.2;
+    if (sharptmp) {
+        PyObject_CallMethod((PyObject *)self, "setSharp", "O", sharptmp);
     }
-}
 
-static void
-SuperSaw_readframes_iai(SuperSaw *self) {
-    MYFLT fr, bal, twoOnSr, val;
-    int i, j, det_ind, bal_ind;
+    if (multmp) {
+        PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
+    }
 
-    fr = PyFloat_AS_DOUBLE(self->freq);
-    MYFLT *detune = Stream_getData((Stream *)self->detune_stream);
-    bal = _clip(PyFloat_AS_DOUBLE(self->bal));
-    twoOnSr = 2.0 / self->sr;
+    if (addtmp) {
+        PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
+    }
 
-    if (fr <= 1.0)
-        fr = 1.0;
-    else if (fr >= self->nyquist)
-        fr = self->nyquist; 
+    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
-    bal_ind = (int)(bal * 126);
-    
-    if (fr != self->lastFilterFreq) {       
-        self->lastFilterFreq = fr;
-        self->w0 = TWOPI * fr / self->sr;
-        self->c = MYCOS(self->w0);
-        self->alpha = MYSIN(self->w0) * 0.5;
-        self->b0 = self->b2 = (1 + self->c) * 0.5;
-        self->b1 = -(1 + self->c);
-        self->a0 = 1 + self->alpha;
-        self->a1 = -2 * self->c;
-        self->a2 = 1 - self->alpha;
-    }
+    (*self->mode_func_ptr)(self);
 
-    for (i=0; i<self->bufsize; i++) {
-        det_ind = (int)(_clip(detune[i]) * 126);
-        val = 0.0;
-        for (j=0; j<7; j++) {
-            val += self->pointerPos[j] * SUPERSAW_BALANCES[j][bal_ind];
-            self->pointerPos[j] += fr * SUPERSAW_DETUNES[j][det_ind] * twoOnSr;
-            if (self->pointerPos[j] < -1.0)
-                self->pointerPos[j] += 2.0;
-            else if (self->pointerPos[j] >= 1.0)
-                self->pointerPos[j] -= 2.0;
-        }
-        self->data[i] = ( (self->b0 * val) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
-        self->y2 = self->y1;
-        self->y1 = self->data[i];
-        self->x2 = self->x1;
-        self->x1 = val;
-        self->data[i] *= 0.2;
-    }
+    return (PyObject *)self;
 }
 
-static void
-SuperSaw_readframes_aai(SuperSaw *self) {
-    MYFLT fr, bal, twoOnSr, val;
-    int i, j, det_ind, bal_ind;
+static PyObject * RCOsc_getServer(RCOsc* self) { GET_SERVER };
+static PyObject * RCOsc_getStream(RCOsc* self) { GET_STREAM };
+static PyObject * RCOsc_setMul(RCOsc *self, PyObject *arg) { SET_MUL };
+static PyObject * RCOsc_setAdd(RCOsc *self, PyObject *arg) { SET_ADD };
+static PyObject * RCOsc_setSub(RCOsc *self, PyObject *arg) { SET_SUB };
+static PyObject * RCOsc_setDiv(RCOsc *self, PyObject *arg) { SET_DIV };
 
-    MYFLT *freq = Stream_getData((Stream *)self->freq_stream);
-    MYFLT *detune = Stream_getData((Stream *)self->detune_stream);
-    bal = _clip(PyFloat_AS_DOUBLE(self->bal));
-    twoOnSr = 2.0 / self->sr;
+static PyObject * RCOsc_play(RCOsc *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * RCOsc_out(RCOsc *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * RCOsc_stop(RCOsc *self) { STOP };
 
-    bal_ind = (int)(bal * 126);
+static PyObject * RCOsc_multiply(RCOsc *self, PyObject *arg) { MULTIPLY };
+static PyObject * RCOsc_inplace_multiply(RCOsc *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * RCOsc_add(RCOsc *self, PyObject *arg) { ADD };
+static PyObject * RCOsc_inplace_add(RCOsc *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * RCOsc_sub(RCOsc *self, PyObject *arg) { SUB };
+static PyObject * RCOsc_inplace_sub(RCOsc *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * RCOsc_div(RCOsc *self, PyObject *arg) { DIV };
+static PyObject * RCOsc_inplace_div(RCOsc *self, PyObject *arg) { INPLACE_DIV };
 
-    for (i=0; i<self->bufsize; i++) {
-        fr = freq[i];
-        if (fr <= 1.0)
-            fr = 1.0;
-        else if (fr >= self->nyquist)
-            fr = self->nyquist; 
-        if (fr != self->lastFilterFreq) {       
-            self->lastFilterFreq = fr;
-            self->w0 = TWOPI * fr / self->sr;
-            self->c = MYCOS(self->w0);
-            self->alpha = MYSIN(self->w0) * 0.5;
-            self->b0 = self->b2 = (1 + self->c) * 0.5;
-            self->b1 = -(1 + self->c);
-            self->a0 = 1 + self->alpha;
-            self->a1 = -2 * self->c;
-            self->a2 = 1 - self->alpha;
-        }
-        det_ind = (int)(_clip(detune[i]) * 126);
-        val = 0.0;
-        for (j=0; j<7; j++) {
-            val += self->pointerPos[j] * SUPERSAW_BALANCES[j][bal_ind];
-            self->pointerPos[j] += fr * SUPERSAW_DETUNES[j][det_ind] * twoOnSr;
-            if (self->pointerPos[j] < -1.0)
-                self->pointerPos[j] += 2.0;
-            else if (self->pointerPos[j] >= 1.0)
-                self->pointerPos[j] -= 2.0;
-        }
-        self->data[i] = ( (self->b0 * val) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
-        self->y2 = self->y1;
-        self->y1 = self->data[i];
-        self->x2 = self->x1;
-        self->x1 = val;
-        self->data[i] *= 0.2;
-    }
+static PyObject *
+RCOsc_setFreq(RCOsc *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->freq);
+	if (isNumber == 1) {
+		self->freq = PyNumber_Float(tmp);
+        self->modebuffer[2] = 0;
+	}
+	else {
+		self->freq = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->freq_stream);
+        self->freq_stream = (Stream *)streamtmp;
+		self->modebuffer[2] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
 }
 
-static void
-SuperSaw_readframes_iia(SuperSaw *self) {
-    MYFLT fr, det, twoOnSr, val;
-    int i, j, det_ind, bal_ind;
-    MYFLT inc[7];
+static PyObject *
+RCOsc_setSharp(RCOsc *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
 
-    fr = PyFloat_AS_DOUBLE(self->freq);
-    det = _clip(PyFloat_AS_DOUBLE(self->detune));
-    MYFLT *balance = Stream_getData((Stream *)self->bal_stream);
-    twoOnSr = 2.0 / self->sr;
+    ASSERT_ARG_NOT_NULL
 
-    if (fr <= 1.0)
-        fr = 1.0;
-    else if (fr >= self->nyquist)
-        fr = self->nyquist; 
+	int isNumber = PyNumber_Check(arg);
 
-    det_ind = (int)(det * 126);
-    
-    if (fr != self->lastFilterFreq) {       
-        self->lastFilterFreq = fr;
-        self->w0 = TWOPI * fr / self->sr;
-        self->c = MYCOS(self->w0);
-        self->alpha = MYSIN(self->w0) * 0.5;
-        self->b0 = self->b2 = (1 + self->c) * 0.5;
-        self->b1 = -(1 + self->c);
-        self->a0 = 1 + self->alpha;
-        self->a1 = -2 * self->c;
-        self->a2 = 1 - self->alpha;
-    }
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->sharp);
+	if (isNumber == 1) {
+		self->sharp = PyNumber_Float(tmp);
+        self->modebuffer[3] = 0;
+	}
+	else {
+		self->sharp = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->sharp, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->sharp_stream);
+        self->sharp_stream = (Stream *)streamtmp;
+		self->modebuffer[3] = 1;
+	}
 
-    for (j=0; j<7; j++) {
-        inc[j] = fr * SUPERSAW_DETUNES[j][det_ind] * twoOnSr;
-    }
+    (*self->mode_func_ptr)(self);
 
-    for (i=0; i<self->bufsize; i++) {
-        bal_ind = (int)(_clip(balance[i]) * 126);
-        val = 0.0;
-        for (j=0; j<7; j++) {
-            val += self->pointerPos[j] * SUPERSAW_BALANCES[j][bal_ind];
-            self->pointerPos[j] += inc[j];
-            if (self->pointerPos[j] < -1.0)
-                self->pointerPos[j] += 2.0;
-            else if (self->pointerPos[j] >= 1.0)
-                self->pointerPos[j] -= 2.0;
-        }
-        self->data[i] = ( (self->b0 * val) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
-        self->y2 = self->y1;
-        self->y1 = self->data[i];
-        self->x2 = self->x1;
-        self->x1 = val;
-        self->data[i] *= 0.2;
-    }
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+RCOsc_reset(RCOsc *self)
+{
+    self->pointerPos = 0.0;
+    Py_INCREF(Py_None);
+    return Py_None;
 }
 
-static void
-SuperSaw_readframes_aia(SuperSaw *self) {
-    MYFLT fr, det, twoOnSr, val;
-    int i, j, det_ind, bal_ind;
+static PyMemberDef RCOsc_members[] = {
+{"server", T_OBJECT_EX, offsetof(RCOsc, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(RCOsc, stream), 0, "Stream object."},
+{"freq", T_OBJECT_EX, offsetof(RCOsc, freq), 0, "Frequency in cycle per second."},
+{"sharp", T_OBJECT_EX, offsetof(RCOsc, sharp), 0, "RCOscillator sharp."},
+{"mul", T_OBJECT_EX, offsetof(RCOsc, mul), 0, "Mul factor."},
+{"add", T_OBJECT_EX, offsetof(RCOsc, add), 0, "Add factor."},
+{NULL}  /* Sentinel */
+};
 
-    MYFLT *freq = Stream_getData((Stream *)self->freq_stream);
-    det = _clip(PyFloat_AS_DOUBLE(self->detune));
-    MYFLT *balance = Stream_getData((Stream *)self->bal_stream);
-    twoOnSr = 2.0 / self->sr;
+static PyMethodDef RCOsc_methods[] = {
+{"getServer", (PyCFunction)RCOsc_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)RCOsc_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)RCOsc_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"out", (PyCFunction)RCOsc_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+{"stop", (PyCFunction)RCOsc_stop, METH_NOARGS, "Stops computing."},
+{"setFreq", (PyCFunction)RCOsc_setFreq, METH_O, "Sets oscillator frequency in cycle per second."},
+{"setSharp", (PyCFunction)RCOsc_setSharp, METH_O, "Sets oscillator sharp."},
+{"reset", (PyCFunction)RCOsc_reset, METH_NOARGS, "Resets pointer position to 0."},
+{"setMul", (PyCFunction)RCOsc_setMul, METH_O, "Sets oscillator mul factor."},
+{"setAdd", (PyCFunction)RCOsc_setAdd, METH_O, "Sets oscillator add factor."},
+{"setSub", (PyCFunction)RCOsc_setSub, METH_O, "Sets oscillator inverse add factor."},
+{"setDiv", (PyCFunction)RCOsc_setDiv, METH_O, "Sets inverse mul factor."},
+{NULL}  /* Sentinel */
+};
 
-    det_ind = (int)(det * 126);
+static PyNumberMethods RCOsc_as_number = {
+(binaryfunc)RCOsc_add,                      /*nb_add*/
+(binaryfunc)RCOsc_sub,                 /*nb_subtract*/
+(binaryfunc)RCOsc_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)RCOsc_inplace_add,              /*inplace_add*/
+(binaryfunc)RCOsc_inplace_sub,         /*inplace_subtract*/
+(binaryfunc)RCOsc_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)RCOsc_div,                       /*nb_true_divide*/
+0,     /*nb_inplace_floor_divide*/
+(binaryfunc)RCOsc_inplace_div,                       /*nb_inplace_true_divide*/
+0,                     /* nb_index */
+};
 
-    for (i=0; i<self->bufsize; i++) {
-        fr = freq[i];
-        if (fr <= 1.0)
-            fr = 1.0;
-        else if (fr >= self->nyquist)
-            fr = self->nyquist; 
-        if (fr != self->lastFilterFreq) {       
-            self->lastFilterFreq = fr;
-            self->w0 = TWOPI * fr / self->sr;
-            self->c = MYCOS(self->w0);
-            self->alpha = MYSIN(self->w0) * 0.5;
-            self->b0 = self->b2 = (1 + self->c) * 0.5;
-            self->b1 = -(1 + self->c);
-            self->a0 = 1 + self->alpha;
-            self->a1 = -2 * self->c;
-            self->a2 = 1 - self->alpha;
-        }
-        bal_ind = (int)(_clip(balance[i]) * 126);
-        val = 0.0;
-        for (j=0; j<7; j++) {
-            val += self->pointerPos[j] * SUPERSAW_BALANCES[j][bal_ind];
-            self->pointerPos[j] += fr * SUPERSAW_DETUNES[j][det_ind] * twoOnSr;
-            if (self->pointerPos[j] < -1.0)
-                self->pointerPos[j] += 2.0;
-            else if (self->pointerPos[j] >= 1.0)
-                self->pointerPos[j] -= 2.0;
-        }
-        self->data[i] = ( (self->b0 * val) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
-        self->y2 = self->y1;
-        self->y1 = self->data[i];
-        self->x2 = self->x1;
-        self->x1 = val;
-        self->data[i] *= 0.2;
-    }
-}
+PyTypeObject RCOscType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.RCOsc_base",         /*tp_name*/
+sizeof(RCOsc),         /*tp_basicsize*/
+0,                         /*tp_itemsize*/
+(destructor)RCOsc_dealloc, /*tp_dealloc*/
+0,                         /*tp_print*/
+0,                         /*tp_getattr*/
+0,                         /*tp_setattr*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
+0,                         /*tp_repr*/
+&RCOsc_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*/
+"RCOsc objects. Waveform simulation of of a RC circuit.",           /* tp_doc */
+(traverseproc)RCOsc_traverse,   /* tp_traverse */
+(inquiry)RCOsc_clear,           /* tp_clear */
+0,		               /* tp_richcompare */
+0,		               /* tp_weaklistoffset */
+0,		               /* tp_iter */
+0,		               /* tp_iternext */
+RCOsc_methods,             /* tp_methods */
+RCOsc_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 */
+RCOsc_new,                 /* tp_new */
+};
 
-static void
-SuperSaw_readframes_iaa(SuperSaw *self) {
-    MYFLT fr, twoOnSr, val;
-    int i, j, det_ind, bal_ind;
+/**************/
+/* TableScale object */
+/**************/
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *table;
+    PyObject *outtable;
+    int modebuffer[2];
+} TableScale;
 
-    fr = PyFloat_AS_DOUBLE(self->freq);
-    MYFLT *detune = Stream_getData((Stream *)self->detune_stream);
-    MYFLT *balance = Stream_getData((Stream *)self->bal_stream);
-    twoOnSr = 2.0 / self->sr;
+static void
+TableScale_readframes_ii(TableScale *self) {
+    int i, num;
+    MYFLT mul, add;
+    MYFLT *tablelist = TableStream_getData(self->table);
+    int size = TableStream_getSize(self->table);
+    MYFLT *outlist = TableStream_getData(self->outtable);
+    int osize = TableStream_getSize(self->outtable);
 
-    if (fr <= 1.0)
-        fr = 1.0;
-    else if (fr >= self->nyquist)
-        fr = self->nyquist; 
-    
-    if (fr != self->lastFilterFreq) {       
-        self->lastFilterFreq = fr;
-        self->w0 = TWOPI * fr / self->sr;
-        self->c = MYCOS(self->w0);
-        self->alpha = MYSIN(self->w0) * 0.5;
-        self->b0 = self->b2 = (1 + self->c) * 0.5;
-        self->b1 = -(1 + self->c);
-        self->a0 = 1 + self->alpha;
-        self->a1 = -2 * self->c;
-        self->a2 = 1 - self->alpha;
-    }
+    mul = PyFloat_AS_DOUBLE(self->mul);
+    add = PyFloat_AS_DOUBLE(self->add);
 
-    for (i=0; i<self->bufsize; i++) {
-        det_ind = (int)(_clip(detune[i]) * 126);
-        bal_ind = (int)(_clip(balance[i]) * 126);
-        val = 0.0;
-        for (j=0; j<7; j++) {
-            val += self->pointerPos[j] * SUPERSAW_BALANCES[j][bal_ind];
-            self->pointerPos[j] += fr * SUPERSAW_DETUNES[j][det_ind] * twoOnSr;
-            if (self->pointerPos[j] < -1.0)
-                self->pointerPos[j] += 2.0;
-            else if (self->pointerPos[j] >= 1.0)
-                self->pointerPos[j] -= 2.0;
-        }
-        self->data[i] = ( (self->b0 * val) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
-        self->y2 = self->y1;
-        self->y1 = self->data[i];
-        self->x2 = self->x1;
-        self->x1 = val;
-        self->data[i] *= 0.2;
+    num = size < osize ? size : osize;
+    for (i=0; i<num; i++) {
+        outlist[i] = tablelist[i] * mul + add;
     }
 }
 
 static void
-SuperSaw_readframes_aaa(SuperSaw *self) {
-    MYFLT fr, twoOnSr, val;
-    int i, j, det_ind, bal_ind;
+TableScale_readframes_ai(TableScale *self) {
+    int i, num;
+    MYFLT add;
+    MYFLT *tablelist = TableStream_getData(self->table);
+    int size = TableStream_getSize(self->table);
+    MYFLT *outlist = TableStream_getData(self->outtable);
+    int osize = TableStream_getSize(self->outtable);
 
-    MYFLT *freq = Stream_getData((Stream *)self->freq_stream);
-    MYFLT *detune = Stream_getData((Stream *)self->detune_stream);
-    MYFLT *balance = Stream_getData((Stream *)self->bal_stream);
-    twoOnSr = 2.0 / self->sr;
+    MYFLT *mul = Stream_getData((Stream *)self->mul_stream);
+    add = PyFloat_AS_DOUBLE(self->add);
 
-    for (i=0; i<self->bufsize; i++) {
-        fr = freq[i];
-        if (fr <= 1.0)
-            fr = 1.0;
-        else if (fr >= self->nyquist)
-            fr = self->nyquist; 
-        if (fr != self->lastFilterFreq) {       
-            self->lastFilterFreq = fr;
-            self->w0 = TWOPI * fr / self->sr;
-            self->c = MYCOS(self->w0);
-            self->alpha = MYSIN(self->w0) * 0.5;
-            self->b0 = self->b2 = (1 + self->c) * 0.5;
-            self->b1 = -(1 + self->c);
-            self->a0 = 1 + self->alpha;
-            self->a1 = -2 * self->c;
-            self->a2 = 1 - self->alpha;
-        }
-        det_ind = (int)(_clip(detune[i]) * 126);
-        bal_ind = (int)(_clip(balance[i]) * 126);
+    num = size < osize ? size : osize;
+    for (i=0; i<num; i++) {
+        outlist[i] = tablelist[i] * mul[i] + add;
+    }
+}
 
-        val = 0.0;
-        for (j=0; j<7; j++) {
-            val += self->pointerPos[j] * SUPERSAW_BALANCES[j][bal_ind];
-            self->pointerPos[j] += fr * SUPERSAW_DETUNES[j][det_ind] * twoOnSr;
-            if (self->pointerPos[j] < -1.0)
-                self->pointerPos[j] += 2.0;
-            else if (self->pointerPos[j] >= 1.0)
-                self->pointerPos[j] -= 2.0;
-        }
-        self->data[i] = ( (self->b0 * val) + (self->b1 * self->x1) + (self->b2 * self->x2) - (self->a1 * self->y1) - (self->a2 * self->y2) ) / self->a0;
-        self->y2 = self->y1;
-        self->y1 = self->data[i];
-        self->x2 = self->x1;
-        self->x1 = val;
-        self->data[i] *= 0.2;
+static void
+TableScale_readframes_ia(TableScale *self) {
+    int i, num;
+    MYFLT mul;
+    MYFLT *tablelist = TableStream_getData(self->table);
+    int size = TableStream_getSize(self->table);
+    MYFLT *outlist = TableStream_getData(self->outtable);
+    int osize = TableStream_getSize(self->outtable);
+
+    mul = PyFloat_AS_DOUBLE(self->mul);
+    MYFLT *add = Stream_getData((Stream *)self->add_stream);
+
+    num = size < osize ? size : osize;
+    for (i=0; i<num; i++) {
+        outlist[i] = tablelist[i] * mul + add[i];
     }
 }
 
-static void SuperSaw_postprocessing_ii(SuperSaw *self) { POST_PROCESSING_II };
-static void SuperSaw_postprocessing_ai(SuperSaw *self) { POST_PROCESSING_AI };
-static void SuperSaw_postprocessing_ia(SuperSaw *self) { POST_PROCESSING_IA };
-static void SuperSaw_postprocessing_aa(SuperSaw *self) { POST_PROCESSING_AA };
-static void SuperSaw_postprocessing_ireva(SuperSaw *self) { POST_PROCESSING_IREVA };
-static void SuperSaw_postprocessing_areva(SuperSaw *self) { POST_PROCESSING_AREVA };
-static void SuperSaw_postprocessing_revai(SuperSaw *self) { POST_PROCESSING_REVAI };
-static void SuperSaw_postprocessing_revaa(SuperSaw *self) { POST_PROCESSING_REVAA };
-static void SuperSaw_postprocessing_revareva(SuperSaw *self) { POST_PROCESSING_REVAREVA };
+static void
+TableScale_readframes_aa(TableScale *self) {
+    int i, num;
+    MYFLT *tablelist = TableStream_getData(self->table);
+    int size = TableStream_getSize(self->table);
+    MYFLT *outlist = TableStream_getData(self->outtable);
+    int osize = TableStream_getSize(self->outtable);
+
+    MYFLT *mul = Stream_getData((Stream *)self->mul_stream);
+    MYFLT *add = Stream_getData((Stream *)self->add_stream);
+
+    num = size < osize ? size : osize;
+    for (i=0; i<num; i++) {
+        outlist[i] = tablelist[i] * mul[i] + add[i];
+    }
+}
 
 static void
-SuperSaw_setProcMode(SuperSaw *self)
+TableScale_setProcMode(TableScale *self)
 {
-    int procmode, muladdmode;
-    procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100;
+    int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
-	switch (procmode) {
-        case 0:        
-            self->proc_func_ptr = SuperSaw_readframes_iii;
-            break;
-        case 1:    
-            self->proc_func_ptr = SuperSaw_readframes_aii;
-            break;
-        case 10:        
-            self->proc_func_ptr = SuperSaw_readframes_iai;
-            break;
-        case 11:    
-            self->proc_func_ptr = SuperSaw_readframes_aai;
-            break;
-        case 100:    
-            self->proc_func_ptr = SuperSaw_readframes_iia;
-            break;
-        case 101:    
-            self->proc_func_ptr = SuperSaw_readframes_aia;
-            break;
-        case 110:    
-            self->proc_func_ptr = SuperSaw_readframes_iaa;
-            break;
-        case 111:    
-            self->proc_func_ptr = SuperSaw_readframes_aaa;
-            break;
-    } 
+
 	switch (muladdmode) {
-        case 0:        
-            self->muladd_func_ptr = SuperSaw_postprocessing_ii;
-            break;
-        case 1:    
-            self->muladd_func_ptr = SuperSaw_postprocessing_ai;
-            break;
-        case 2:    
-            self->muladd_func_ptr = SuperSaw_postprocessing_revai;
-            break;
-        case 10:        
-            self->muladd_func_ptr = SuperSaw_postprocessing_ia;
-            break;
-        case 11:    
-            self->muladd_func_ptr = SuperSaw_postprocessing_aa;
-            break;
-        case 12:    
-            self->muladd_func_ptr = SuperSaw_postprocessing_revaa;
+        case 0:
+            self->proc_func_ptr = TableScale_readframes_ii;
             break;
-        case 20:        
-            self->muladd_func_ptr = SuperSaw_postprocessing_ireva;
+        case 1:
+            self->proc_func_ptr = TableScale_readframes_ai;
             break;
-        case 21:    
-            self->muladd_func_ptr = SuperSaw_postprocessing_areva;
+        case 10:
+            self->proc_func_ptr = TableScale_readframes_ia;
             break;
-        case 22:    
-            self->muladd_func_ptr = SuperSaw_postprocessing_revareva;
+        case 11:
+            self->proc_func_ptr = TableScale_readframes_aa;
             break;
-    } 
+    }
 }
 
 static void
-SuperSaw_compute_next_data_frame(SuperSaw *self)
+TableScale_compute_next_data_frame(TableScale *self)
 {
-    (*self->proc_func_ptr)(self); 
-    (*self->muladd_func_ptr)(self);
+    (*self->proc_func_ptr)(self);
 }
 
 static int
-SuperSaw_traverse(SuperSaw *self, visitproc visit, void *arg)
+TableScale_traverse(TableScale *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
-    Py_VISIT(self->detune);    
-    Py_VISIT(self->detune_stream);    
-    Py_VISIT(self->bal);    
-    Py_VISIT(self->bal_stream);    
+    Py_VISIT(self->table);
+    Py_VISIT(self->outtable);
     return 0;
 }
 
-static int 
-SuperSaw_clear(SuperSaw *self)
+static int
+TableScale_clear(TableScale *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
-    Py_CLEAR(self->detune);    
-    Py_CLEAR(self->detune_stream);    
-    Py_CLEAR(self->bal);    
-    Py_CLEAR(self->bal_stream);    
+    Py_CLEAR(self->table);
+    Py_CLEAR(self->outtable);
     return 0;
 }
 
 static void
-SuperSaw_dealloc(SuperSaw* self)
+TableScale_dealloc(TableScale* self)
 {
     pyo_DEALLOC
-    SuperSaw_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    TableScale_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
-SuperSaw_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+TableScale_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
-    PyObject *freqtmp=NULL, *detunetmp=NULL, *baltmp=NULL, *multmp=NULL, *addtmp=NULL;
-    SuperSaw *self;
-    self = (SuperSaw *)type->tp_alloc(type, 0);
-    
-    self->freq = PyFloat_FromDouble(100);
-    self->detune = PyFloat_FromDouble(0.5);
-    self->bal = PyFloat_FromDouble(0.7);
+    PyObject *tabletmp, *outtabletmp, *multmp=NULL, *addtmp=NULL;
+    TableScale *self;
+    self = (TableScale *)type->tp_alloc(type, 0);
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-	self->modebuffer[2] = 0;
-	self->modebuffer[3] = 0;
-	self->modebuffer[4] = 0;
-    self->pointerPos[0] = -0.75;
-    self->pointerPos[1] = -0.5;
-    self->pointerPos[2] = -0.25;
-    self->pointerPos[3] = 0.0;
-    self->pointerPos[4] = 0.25;
-    self->pointerPos[5] = 0.5;
-    self->pointerPos[6] = 0.75;
-    self->lastFilterFreq = -1.0;
-    self->x1 = self->x2 = self->y1 = self->y2 = 0.0;
-    
+
     INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, TableScale_compute_next_data_frame);
+    self->mode_func_ptr = TableScale_setProcMode;
 
-    self->nyquist = (MYFLT)self->sr * 0.49;
+    static char *kwlist[] = {"table", "outtable", "mul", "add", NULL};
 
-    Stream_setFunctionPtr(self->stream, SuperSaw_compute_next_data_frame);
-    self->mode_func_ptr = SuperSaw_setProcMode;
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist, &tabletmp, &outtabletmp, &multmp, &addtmp))
+        Py_RETURN_NONE;
 
-    static char *kwlist[] = {"freq", "detune", "bal", "mul", "add", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOO", kwlist, &freqtmp, &detunetmp, &baltmp, &multmp, &addtmp))
+    if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
+        PyErr_SetString(PyExc_TypeError, "\"table\" argument of TableScale must be a PyoTableObject.\n");
         Py_RETURN_NONE;
-    
-    if (freqtmp) {
-        PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
+    Py_XDECREF(self->table);
+    self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", "");
 
-    if (detunetmp) {
-        PyObject_CallMethod((PyObject *)self, "setDetune", "O", detunetmp);
+    if ( PyObject_HasAttrString((PyObject *)outtabletmp, "getTableStream") == 0 ) {
+        PyErr_SetString(PyExc_TypeError, "\"outtable\" argument of TableScale must be a PyoTableObject.\n");
+        Py_RETURN_NONE;
     }
+    Py_XDECREF(self->outtable);
+    self->outtable = PyObject_CallMethod((PyObject *)outtabletmp, "getTableStream", "");
 
-    if (baltmp) {
-        PyObject_CallMethod((PyObject *)self, "setBal", "O", baltmp);
-    }
-    
-    if (multmp) {
+    if (addtmp) {
         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 * SuperSaw_getServer(SuperSaw* self) { GET_SERVER };
-static PyObject * SuperSaw_getStream(SuperSaw* self) { GET_STREAM };
-static PyObject * SuperSaw_setMul(SuperSaw *self, PyObject *arg) { SET_MUL };	
-static PyObject * SuperSaw_setAdd(SuperSaw *self, PyObject *arg) { SET_ADD };	
-static PyObject * SuperSaw_setSub(SuperSaw *self, PyObject *arg) { SET_SUB };	
-static PyObject * SuperSaw_setDiv(SuperSaw *self, PyObject *arg) { SET_DIV };	
+static PyObject * TableScale_getServer(TableScale* self) { GET_SERVER };
+static PyObject * TableScale_getStream(TableScale* self) { GET_STREAM };
+static PyObject * TableScale_setMul(TableScale *self, PyObject *arg) { SET_MUL };
+static PyObject * TableScale_setAdd(TableScale *self, PyObject *arg) { SET_ADD };
+static PyObject * TableScale_setSub(TableScale *self, PyObject *arg) { SET_SUB };
+static PyObject * TableScale_setDiv(TableScale *self, PyObject *arg) { SET_DIV };
 
-static PyObject * SuperSaw_play(SuperSaw *self, PyObject *args, PyObject *kwds) { PLAY };
-static PyObject * SuperSaw_out(SuperSaw *self, PyObject *args, PyObject *kwds) { OUT };
-static PyObject * SuperSaw_stop(SuperSaw *self) { STOP };
+static PyObject * TableScale_play(TableScale *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * TableScale_out(TableScale *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * TableScale_stop(TableScale *self) { STOP };
 
-static PyObject * SuperSaw_multiply(SuperSaw *self, PyObject *arg) { MULTIPLY };
-static PyObject * SuperSaw_inplace_multiply(SuperSaw *self, PyObject *arg) { INPLACE_MULTIPLY };
-static PyObject * SuperSaw_add(SuperSaw *self, PyObject *arg) { ADD };
-static PyObject * SuperSaw_inplace_add(SuperSaw *self, PyObject *arg) { INPLACE_ADD };
-static PyObject * SuperSaw_sub(SuperSaw *self, PyObject *arg) { SUB };
-static PyObject * SuperSaw_inplace_sub(SuperSaw *self, PyObject *arg) { INPLACE_SUB };
-static PyObject * SuperSaw_div(SuperSaw *self, PyObject *arg) { DIV };
-static PyObject * SuperSaw_inplace_div(SuperSaw *self, PyObject *arg) { INPLACE_DIV };
+static PyObject * TableScale_multiply(TableScale *self, PyObject *arg) { MULTIPLY };
+static PyObject * TableScale_inplace_multiply(TableScale *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * TableScale_add(TableScale *self, PyObject *arg) { ADD };
+static PyObject * TableScale_inplace_add(TableScale *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * TableScale_sub(TableScale *self, PyObject *arg) { SUB };
+static PyObject * TableScale_inplace_sub(TableScale *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * TableScale_div(TableScale *self, PyObject *arg) { DIV };
+static PyObject * TableScale_inplace_div(TableScale *self, PyObject *arg) { INPLACE_DIV };
 
 static PyObject *
-SuperSaw_setFreq(SuperSaw *self, PyObject *arg)
+TableScale_getTable(TableScale* self)
 {
-	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	int isNumber = PyNumber_Check(arg);
-	
-	tmp = arg;
-	Py_INCREF(tmp);
-	Py_DECREF(self->freq);
-	if (isNumber == 1) {
-		self->freq = PyNumber_Float(tmp);
-        self->modebuffer[2] = 0;
-	}
-	else {
-		self->freq = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL);
-        Py_INCREF(streamtmp);
-        Py_XDECREF(self->freq_stream);
-        self->freq_stream = (Stream *)streamtmp;
-		self->modebuffer[2] = 1;
-	}
-    
-    (*self->mode_func_ptr)(self);
-    
-	Py_INCREF(Py_None);
-	return Py_None;
-}	
+    Py_INCREF(self->table);
+    return self->table;
+};
 
 static PyObject *
-SuperSaw_setDetune(SuperSaw *self, PyObject *arg)
+TableScale_setTable(TableScale *self, PyObject *arg)
 {
-	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	int isNumber = PyNumber_Check(arg);
-	
+	PyObject *tmp;
+
+    ASSERT_ARG_NOT_NULL
+
 	tmp = arg;
-	Py_INCREF(tmp);
-	Py_DECREF(self->detune);
-	if (isNumber == 1) {
-		self->detune = PyNumber_Float(tmp);
-        self->modebuffer[3] = 0;
-	}
-	else {
-		self->detune = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->detune, "_getStream", NULL);
-        Py_INCREF(streamtmp);
-        Py_XDECREF(self->detune_stream);
-        self->detune_stream = (Stream *)streamtmp;
-		self->modebuffer[3] = 1;
-	}
-    
-    (*self->mode_func_ptr)(self);
-    
+	Py_DECREF(self->table);
+    self->table = PyObject_CallMethod((PyObject *)tmp, "getTableStream", "");
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
-SuperSaw_setBal(SuperSaw *self, PyObject *arg)
+TableScale_getOuttable(TableScale* self)
 {
-	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	int isNumber = PyNumber_Check(arg);
-	
+    Py_INCREF(self->outtable);
+    return self->outtable;
+};
+
+static PyObject *
+TableScale_setOuttable(TableScale *self, PyObject *arg)
+{
+	PyObject *tmp;
+
+    ASSERT_ARG_NOT_NULL
+
 	tmp = arg;
-	Py_INCREF(tmp);
-	Py_DECREF(self->bal);
-	if (isNumber == 1) {
-		self->bal = PyNumber_Float(tmp);
-        self->modebuffer[4] = 0;
-	}
-	else {
-		self->bal = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->bal, "_getStream", NULL);
-        Py_INCREF(streamtmp);
-        Py_XDECREF(self->bal_stream);
-        self->bal_stream = (Stream *)streamtmp;
-		self->modebuffer[4] = 1;
-	}
-    
-    (*self->mode_func_ptr)(self);
-    
+	Py_DECREF(self->outtable);
+    self->outtable = PyObject_CallMethod((PyObject *)tmp, "getTableStream", "");
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
-static PyMemberDef SuperSaw_members[] = {
-{"server", T_OBJECT_EX, offsetof(SuperSaw, server), 0, "Pyo server."},
-{"stream", T_OBJECT_EX, offsetof(SuperSaw, stream), 0, "Stream object."},
-{"freq", T_OBJECT_EX, offsetof(SuperSaw, freq), 0, "Frequency in cycle per second."},
-{"detune", T_OBJECT_EX, offsetof(SuperSaw, detune), 0, "Detune factor."},
-{"bal", T_OBJECT_EX, offsetof(SuperSaw, bal), 0, "Mix factor."},
-{"mul", T_OBJECT_EX, offsetof(SuperSaw, mul), 0, "Mul factor."},
-{"add", T_OBJECT_EX, offsetof(SuperSaw, add), 0, "Add factor."},
+static PyMemberDef TableScale_members[] = {
+{"server", T_OBJECT_EX, offsetof(TableScale, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(TableScale, stream), 0, "Stream object."},
+{"table", T_OBJECT_EX, offsetof(TableScale, table), 0, "Waveform table."},
+{"outtable", T_OBJECT_EX, offsetof(TableScale, outtable), 0, "Output table."},
+{"mul", T_OBJECT_EX, offsetof(TableScale, mul), 0, "Mul factor."},
+{"add", T_OBJECT_EX, offsetof(TableScale, add), 0, "Add factor."},
 {NULL}  /* Sentinel */
 };
 
-static PyMethodDef SuperSaw_methods[] = {
-{"getServer", (PyCFunction)SuperSaw_getServer, METH_NOARGS, "Returns server object."},
-{"_getStream", (PyCFunction)SuperSaw_getStream, METH_NOARGS, "Returns stream object."},
-{"play", (PyCFunction)SuperSaw_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
-{"out", (PyCFunction)SuperSaw_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
-{"stop", (PyCFunction)SuperSaw_stop, METH_NOARGS, "Stops computing."},
-{"setFreq", (PyCFunction)SuperSaw_setFreq, METH_O, "Sets oscillator frequency in cycle per second."},
-{"setDetune", (PyCFunction)SuperSaw_setDetune, METH_O, "Sets oscillator detune factor."},
-{"setBal", (PyCFunction)SuperSaw_setBal, METH_O, "Sets oscillator mix factor."},
-{"setMul", (PyCFunction)SuperSaw_setMul, METH_O, "Sets oscillator mul factor."},
-{"setAdd", (PyCFunction)SuperSaw_setAdd, METH_O, "Sets oscillator add factor."},
-{"setSub", (PyCFunction)SuperSaw_setSub, METH_O, "Sets oscillator inverse add factor."},
-{"setDiv", (PyCFunction)SuperSaw_setDiv, METH_O, "Sets inverse mul factor."},
+static PyMethodDef TableScale_methods[] = {
+{"getTable", (PyCFunction)TableScale_getTable, METH_NOARGS, "Returns waveform table object."},
+{"getOuttable", (PyCFunction)TableScale_getOuttable, METH_NOARGS, "Returns output table object."},
+{"getServer", (PyCFunction)TableScale_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)TableScale_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)TableScale_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"out", (PyCFunction)TableScale_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+{"stop", (PyCFunction)TableScale_stop, METH_NOARGS, "Stops computing."},
+{"setTable", (PyCFunction)TableScale_setTable, METH_O, "Sets oscillator table."},
+{"setOuttable", (PyCFunction)TableScale_setOuttable, METH_O, "Sets output table."},
+{"setMul", (PyCFunction)TableScale_setMul, METH_O, "Sets oscillator mul factor."},
+{"setAdd", (PyCFunction)TableScale_setAdd, METH_O, "Sets oscillator add factor."},
+{"setSub", (PyCFunction)TableScale_setSub, METH_O, "Sets oscillator inverse add factor."},
+{"setDiv", (PyCFunction)TableScale_setDiv, METH_O, "Sets inverse mul factor."},
 {NULL}  /* Sentinel */
 };
 
-static PyNumberMethods SuperSaw_as_number = {
-(binaryfunc)SuperSaw_add,                      /*nb_add*/
-(binaryfunc)SuperSaw_sub,                 /*nb_subtract*/
-(binaryfunc)SuperSaw_multiply,                 /*nb_multiply*/
-(binaryfunc)SuperSaw_div,                   /*nb_divide*/
+static PyNumberMethods TableScale_as_number = {
+(binaryfunc)TableScale_add,                      /*nb_add*/
+(binaryfunc)TableScale_sub,                 /*nb_subtract*/
+(binaryfunc)TableScale_multiply,                 /*nb_multiply*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -10274,523 +12657,219 @@ static PyNumberMethods SuperSaw_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
-(binaryfunc)SuperSaw_inplace_add,              /*inplace_add*/
-(binaryfunc)SuperSaw_inplace_sub,         /*inplace_subtract*/
-(binaryfunc)SuperSaw_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)SuperSaw_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
+(binaryfunc)TableScale_inplace_add,              /*inplace_add*/
+(binaryfunc)TableScale_inplace_sub,         /*inplace_subtract*/
+(binaryfunc)TableScale_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*/
-0,              /*nb_true_divide*/
-0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
-0,                     /* nb_index */
-};
-
-PyTypeObject SuperSawType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
-"_pyo.SuperSaw_base",         /*tp_name*/
-sizeof(SuperSaw),         /*tp_basicsize*/
-0,                         /*tp_itemsize*/
-(destructor)SuperSaw_dealloc, /*tp_dealloc*/
-0,                         /*tp_print*/
-0,                         /*tp_getattr*/
-0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
-0,                         /*tp_repr*/
-&SuperSaw_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*/
-"SuperSaw objects. detune incrementor from 0 to 1.",           /* tp_doc */
-(traverseproc)SuperSaw_traverse,   /* tp_traverse */
-(inquiry)SuperSaw_clear,           /* tp_clear */
-0,		               /* tp_richcompare */
-0,		               /* tp_weaklistoffset */
-0,		               /* tp_iter */
-0,		               /* tp_iternext */
-SuperSaw_methods,             /* tp_methods */
-SuperSaw_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 */
-SuperSaw_new,                 /* tp_new */
-};
-
-/**************/
-/* RCOsc object */
-/**************/
-typedef struct {
-    pyo_audio_HEAD
-    PyObject *freq;
-    Stream *freq_stream;
-    PyObject *sharp;
-    Stream *sharp_stream;
-    int modebuffer[4];
-    MYFLT pointerPos;
-} RCOsc;
-
-static void
-RCOsc_readframes_ii(RCOsc *self) {
-    MYFLT fr, sh, inc, down_phase, up_phase;
-    int i;
-    
-    fr = PyFloat_AS_DOUBLE(self->freq);
-    sh = _clip(PyFloat_AS_DOUBLE(self->sharp));
-    sh = sh * sh * 99.0 + 1.0;
-    inc = fr * 2 / self->sr;
-    
-    for (i=0; i<self->bufsize; i++) {
-        if (self->pointerPos < 1) {
-            down_phase = 1.0 - self->pointerPos;
-            up_phase = 1.0;
-        }
-        else {
-            down_phase = 0.0;
-            up_phase = 2.0 - self->pointerPos;
-        }
-        self->data[i] = ( (1.0 - MYPOW(down_phase, sh)) + (MYPOW(up_phase, sh)) ) * 2.0 - 3.0;
-        self->pointerPos += inc;
-        if (self->pointerPos < 0)
-            self->pointerPos += 2.0;
-        else if (self->pointerPos >= 2)
-            self->pointerPos -= 2.0;
-    }
-}
-
-static void
-RCOsc_readframes_ai(RCOsc *self) {
-    MYFLT sh, down_phase, up_phase, twoOverSr;
-    int i;
-    
-    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    sh = _clip(PyFloat_AS_DOUBLE(self->sharp));
-    sh = sh * sh * 99.0 + 1.0;
-    
-    twoOverSr = 2.0 / self->sr;
-    for (i=0; i<self->bufsize; i++) {
-        if (self->pointerPos < 1) {
-            down_phase = 1.0 - self->pointerPos;
-            up_phase = 1.0;
-        }
-        else {
-            down_phase = 0.0;
-            up_phase = 2.0 - self->pointerPos;
-        }
-        self->data[i] = ( (1.0 - MYPOW(down_phase, sh)) + (MYPOW(up_phase, sh)) ) * 2.0 - 3.0;
-        self->pointerPos += fr[i] * twoOverSr;
-        if (self->pointerPos < 0)
-            self->pointerPos += 2.0;
-        else if (self->pointerPos >= 2)
-            self->pointerPos -= 2.0;
-    }
-}
-
-static void
-RCOsc_readframes_ia(RCOsc *self) {
-    MYFLT fr, sh, inc, down_phase, up_phase;
-    int i;
-    
-    fr = PyFloat_AS_DOUBLE(self->freq);
-    MYFLT *sharp = Stream_getData((Stream *)self->sharp_stream);
-    inc = fr * 2 / self->sr;
-    
-    for (i=0; i<self->bufsize; i++) {
-        sh = _clip(sharp[i]);
-        sh = sh * sh * 99.0 + 1.0;        
-        if (self->pointerPos < 1) {
-            down_phase = 1.0 - self->pointerPos;
-            up_phase = 1.0;
-        }
-        else {
-            down_phase = 0.0;
-            up_phase = 2.0 - self->pointerPos;
-        }
-        self->data[i] = ( (1.0 - MYPOW(down_phase, sh)) + (MYPOW(up_phase, sh)) ) * 2.0 - 3.0;
-        self->pointerPos += inc;
-        if (self->pointerPos < 0)
-            self->pointerPos += 2.0;
-        else if (self->pointerPos >= 2)
-            self->pointerPos -= 2.0;
-    }
-}
-
-static void
-RCOsc_readframes_aa(RCOsc *self) {
-    MYFLT sh, down_phase, up_phase, twoOverSr;
-    int i;
-    
-    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    MYFLT *sharp = Stream_getData((Stream *)self->sharp_stream);
-    
-    twoOverSr = 2.0 / self->sr;
-    for (i=0; i<self->bufsize; i++) {
-        sh = _clip(sharp[i]);
-        sh = sh * sh * 99.0 + 1.0;        
-        if (self->pointerPos < 1) {
-            down_phase = 1.0 - self->pointerPos;
-            up_phase = 1.0;
-        }
-        else {
-            down_phase = 0.0;
-            up_phase = 2.0 - self->pointerPos;
-        }
-        self->data[i] = ( (1.0 - MYPOW(down_phase, sh)) + (MYPOW(up_phase, sh)) ) * 2.0 - 3.0;
-        self->pointerPos += fr[i] * twoOverSr;
-        if (self->pointerPos < 0)
-            self->pointerPos += 2.0;
-        else if (self->pointerPos >= 2)
-            self->pointerPos -= 2.0;
-    }
-}
+0,           /*inplace_power*/
+0,       /*inplace_lshift*/
+0,      /*inplace_rshift*/
+0,      /*inplace_and*/
+0,      /*inplace_xor*/
+0,       /*inplace_or*/
+0,             /*nb_floor_divide*/
+(binaryfunc)TableScale_div,                       /*nb_true_divide*/
+0,     /*nb_inplace_floor_divide*/
+(binaryfunc)TableScale_inplace_div,                       /*nb_inplace_true_divide*/
+0,                     /* nb_index */
+};
 
-static void RCOsc_postprocessing_ii(RCOsc *self) { POST_PROCESSING_II };
-static void RCOsc_postprocessing_ai(RCOsc *self) { POST_PROCESSING_AI };
-static void RCOsc_postprocessing_ia(RCOsc *self) { POST_PROCESSING_IA };
-static void RCOsc_postprocessing_aa(RCOsc *self) { POST_PROCESSING_AA };
-static void RCOsc_postprocessing_ireva(RCOsc *self) { POST_PROCESSING_IREVA };
-static void RCOsc_postprocessing_areva(RCOsc *self) { POST_PROCESSING_AREVA };
-static void RCOsc_postprocessing_revai(RCOsc *self) { POST_PROCESSING_REVAI };
-static void RCOsc_postprocessing_revaa(RCOsc *self) { POST_PROCESSING_REVAA };
-static void RCOsc_postprocessing_revareva(RCOsc *self) { POST_PROCESSING_REVAREVA };
+PyTypeObject TableScaleType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.TableScale_base",         /*tp_name*/
+sizeof(TableScale),         /*tp_basicsize*/
+0,                         /*tp_itemsize*/
+(destructor)TableScale_dealloc, /*tp_dealloc*/
+0,                         /*tp_print*/
+0,                         /*tp_getattr*/
+0,                         /*tp_setattr*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
+0,                         /*tp_repr*/
+&TableScale_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*/
+"TableScale objects. Scale a PyoTable and save the result in another table.",           /* tp_doc */
+(traverseproc)TableScale_traverse,   /* tp_traverse */
+(inquiry)TableScale_clear,           /* tp_clear */
+0,		               /* tp_richcompare */
+0,		               /* tp_weaklistoffset */
+0,		               /* tp_iter */
+0,		               /* tp_iternext */
+TableScale_methods,             /* tp_methods */
+TableScale_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 */
+TableScale_new,                 /* tp_new */
+};
 
-static void
-RCOsc_setProcMode(RCOsc *self)
-{
-    int procmode, muladdmode;
-    procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
-    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
-	switch (procmode) {
-        case 0:        
-            self->proc_func_ptr = RCOsc_readframes_ii;
-            break;
-        case 1:    
-            self->proc_func_ptr = RCOsc_readframes_ai;
-            break;
-        case 10:        
-            self->proc_func_ptr = RCOsc_readframes_ia;
-            break;
-        case 11:    
-            self->proc_func_ptr = RCOsc_readframes_aa;
-            break;
-    } 
-	switch (muladdmode) {
-        case 0:        
-            self->muladd_func_ptr = RCOsc_postprocessing_ii;
-            break;
-        case 1:    
-            self->muladd_func_ptr = RCOsc_postprocessing_ai;
-            break;
-        case 2:    
-            self->muladd_func_ptr = RCOsc_postprocessing_revai;
-            break;
-        case 10:        
-            self->muladd_func_ptr = RCOsc_postprocessing_ia;
-            break;
-        case 11:    
-            self->muladd_func_ptr = RCOsc_postprocessing_aa;
-            break;
-        case 12:    
-            self->muladd_func_ptr = RCOsc_postprocessing_revaa;
-            break;
-        case 20:        
-            self->muladd_func_ptr = RCOsc_postprocessing_ireva;
-            break;
-        case 21:    
-            self->muladd_func_ptr = RCOsc_postprocessing_areva;
-            break;
-        case 22:    
-            self->muladd_func_ptr = RCOsc_postprocessing_revareva;
-            break;
-    } 
-}
+/******************************/
+/* TableFill object definition */
+/******************************/
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *input;
+    Stream *input_stream;
+    PyObject *table;
+    int pointer;
+} TableFill;
 
 static void
-RCOsc_compute_next_data_frame(RCOsc *self)
+TableFill_compute_next_data_frame(TableFill *self)
 {
-    (*self->proc_func_ptr)(self); 
-    (*self->muladd_func_ptr)(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
-RCOsc_traverse(RCOsc *self, visitproc visit, void *arg)
+TableFill_traverse(TableFill *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->sharp);    
-    Py_VISIT(self->sharp_stream);    
-    Py_VISIT(self->freq);    
-    Py_VISIT(self->freq_stream);    
+    Py_VISIT(self->input);
+    Py_VISIT(self->input_stream);
+    Py_VISIT(self->table);
     return 0;
 }
 
-static int 
-RCOsc_clear(RCOsc *self)
+static int
+TableFill_clear(TableFill *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->sharp);    
-    Py_CLEAR(self->sharp_stream);    
-    Py_CLEAR(self->freq);    
-    Py_CLEAR(self->freq_stream);    
+    Py_CLEAR(self->input);
+    Py_CLEAR(self->input_stream);
+    Py_CLEAR(self->table);
     return 0;
 }
 
 static void
-RCOsc_dealloc(RCOsc* self)
+TableFill_dealloc(TableFill* self)
 {
     pyo_DEALLOC
-    RCOsc_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    TableFill_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
-RCOsc_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+TableFill_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
-    PyObject *freqtmp=NULL, *sharptmp=NULL, *multmp=NULL, *addtmp=NULL;
-    RCOsc *self;
-    self = (RCOsc *)type->tp_alloc(type, 0);
-    
-    self->freq = PyFloat_FromDouble(100);
-    self->sharp = PyFloat_FromDouble(0.25);
-	self->modebuffer[0] = 0;
-	self->modebuffer[1] = 0;
-	self->modebuffer[2] = 0;
-	self->modebuffer[3] = 0;
-    self->pointerPos = 0.;
-    
+    PyObject *inputtmp, *input_streamtmp, *tabletmp;
+    TableFill *self;
+    self = (TableFill *)type->tp_alloc(type, 0);
+
+    self->pointer = 0;
+
     INIT_OBJECT_COMMON
-    Stream_setFunctionPtr(self->stream, RCOsc_compute_next_data_frame);
-    self->mode_func_ptr = RCOsc_setProcMode;
 
-    static char *kwlist[] = {"freq", "sharp", "mul", "add", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &freqtmp, &sharptmp, &multmp, &addtmp))
+    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;
-    
-    if (freqtmp) {
-        PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
-    }
 
-    if (sharptmp) {
-        PyObject_CallMethod((PyObject *)self, "setSharp", "O", sharptmp);
-    }
-    
-    if (multmp) {
-        PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
-    }
-    
-    if (addtmp) {
-        PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
+    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);
-    
-    (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
-static PyObject * RCOsc_getServer(RCOsc* self) { GET_SERVER };
-static PyObject * RCOsc_getStream(RCOsc* self) { GET_STREAM };
-static PyObject * RCOsc_setMul(RCOsc *self, PyObject *arg) { SET_MUL };	
-static PyObject * RCOsc_setAdd(RCOsc *self, PyObject *arg) { SET_ADD };	
-static PyObject * RCOsc_setSub(RCOsc *self, PyObject *arg) { SET_SUB };	
-static PyObject * RCOsc_setDiv(RCOsc *self, PyObject *arg) { SET_DIV };	
+static PyObject * TableFill_getServer(TableFill* self) { GET_SERVER };
+static PyObject * TableFill_getStream(TableFill* self) { GET_STREAM };
 
-static PyObject * RCOsc_play(RCOsc *self, PyObject *args, PyObject *kwds) { PLAY };
-static PyObject * RCOsc_out(RCOsc *self, PyObject *args, PyObject *kwds) { OUT };
-static PyObject * RCOsc_stop(RCOsc *self) { STOP };
+static PyObject * TableFill_play(TableFill *self, PyObject *args, PyObject *kwds)
+{
+    self->pointer = 0;
+    PLAY
+};
 
-static PyObject * RCOsc_multiply(RCOsc *self, PyObject *arg) { MULTIPLY };
-static PyObject * RCOsc_inplace_multiply(RCOsc *self, PyObject *arg) { INPLACE_MULTIPLY };
-static PyObject * RCOsc_add(RCOsc *self, PyObject *arg) { ADD };
-static PyObject * RCOsc_inplace_add(RCOsc *self, PyObject *arg) { INPLACE_ADD };
-static PyObject * RCOsc_sub(RCOsc *self, PyObject *arg) { SUB };
-static PyObject * RCOsc_inplace_sub(RCOsc *self, PyObject *arg) { INPLACE_SUB };
-static PyObject * RCOsc_div(RCOsc *self, PyObject *arg) { DIV };
-static PyObject * RCOsc_inplace_div(RCOsc *self, PyObject *arg) { INPLACE_DIV };
+static PyObject * TableFill_stop(TableFill *self) { STOP };
 
 static PyObject *
-RCOsc_setFreq(RCOsc *self, PyObject *arg)
+TableFill_setTable(TableFill *self, PyObject *arg)
 {
-	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	int isNumber = PyNumber_Check(arg);
-	
-	tmp = arg;
-	Py_INCREF(tmp);
-	Py_DECREF(self->freq);
-	if (isNumber == 1) {
-		self->freq = PyNumber_Float(tmp);
-        self->modebuffer[2] = 0;
-	}
-	else {
-		self->freq = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL);
-        Py_INCREF(streamtmp);
-        Py_XDECREF(self->freq_stream);
-        self->freq_stream = (Stream *)streamtmp;
-		self->modebuffer[2] = 1;
-	}
-    
-    (*self->mode_func_ptr)(self);
-    
-	Py_INCREF(Py_None);
-	return Py_None;
-}	
+	PyObject *tmp;
+
+    ASSERT_ARG_NOT_NULL
 
-static PyObject *
-RCOsc_setSharp(RCOsc *self, PyObject *arg)
-{
-	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	int isNumber = PyNumber_Check(arg);
-	
 	tmp = arg;
-	Py_INCREF(tmp);
-	Py_DECREF(self->sharp);
-	if (isNumber == 1) {
-		self->sharp = PyNumber_Float(tmp);
-        self->modebuffer[3] = 0;
-	}
-	else {
-		self->sharp = tmp;
-        streamtmp = PyObject_CallMethod((PyObject *)self->sharp, "_getStream", NULL);
-        Py_INCREF(streamtmp);
-        Py_XDECREF(self->sharp_stream);
-        self->sharp_stream = (Stream *)streamtmp;
-		self->modebuffer[3] = 1;
-	}
-    
-    (*self->mode_func_ptr)(self);
-    
+    Py_INCREF(tmp);
+	Py_DECREF(self->table);
+    self->table = PyObject_CallMethod((PyObject *)tmp, "getTableStream", "");
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
-
-static PyObject * 
-RCOsc_reset(RCOsc *self) 
-{
-    self->pointerPos = 0.0;
-    Py_INCREF(Py_None);
-    return Py_None;
 }
-
-static PyMemberDef RCOsc_members[] = {
-{"server", T_OBJECT_EX, offsetof(RCOsc, server), 0, "Pyo server."},
-{"stream", T_OBJECT_EX, offsetof(RCOsc, stream), 0, "Stream object."},
-{"freq", T_OBJECT_EX, offsetof(RCOsc, freq), 0, "Frequency in cycle per second."},
-{"sharp", T_OBJECT_EX, offsetof(RCOsc, sharp), 0, "RCOscillator sharp."},
-{"mul", T_OBJECT_EX, offsetof(RCOsc, mul), 0, "Mul factor."},
-{"add", T_OBJECT_EX, offsetof(RCOsc, add), 0, "Add factor."},
-{NULL}  /* Sentinel */
-};
-
-static PyMethodDef RCOsc_methods[] = {
-{"getServer", (PyCFunction)RCOsc_getServer, METH_NOARGS, "Returns server object."},
-{"_getStream", (PyCFunction)RCOsc_getStream, METH_NOARGS, "Returns stream object."},
-{"play", (PyCFunction)RCOsc_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
-{"out", (PyCFunction)RCOsc_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
-{"stop", (PyCFunction)RCOsc_stop, METH_NOARGS, "Stops computing."},
-{"setFreq", (PyCFunction)RCOsc_setFreq, METH_O, "Sets oscillator frequency in cycle per second."},
-{"setSharp", (PyCFunction)RCOsc_setSharp, METH_O, "Sets oscillator sharp."},
-{"reset", (PyCFunction)RCOsc_reset, METH_NOARGS, "Resets pointer position to 0."},
-{"setMul", (PyCFunction)RCOsc_setMul, METH_O, "Sets oscillator mul factor."},
-{"setAdd", (PyCFunction)RCOsc_setAdd, METH_O, "Sets oscillator add factor."},
-{"setSub", (PyCFunction)RCOsc_setSub, METH_O, "Sets oscillator inverse add factor."},
-{"setDiv", (PyCFunction)RCOsc_setDiv, METH_O, "Sets inverse mul factor."},
+
+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 PyNumberMethods RCOsc_as_number = {
-(binaryfunc)RCOsc_add,                      /*nb_add*/
-(binaryfunc)RCOsc_sub,                 /*nb_subtract*/
-(binaryfunc)RCOsc_multiply,                 /*nb_multiply*/
-(binaryfunc)RCOsc_div,                   /*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*/
-0,                                          /*nb_coerce*/
-0,                       /*nb_int*/
-0,                      /*nb_long*/
-0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
-(binaryfunc)RCOsc_inplace_add,              /*inplace_add*/
-(binaryfunc)RCOsc_inplace_sub,         /*inplace_subtract*/
-(binaryfunc)RCOsc_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)RCOsc_inplace_div,           /*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*/
-0,              /*nb_true_divide*/
-0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
-0,                     /* nb_index */
+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 RCOscType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
-"_pyo.RCOsc_base",         /*tp_name*/
-sizeof(RCOsc),         /*tp_basicsize*/
+PyTypeObject TableFillType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.TableFill_base",         /*tp_name*/
+sizeof(TableFill),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
-(destructor)RCOsc_dealloc, /*tp_dealloc*/
+(destructor)TableFill_dealloc, /*tp_dealloc*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
-&RCOsc_as_number,             /*tp_as_number*/
+0,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
 0,                         /*tp_as_mapping*/
 0,                         /*tp_hash */
@@ -10800,15 +12879,15 @@ sizeof(RCOsc),         /*tp_basicsize*/
 0,                         /*tp_setattro*/
 0,                         /*tp_as_buffer*/
 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
-"RCOsc objects. Waveform simulation of of a RC circuit.",           /* tp_doc */
-(traverseproc)RCOsc_traverse,   /* tp_traverse */
-(inquiry)RCOsc_clear,           /* tp_clear */
+"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 */
-RCOsc_methods,             /* tp_methods */
-RCOsc_members,             /* tp_members */
+TableFill_methods,             /* tp_methods */
+TableFill_members,             /* tp_members */
 0,                      /* tp_getset */
 0,                         /* tp_base */
 0,                         /* tp_dict */
@@ -10817,301 +12896,244 @@ RCOsc_members,             /* tp_members */
 0,                         /* tp_dictoffset */
 0,      /* tp_init */
 0,                         /* tp_alloc */
-RCOsc_new,                 /* tp_new */
+TableFill_new,                 /* tp_new */
 };
 
 /**************/
-/* TableScale object */
+/* TableScan object */
 /**************/
 typedef struct {
     pyo_audio_HEAD
     PyObject *table;
-    PyObject *outtable;
     int modebuffer[2];
-} TableScale;
-
-static void
-TableScale_readframes_ii(TableScale *self) {
-    int i, num;
-    MYFLT mul, add;
-    MYFLT *tablelist = TableStream_getData(self->table);
-    int size = TableStream_getSize(self->table);
-    MYFLT *outlist = TableStream_getData(self->outtable);
-    int osize = TableStream_getSize(self->outtable);
-
-    mul = PyFloat_AS_DOUBLE(self->mul);
-    add = PyFloat_AS_DOUBLE(self->add);
-    
-    num = size < osize ? size : osize;
-    for (i=0; i<num; i++) {
-        outlist[i] = tablelist[i] * mul + add;
-    }
-}
-
-static void
-TableScale_readframes_ai(TableScale *self) {
-    int i, num;
-    MYFLT add;
-    MYFLT *tablelist = TableStream_getData(self->table);
-    int size = TableStream_getSize(self->table);
-    MYFLT *outlist = TableStream_getData(self->outtable);
-    int osize = TableStream_getSize(self->outtable);
-
-    MYFLT *mul = Stream_getData((Stream *)self->mul_stream);
-    add = PyFloat_AS_DOUBLE(self->add);
-    
-    num = size < osize ? size : osize;
-    for (i=0; i<num; i++) {
-        outlist[i] = tablelist[i] * mul[i] + add;
-    }
-}
+    int pointerPos;
+} TableScan;
 
 static void
-TableScale_readframes_ia(TableScale *self) {
-    int i, num;
-    MYFLT mul;
+TableScan_readframes(TableScan *self) {
+    int i;
     MYFLT *tablelist = TableStream_getData(self->table);
     int size = TableStream_getSize(self->table);
-    MYFLT *outlist = TableStream_getData(self->outtable);
-    int osize = TableStream_getSize(self->outtable);
 
-    mul = PyFloat_AS_DOUBLE(self->mul);
-    MYFLT *add = Stream_getData((Stream *)self->add_stream);
-    
-    num = size < osize ? size : osize;
-    for (i=0; i<num; i++) {
-        outlist[i] = tablelist[i] * mul + add[i];
+    for (i=0; i<self->bufsize; i++) {
+        self->data[i] = tablelist[self->pointerPos++];
+        if (self->pointerPos >= size)
+            self->pointerPos = 0;
     }
 }
 
-static void
-TableScale_readframes_aa(TableScale *self) {
-    int i, num;
-    MYFLT *tablelist = TableStream_getData(self->table);
-    int size = TableStream_getSize(self->table);
-    MYFLT *outlist = TableStream_getData(self->outtable);
-    int osize = TableStream_getSize(self->outtable);
-
-    MYFLT *mul = Stream_getData((Stream *)self->mul_stream);
-    MYFLT *add = Stream_getData((Stream *)self->add_stream);
-    
-    num = size < osize ? size : osize;
-    for (i=0; i<num; i++) {
-        outlist[i] = tablelist[i] * mul[i] + add[i];
-    }
-}
+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
-TableScale_setProcMode(TableScale *self)
+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->proc_func_ptr = TableScale_readframes_ii;
+        case 0:
+            self->muladd_func_ptr = TableScan_postprocessing_ii;
             break;
-        case 1:    
-            self->proc_func_ptr = TableScale_readframes_ai;
+        case 1:
+            self->muladd_func_ptr = TableScan_postprocessing_ai;
             break;
-        case 10:        
-            self->proc_func_ptr = TableScale_readframes_ia;
+        case 2:
+            self->muladd_func_ptr = TableScan_postprocessing_revai;
             break;
-        case 11:    
-            self->proc_func_ptr = TableScale_readframes_aa;
+        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
-TableScale_compute_next_data_frame(TableScale *self)
+TableScan_compute_next_data_frame(TableScan *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
+    (*self->muladd_func_ptr)(self);
 }
 
 static int
-TableScale_traverse(TableScale *self, visitproc visit, void *arg)
+TableScan_traverse(TableScan *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->table);
-    Py_VISIT(self->outtable);
     return 0;
 }
 
-static int 
-TableScale_clear(TableScale *self)
+static int
+TableScan_clear(TableScan *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->table);
-    Py_CLEAR(self->outtable);
     return 0;
 }
 
 static void
-TableScale_dealloc(TableScale* self)
+TableScan_dealloc(TableScan* self)
 {
     pyo_DEALLOC
-    TableScale_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    TableScan_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
-TableScale_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+TableScan_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
-    PyObject *tabletmp, *outtabletmp, *multmp=NULL, *addtmp=NULL;
-    TableScale *self;
-    self = (TableScale *)type->tp_alloc(type, 0);
-    
+    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, TableScale_compute_next_data_frame);
-    self->mode_func_ptr = TableScale_setProcMode;
+    Stream_setFunctionPtr(self->stream, TableScan_compute_next_data_frame);
+    self->mode_func_ptr = TableScan_setProcMode;
 
-    static char *kwlist[] = {"table", "outtable", "mul", "add", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist, &tabletmp, &outtabletmp, &multmp, &addtmp))
+    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 ) {
-        PySys_WriteStderr("TypeError: \"table\" argument of TableScale must be a PyoTableObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        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 ( PyObject_HasAttrString((PyObject *)outtabletmp, "getTableStream") == 0 ) {
-        PySys_WriteStderr("TypeError: \"outtable\" argument of TableScale must be a PyoTableObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
-    }
-    Py_XDECREF(self->outtable);
-    self->outtable = PyObject_CallMethod((PyObject *)outtabletmp, "getTableStream", "");
 
-    if (addtmp) {
+    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 * TableScale_getServer(TableScale* self) { GET_SERVER };
-static PyObject * TableScale_getStream(TableScale* self) { GET_STREAM };
-static PyObject * TableScale_setMul(TableScale *self, PyObject *arg) { SET_MUL };	
-static PyObject * TableScale_setAdd(TableScale *self, PyObject *arg) { SET_ADD };	
-static PyObject * TableScale_setSub(TableScale *self, PyObject *arg) { SET_SUB };	
-static PyObject * TableScale_setDiv(TableScale *self, PyObject *arg) { SET_DIV };	
+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 * TableScale_play(TableScale *self, PyObject *args, PyObject *kwds) { PLAY };
-static PyObject * TableScale_out(TableScale *self, PyObject *args, PyObject *kwds) { OUT };
-static PyObject * TableScale_stop(TableScale *self) { STOP };
+static PyObject * TableScan_play(TableScan *self, PyObject *args, PyObject *kwds)
+{
+    self->pointerPos = 0;
+    PLAY
+};
 
-static PyObject * TableScale_multiply(TableScale *self, PyObject *arg) { MULTIPLY };
-static PyObject * TableScale_inplace_multiply(TableScale *self, PyObject *arg) { INPLACE_MULTIPLY };
-static PyObject * TableScale_add(TableScale *self, PyObject *arg) { ADD };
-static PyObject * TableScale_inplace_add(TableScale *self, PyObject *arg) { INPLACE_ADD };
-static PyObject * TableScale_sub(TableScale *self, PyObject *arg) { SUB };
-static PyObject * TableScale_inplace_sub(TableScale *self, PyObject *arg) { INPLACE_SUB };
-static PyObject * TableScale_div(TableScale *self, PyObject *arg) { DIV };
-static PyObject * TableScale_inplace_div(TableScale *self, PyObject *arg) { INPLACE_DIV };
+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 *
-TableScale_getTable(TableScale* self)
+TableScan_getTable(TableScan* self)
 {
     Py_INCREF(self->table);
     return self->table;
 };
 
 static PyObject *
-TableScale_setTable(TableScale *self, PyObject *arg)
+TableScan_setTable(TableScan *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    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 *
-TableScale_getOuttable(TableScale* self)
-{
-    Py_INCREF(self->outtable);
-    return self->outtable;
-};
+}
 
 static PyObject *
-TableScale_setOuttable(TableScale *self, PyObject *arg)
+TableScan_reset(TableScan *self)
 {
-	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	tmp = arg;
-	Py_DECREF(self->outtable);
-    self->outtable = PyObject_CallMethod((PyObject *)tmp, "getTableStream", "");
-    
-	Py_INCREF(Py_None);
-	return Py_None;
-}	
+    self->pointerPos = 0;
+    Py_INCREF(Py_None);
+    return Py_None;
+}
 
-static PyMemberDef TableScale_members[] = {
-{"server", T_OBJECT_EX, offsetof(TableScale, server), 0, "Pyo server."},
-{"stream", T_OBJECT_EX, offsetof(TableScale, stream), 0, "Stream object."},
-{"table", T_OBJECT_EX, offsetof(TableScale, table), 0, "Waveform table."},
-{"outtable", T_OBJECT_EX, offsetof(TableScale, outtable), 0, "Output table."},
-{"mul", T_OBJECT_EX, offsetof(TableScale, mul), 0, "Mul factor."},
-{"add", T_OBJECT_EX, offsetof(TableScale, add), 0, "Add factor."},
+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 TableScale_methods[] = {
-{"getTable", (PyCFunction)TableScale_getTable, METH_NOARGS, "Returns waveform table object."},
-{"getOuttable", (PyCFunction)TableScale_getOuttable, METH_NOARGS, "Returns output table object."},
-{"getServer", (PyCFunction)TableScale_getServer, METH_NOARGS, "Returns server object."},
-{"_getStream", (PyCFunction)TableScale_getStream, METH_NOARGS, "Returns stream object."},
-{"play", (PyCFunction)TableScale_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
-{"out", (PyCFunction)TableScale_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
-{"stop", (PyCFunction)TableScale_stop, METH_NOARGS, "Stops computing."},
-{"setTable", (PyCFunction)TableScale_setTable, METH_O, "Sets oscillator table."},
-{"setOuttable", (PyCFunction)TableScale_setOuttable, METH_O, "Sets output table."},
-{"setMul", (PyCFunction)TableScale_setMul, METH_O, "Sets oscillator mul factor."},
-{"setAdd", (PyCFunction)TableScale_setAdd, METH_O, "Sets oscillator add factor."},
-{"setSub", (PyCFunction)TableScale_setSub, METH_O, "Sets oscillator inverse add factor."},
-{"setDiv", (PyCFunction)TableScale_setDiv, METH_O, "Sets inverse mul factor."},
+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 TableScale_as_number = {
-(binaryfunc)TableScale_add,                      /*nb_add*/
-(binaryfunc)TableScale_sub,                 /*nb_subtract*/
-(binaryfunc)TableScale_multiply,                 /*nb_multiply*/
-(binaryfunc)TableScale_div,                   /*nb_divide*/
+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*/
@@ -11125,16 +13147,16 @@ static PyNumberMethods TableScale_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
-(binaryfunc)TableScale_inplace_add,              /*inplace_add*/
-(binaryfunc)TableScale_inplace_sub,         /*inplace_subtract*/
-(binaryfunc)TableScale_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)TableScale_inplace_div,           /*inplace_divide*/
+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*/
@@ -11143,25 +13165,24 @@ static PyNumberMethods TableScale_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)TableScan_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)TableScan_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
-PyTypeObject TableScaleType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
-"_pyo.TableScale_base",         /*tp_name*/
-sizeof(TableScale),         /*tp_basicsize*/
+PyTypeObject TableScanType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.TableScan_base",         /*tp_name*/
+sizeof(TableScan),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
-(destructor)TableScale_dealloc, /*tp_dealloc*/
+(destructor)TableScan_dealloc, /*tp_dealloc*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
-&TableScale_as_number,             /*tp_as_number*/
+&TableScan_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
 0,                         /*tp_as_mapping*/
 0,                         /*tp_hash */
@@ -11171,15 +13192,15 @@ sizeof(TableScale),         /*tp_basicsize*/
 0,                         /*tp_setattro*/
 0,                         /*tp_as_buffer*/
 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
-"TableScale objects. Scale a PyoTable and save the result in another table.",           /* tp_doc */
-(traverseproc)TableScale_traverse,   /* tp_traverse */
-(inquiry)TableScale_clear,           /* tp_clear */
+"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 */
-TableScale_methods,             /* tp_methods */
-TableScale_members,             /* tp_members */
+TableScan_methods,             /* tp_methods */
+TableScan_members,             /* tp_members */
 0,                      /* tp_getset */
 0,                         /* tp_base */
 0,                         /* tp_dict */
@@ -11188,5 +13209,5 @@ TableScale_members,             /* tp_members */
 0,                         /* tp_dictoffset */
 0,      /* tp_init */
 0,                         /* tp_alloc */
-TableScale_new,                 /* tp_new */
-};
\ No newline at end of file
+TableScan_new,                 /* tp_new */
+};
diff --git a/src/objects/oscmodule.c b/src/objects/oscmodule.c
index a8e8f05..2df96fd 100644
--- a/src/objects/oscmodule.c
+++ b/src/objects/oscmodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
@@ -27,9 +28,9 @@
 #include "dummymodule.h"
 #include "lo/lo.h"
 
-void error(int num, const char *msg, const char *path)
+static void error(int num, const char *msg, const char *path)
 {
-    printf("liblo server error %d in path %s: %s\n", num, path, msg);
+    PySys_WriteStdout("liblo server error %d in path %s: %s\n", num, path, msg);
 }
 
 /* main OSC receiver */
@@ -45,7 +46,7 @@ int OscReceiver_handler(const char *path, const char *types, lo_arg **argv, int
                         void *data, void *user_data)
 {
     OscReceiver *self = user_data;
-    PyDict_SetItem(self->dict, PyString_FromString(path), PyFloat_FromDouble(argv[0]->FLOAT_VALUE));
+    PyDict_SetItem(self->dict, PyUnicode_FromString(path), PyFloat_FromDouble(argv[0]->FLOAT_VALUE));
     return 0;
 }
 
@@ -71,7 +72,7 @@ OscReceiver_traverse(OscReceiver *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 OscReceiver_clear(OscReceiver *self)
 {
     pyo_CLEAR
@@ -86,7 +87,7 @@ OscReceiver_dealloc(OscReceiver* self)
     lo_server_free(self->osc_server);
     pyo_DEALLOC
     OscReceiver_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -96,45 +97,41 @@ OscReceiver_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *pathtmp;
     OscReceiver *self;
     self = (OscReceiver *)type->tp_alloc(type, 0);
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, OscReceiver_compute_next_data_frame);
+    Stream_setStreamActive(self->stream, 1);
 
     static char *kwlist[] = {"port", "address", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "iO", kwlist, &self->port, &pathtmp))
         Py_RETURN_NONE;
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     self->dict = PyDict_New();
-    
-    if (PyString_Check(pathtmp) || PyList_Check(pathtmp)) {
-        Py_INCREF(pathtmp);    
+
+    if (PyList_Check(pathtmp)) {
+        Py_INCREF(pathtmp);
         Py_XDECREF(self->address_path);
         self->address_path = pathtmp;
     }
     else {
-        PyErr_SetString(PyExc_TypeError, "The address attributes must be a string or a list of strings.");
+        PyErr_SetString(PyExc_TypeError, "The OscReceiver_base 'address' attributes must be a list of strings and/or unicodes.");
         Py_RETURN_NONE;
-    }    
-    
-    if (PyString_Check(self->address_path)) {
-        PyDict_SetItem(self->dict, self->address_path, PyFloat_FromDouble(0.));
-    }    
-    else if (PyList_Check(self->address_path)) {
-        int lsize = PyList_Size(self->address_path);
-        for (i=0; i<lsize; i++) {
-            PyDict_SetItem(self->dict, PyList_GET_ITEM(self->address_path, i), PyFloat_FromDouble(0.));
-        }    
     }
-    
+
+    int lsize = PyList_Size(self->address_path);
+    for (i=0; i<lsize; i++) {
+        PyDict_SetItem(self->dict, PyList_GET_ITEM(self->address_path, i), PyFloat_FromDouble(0.));
+    }
+
     char buf[20];
     sprintf(buf, "%i", self->port);
     self->osc_server = lo_server_new(buf, error);
-    
+
     lo_server_add_method(self->osc_server, NULL, TYPE_F, OscReceiver_handler, self);
-    
+
     return (PyObject *)self;
 }
 
@@ -142,50 +139,48 @@ static PyObject *
 OscReceiver_addAddress(OscReceiver *self, PyObject *arg)
 {
     int i;
-    if (PyString_Check(arg)) {
+    if (PY_STRING_CHECK(arg)) {
         PyDict_SetItem(self->dict, arg, PyFloat_FromDouble(0.));
-    }    
+    }
     else if (PyList_Check(arg)) {
         Py_ssize_t lsize = PyList_Size(arg);
         for (i=0; i<lsize; i++) {
             PyDict_SetItem(self->dict, PyList_GET_ITEM(arg, i), PyFloat_FromDouble(0.));
-        }    
-    } 
-	Py_INCREF(Py_None);
-	return Py_None;
+        }
+    }
+	Py_RETURN_NONE;
 }
 
 static PyObject *
 OscReceiver_delAddress(OscReceiver *self, PyObject *arg)
 {
     int i;
-    if (PyString_Check(arg)) {
+    if (PY_STRING_CHECK(arg)) {
         PyDict_DelItem(self->dict, arg);
-    }    
+    }
     else if (PyList_Check(arg)) {
         Py_ssize_t lsize = PyList_Size(arg);
         for (i=0; i<lsize; i++) {
             PyDict_DelItem(self->dict, PyList_GET_ITEM(arg, i));
-        }    
-    } 
-	Py_INCREF(Py_None);
-	return Py_None;
+        }
+    }
+	Py_RETURN_NONE;
 }
 
 static PyObject *
 OscReceiver_setValue(OscReceiver *self, PyObject *args, PyObject *kwds)
 {
     PyObject *address, *value;
-    
+
     static char *kwlist[] = {"address", "value", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &address, &value))
         Py_RETURN_NONE;
 
     PyDict_SetItem(self->dict, address, value);
     Py_RETURN_NONE;
 }
-  
+
 static PyObject * OscReceiver_getServer(OscReceiver* self) { GET_SERVER };
 static PyObject * OscReceiver_getStream(OscReceiver* self) { GET_STREAM };
 
@@ -205,8 +200,7 @@ static PyMethodDef OscReceiver_methods[] = {
 };
 
 PyTypeObject OscReceiverType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.OscReceiver_base",         /*tp_name*/
 sizeof(OscReceiver),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -214,7 +208,7 @@ sizeof(OscReceiver),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 0,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -272,33 +266,33 @@ OscReceive_setProcMode(OscReceive *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = OscReceive_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = OscReceive_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = OscReceive_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = OscReceive_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = OscReceive_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = OscReceive_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = OscReceive_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = OscReceive_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = OscReceive_postprocessing_revareva;
             break;
     }
@@ -309,17 +303,16 @@ OscReceive_compute_next_data_frame(OscReceive *self)
 {
     int i;
     MYFLT val = OscReceiver_getValue((OscReceiver *)self->input, self->address_path);
-    
+
     if (self->interpolation == 1) {
-        
         for (i=0; i<self->bufsize; i++) {
             self->data[i] = self->value = self->value + (val - self->value) * self->factor;
-        }  
+        }
     }
     else {
         for (i=0; i<self->bufsize; i++) {
             self->data[i] = self->value = val;
-        }  
+        }
     }
 
     (*self->muladd_func_ptr)(self);
@@ -334,7 +327,7 @@ OscReceive_traverse(OscReceive *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 OscReceive_clear(OscReceive *self)
 {
     pyo_CLEAR
@@ -348,7 +341,7 @@ OscReceive_dealloc(OscReceive* self)
 {
     pyo_DEALLOC
     OscReceive_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -383,22 +376,22 @@ OscReceive_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     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);
 
-    if (! PyString_Check(pathtmp)) {
-        PyErr_SetString(PyExc_TypeError, "The address attributes must be a string.");
+    if (!PY_STRING_CHECK(pathtmp)) {
+        PyErr_SetString(PyExc_TypeError, "The address attributes must be a string or a unicode.");
         Py_RETURN_NONE;
-    }    
-        
-    Py_INCREF(pathtmp);    
+    }
+
+    Py_INCREF(pathtmp);
     Py_XDECREF(self->address_path);
     self->address_path = pathtmp;
-        
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
@@ -407,23 +400,19 @@ OscReceive_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 static PyObject *
 OscReceive_setInterpolation(OscReceive *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
     self->interpolation = PyInt_AsLong(arg);
-    
-	Py_INCREF(Py_None);
-	return Py_None;
+
+	Py_RETURN_NONE;
 }
 
 static PyObject * OscReceive_getServer(OscReceive* self) { GET_SERVER };
 static PyObject * OscReceive_getStream(OscReceive* self) { GET_STREAM };
-static PyObject * OscReceive_setMul(OscReceive *self, PyObject *arg) { SET_MUL };	
-static PyObject * OscReceive_setAdd(OscReceive *self, PyObject *arg) { SET_ADD };	
-static PyObject * OscReceive_setSub(OscReceive *self, PyObject *arg) { SET_SUB };	
-static PyObject * OscReceive_setDiv(OscReceive *self, PyObject *arg) { SET_DIV };	
+static PyObject * OscReceive_setMul(OscReceive *self, PyObject *arg) { SET_MUL };
+static PyObject * OscReceive_setAdd(OscReceive *self, PyObject *arg) { SET_ADD };
+static PyObject * OscReceive_setSub(OscReceive *self, PyObject *arg) { SET_SUB };
+static PyObject * OscReceive_setDiv(OscReceive *self, PyObject *arg) { SET_DIV };
 
 static PyObject * OscReceive_play(OscReceive *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * OscReceive_stop(OscReceive *self) { STOP };
@@ -462,7 +451,7 @@ static PyNumberMethods OscReceive_as_number = {
     (binaryfunc)OscReceive_add,                      /*nb_add*/
     (binaryfunc)OscReceive_sub,                 /*nb_subtract*/
     (binaryfunc)OscReceive_multiply,                 /*nb_multiply*/
-    (binaryfunc)OscReceive_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -476,16 +465,16 @@ static PyNumberMethods OscReceive_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)OscReceive_inplace_add,              /*inplace_add*/
     (binaryfunc)OscReceive_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)OscReceive_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)OscReceive_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -494,15 +483,14 @@ static PyNumberMethods OscReceive_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)OscReceive_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)OscReceive_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject OscReceiveType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.OscReceive_base",         /*tp_name*/
     sizeof(OscReceive),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -510,7 +498,7 @@ PyTypeObject OscReceiveType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &OscReceive_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -558,16 +546,22 @@ typedef struct {
 static void
 OscSend_compute_next_data_frame(OscSend *self)
 {
+    char *path=NULL;
     self->count++;
     if (self->count >= self->bufrate) {
         self->count = 0;
         MYFLT *in = Stream_getData((Stream *)self->input_stream);
         float value = (float)in[0];
-    
-        char *path  = PyString_AsString(self->address_path);
-    
+
+        if (PyBytes_Check(self->address_path))
+            path = PyBytes_AsString(self->address_path);
+        else
+            path = PY_UNICODE_AS_UNICODE(self->address_path);
+
         if (lo_send(self->address, path, "f", value) == -1) {
-            printf("OSC error %d: %s\n", lo_address_errno(self->address), lo_address_errstr(self->address));
+            PySys_WriteStdout("OSC error %d: %s\n", 
+                              lo_address_errno(self->address), 
+                              lo_address_errstr(self->address));
         }
     }
 }
@@ -582,7 +576,7 @@ OscSend_traverse(OscSend *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 OscSend_clear(OscSend *self)
 {
     pyo_CLEAR
@@ -597,7 +591,7 @@ OscSend_dealloc(OscSend* self)
 {
     pyo_DEALLOC
     OscSend_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -607,53 +601,49 @@ OscSend_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *pathtmp;
     OscSend *self;
     self = (OscSend *)type->tp_alloc(type, 0);
-    
+
     self->host = NULL;
     self->count = 0;
     self->bufrate = 1;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, OscSend_compute_next_data_frame);
 
     static char *kwlist[] = {"input", "port", "address", "host", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OiO|s", kwlist, &inputtmp, &self->port, &pathtmp, &self->host))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
- 
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
-    if (! PyString_Check(pathtmp)) {
-        PyErr_SetString(PyExc_TypeError, "The address attributes must be a string.");
+
+    if (!PY_STRING_CHECK(pathtmp)) {
+        PyErr_SetString(PyExc_TypeError, "The address attributes must be a string or a unicode (bytes or string in Python 3).");
         Py_RETURN_NONE;
-    }    
-    
-    Py_INCREF(pathtmp);    
+    }
+
+    Py_INCREF(pathtmp);
     Py_XDECREF(self->address_path);
     self->address_path = pathtmp;
-    
+
     char buf[20];
     sprintf(buf, "%i", self->port);
     self->address = lo_address_new(self->host, buf);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject *
 OscSend_setBufferRate(OscSend *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
     self->bufrate = PyInt_AsLong(arg);
     if (self->bufrate < 1)
         self->bufrate = 1;
-    
-	Py_INCREF(Py_None);
-	return Py_None;
+
+	Py_RETURN_NONE;
 }
 
 static PyObject * OscSend_getServer(OscSend* self) { GET_SERVER };
@@ -679,8 +669,7 @@ static PyMethodDef OscSend_methods[] = {
 };
 
 PyTypeObject OscSendType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.OscSend_base",         /*tp_name*/
 sizeof(OscSend),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -688,7 +677,7 @@ sizeof(OscSend),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 0,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -735,42 +724,88 @@ typedef struct {
 
 static void
 OscDataSend_compute_next_data_frame(OscDataSend *self)
-{    
-    int i;
+{
+    int i, j = 0;
+    Py_ssize_t blobsize = 0;
+    PyObject *inlist = NULL;
+    PyObject *datalist = NULL;
+    char *blobdata = NULL;
+    uint8_t midi[4];
+    lo_blob *blob = NULL;
+    char *path=NULL;
     lo_message *msg;
-    char *path  = PyString_AsString(self->address_path);
-        
-    if (self->something_to_send == 1) {
+
+    while (self->something_to_send) {
+        if (PyBytes_Check(self->address_path))
+            path = PyBytes_AsString(self->address_path);
+        else
+            path = PY_UNICODE_AS_UNICODE(self->address_path);
         msg = lo_message_new();
 
+        self->something_to_send--;
+        inlist = PyList_GetItem(self->value, self->something_to_send);
         for (i=0; i<self->num_items; i++) {
             switch (self->types[i]) {
                 case LO_INT32:
-                    lo_message_add_int32(msg, PyInt_AsLong(PyList_GetItem(self->value, i)));
+                    lo_message_add_int32(msg, PyInt_AS_LONG(PyList_GET_ITEM(inlist, i)));
                     break;
                 case LO_INT64:
-                    lo_message_add_int64(msg, (long)PyLong_AsLong(PyList_GetItem(self->value, i)));
+                    lo_message_add_int64(msg, (long)PyLong_AsLong(PyList_GET_ITEM(inlist, i)));
                     break;
                 case LO_FLOAT:
-                    lo_message_add_float(msg, PyFloat_AsDouble(PyList_GetItem(self->value, i)));
+                    lo_message_add_float(msg, (float)PyFloat_AsDouble(PyList_GET_ITEM(inlist, i)));
                     break;
                 case LO_DOUBLE:
-                    lo_message_add_double(msg, (double)PyFloat_AsDouble(PyList_GetItem(self->value, i)));
+                    lo_message_add_double(msg, (double)PyFloat_AsDouble(PyList_GET_ITEM(inlist, i)));
                     break;
                 case LO_STRING:
-                    lo_message_add_string(msg, PyString_AsString(PyList_GetItem(self->value, i)));
+                    lo_message_add_string(msg, PY_STRING_AS_STRING(PyList_GET_ITEM(inlist, i)));
+                    break;
+                case LO_CHAR:
+                    lo_message_add_char(msg, (char)PY_STRING_AS_STRING(PyList_GET_ITEM(inlist, i))[0]);
+                    break;
+                case LO_BLOB:
+                    datalist = PyList_GET_ITEM(inlist, i);
+                    blobsize = PyList_Size(datalist);
+                    blobdata = (char *)malloc(blobsize * sizeof(char));
+                    for (j=0; j<blobsize; j++) {
+                        blobdata[j] = (char)PY_STRING_AS_STRING(PyList_GET_ITEM(datalist, j))[0];
+                    }
+                    blob = lo_blob_new(blobsize * sizeof(char), blobdata);
+                    lo_message_add_blob(msg, blob);
+                    break;
+                case LO_MIDI:
+                    datalist = PyList_GET_ITEM(inlist, i);
+                    for (j=0; j<4; j++) {
+                        midi[j] = (uint8_t)PyInt_AS_LONG(PyList_GET_ITEM(datalist, j));
+                    }
+                    lo_message_add_midi(msg, midi);
+                    break;
+                case LO_NIL:
+                    lo_message_add_nil(msg);
+                    break;
+                case LO_TRUE:
+                    lo_message_add_true(msg);
+                    break;
+                case LO_FALSE:
+                    lo_message_add_false(msg);
                     break;
                 default:
                     break;
             }
         }
         if (lo_send_message(self->address, path, msg) == -1) {
-            printf("OSC error %d: %s\n", lo_address_errno(self->address), lo_address_errstr(self->address));
+            PySys_WriteStdout("OSC error %d: %s\n", lo_address_errno(self->address), 
+                                         lo_address_errstr(self->address));
         }
-        self->something_to_send = 0;
+        Py_DECREF(inlist);
+        PySequence_DelItem(self->value, self->something_to_send);
         lo_message_free(msg);
+        if (blob != NULL)
+            lo_blob_free(blob);
+        if (blobdata != NULL)
+            free(blobdata);
     }
-    
 }
 
 static int
@@ -782,7 +817,7 @@ OscDataSend_traverse(OscDataSend *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 OscDataSend_clear(OscDataSend *self)
 {
     pyo_CLEAR
@@ -796,7 +831,7 @@ OscDataSend_dealloc(OscDataSend* self)
 {
     pyo_DEALLOC
     OscDataSend_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -806,34 +841,36 @@ OscDataSend_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *pathtmp;
     OscDataSend *self;
     self = (OscDataSend *)type->tp_alloc(type, 0);
-    
+
+    self->value = PyList_New(0);
+    self->something_to_send = 0;
     self->host = NULL;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, OscDataSend_compute_next_data_frame);
 
     static char *kwlist[] = {"types", "port", "address", "host", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "siO|s", kwlist, &self->types, &self->port, &pathtmp, &self->host))
         Py_RETURN_NONE;
 
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
-    if (! PyString_Check(pathtmp)) {
-        PyErr_SetString(PyExc_TypeError, "The address attributes must be a string.");
+
+    if (!PY_STRING_CHECK(pathtmp)) {
+        PyErr_SetString(PyExc_TypeError, "The address attributes must be of type string or unicode (bytes or string in Python 3).");
         Py_RETURN_NONE;
-    }    
-    
+    }
+
     self->num_items = strlen(self->types);
-    
-    Py_INCREF(pathtmp);    
+
+    Py_INCREF(pathtmp);
     Py_XDECREF(self->address_path);
     self->address_path = pathtmp;
-    
+
     char buf[20];
     sprintf(buf, "%i", self->port);
     self->address = lo_address_new(self->host, buf);
-    
+
     return (PyObject *)self;
 }
 
@@ -845,27 +882,22 @@ static PyObject * OscDataSend_stop(OscDataSend *self) { STOP };
 
 static PyObject *
 OscDataSend_send(OscDataSend *self, PyObject *arg)
-{	
+{
     PyObject *tmp;
-    
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
     if (PyList_Check(arg)) {
         tmp = arg;
-        Py_XDECREF(self->value);
         Py_INCREF(tmp);
-        self->value = tmp;
-        self->something_to_send = 1;
+        PyList_Append(self->value, tmp);
+        self->something_to_send++;
     }
     else
-        printf("argument to send() method must be a tuple of values.\n");
+        PySys_WriteStdout("OscDataSend: argument to send() method must be a list of values.\n");
 
-	Py_INCREF(Py_None);
-	return Py_None;
-}	
+	Py_RETURN_NONE;
+}
 
 static PyMemberDef OscDataSend_members[] = {
     {"server", T_OBJECT_EX, offsetof(OscDataSend, server), 0, "Pyo server."},
@@ -883,8 +915,7 @@ static PyMethodDef OscDataSend_methods[] = {
 };
 
 PyTypeObject OscDataSendType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.OscDataSend_base",         /*tp_name*/
     sizeof(OscDataSend),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -892,7 +923,7 @@ PyTypeObject OscDataSendType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     0,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -937,45 +968,92 @@ int OscDataReceive_handler(const char *path, const char *types, lo_arg **argv, i
                         void *data, void *user_data)
 {
     OscDataReceive *self = user_data;
-    PyObject *tup, *result;
+    PyObject *tup, *result=NULL;
+    lo_blob *blob = NULL;
+    char *blobdata = NULL;
+    uint32_t blobsize = 0;
+    PyObject *charlist = NULL; 
     tup = PyTuple_New(argc+1);
     int i, ok = 0;
-    
+    uint32_t j = 0;
+
     Py_ssize_t lsize = PyList_Size(self->address_path);
     for (i=0; i<lsize; i++) {
-        if (lo_pattern_match(path, PyString_AsString(PyList_GetItem(self->address_path, i)))) {
-            ok = 1;
-            break;
+        if (PyBytes_Check(PyList_GET_ITEM(self->address_path, i))) {
+            if (lo_pattern_match(path, PyBytes_AsString(PyList_GET_ITEM(self->address_path, i)))) {
+                ok = 1;
+                break;
+            }
+        }
+        else {
+            if (lo_pattern_match(path, PY_UNICODE_AS_UNICODE(PyList_GET_ITEM(self->address_path, i)))) {
+                ok = 1;
+                break;
+            }
         }
     }
-    
     if (ok) {
-        PyTuple_SetItem(tup, 0, PyString_FromString(path));
+        PyTuple_SET_ITEM(tup, 0, PyUnicode_FromString(path));
         for (i=0; i<argc; i++) {
             switch (types[i]) {
                 case LO_INT32:
-                    PyTuple_SetItem(tup, i+1, PyInt_FromLong(argv[i]->i));
+                    PyTuple_SET_ITEM(tup, i+1, PyInt_FromLong(argv[i]->i));
                     break;
                 case LO_INT64:
-                    PyTuple_SetItem(tup, i+1, PyLong_FromLong(argv[i]->h));
+                    PyTuple_SET_ITEM(tup, i+1, PyLong_FromLong(argv[i]->h));
                     break;
                 case LO_FLOAT:
-                    PyTuple_SetItem(tup, i+1, PyFloat_FromDouble(argv[i]->f));
+                    PyTuple_SET_ITEM(tup, i+1, PyFloat_FromDouble(argv[i]->f));
                     break;
                 case LO_DOUBLE:
-                    PyTuple_SetItem(tup, i+1, PyFloat_FromDouble(argv[i]->d));
+                    PyTuple_SET_ITEM(tup, i+1, PyFloat_FromDouble(argv[i]->d));
                     break;
                 case LO_STRING:
-                    PyTuple_SetItem(tup, i+1, PyString_FromString(&argv[i]->s));
+                    PyTuple_SET_ITEM(tup, i+1, PyUnicode_FromString(&argv[i]->s));
+                    break;
+                case LO_CHAR:
+                    PyTuple_SET_ITEM(tup, i+1, PyUnicode_FromFormat("%c", argv[i]->c));
+                    break;
+                case LO_BLOB:
+                    blob = (lo_blob)argv[i];
+                    blobsize = lo_blob_datasize(blob);
+                    blobdata = lo_blob_dataptr(blob);
+                    charlist = PyList_New(blobsize);
+                    for (j=0; j<blobsize; j++) {
+                        PyList_SET_ITEM(charlist, j, PyUnicode_FromFormat("%c", blobdata[j]));
+                    }
+                    PyTuple_SET_ITEM(tup, i+1, charlist);
+                    break;
+                case LO_MIDI:
+                    charlist = PyList_New(4);
+                    for (j=0; j<4; j++) {
+                        PyList_SET_ITEM(charlist, j, PyInt_FromLong(argv[i]->m[j]));
+                    }
+                    PyTuple_SET_ITEM(tup, i+1, charlist);                    
+                    break;
+                case LO_NIL:
+                    Py_INCREF(Py_None);
+                    PyTuple_SET_ITEM(tup, i+1, Py_None);
+                    break;
+                case LO_TRUE:
+                    Py_INCREF(Py_True);
+                    PyTuple_SET_ITEM(tup, i+1, Py_True);
+                    break;
+                case LO_FALSE:
+                    Py_INCREF(Py_False);
+                    PyTuple_SET_ITEM(tup, i+1, Py_False);
                     break;
                 default:
                     break;
             }
         }
-        result = PyObject_Call(self->callable, tup, NULL);     
+        result = PyObject_Call(self->callable, tup, NULL);
         if (result == NULL)
             PyErr_Print();
     }
+    Py_XDECREF(tup);
+    Py_XDECREF(result);
+    Py_XDECREF(charlist);
     return 0;
 }
 
@@ -994,7 +1072,7 @@ OscDataReceive_traverse(OscDataReceive *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 OscDataReceive_clear(OscDataReceive *self)
 {
     pyo_CLEAR
@@ -1009,7 +1087,7 @@ OscDataReceive_dealloc(OscDataReceive* self)
     lo_server_free(self->osc_server);
     pyo_DEALLOC
     OscDataReceive_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1019,47 +1097,49 @@ OscDataReceive_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *pathtmp, *calltmp;
     OscDataReceive *self;
     self = (OscDataReceive *)type->tp_alloc(type, 0);
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, OscDataReceive_compute_next_data_frame);
 
     static char *kwlist[] = {"port", "address", "callable", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "iOO", kwlist, &self->port, &pathtmp, &calltmp))
         Py_RETURN_NONE;
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     Py_XDECREF(self->callable);
     self->callable = calltmp;
-    
-    if (PyString_Check(pathtmp) || PyList_Check(pathtmp)) {
-        Py_INCREF(pathtmp);    
+
+    if (PyList_Check(pathtmp)) {
+        Py_INCREF(pathtmp);
         Py_XDECREF(self->address_path);
         self->address_path = pathtmp;
     }
     else {
-        PyErr_SetString(PyExc_TypeError, "The address attributes must be a string or a list of strings.");
+        PyErr_SetString(PyExc_TypeError, "The address attributes must be a list of strings and/or unicodes.");
         Py_RETURN_NONE;
-    }    
+    }
 
     char buf[20];
     sprintf(buf, "%i", self->port);
     self->osc_server = lo_server_new(buf, error);
-    
+
     lo_server_add_method(self->osc_server, NULL, NULL, OscDataReceive_handler, self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * OscDataReceive_getServer(OscDataReceive* self) { GET_SERVER };
 static PyObject * OscDataReceive_getStream(OscDataReceive* self) { GET_STREAM };
+static PyObject * OscDataReceive_play(OscDataReceive *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * OscDataReceive_stop(OscDataReceive *self) { STOP };
 
 static PyObject *
 OscDataReceive_addAddress(OscDataReceive *self, PyObject *arg) {
     int i;
     if (arg != NULL) {
-        if (PyString_Check(arg))
+        if (PY_STRING_CHECK(arg))
             PyList_Append(self->address_path, arg);
         else if (PyList_Check(arg)) {
             Py_ssize_t len = PyList_Size(arg);
@@ -1069,8 +1149,7 @@ OscDataReceive_addAddress(OscDataReceive *self, PyObject *arg) {
         }
     }
 
-    Py_INCREF(Py_None);
-    return Py_None;
+    Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -1081,8 +1160,7 @@ OscDataReceive_delAddress(OscDataReceive *self, PyObject *arg) {
         }
     }
 
-    Py_INCREF(Py_None);
-    return Py_None;
+    Py_RETURN_NONE;
 }
 
 static PyMemberDef OscDataReceive_members[] = {
@@ -1094,14 +1172,15 @@ static PyMemberDef OscDataReceive_members[] = {
 static PyMethodDef OscDataReceive_methods[] = {
     {"getServer", (PyCFunction)OscDataReceive_getServer, METH_NOARGS, "Returns server object."},
     {"_getStream", (PyCFunction)OscDataReceive_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)OscDataReceive_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+    {"stop", (PyCFunction)OscDataReceive_stop, METH_NOARGS, "Stops computing."},
     {"addAddress", (PyCFunction)OscDataReceive_addAddress, METH_O, "Add new paths to the object."},
     {"delAddress", (PyCFunction)OscDataReceive_delAddress, METH_O, "Remove path from the object."},
     {NULL}  /* Sentinel */
 };
 
 PyTypeObject OscDataReceiveType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.OscDataReceive_base",         /*tp_name*/
     sizeof(OscDataReceive),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -1109,7 +1188,7 @@ PyTypeObject OscDataReceiveType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     0,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -1163,11 +1242,11 @@ int OscListReceiver_handler(const char *path, const char *types, lo_arg **argv,
     for (i=0; i<self->num; i++) {
         PyList_SET_ITEM(flist, i, PyFloat_FromDouble(argv[i]->FLOAT_VALUE));
     }
-    PyDict_SetItem(self->dict, PyString_FromString(path), flist);
+    PyDict_SetItem(self->dict, PyUnicode_FromString(path), flist);
     return 0;
 }
 
-PyObject * 
+PyObject *
 OscListReceiver_getValue(OscListReceiver *self, PyObject *path)
 {
     PyObject *tmp;
@@ -1190,7 +1269,7 @@ OscListReceiver_traverse(OscListReceiver *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 OscListReceiver_clear(OscListReceiver *self)
 {
     pyo_CLEAR
@@ -1205,7 +1284,7 @@ OscListReceiver_dealloc(OscListReceiver* self)
     lo_server_free(self->osc_server);
     pyo_DEALLOC
     OscListReceiver_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1215,55 +1294,47 @@ OscListReceiver_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *pathtmp, *flist;
     OscListReceiver *self;
     self = (OscListReceiver *)type->tp_alloc(type, 0);
-    
+
     self->num = 8;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, OscListReceiver_compute_next_data_frame);
+    Stream_setStreamActive(self->stream, 1);
 
     static char *kwlist[] = {"port", "address", "num", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "iO|i", kwlist, &self->port, &pathtmp, &self->num))
         Py_RETURN_NONE;
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     self->dict = PyDict_New();
-    
-    if (PyString_Check(pathtmp) || PyList_Check(pathtmp)) {
-        Py_INCREF(pathtmp);    
+
+    if (PyList_Check(pathtmp)) {
+        Py_INCREF(pathtmp);
         Py_XDECREF(self->address_path);
         self->address_path = pathtmp;
     }
     else {
-        PyErr_SetString(PyExc_TypeError, "The address attributes must be a string or a list of strings.");
+        PyErr_SetString(PyExc_TypeError, "The address attributes must be a list of strings and/or unicodes.");
         Py_RETURN_NONE;
-    }    
+    }
 
-    if (PyString_Check(self->address_path)) {
+    int lsize = PyList_Size(self->address_path);
+    for (i=0; i<lsize; i++) {
         flist = PyList_New(self->num);
         for (j=0; j<self->num; j++) {
             PyList_SET_ITEM(flist, j, PyFloat_FromDouble(0.));
         }
-        PyDict_SetItem(self->dict, self->address_path, flist);
-    }    
-    else if (PyList_Check(self->address_path)) {
-        int lsize = PyList_Size(self->address_path);
-        for (i=0; i<lsize; i++) {
-            flist = PyList_New(self->num);
-            for (j=0; j<self->num; j++) {
-                PyList_SET_ITEM(flist, j, PyFloat_FromDouble(0.));
-            }
-            PyDict_SetItem(self->dict, PyList_GET_ITEM(self->address_path, i), flist);
-        }    
+        PyDict_SetItem(self->dict, PyList_GET_ITEM(self->address_path, i), flist);
     }
-    
+
     char buf[20];
     sprintf(buf, "%i", self->port);
     self->osc_server = lo_server_new(buf, error);
-    
+
     lo_server_add_method(self->osc_server, NULL, NULL, OscListReceiver_handler, self);
-    
+
     return (PyObject *)self;
 }
 
@@ -1273,13 +1344,13 @@ OscListReceiver_addAddress(OscListReceiver *self, PyObject *arg)
     PyObject *flist;
     int i, j;
 
-    if (PyString_Check(arg)) {
+    if (PY_STRING_CHECK(arg)) {
         flist = PyList_New(self->num);
         for (j=0; j<self->num; j++) {
             PyList_SET_ITEM(flist, j, PyFloat_FromDouble(0.));
         }
         PyDict_SetItem(self->dict, arg, flist);
-    }    
+    }
     else if (PyList_Check(arg)) {
         Py_ssize_t lsize = PyList_Size(arg);
         for (i=0; i<lsize; i++) {
@@ -1288,27 +1359,26 @@ OscListReceiver_addAddress(OscListReceiver *self, PyObject *arg)
                 PyList_SET_ITEM(flist, j, PyFloat_FromDouble(0.));
             }
             PyDict_SetItem(self->dict, PyList_GET_ITEM(arg, i), flist);
-        }    
-    } 
-	Py_INCREF(Py_None);
-	return Py_None;
+        }
+    }
+	Py_RETURN_NONE;
 }
 
 static PyObject *
 OscListReceiver_delAddress(OscListReceiver *self, PyObject *arg)
 {
     int i;
-    if (PyString_Check(arg)) {
+    if (PY_STRING_CHECK(arg)) {
         PyDict_DelItem(self->dict, arg);
-    }    
+    }
     else if (PyList_Check(arg)) {
         Py_ssize_t lsize = PyList_Size(arg);
         for (i=0; i<lsize; i++) {
-            PyDict_DelItem(self->dict, PyList_GET_ITEM(arg, i));
-        }    
-    } 
-	Py_INCREF(Py_None);
-	return Py_None;
+            if (PyDict_Contains(self->dict, PyList_GET_ITEM(arg, i)))
+                PyDict_DelItem(self->dict, PyList_GET_ITEM(arg, i));
+        }
+    }
+	Py_RETURN_NONE;
 }
 
 static PyObject *
@@ -1317,10 +1387,10 @@ OscListReceiver_setValue(OscListReceiver *self, PyObject *args, PyObject *kwds)
     PyObject *address, *value;
 
     static char *kwlist[] = {"address", "value", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &address, &value))
         Py_RETURN_NONE;
-    
+
     PyDict_SetItem(self->dict, address, value);
     Py_RETURN_NONE;
 }
@@ -1344,8 +1414,7 @@ static PyMethodDef OscListReceiver_methods[] = {
 };
 
 PyTypeObject OscListReceiverType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.OscListReceiver_base",         /*tp_name*/
     sizeof(OscListReceiver),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -1353,7 +1422,7 @@ PyTypeObject OscListReceiverType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     0,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -1412,33 +1481,33 @@ OscListReceive_setProcMode(OscListReceive *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = OscListReceive_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = OscListReceive_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = OscListReceive_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = OscListReceive_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = OscListReceive_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = OscListReceive_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = OscListReceive_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = OscListReceive_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = OscListReceive_postprocessing_revareva;
             break;
     }
@@ -1452,17 +1521,17 @@ OscListReceive_compute_next_data_frame(OscListReceive *self)
     MYFLT val = PyFloat_AsDouble(PyList_GET_ITEM(flist, self->order));
 
     if (self->interpolation == 1) {
-        
+
         for (i=0; i<self->bufsize; i++) {
             self->data[i] = self->value = self->value + (val - self->value) * self->factor;
-        }  
+        }
     }
     else {
         for (i=0; i<self->bufsize; i++) {
             self->data[i] = self->value = val;
-        }  
+        }
     }
-    
+
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1475,7 +1544,7 @@ OscListReceive_traverse(OscListReceive *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 OscListReceive_clear(OscListReceive *self)
 {
     pyo_CLEAR
@@ -1489,7 +1558,7 @@ OscListReceive_dealloc(OscListReceive* self)
 {
     pyo_DEALLOC
     OscListReceive_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1499,73 +1568,69 @@ OscListReceive_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp=NULL, *pathtmp=NULL, *multmp=NULL, *addtmp=NULL;;
     OscListReceive *self;
     self = (OscListReceive *)type->tp_alloc(type, 0);
-    
+
     self->order = 0;
     self->value = 0.;
     self->interpolation = 1;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
-    
+
     self->factor = 1. / (0.01 * self->sr);
-    
+
     Stream_setFunctionPtr(self->stream, OscListReceive_compute_next_data_frame);
     self->mode_func_ptr = OscListReceive_setProcMode;
 
     static char *kwlist[] = {"input", "address", "order", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OOi|OO", kwlist, &inputtmp, &pathtmp, &self->order, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     Py_XDECREF(self->input);
     Py_INCREF(inputtmp);
     self->input = inputtmp;
-    
+
     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);
-    
-    if (! PyString_Check(pathtmp)) {
-        PyErr_SetString(PyExc_TypeError, "The address attributes must be a string.");
+
+    if (!PY_STRING_CHECK(pathtmp)) {
+        PyErr_SetString(PyExc_TypeError, "OscListReceive: the address attributes must be a string or a unicode.");
         Py_RETURN_NONE;
-    }    
-    
-    Py_INCREF(pathtmp);    
+    }
+
+    Py_INCREF(pathtmp);
     Py_XDECREF(self->address_path);
     self->address_path = pathtmp;
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject *
 OscListReceive_setInterpolation(OscListReceive *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
     self->interpolation = PyInt_AsLong(arg);
-    
-	Py_INCREF(Py_None);
-	return Py_None;
+
+	Py_RETURN_NONE;
 }
 
 static PyObject * OscListReceive_getServer(OscListReceive* self) { GET_SERVER };
 static PyObject * OscListReceive_getStream(OscListReceive* self) { GET_STREAM };
-static PyObject * OscListReceive_setMul(OscListReceive *self, PyObject *arg) { SET_MUL };	
-static PyObject * OscListReceive_setAdd(OscListReceive *self, PyObject *arg) { SET_ADD };	
-static PyObject * OscListReceive_setSub(OscListReceive *self, PyObject *arg) { SET_SUB };	
-static PyObject * OscListReceive_setDiv(OscListReceive *self, PyObject *arg) { SET_DIV };	
+static PyObject * OscListReceive_setMul(OscListReceive *self, PyObject *arg) { SET_MUL };
+static PyObject * OscListReceive_setAdd(OscListReceive *self, PyObject *arg) { SET_ADD };
+static PyObject * OscListReceive_setSub(OscListReceive *self, PyObject *arg) { SET_SUB };
+static PyObject * OscListReceive_setDiv(OscListReceive *self, PyObject *arg) { SET_DIV };
 
 static PyObject * OscListReceive_play(OscListReceive *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * OscListReceive_stop(OscListReceive *self) { STOP };
@@ -1604,7 +1669,7 @@ static PyNumberMethods OscListReceive_as_number = {
     (binaryfunc)OscListReceive_add,                      /*nb_add*/
     (binaryfunc)OscListReceive_sub,                 /*nb_subtract*/
     (binaryfunc)OscListReceive_multiply,                 /*nb_multiply*/
-    (binaryfunc)OscListReceive_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -1618,16 +1683,16 @@ static PyNumberMethods OscListReceive_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)OscListReceive_inplace_add,              /*inplace_add*/
     (binaryfunc)OscListReceive_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)OscListReceive_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)OscListReceive_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -1636,15 +1701,14 @@ static PyNumberMethods OscListReceive_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)OscListReceive_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)OscListReceive_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject OscListReceiveType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.OscListReceive_base",         /*tp_name*/
     sizeof(OscListReceive),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -1652,7 +1716,7 @@ PyTypeObject OscListReceiveType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &OscListReceive_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -1682,4 +1746,4 @@ PyTypeObject OscListReceiveType = {
     0,      /* tp_init */
     0,                         /* tp_alloc */
     OscListReceive_new,                 /* tp_new */
-};
+};
\ No newline at end of file
diff --git a/src/objects/panmodule.c b/src/objects/panmodule.c
index 7cdc876..2880276 100644
--- a/src/objects/panmodule.c
+++ b/src/objects/panmodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
@@ -53,10 +54,10 @@ static void
 Panner_splitter_thru(Panner *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->buffer_streams[i] = in[i];
-    }    
+    }
 }
 
 static void
@@ -64,17 +65,17 @@ Panner_splitter_st_i(Panner *self) {
     MYFLT val, inval;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     MYFLT pan = PyFloat_AS_DOUBLE(self->pan);
     pan = P_clip(pan);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inval = in[i];
         val = inval * MYSQRT(1.0 - pan);
         self->buffer_streams[i] = val;
         val = inval * MYSQRT(pan);
         self->buffer_streams[i+self->bufsize] = val;
-    }    
+    }
 }
 
 static void
@@ -82,9 +83,9 @@ Panner_splitter_st_a(Panner *self) {
     MYFLT val, inval, panval;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     MYFLT *pan = Stream_getData((Stream *)self->pan_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inval = in[i];
         panval = P_clip(pan[i]);
@@ -92,7 +93,7 @@ Panner_splitter_st_a(Panner *self) {
         self->buffer_streams[i] = val;
         val = inval * MYSQRT(panval);
         self->buffer_streams[i+self->bufsize] = val;
-    }    
+    }
 }
 
 static void
@@ -103,10 +104,10 @@ Panner_splitter_ii(Panner *self) {
 
     MYFLT pan = PyFloat_AS_DOUBLE(self->pan);
     MYFLT spd = PyFloat_AS_DOUBLE(self->spread);
-    
+
     pan = P_clip(pan);
     spd = P_clip(spd);
-    
+
     sprd = 20.0 - (MYSQRT(spd) * 20.0) + 0.1;
 
     for (i=0; i<self->bufsize; i++) {
@@ -116,7 +117,7 @@ Panner_splitter_ii(Panner *self) {
             val = inval * MYPOW(MYCOS((pan - phase) * TWOPI) * 0.5 + 0.5, sprd);
             self->buffer_streams[i+j*self->bufsize] = val;
         }
-    }    
+    }
 }
 
 static void
@@ -124,14 +125,14 @@ Panner_splitter_ai(Panner *self) {
     MYFLT val, inval, phase, sprd;
     int j, i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     MYFLT *pan = Stream_getData((Stream *)self->pan_stream);
     MYFLT spd = PyFloat_AS_DOUBLE(self->spread);
 
     spd = P_clip(spd);
-    
+
     sprd = 20.0 - (MYSQRT(spd) * 20.0) + 0.1;
-    
+
     for (i=0; i<self->bufsize; i++) {
         inval = in[i];
         for (j=0; j<self->chnls; j++) {
@@ -139,7 +140,7 @@ Panner_splitter_ai(Panner *self) {
             val = inval * MYPOW(MYCOS((P_clip(pan[i]) - phase) * TWOPI) * 0.5 + 0.5, sprd);
             self->buffer_streams[i+j*self->bufsize] = val;
         }
-    }    
+    }
 }
 
 static void
@@ -147,12 +148,12 @@ Panner_splitter_ia(Panner *self) {
     MYFLT val, inval, phase, spdval, sprd;
     int j, i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     MYFLT pan = PyFloat_AS_DOUBLE(self->pan);
     MYFLT *spd = Stream_getData((Stream *)self->spread_stream);
 
     pan = P_clip(pan);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inval = in[i];
         spdval = P_clip(spd[i]);
@@ -162,7 +163,7 @@ Panner_splitter_ia(Panner *self) {
             val = inval * MYPOW(MYCOS((pan - phase) * TWOPI) * 0.5 + 0.5, sprd);
             self->buffer_streams[i+j*self->bufsize] = val;
         }
-    }    
+    }
 }
 
 static void
@@ -170,11 +171,11 @@ Panner_splitter_aa(Panner *self) {
     MYFLT val, inval, phase, spdval, sprd;
     int j, i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     MYFLT *pan = Stream_getData((Stream *)self->pan_stream);
     MYFLT *spd = Stream_getData((Stream *)self->spread_stream);
-    
-    
+
+
     for (i=0; i<self->bufsize; i++) {
         inval = in[i];
         spdval = P_clip(spd[i]);
@@ -184,56 +185,56 @@ Panner_splitter_aa(Panner *self) {
             val = inval * MYPOW(MYCOS((P_clip(pan[i]) - phase) * TWOPI) * 0.5 + 0.5, sprd);
             self->buffer_streams[i+j*self->bufsize] = val;
         }
-    }    
+    }
 }
 
 MYFLT *
 Panner_getSamplesBuffer(Panner *self)
 {
     return (MYFLT *)self->buffer_streams;
-}    
+}
 
 static void
 Panner_setProcMode(Panner *self)
-{        
+{
     int procmode;
     procmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
     if (self->chnls > 2) {
         switch (procmode) {
-            case 0:        
+            case 0:
                 self->proc_func_ptr = Panner_splitter_ii;
                 break;
-            case 1:    
+            case 1:
                 self->proc_func_ptr = Panner_splitter_ai;
                 break;
-            case 10:    
+            case 10:
                 self->proc_func_ptr = Panner_splitter_ia;
                 break;
-            case 11:    
+            case 11:
                 self->proc_func_ptr = Panner_splitter_aa;
                 break;
-        }         
-    } 
+        }
+    }
     else if (self->chnls == 2) {
         switch (self->modebuffer[0]) {
-            case 0:        
+            case 0:
                 self->proc_func_ptr = Panner_splitter_st_i;
                 break;
-            case 1:    
+            case 1:
                 self->proc_func_ptr = Panner_splitter_st_a;
                 break;
-        }         
-    }         
+        }
+    }
     else if (self->chnls == 1) {
         self->proc_func_ptr = Panner_splitter_thru;
-    }         
+    }
 }
 
 static void
 Panner_compute_next_data_frame(Panner *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -249,7 +250,7 @@ Panner_traverse(Panner *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Panner_clear(Panner *self)
 {
     pyo_CLEAR
@@ -268,7 +269,7 @@ Panner_dealloc(Panner* self)
     pyo_DEALLOC
     free(self->buffer_streams);
     Panner_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -278,7 +279,7 @@ Panner_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *pantmp=NULL, *spreadtmp=NULL;
     Panner *self;
     self = (Panner *)type->tp_alloc(type, 0);
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Panner_compute_next_data_frame);
     self->mode_func_ptr = Panner_setProcMode;
@@ -326,14 +327,11 @@ static PyObject *
 Panner_setPan(Panner *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->pan);
@@ -349,25 +347,22 @@ Panner_setPan(Panner *self, PyObject *arg)
         self->pan_stream = (Stream *)streamtmp;
 		self->modebuffer[0] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Panner_setSpread(Panner *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->spread);
@@ -383,12 +378,12 @@ Panner_setSpread(Panner *self, PyObject *arg)
         self->spread_stream = (Stream *)streamtmp;
 		self->modebuffer[1] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Panner_members[] = {
 {"server", T_OBJECT_EX, offsetof(Panner, server), 0, "Pyo server."},
@@ -410,8 +405,7 @@ static PyMethodDef Panner_methods[] = {
 };
 
 PyTypeObject PannerType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Panner_base",                                   /*tp_name*/
 sizeof(Panner),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -419,7 +413,7 @@ sizeof(Panner),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 0,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -476,33 +470,33 @@ Pan_setProcMode(Pan *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Pan_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Pan_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Pan_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Pan_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Pan_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Pan_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Pan_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Pan_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Pan_postprocessing_revareva;
             break;
     }
@@ -517,7 +511,7 @@ Pan_compute_next_data_frame(Pan *self)
     tmp = Panner_getSamplesBuffer((Panner *)self->mainSplitter);
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = tmp[i + offset];
-    }    
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -529,11 +523,11 @@ Pan_traverse(Pan *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Pan_clear(Pan *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->mainSplitter);    
+    Py_CLEAR(self->mainSplitter);
     return 0;
 }
 
@@ -542,7 +536,7 @@ Pan_dealloc(Pan* self)
 {
     pyo_DEALLOC
     Pan_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -552,44 +546,44 @@ Pan_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL;
     Pan *self;
     self = (Pan *)type->tp_alloc(type, 0);
-    
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Pan_compute_next_data_frame);
     self->mode_func_ptr = Pan_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 = (Panner *)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 * Pan_getServer(Pan* self) { GET_SERVER };
 static PyObject * Pan_getStream(Pan* self) { GET_STREAM };
-static PyObject * Pan_setMul(Pan *self, PyObject *arg) { SET_MUL };	
-static PyObject * Pan_setAdd(Pan *self, PyObject *arg) { SET_ADD };	
-static PyObject * Pan_setSub(Pan *self, PyObject *arg) { SET_SUB };	
-static PyObject * Pan_setDiv(Pan *self, PyObject *arg) { SET_DIV };	
+static PyObject * Pan_setMul(Pan *self, PyObject *arg) { SET_MUL };
+static PyObject * Pan_setAdd(Pan *self, PyObject *arg) { SET_ADD };
+static PyObject * Pan_setSub(Pan *self, PyObject *arg) { SET_SUB };
+static PyObject * Pan_setDiv(Pan *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Pan_play(Pan *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Pan_out(Pan *self, PyObject *args, PyObject *kwds) { OUT };
@@ -629,7 +623,7 @@ static PyNumberMethods Pan_as_number = {
 (binaryfunc)Pan_add,                      /*nb_add*/
 (binaryfunc)Pan_sub,                 /*nb_subtract*/
 (binaryfunc)Pan_multiply,                 /*nb_multiply*/
-(binaryfunc)Pan_div,                   /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -643,16 +637,16 @@ static PyNumberMethods Pan_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
 (binaryfunc)Pan_inplace_add,              /*inplace_add*/
 (binaryfunc)Pan_inplace_sub,         /*inplace_subtract*/
 (binaryfunc)Pan_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)Pan_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -661,15 +655,14 @@ static PyNumberMethods Pan_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)Pan_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)Pan_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
 PyTypeObject PanType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Pan_base",         /*tp_name*/
 sizeof(Pan),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -677,7 +670,7 @@ sizeof(Pan),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &Pan_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -729,10 +722,10 @@ static void
 SPanner_splitter_thru(SPanner *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->buffer_streams[i] = in[i];
-    }    
+    }
 }
 
 static void
@@ -740,17 +733,17 @@ SPanner_splitter_st_i(SPanner *self) {
     MYFLT val, inval;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     MYFLT pan = PyFloat_AS_DOUBLE(self->pan);
     pan = P_clip(pan);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inval = in[i];
         val = inval * MYSQRT(1.0 - pan);
         self->buffer_streams[i] = val;
         val = inval * MYSQRT(pan);
         self->buffer_streams[i+self->bufsize] = val;
-    }    
+    }
 }
 
 static void
@@ -758,9 +751,9 @@ SPanner_splitter_st_a(SPanner *self) {
     MYFLT val, inval, panval;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     MYFLT *pan = Stream_getData((Stream *)self->pan_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inval = in[i];
         panval = P_clip(pan[i]);
@@ -768,7 +761,7 @@ SPanner_splitter_st_a(SPanner *self) {
         self->buffer_streams[i] = val;
         val = inval * MYSQRT(panval);
         self->buffer_streams[i+self->bufsize] = val;
-    }    
+    }
 }
 
 static void
@@ -783,7 +776,7 @@ SPanner_splitter_i(SPanner *self) {
         self->buffer_streams[i+self->k1] = 0.0;
         self->buffer_streams[i+self->k2] = 0.0;
     }
-    
+
     min = 0;
     self->k1 = 0;
     self->k2 = self->bufsize;
@@ -799,7 +792,7 @@ SPanner_splitter_i(SPanner *self) {
                 self->k2 = j * self->bufsize;
             break;
         }
-    }    
+    }
 
     pan = P_clip((pan - min) * self->chnls);
     pan1 = MYSQRT(1.0 - pan);
@@ -810,7 +803,7 @@ SPanner_splitter_i(SPanner *self) {
         self->buffer_streams[i+self->k1] = val;
         val = inval * pan2;
         self->buffer_streams[i+self->k2] = val;
-    }    
+    }
 }
 
 static void
@@ -820,19 +813,19 @@ SPanner_splitter_a(SPanner *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *apan = Stream_getData((Stream *)self->pan_stream);
     MYFLT fchnls = (MYFLT)self->chnls;
-    
+
     len = self->chnls * self->bufsize;
     for (i=0; i<len; i++) {
         self->buffer_streams[i] = 0.0;
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         pan = apan[i];
         inval = in[i];
         min = 0;
         self->k1 = 0;
         self->k2 = self->bufsize;
-        
+
         for (j=self->chnls; j>0; j--) {
             j1 = j - 1;
             min = j1 / fchnls;
@@ -840,61 +833,61 @@ SPanner_splitter_a(SPanner *self) {
                 self->k1 = j1 * self->bufsize;
                 if (j == self->chnls)
                     self->k2 = 0;
-                else                    
+                else
                     self->k2 = j * self->bufsize;
                 break;
             }
-        }    
-        
+        }
+
         pan = P_clip((pan - min) * self->chnls);
         val = inval * MYSQRT(1.0 - pan);
         self->buffer_streams[i+self->k1] = val;
         val = inval * MYSQRT(pan);
         self->buffer_streams[i+self->k2] = val;
-    }    
+    }
 }
 
 MYFLT *
 SPanner_getSamplesBuffer(SPanner *self)
 {
     return (MYFLT *)self->buffer_streams;
-}    
+}
 
 static void
 SPanner_setProcMode(SPanner *self)
-{        
+{
     int procmode;
     procmode = self->modebuffer[0];
-    
+
     if (self->chnls > 2) {
         switch (procmode) {
-            case 0:        
+            case 0:
                 self->proc_func_ptr = SPanner_splitter_i;
                 break;
-            case 1:    
+            case 1:
                 self->proc_func_ptr = SPanner_splitter_a;
                 break;
-        }         
-    } 
+        }
+    }
     else if (self->chnls == 2) {
         switch (self->modebuffer[0]) {
-            case 0:        
+            case 0:
                 self->proc_func_ptr = SPanner_splitter_st_i;
                 break;
-            case 1:    
+            case 1:
                 self->proc_func_ptr = SPanner_splitter_st_a;
                 break;
-        }         
-    }         
+        }
+    }
     else if (self->chnls == 1) {
             self->proc_func_ptr = SPanner_splitter_thru;
-    }         
+    }
 }
 
 static void
 SPanner_compute_next_data_frame(SPanner *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -908,7 +901,7 @@ SPanner_traverse(SPanner *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 SPanner_clear(SPanner *self)
 {
     pyo_CLEAR
@@ -925,7 +918,7 @@ SPanner_dealloc(SPanner* self)
     pyo_DEALLOC
     free(self->buffer_streams);
     SPanner_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -935,11 +928,11 @@ SPanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *pantmp=NULL;
     SPanner *self;
     self = (SPanner *)type->tp_alloc(type, 0);
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, SPanner_compute_next_data_frame);
     self->mode_func_ptr = SPanner_setProcMode;
-    
+
     self->pan = PyFloat_FromDouble(0.5);
     self->chnls = 2;
     self->k1 = 0;
@@ -947,12 +940,12 @@ SPanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->modebuffer[0] = 0;
 
     static char *kwlist[] = {"input", "outs", "pan", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iO", kwlist, &inputtmp, &self->chnls, &pantmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (pantmp) {
         PyObject_CallMethod((PyObject *)self, "setPan", "O", pantmp);
     }
@@ -961,16 +954,16 @@ SPanner_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
     if (self->chnls < 1)
         self->chnls = 1;
-    
+
     self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, self->chnls * self->bufsize * sizeof(MYFLT));
-    
+
     (*self->mode_func_ptr)(self);
 
     int len = self->chnls*self->bufsize;
     for (i=0; i<len; i++) {
         self->buffer_streams[i] = 0.0;
     }
-    
+
     return (PyObject *)self;
 }
 
@@ -984,14 +977,11 @@ static PyObject *
 SPanner_setPan(SPanner *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->pan);
@@ -1007,12 +997,12 @@ SPanner_setPan(SPanner *self, PyObject *arg)
         self->pan_stream = (Stream *)streamtmp;
 		self->modebuffer[0] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef SPanner_members[] = {
 {"server", T_OBJECT_EX, offsetof(SPanner, server), 0, "Pyo server."},
@@ -1032,8 +1022,7 @@ static PyMethodDef SPanner_methods[] = {
 };
 
 PyTypeObject SPannerType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.SPanner_base",                                   /*tp_name*/
 sizeof(SPanner),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -1041,7 +1030,7 @@ sizeof(SPanner),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 0,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -1098,33 +1087,33 @@ SPan_setProcMode(SPan *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = SPan_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = SPan_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = SPan_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = SPan_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = SPan_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = SPan_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = SPan_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = SPan_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = SPan_postprocessing_revareva;
             break;
     }
@@ -1139,7 +1128,7 @@ SPan_compute_next_data_frame(SPan *self)
     tmp = SPanner_getSamplesBuffer((SPanner *)self->mainSplitter);
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = tmp[i + offset];
-    }    
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1151,11 +1140,11 @@ SPan_traverse(SPan *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 SPan_clear(SPan *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->mainSplitter);    
+    Py_CLEAR(self->mainSplitter);
     return 0;
 }
 
@@ -1164,7 +1153,7 @@ SPan_dealloc(SPan* self)
 {
     pyo_DEALLOC
     SPan_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1174,44 +1163,44 @@ SPan_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL;
     SPan *self;
     self = (SPan *)type->tp_alloc(type, 0);
-    
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, SPan_compute_next_data_frame);
     self->mode_func_ptr = SPan_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 = (SPanner *)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 * SPan_getServer(SPan* self) { GET_SERVER };
 static PyObject * SPan_getStream(SPan* self) { GET_STREAM };
-static PyObject * SPan_setMul(SPan *self, PyObject *arg) { SET_MUL };	
-static PyObject * SPan_setAdd(SPan *self, PyObject *arg) { SET_ADD };	
-static PyObject * SPan_setSub(SPan *self, PyObject *arg) { SET_SUB };	
-static PyObject * SPan_setDiv(SPan *self, PyObject *arg) { SET_DIV };	
+static PyObject * SPan_setMul(SPan *self, PyObject *arg) { SET_MUL };
+static PyObject * SPan_setAdd(SPan *self, PyObject *arg) { SET_ADD };
+static PyObject * SPan_setSub(SPan *self, PyObject *arg) { SET_SUB };
+static PyObject * SPan_setDiv(SPan *self, PyObject *arg) { SET_DIV };
 
 static PyObject * SPan_play(SPan *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * SPan_out(SPan *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1251,7 +1240,7 @@ static PyNumberMethods SPan_as_number = {
 (binaryfunc)SPan_add,                      /*nb_add*/
 (binaryfunc)SPan_sub,                 /*nb_subtract*/
 (binaryfunc)SPan_multiply,                 /*nb_multiply*/
-(binaryfunc)SPan_div,                   /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -1265,16 +1254,16 @@ static PyNumberMethods SPan_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
 (binaryfunc)SPan_inplace_add,              /*inplace_add*/
 (binaryfunc)SPan_inplace_sub,         /*inplace_subtract*/
 (binaryfunc)SPan_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)SPan_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -1283,15 +1272,14 @@ static PyNumberMethods SPan_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)SPan_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)SPan_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
 PyTypeObject SPanType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.SPan_base",         /*tp_name*/
 sizeof(SPan),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -1299,7 +1287,7 @@ sizeof(SPan),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &SPan_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -1354,7 +1342,7 @@ Switcher_clip_voice(Switcher *self, MYFLT v) {
         return 0.0;
     else if (v > chnls)
         return chnls;
-    else 
+    else
         return v;
 }
 
@@ -1364,7 +1352,7 @@ Switcher_splitter_i(Switcher *self) {
     int j1, j, i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT voice = Switcher_clip_voice(self, PyFloat_AS_DOUBLE(self->voice));
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->buffer_streams[i+self->k1] = 0.0;
         self->buffer_streams[i+self->k2] = 0.0;
@@ -1375,7 +1363,7 @@ Switcher_splitter_i(Switcher *self) {
     if (j1 >= (self->chnls-1)) {
         j1--; j--;
     }
-    
+
     self->k1 = j1 * self->bufsize;
     self->k2 = j * self->bufsize;
 
@@ -1389,7 +1377,7 @@ Switcher_splitter_i(Switcher *self) {
         self->buffer_streams[i+self->k1] = val;
         val = inval * voice2;
         self->buffer_streams[i+self->k2] = val;
-    }    
+    }
 }
 
 static void
@@ -1398,12 +1386,12 @@ Switcher_splitter_a(Switcher *self) {
     int i, j, j1, len;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *avoice = Stream_getData((Stream *)self->voice_stream);
-    
+
     len = self->chnls * self->bufsize;
     for (i=0; i<len; i++) {
         self->buffer_streams[i] = 0.0;
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         voice = Switcher_clip_voice(self, avoice[i]);
         inval = in[i];
@@ -1413,31 +1401,31 @@ Switcher_splitter_a(Switcher *self) {
         if (j1 >= (self->chnls-1)) {
             j1--; j--;
         }
-        
+
         self->k1 = j1 * self->bufsize;
         self->k2 = j * self->bufsize;
-        
+
         voice = P_clip(voice - j1);
-        
+
         self->buffer_streams[i+self->k1] = inval * MYSQRT(1.0 - voice);
         self->buffer_streams[i+self->k2] = inval * MYSQRT(voice);
-    }    
+    }
 }
 
 MYFLT *
 Switcher_getSamplesBuffer(Switcher *self)
 {
     return (MYFLT *)self->buffer_streams;
-}    
+}
 
 static void
 Switcher_setProcMode(Switcher *self)
-{   
+{
     switch (self->modebuffer[0]) {
-        case 0:        
+        case 0:
             self->proc_func_ptr = Switcher_splitter_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Switcher_splitter_a;
             break;
     }
@@ -1446,7 +1434,7 @@ Switcher_setProcMode(Switcher *self)
 static void
 Switcher_compute_next_data_frame(Switcher *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -1460,7 +1448,7 @@ Switcher_traverse(Switcher *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Switcher_clear(Switcher *self)
 {
     pyo_CLEAR
@@ -1477,7 +1465,7 @@ Switcher_dealloc(Switcher* self)
     pyo_DEALLOC
     free(self->buffer_streams);
     Switcher_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1487,11 +1475,11 @@ Switcher_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *voicetmp=NULL;
     Switcher *self;
     self = (Switcher *)type->tp_alloc(type, 0);
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Switcher_compute_next_data_frame);
     self->mode_func_ptr = Switcher_setProcMode;
-    
+
     self->voice = PyFloat_FromDouble(0.0);
     self->chnls = 2;
     self->k1 = 0;
@@ -1499,27 +1487,27 @@ Switcher_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->modebuffer[0] = 0;
 
     static char *kwlist[] = {"input", "outs", "voice", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iO", kwlist, &inputtmp, &self->chnls, &voicetmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (voicetmp) {
         PyObject_CallMethod((PyObject *)self, "setVoice", "O", voicetmp);
     }
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, self->chnls * self->bufsize * sizeof(MYFLT));
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     int len = self->chnls*self->bufsize;
     for (i=0; i<len; i++) {
         self->buffer_streams[i] = 0.0;
     }
-    
+
     return (PyObject *)self;
 }
 
@@ -1533,14 +1521,11 @@ static PyObject *
 Switcher_setVoice(Switcher *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->voice);
@@ -1556,12 +1541,12 @@ Switcher_setVoice(Switcher *self, PyObject *arg)
         self->voice_stream = (Stream *)streamtmp;
 		self->modebuffer[0] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Switcher_members[] = {
     {"server", T_OBJECT_EX, offsetof(Switcher, server), 0, "Pyo server."},
@@ -1581,8 +1566,7 @@ static PyMethodDef Switcher_methods[] = {
 };
 
 PyTypeObject SwitcherType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Switcher_base",                                   /*tp_name*/
     sizeof(Switcher),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -1590,7 +1574,7 @@ PyTypeObject SwitcherType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     0,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -1647,33 +1631,33 @@ Switch_setProcMode(Switch *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Switch_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Switch_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Switch_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Switch_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Switch_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Switch_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Switch_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Switch_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Switch_postprocessing_revareva;
             break;
     }
@@ -1688,7 +1672,7 @@ Switch_compute_next_data_frame(Switch *self)
     tmp = Switcher_getSamplesBuffer((Switcher *)self->mainSplitter);
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = tmp[i + offset];
-    }    
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1700,11 +1684,11 @@ Switch_traverse(Switch *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Switch_clear(Switch *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->mainSplitter);    
+    Py_CLEAR(self->mainSplitter);
     return 0;
 }
 
@@ -1713,7 +1697,7 @@ Switch_dealloc(Switch* self)
 {
     pyo_DEALLOC
     Switch_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1723,44 +1707,44 @@ Switch_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL;
     Switch *self;
     self = (Switch *)type->tp_alloc(type, 0);
-    
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Switch_compute_next_data_frame);
     self->mode_func_ptr = Switch_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 = (Switcher *)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 * Switch_getServer(Switch* self) { GET_SERVER };
 static PyObject * Switch_getStream(Switch* self) { GET_STREAM };
-static PyObject * Switch_setMul(Switch *self, PyObject *arg) { SET_MUL };	
-static PyObject * Switch_setAdd(Switch *self, PyObject *arg) { SET_ADD };	
-static PyObject * Switch_setSub(Switch *self, PyObject *arg) { SET_SUB };	
-static PyObject * Switch_setDiv(Switch *self, PyObject *arg) { SET_DIV };	
+static PyObject * Switch_setMul(Switch *self, PyObject *arg) { SET_MUL };
+static PyObject * Switch_setAdd(Switch *self, PyObject *arg) { SET_ADD };
+static PyObject * Switch_setSub(Switch *self, PyObject *arg) { SET_SUB };
+static PyObject * Switch_setDiv(Switch *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Switch_play(Switch *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Switch_out(Switch *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1800,7 +1784,7 @@ static PyNumberMethods Switch_as_number = {
     (binaryfunc)Switch_add,                      /*nb_add*/
     (binaryfunc)Switch_sub,                 /*nb_subtract*/
     (binaryfunc)Switch_multiply,                 /*nb_multiply*/
-    (binaryfunc)Switch_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -1814,16 +1798,16 @@ static PyNumberMethods Switch_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)Switch_inplace_add,              /*inplace_add*/
     (binaryfunc)Switch_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)Switch_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)Switch_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -1832,15 +1816,14 @@ static PyNumberMethods Switch_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)Switch_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)Switch_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject SwitchType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Switch_base",         /*tp_name*/
     sizeof(Switch),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -1848,7 +1831,7 @@ PyTypeObject SwitchType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &Switch_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -1890,7 +1873,7 @@ typedef struct {
     Stream **trigger_streams;
     int maxVoices;
     int *voices;
-    int modebuffer[2]; // need at least 2 slots for mul & add 
+    int modebuffer[2]; // need at least 2 slots for mul & add
 } VoiceManager;
 
 static void
@@ -1902,7 +1885,7 @@ VoiceManager_generate(VoiceManager *self) {
     for (i=0; i<self->bufsize; i++)
         self->data[i] = -1.0;
 
-    if (self->maxVoices > 0) {    
+    if (self->maxVoices > 0) {
         for (i=0; i<self->bufsize; i++) {
             for (j=0; j<self->maxVoices; j++) {
                 if (Stream_getData(self->trigger_streams[j])[i] == 1.0)
@@ -1936,64 +1919,70 @@ VoiceManager_setProcMode(VoiceManager *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = VoiceManager_generate;
-	
+
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = VoiceManager_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = VoiceManager_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = VoiceManager_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = VoiceManager_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = VoiceManager_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = VoiceManager_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = VoiceManager_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = VoiceManager_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = VoiceManager_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 VoiceManager_compute_next_data_frame(VoiceManager *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
 static int
 VoiceManager_traverse(VoiceManager *self, visitproc visit, void *arg)
 {
+    int i;
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->trigger_streams);
+    for (i=0; i<self->maxVoices; i++) {
+        Py_VISIT(self->trigger_streams[i]);
+    }
     return 0;
 }
 
-static int 
+static int
 VoiceManager_clear(VoiceManager *self)
 {
+    int i;
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->trigger_streams);
+    for (i=0; i<self->maxVoices; i++) {
+        Py_CLEAR(self->trigger_streams[i]);
+    }
     return 0;
 }
 
@@ -2001,10 +1990,12 @@ static void
 VoiceManager_dealloc(VoiceManager* self)
 {
     pyo_DEALLOC
-    if (self->voices != NULL)
+    if (self->voices != NULL) {
         free(self->voices);
+        free(self->trigger_streams);
+    }
     VoiceManager_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2016,10 +2007,10 @@ VoiceManager_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self = (VoiceManager *)type->tp_alloc(type, 0);
 
     self->voices = NULL;
-    self->maxVoices = 0; 
+    self->maxVoices = 0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
- 
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, VoiceManager_compute_next_data_frame);
     self->mode_func_ptr = VoiceManager_setProcMode;
@@ -2028,21 +2019,21 @@ VoiceManager_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &triggerstmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-   
+
     INIT_INPUT_STREAM
-    
+
     if (triggerstmp && triggerstmp != Py_None) {
         PyObject_CallMethod((PyObject *)self, "setTriggers", "O", triggerstmp);
     }
-    
+
     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);
@@ -2052,10 +2043,10 @@ VoiceManager_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * VoiceManager_getServer(VoiceManager* self) { GET_SERVER };
 static PyObject * VoiceManager_getStream(VoiceManager* self) { GET_STREAM };
-static PyObject * VoiceManager_setMul(VoiceManager *self, PyObject *arg) { SET_MUL };	
-static PyObject * VoiceManager_setAdd(VoiceManager *self, PyObject *arg) { SET_ADD };	
-static PyObject * VoiceManager_setSub(VoiceManager *self, PyObject *arg) { SET_SUB };	
-static PyObject * VoiceManager_setDiv(VoiceManager *self, PyObject *arg) { SET_DIV };	
+static PyObject * VoiceManager_setMul(VoiceManager *self, PyObject *arg) { SET_MUL };
+static PyObject * VoiceManager_setAdd(VoiceManager *self, PyObject *arg) { SET_ADD };
+static PyObject * VoiceManager_setSub(VoiceManager *self, PyObject *arg) { SET_SUB };
+static PyObject * VoiceManager_setDiv(VoiceManager *self, PyObject *arg) { SET_DIV };
 
 static PyObject * VoiceManager_play(VoiceManager *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * VoiceManager_stop(VoiceManager *self) { STOP };
@@ -2073,13 +2064,13 @@ static PyObject *
 VoiceManager_setTriggers(VoiceManager *self, PyObject *arg)
 {
     int i;
-	
+
 	if (! PyList_Check(arg)) {
         PyErr_SetString(PyExc_TypeError, "The triggers attribute must be a list.");
 		Py_INCREF(Py_None);
 		return Py_None;
 	}
-    
+
     self->maxVoices = PyList_Size(arg);
     self->trigger_streams = (Stream **)realloc(self->trigger_streams, self->maxVoices * sizeof(Stream *));
     self->voices = (int *)realloc(self->voices, self->maxVoices * sizeof(int));
@@ -2089,7 +2080,7 @@ VoiceManager_setTriggers(VoiceManager *self, PyObject *arg)
     }
 
     Py_RETURN_NONE;
-}	
+}
 
 static PyMemberDef VoiceManager_members[] = {
 {"server", T_OBJECT_EX, offsetof(VoiceManager, server), 0, "Pyo server."},
@@ -2118,7 +2109,7 @@ static PyNumberMethods VoiceManager_as_number = {
 (binaryfunc)VoiceManager_add,                         /*nb_add*/
 (binaryfunc)VoiceManager_sub,                         /*nb_subtract*/
 (binaryfunc)VoiceManager_multiply,                    /*nb_multiply*/
-(binaryfunc)VoiceManager_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -2132,16 +2123,16 @@ static PyNumberMethods VoiceManager_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)VoiceManager_inplace_add,                 /*inplace_add*/
 (binaryfunc)VoiceManager_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)VoiceManager_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)VoiceManager_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -2150,15 +2141,14 @@ static PyNumberMethods VoiceManager_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)VoiceManager_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)VoiceManager_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject VoiceManagerType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.VoiceManager_base",                                   /*tp_name*/
 sizeof(VoiceManager),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -2166,7 +2156,7 @@ sizeof(VoiceManager),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &VoiceManager_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -2226,7 +2216,7 @@ Mixer_generate(Mixer *self) {
     for (i=0; i<(self->num_outs * self->bufsize); i++) {
         self->buffer_streams[i] = 0.0;
     }
-    
+
     keys = PyDict_Keys(self->inputs);
     num = PyList_Size(keys);
 
@@ -2248,7 +2238,7 @@ Mixer_generate(Mixer *self) {
                 tmpCount = 0;
                 tmpStepVal = (amp - currentAmp) / self->timeStep;
                 PyList_SetItem(list_of_last_gains, k, PyFloat_FromDouble(amp));
-            }    
+            }
             for (i=0; i<self->bufsize; i++) {
                 if (tmpCount == (self->timeStep - 1)) {
                     currentAmp = amp;
@@ -2257,7 +2247,7 @@ Mixer_generate(Mixer *self) {
                 else if (tmpCount < self->timeStep) {
                     currentAmp += tmpStepVal;
                     tmpCount++;
-                }    
+                }
                 self->buffer_streams[self->bufsize * k + i] += st[i] * currentAmp;
             }
             PyList_SetItem(list_of_current_gains, k, PyFloat_FromDouble(currentAmp));
@@ -2272,7 +2262,7 @@ MYFLT *
 Mixer_getSamplesBuffer(Mixer *self)
 {
     return (MYFLT *)self->buffer_streams;
-}    
+}
 
 static void
 Mixer_setProcMode(Mixer *self)
@@ -2283,7 +2273,7 @@ Mixer_setProcMode(Mixer *self)
 static void
 Mixer_compute_next_data_frame(Mixer *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -2299,7 +2289,7 @@ Mixer_traverse(Mixer *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Mixer_clear(Mixer *self)
 {
     pyo_CLEAR
@@ -2318,7 +2308,7 @@ Mixer_dealloc(Mixer* self)
     pyo_DEALLOC
     free(self->buffer_streams);
     Mixer_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2328,7 +2318,7 @@ Mixer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *timetmp=NULL;
     Mixer *self;
     self = (Mixer *)type->tp_alloc(type, 0);
-    
+
     self->inputs = PyDict_New();
     self->gains = PyDict_New();
     self->lastGains = PyDict_New();
@@ -2338,26 +2328,26 @@ Mixer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->num_outs = 2;
     self->time = 0.025;
     self->timeStep = (long)(self->time * self->sr);
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Mixer_compute_next_data_frame);
     self->mode_func_ptr = Mixer_setProcMode;
 
     static char *kwlist[] = {"outs", "time", NULL};
-        
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|iO", kwlist, &self->num_outs, &timetmp))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     if (timetmp) {
         PyObject_CallMethod((PyObject *)self, "setTime", "O", timetmp);
     }
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, self->num_outs * self->bufsize * sizeof(MYFLT));
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
@@ -2372,20 +2362,17 @@ Mixer_setTime(Mixer *self, PyObject *arg)
 {
     int i, j, num;
 	PyObject *tmp, *keys, *key, *list_of_time_counts;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	if (isNumber == 1) {
-		self->time = PyFloat_AS_DOUBLE(PyNumber_Float(tmp));
+		self->time = PyFloat_AsDouble(tmp);
         self->timeStep = (long)(self->time * self->sr);
-        
+
         keys = PyDict_Keys(self->inputs);
         num = PyList_Size(keys);
         if (num != 0) {
@@ -2394,14 +2381,14 @@ Mixer_setTime(Mixer *self, PyObject *arg)
                 list_of_time_counts = PyDict_GetItem(self->timeCounts, key);
                 for (i=0; i<self->num_outs; i++) {
                     PyList_SET_ITEM(list_of_time_counts, i, PyLong_FromLong(self->timeStep-1));
-                }    
+                }
             }
-        }    
+        }
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Mixer_addInput(Mixer *self, PyObject *args, PyObject *kwds)
@@ -2416,12 +2403,12 @@ Mixer_addInput(Mixer *self, PyObject *args, PyObject *kwds)
     PyObject *voice;
 
     static char *kwlist[] = {"voice", "input", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &voice, &tmp)) {
         Py_INCREF(Py_None);
         return Py_None;
     }
-    
+
     PyDict_SetItem(self->inputs, voice, tmp);
     initGains = PyList_New(self->num_outs);
     initLastGains = PyList_New(self->num_outs);
@@ -2440,16 +2427,16 @@ Mixer_addInput(Mixer *self, PyObject *args, PyObject *kwds)
     PyDict_SetItem(self->currentGains, voice, initCurrentGains);
     PyDict_SetItem(self->stepVals, voice, initStepVals);
     PyDict_SetItem(self->timeCounts, voice, initTimeCounts);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Mixer_delInput(Mixer *self, PyObject *arg)
 {
     int ret;
-    
+
     PyObject *key = arg;
     ret = PyDict_DelItem(self->inputs, key);
     if (ret == 0) {
@@ -2458,14 +2445,14 @@ Mixer_delInput(Mixer *self, PyObject *arg)
         PyDict_DelItem(self->currentGains, key);
         PyDict_DelItem(self->stepVals, key);
         PyDict_DelItem(self->timeCounts, key);
-    }    
+    }
     else {
         Py_INCREF(Py_None);
         return Py_None;
     }
 
 	Py_INCREF(Py_None);
-	return Py_None;        
+	return Py_None;
 }
 
 static PyObject *
@@ -2474,18 +2461,18 @@ Mixer_setAmp(Mixer *self, PyObject *args, PyObject *kwds)
     int tmpout;
     PyObject *tmpin, *amp;
     static char *kwlist[] = {"vin", "vout", "amp", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OiO", kwlist, &tmpin, &tmpout, &amp)) {
         Py_INCREF(Py_None);
         return Py_None;
     }
-    
+
     if (! PyNumber_Check(amp)) {
-        printf("Amplitude must be a number!n");
+        PySys_WriteStdout("Mixer: amp argument must be a number!n");
         Py_INCREF(Py_None);
-        return Py_None;        
+        return Py_None;
     }
-    
+
     Py_INCREF(amp);
     PyList_SET_ITEM(PyDict_GetItem(self->gains, tmpin), tmpout, PyNumber_Float(amp));
 
@@ -2514,8 +2501,7 @@ static PyMethodDef Mixer_methods[] = {
 };
 
 PyTypeObject MixerType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Mixer_base",                                   /*tp_name*/
     sizeof(Mixer),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -2523,7 +2509,7 @@ PyTypeObject MixerType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     0,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -2580,33 +2566,33 @@ MixerVoice_setProcMode(MixerVoice *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = MixerVoice_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = MixerVoice_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = MixerVoice_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = MixerVoice_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = MixerVoice_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = MixerVoice_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = MixerVoice_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = MixerVoice_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = MixerVoice_postprocessing_revareva;
             break;
     }
@@ -2621,7 +2607,7 @@ MixerVoice_compute_next_data_frame(MixerVoice *self)
     tmp = Mixer_getSamplesBuffer((Mixer *)self->mainMixer);
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = tmp[i + offset];
-    }    
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -2633,11 +2619,11 @@ MixerVoice_traverse(MixerVoice *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 MixerVoice_clear(MixerVoice *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->mainMixer);    
+    Py_CLEAR(self->mainMixer);
     return 0;
 }
 
@@ -2646,7 +2632,7 @@ MixerVoice_dealloc(MixerVoice* self)
 {
     pyo_DEALLOC
     MixerVoice_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2656,42 +2642,42 @@ MixerVoice_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL;
     MixerVoice *self;
     self = (MixerVoice *)type->tp_alloc(type, 0);
-    
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, MixerVoice_compute_next_data_frame);
     self->mode_func_ptr = MixerVoice_setProcMode;
 
     static char *kwlist[] = {"mainMixer", "chnl", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "Oi|OO", kwlist, &maintmp, &self->chnl, &multmp, &addtmp))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     Py_XDECREF(self->mainMixer);
     Py_INCREF(maintmp);
     self->mainMixer = (Mixer *)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);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * MixerVoice_getServer(MixerVoice* self) { GET_SERVER };
 static PyObject * MixerVoice_getStream(MixerVoice* self) { GET_STREAM };
-static PyObject * MixerVoice_setMul(MixerVoice *self, PyObject *arg) { SET_MUL };	
-static PyObject * MixerVoice_setAdd(MixerVoice *self, PyObject *arg) { SET_ADD };	
-static PyObject * MixerVoice_setSub(MixerVoice *self, PyObject *arg) { SET_SUB };	
-static PyObject * MixerVoice_setDiv(MixerVoice *self, PyObject *arg) { SET_DIV };	
+static PyObject * MixerVoice_setMul(MixerVoice *self, PyObject *arg) { SET_MUL };
+static PyObject * MixerVoice_setAdd(MixerVoice *self, PyObject *arg) { SET_ADD };
+static PyObject * MixerVoice_setSub(MixerVoice *self, PyObject *arg) { SET_SUB };
+static PyObject * MixerVoice_setDiv(MixerVoice *self, PyObject *arg) { SET_DIV };
 
 static PyObject * MixerVoice_play(MixerVoice *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * MixerVoice_out(MixerVoice *self, PyObject *args, PyObject *kwds) { OUT };
@@ -2731,7 +2717,7 @@ static PyNumberMethods MixerVoice_as_number = {
     (binaryfunc)MixerVoice_add,                      /*nb_add*/
     (binaryfunc)MixerVoice_sub,                 /*nb_subtract*/
     (binaryfunc)MixerVoice_multiply,                 /*nb_multiply*/
-    (binaryfunc)MixerVoice_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -2745,16 +2731,16 @@ static PyNumberMethods MixerVoice_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)MixerVoice_inplace_add,              /*inplace_add*/
     (binaryfunc)MixerVoice_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)MixerVoice_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)MixerVoice_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -2763,15 +2749,14 @@ static PyNumberMethods MixerVoice_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)MixerVoice_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)MixerVoice_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject MixerVoiceType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.MixerVoice_base",         /*tp_name*/
     sizeof(MixerVoice),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -2779,7 +2764,7 @@ PyTypeObject MixerVoiceType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &MixerVoice_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -2820,7 +2805,8 @@ typedef struct {
     PyObject *voice;
     Stream *voice_stream;
     int chSize;
-    int modebuffer[3]; // need at least 2 slots for mul & add 
+    int mode;
+    int modebuffer[3]; // need at least 2 slots for mul & add
 } Selector;
 
 static MYFLT
@@ -2830,7 +2816,7 @@ Selector_clip_voice(Selector *self, MYFLT v) {
         return 0.0;
     else if (v > chSize)
         return chSize;
-    else 
+    else
         return v;
 }
 
@@ -2852,27 +2838,48 @@ Selector_generate_i(Selector *self) {
     voice = P_clip(voice - j1);
     voice1 = MYSQRT(1.0 - voice);
     voice2 = MYSQRT(voice);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = st1[i] * voice1 + st2[i] * voice2;
     }
 }
 
 static void
+Selector_generate_lin_i(Selector *self) {
+    int j1, j, i;
+    MYFLT voice = Selector_clip_voice(self, PyFloat_AS_DOUBLE(self->voice));
+
+    j1 = (int)voice;
+    j = j1 + 1;
+    if (j1 >= (self->chSize-1)) {
+        j1--; j--;
+    }
+
+    MYFLT *st1 = Stream_getData((Stream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->inputs, j1), "_getStream", NULL));
+    MYFLT *st2 = Stream_getData((Stream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->inputs, j), "_getStream", NULL));
+
+    voice = P_clip(voice - j1);
+
+    for (i=0; i<self->bufsize; i++) {
+        self->data[i] = st1[i] * (1.0 - voice) + st2[i] * voice;
+    }
+}
+
+static void
 Selector_generate_a(Selector *self) {
     int old_j1, old_j, j1, j, i;
     MYFLT  voice;
     MYFLT *st1, *st2;
     MYFLT *vc = Stream_getData((Stream *)self->voice_stream);
 
-    old_j1 = 0; 
+    old_j1 = 0;
     old_j = 1;
     st1 = Stream_getData((Stream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->inputs, old_j1), "_getStream", NULL));
     st2 = Stream_getData((Stream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->inputs, old_j), "_getStream", NULL));
-    
+
     for (i=0; i<self->bufsize; i++) {
         voice = Selector_clip_voice(self, vc[i]);
-        
+
         j1 = (int)voice;
         j = j1 + 1;
         if (j1 >= (self->chSize-1)) {
@@ -2881,11 +2888,11 @@ Selector_generate_a(Selector *self) {
         if (j1 != old_j1) {
             st1 = Stream_getData((Stream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->inputs, j1), "_getStream", NULL));
             old_j1 = j1;
-        }    
+        }
         if (j != old_j) {
             st2 = Stream_getData((Stream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->inputs, j), "_getStream", NULL));
             old_j = j;
-        }    
+        }
 
         voice = P_clip(voice - j1);
 
@@ -2893,6 +2900,41 @@ Selector_generate_a(Selector *self) {
     }
 }
 
+static void
+Selector_generate_lin_a(Selector *self) {
+    int old_j1, old_j, j1, j, i;
+    MYFLT  voice;
+    MYFLT *st1, *st2;
+    MYFLT *vc = Stream_getData((Stream *)self->voice_stream);
+
+    old_j1 = 0;
+    old_j = 1;
+    st1 = Stream_getData((Stream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->inputs, old_j1), "_getStream", NULL));
+    st2 = Stream_getData((Stream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->inputs, old_j), "_getStream", NULL));
+
+    for (i=0; i<self->bufsize; i++) {
+        voice = Selector_clip_voice(self, vc[i]);
+
+        j1 = (int)voice;
+        j = j1 + 1;
+        if (j1 >= (self->chSize-1)) {
+            j1--; j--;
+        }
+        if (j1 != old_j1) {
+            st1 = Stream_getData((Stream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->inputs, j1), "_getStream", NULL));
+            old_j1 = j1;
+        }
+        if (j != old_j) {
+            st2 = Stream_getData((Stream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->inputs, j), "_getStream", NULL));
+            old_j = j;
+        }
+
+        voice = P_clip(voice - j1);
+
+        self->data[i] = st1[i] * (1.0 - voice) + st2[i] * voice;
+    }
+}
+
 static void Selector_postprocessing_ii(Selector *self) { POST_PROCESSING_II };
 static void Selector_postprocessing_ai(Selector *self) { POST_PROCESSING_AI };
 static void Selector_postprocessing_ia(Selector *self) { POST_PROCESSING_IA };
@@ -2909,50 +2951,56 @@ Selector_setProcMode(Selector *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2];
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
-            self->proc_func_ptr = Selector_generate_i;
+        case 0:
+            if (self->mode == 0)
+                self->proc_func_ptr = Selector_generate_i;
+            else
+                self->proc_func_ptr = Selector_generate_lin_i;
             break;
-        case 1:    
-            self->proc_func_ptr = Selector_generate_a;
+        case 1:
+            if (self->mode == 0)
+                self->proc_func_ptr = Selector_generate_a;
+            else
+                self->proc_func_ptr = Selector_generate_lin_a;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Selector_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Selector_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Selector_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Selector_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Selector_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Selector_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Selector_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Selector_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Selector_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 Selector_compute_next_data_frame(Selector *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -2966,7 +3014,7 @@ Selector_traverse(Selector *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Selector_clear(Selector *self)
 {
     pyo_CLEAR
@@ -2981,7 +3029,7 @@ Selector_dealloc(Selector* self)
 {
     pyo_DEALLOC
     Selector_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2991,39 +3039,40 @@ Selector_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputstmp=NULL, *voicetmp=NULL, *multmp=NULL, *addtmp=NULL;
     Selector *self;
     self = (Selector *)type->tp_alloc(type, 0);
-    
+
     self->voice = PyFloat_FromDouble(0.);
+    self->mode = 0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Selector_compute_next_data_frame);
     self->mode_func_ptr = Selector_setProcMode;
 
     static char *kwlist[] = {"inputs", "voice", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputstmp, &voicetmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     if (inputstmp) {
         PyObject_CallMethod((PyObject *)self, "setInputs", "O", inputstmp);
     }
-    
+
     if (voicetmp) {
         PyObject_CallMethod((PyObject *)self, "setVoice", "O", voicetmp);
     }
-    
+
     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;
@@ -3031,10 +3080,10 @@ Selector_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Selector_getServer(Selector* self) { GET_SERVER };
 static PyObject * Selector_getStream(Selector* self) { GET_STREAM };
-static PyObject * Selector_setMul(Selector *self, PyObject *arg) { SET_MUL };	
-static PyObject * Selector_setAdd(Selector *self, PyObject *arg) { SET_ADD };	
-static PyObject * Selector_setSub(Selector *self, PyObject *arg) { SET_SUB };	
-static PyObject * Selector_setDiv(Selector *self, PyObject *arg) { SET_DIV };	
+static PyObject * Selector_setMul(Selector *self, PyObject *arg) { SET_MUL };
+static PyObject * Selector_setAdd(Selector *self, PyObject *arg) { SET_ADD };
+static PyObject * Selector_setSub(Selector *self, PyObject *arg) { SET_SUB };
+static PyObject * Selector_setDiv(Selector *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Selector_play(Selector *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Selector_out(Selector *self, PyObject *args, PyObject *kwds) { OUT };
@@ -3053,13 +3102,13 @@ static PyObject *
 Selector_setInputs(Selector *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
+
 	if (! PyList_Check(arg)) {
         PyErr_SetString(PyExc_TypeError, "The inputs attribute must be a list.");
 		Py_INCREF(Py_None);
 		return Py_None;
 	}
-    
+
     tmp = arg;
     self->chSize = PyList_Size(tmp);
     Py_INCREF(tmp);
@@ -3068,20 +3117,17 @@ Selector_setInputs(Selector *self, PyObject *arg)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Selector_setVoice(Selector *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->voice);
@@ -3097,12 +3143,27 @@ Selector_setVoice(Selector *self, PyObject *arg)
         self->voice_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+Selector_setMode(Selector *self, PyObject *arg)
+{
+    ASSERT_ARG_NOT_NULL
+
+	if (PyInt_Check(arg) == 1) {
+		self->mode = PyLong_AsLong(arg);
+	}
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Selector_members[] = {
 {"server", T_OBJECT_EX, offsetof(Selector, server), 0, "Pyo server."},
@@ -3122,6 +3183,7 @@ static PyMethodDef Selector_methods[] = {
 {"stop", (PyCFunction)Selector_stop, METH_NOARGS, "Stops computing."},
 {"setInputs", (PyCFunction)Selector_setInputs, METH_O, "Sets list of input streams."},
 {"setVoice", (PyCFunction)Selector_setVoice, METH_O, "Sets voice position pointer."},
+{"setMode", (PyCFunction)Selector_setMode, METH_O, "Sets interpolation algorithm."},
 {"setMul", (PyCFunction)Selector_setMul, METH_O, "Sets mul factor."},
 {"setAdd", (PyCFunction)Selector_setAdd, METH_O, "Sets add factor."},
 {"setSub", (PyCFunction)Selector_setSub, METH_O, "Sets inverse add factor."},
@@ -3133,7 +3195,7 @@ static PyNumberMethods Selector_as_number = {
 (binaryfunc)Selector_add,                         /*nb_add*/
 (binaryfunc)Selector_sub,                         /*nb_subtract*/
 (binaryfunc)Selector_multiply,                    /*nb_multiply*/
-(binaryfunc)Selector_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -3147,16 +3209,16 @@ static PyNumberMethods Selector_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)Selector_inplace_add,                 /*inplace_add*/
 (binaryfunc)Selector_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)Selector_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)Selector_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -3165,15 +3227,14 @@ static PyNumberMethods Selector_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)Selector_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)Selector_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject SelectorType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Selector_base",                                   /*tp_name*/
 sizeof(Selector),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -3181,7 +3242,7 @@ sizeof(Selector),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &Selector_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -3213,4 +3274,3 @@ Selector_members,                                 /* tp_members */
 Selector_new,                                     /* tp_new */
 };
 
-
diff --git a/src/objects/patternmodule.c b/src/objects/patternmodule.c
index 9733bdd..88f2915 100644
--- a/src/objects/patternmodule.c
+++ b/src/objects/patternmodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include "pyomodule.h"
 #include "streammodule.h"
@@ -30,6 +31,7 @@ typedef struct {
     PyObject *callable;
     PyObject *time;
     Stream *time_stream;
+    PyObject *arg;
     int modebuffer[1];
     MYFLT sampleToSec;
     double currentTime;
@@ -38,63 +40,84 @@ typedef struct {
 
 static void
 Pattern_generate_i(Pattern *self) {
+    int i;
     MYFLT tm;
-    int i, flag;
-    PyObject *result;
-    
-    flag = 0;
+    PyObject *tuple, *result;
+
     tm = PyFloat_AS_DOUBLE(self->time);
 
+    if (self->init) {
+        self->init = 0;
+        self->currentTime = tm;
+    }
+
     for (i=0; i<self->bufsize; i++) {
         if (self->currentTime >= tm) {
-            flag = 1;
-            self->currentTime = 0.;
-        }    
-
+            self->currentTime = 0.0;
+            if (self->arg == Py_None) {
+                result = PyObject_Call((PyObject *)self->callable, PyTuple_New(0), NULL);
+                if (result == NULL) {
+                    PyErr_Print();
+                    return;
+                }
+            } else {
+                tuple = PyTuple_New(1);
+                PyTuple_SET_ITEM(tuple, 0, self->arg);
+                result = PyObject_Call((PyObject *)self->callable, tuple, NULL);
+                if (result == NULL) {
+                    PyErr_Print();
+                    return;
+                }
+            }
+        }
         self->currentTime += self->sampleToSec;
     }
-    if (flag == 1 || self->init == 1) {
-        self->init = 0;
-        result = PyObject_Call((PyObject *)self->callable, PyTuple_New(0), NULL);
-        if (result == NULL)
-            PyErr_Print();
-    }
 }
 
 static void
 Pattern_generate_a(Pattern *self) {
-    int i, flag;
-    PyObject *result;
-    
+    int i;
+    PyObject *tuple, *result;
+
     MYFLT *tm = Stream_getData((Stream *)self->time_stream);
-    
-    flag = 0;
+
+    if (self->init) {
+        self->init = 0;
+        self->currentTime = tm[0];
+    }
+
     for (i=0; i<self->bufsize; i++) {
         if (self->currentTime >= tm[i]) {
-            flag = 1;
-            self->currentTime = 0.;
-        }    
-        
+            self->currentTime = 0.0;
+            if (self->arg == Py_None) {
+                result = PyObject_Call((PyObject *)self->callable, PyTuple_New(0), NULL);
+                if (result == NULL) {
+                    PyErr_Print();
+                    return;
+                }
+            } else {
+                tuple = PyTuple_New(1);
+                PyTuple_SET_ITEM(tuple, 0, self->arg);
+                result = PyObject_Call((PyObject *)self->callable, tuple, NULL);
+                if (result == NULL) {
+                    PyErr_Print();
+                    return;
+                }
+            }
+        }
         self->currentTime += self->sampleToSec;
     }
-    if (flag == 1 || self->init == 1) {
-        self->init = 0;
-        result = PyObject_Call((PyObject *)self->callable, PyTuple_New(0), NULL);
-        if (result == NULL)
-            PyErr_Print();
-    }    
 }
 
-
 static void
 Pattern_setProcMode(Pattern *self)
 {
     int procmode = self->modebuffer[0];
     switch (procmode) {
-        case 0:        
+        case 0:
             self->proc_func_ptr = Pattern_generate_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Pattern_generate_a;
             break;
     }
@@ -103,7 +126,7 @@ Pattern_setProcMode(Pattern *self)
 static void
 Pattern_compute_next_data_frame(Pattern *self)
 {
-    (*self->proc_func_ptr)(self);     
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -111,18 +134,20 @@ Pattern_traverse(Pattern *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->callable);
-    Py_VISIT(self->time);    
-    Py_VISIT(self->time_stream);    
+    Py_VISIT(self->time);
+    Py_VISIT(self->time_stream);
+    Py_VISIT(self->arg);
     return 0;
 }
 
-static int 
+static int
 Pattern_clear(Pattern *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->callable);
-    Py_CLEAR(self->time);    
+    Py_CLEAR(self->time);
     Py_CLEAR(self->time_stream);
+    Py_CLEAR(self->arg);
     return 0;
 }
 
@@ -131,58 +156,68 @@ Pattern_dealloc(Pattern* self)
 {
     pyo_DEALLOC
     Pattern_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
 Pattern_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
-    PyObject *timetmp=NULL, *calltmp=NULL;
+    PyObject *timetmp=NULL, *calltmp=NULL, *argtmp=NULL;
     Pattern *self;
     self = (Pattern *)type->tp_alloc(type, 0);
-    
+
     self->time = PyFloat_FromDouble(1.);
 	self->modebuffer[0] = 0;
     self->init = 1;
+    self->arg = Py_None;
 
     INIT_OBJECT_COMMON
     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.;
 
-    static char *kwlist[] = {"callable", "time", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, &calltmp, &timetmp))
+    static char *kwlist[] = {"callable", "time", "arg", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &calltmp, &timetmp, &argtmp))
         Py_RETURN_NONE;
-   
+
     if (calltmp) {
         PyObject_CallMethod((PyObject *)self, "setFunction", "O", calltmp);
     }
-    
+
     if (timetmp) {
         PyObject_CallMethod((PyObject *)self, "setTime", "O", timetmp);
     }
-    
+
+    if (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);
 
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * Pattern_getServer(Pattern* self) { GET_SERVER };
 static PyObject * Pattern_getStream(Pattern* self) { GET_STREAM };
 
-static PyObject * 
-Pattern_play(Pattern *self, PyObject *args, PyObject *kwds) 
-{ 
+static PyObject *
+Pattern_play(Pattern *self, PyObject *args, PyObject *kwds)
+{
     self->init = 1;
-    PLAY 
+    PLAY
 };
 
 static PyObject * Pattern_stop(Pattern *self) { STOP };
@@ -191,34 +226,31 @@ static PyObject *
 Pattern_setFunction(Pattern *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
+
 	if (! PyCallable_Check(arg)) {
         PyErr_SetString(PyExc_TypeError, "The callable attribute must be a valid Python function.");
 		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;
-}	
+}
 
 static PyObject *
 Pattern_setTime(Pattern *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->time);
@@ -234,12 +266,26 @@ Pattern_setTime(Pattern *self, PyObject *arg)
         self->time_stream = (Stream *)streamtmp;
 		self->modebuffer[0] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
+
+static PyObject *
+Pattern_setArg(Pattern *self, PyObject *arg)
+{
+	PyObject *tmp;
+
+    tmp = arg;
+    Py_XDECREF(self->arg);
+    Py_INCREF(tmp);
+    self->arg = tmp;
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
 
 static PyMemberDef Pattern_members[] = {
 {"server", T_OBJECT_EX, offsetof(Pattern, server), 0, "Pyo server."},
@@ -255,12 +301,12 @@ static PyMethodDef Pattern_methods[] = {
 {"stop", (PyCFunction)Pattern_stop, METH_NOARGS, "Stops computing."},
 {"setTime", (PyCFunction)Pattern_setTime, METH_O, "Sets time factor."},
 {"setFunction", (PyCFunction)Pattern_setFunction, METH_O, "Sets the function to be called."},
+{"setArg", (PyCFunction)Pattern_setArg, METH_O, "Sets function's argument."},
 {NULL}  /* Sentinel */
 };
 
 PyTypeObject PatternType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Pattern_base",         /*tp_name*/
 sizeof(Pattern),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -268,7 +314,7 @@ sizeof(Pattern),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 0,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -315,16 +361,16 @@ typedef struct {
 static void
 Score_selector(Score *self) {
     int i, inval;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inval = (int)in[i];
         if (inval != self->last_value) {
             sprintf(self->curfname, "%s%i()\n", self->fname, inval);
             PyRun_SimpleString(self->curfname);
             self->last_value = inval;
-        }    
+        }
     }
 }
 
@@ -337,23 +383,23 @@ Score_setProcMode(Score *self)
 static void
 Score_compute_next_data_frame(Score *self)
 {
-    (*self->proc_func_ptr)(self);    
+    (*self->proc_func_ptr)(self);
 }
 
 static int
 Score_traverse(Score *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->input);    
-    Py_VISIT(self->input_stream);    
+    Py_VISIT(self->input);
+    Py_VISIT(self->input_stream);
     return 0;
 }
 
-static int 
+static int
 Score_clear(Score *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->input);    
+    Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
     return 0;
 }
@@ -363,7 +409,7 @@ Score_dealloc(Score* self)
 {
     pyo_DEALLOC
     Score_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -373,24 +419,24 @@ Score_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp;
     Score *self;
     self = (Score *)type->tp_alloc(type, 0);
-    
+
     self->last_value = -99;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Score_compute_next_data_frame);
     self->mode_func_ptr = Score_setProcMode;
 
     static char *kwlist[] = {"input", "fname", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|s", kwlist, &inputtmp, &self->fname))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-        
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
@@ -415,8 +461,7 @@ static PyMethodDef Score_methods[] = {
 };
 
 PyTypeObject ScoreType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Score_base",         /*tp_name*/
 sizeof(Score),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -424,7 +469,7 @@ sizeof(Score),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 0,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -481,10 +526,11 @@ CallAfter_generate(CallAfter *self) {
                 tuple = PyTuple_New(1);
                 PyTuple_SET_ITEM(tuple, 0, self->arg);
             }
-            result = PyObject_Call(self->callable, tuple, NULL);                
+            result = PyObject_Call(self->callable, tuple, NULL);
             if (result == NULL)
                 PyErr_Print();
-            PyObject_CallMethod((PyObject *)self, "stop", NULL);
+            if (self->stream != NULL)
+                PyObject_CallMethod((PyObject *)self, "stop", NULL);
             break;
         }
         self->currentTime += self->sampleToSec;
@@ -493,14 +539,14 @@ CallAfter_generate(CallAfter *self) {
 
 static void
 CallAfter_setProcMode(CallAfter *self)
-{        
+{
     self->proc_func_ptr = CallAfter_generate;
 }
 
 static void
 CallAfter_compute_next_data_frame(CallAfter *self)
 {
-    (*self->proc_func_ptr)(self);     
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -512,7 +558,7 @@ CallAfter_traverse(CallAfter *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 CallAfter_clear(CallAfter *self)
 {
     pyo_CLEAR
@@ -526,7 +572,7 @@ CallAfter_dealloc(CallAfter* self)
 {
     pyo_DEALLOC
     CallAfter_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -536,10 +582,10 @@ CallAfter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *calltmp=NULL, *argtmp=NULL;
     CallAfter *self;
     self = (CallAfter *)type->tp_alloc(type, 0);
-    
+
     self->time = 1.;
     self->arg = Py_None;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, CallAfter_compute_next_data_frame);
     self->mode_func_ptr = CallAfter_setProcMode;
@@ -548,10 +594,10 @@ CallAfter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->currentTime = 0.;
 
     static char *kwlist[] = {"callable", "time", "arg", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_FO, kwlist, &calltmp, &self->time, &argtmp))
         Py_RETURN_NONE;
-    
+
     if (! PyCallable_Check(calltmp))
         Py_RETURN_NONE;
 
@@ -560,22 +606,25 @@ CallAfter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         Py_INCREF(argtmp);
         self->arg = argtmp;
     }
-    
+
     Py_INCREF(calltmp);
     Py_XDECREF(self->callable);
     self->callable = calltmp;
 
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * CallAfter_getServer(CallAfter* self) { GET_SERVER };
 static PyObject * CallAfter_getStream(CallAfter* self) { GET_STREAM };
 
-static PyObject * CallAfter_play(CallAfter *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * CallAfter_play(CallAfter *self, PyObject *args, PyObject *kwds) { 
+    self->currentTime = 0.;
+    PLAY 
+};
 static PyObject * CallAfter_stop(CallAfter *self) { STOP };
 
 static PyMemberDef CallAfter_members[] = {
@@ -593,8 +642,7 @@ static PyMethodDef CallAfter_methods[] = {
 };
 
 PyTypeObject CallAfterType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.CallAfter_base",         /*tp_name*/
 sizeof(CallAfter),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -602,7 +650,7 @@ sizeof(CallAfter),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 0,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -632,4 +680,4 @@ CallAfter_members,             /* tp_members */
 0,      /* tp_init */
 0,                         /* tp_alloc */
 CallAfter_new,                 /* tp_new */
-};
+};
\ No newline at end of file
diff --git a/src/objects/phasevocmodule.c b/src/objects/phasevocmodule.c
index af5d3dc..73b9d58 100644
--- a/src/objects/phasevocmodule.c
+++ b/src/objects/phasevocmodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
@@ -30,7 +31,7 @@
 #include "fft.h"
 #include "wind.h"
 
-static int 
+static int
 isPowerOfTwo(int x) {
     return (x != 0) && ((x & (x - 1)) == 0);
 }
@@ -52,9 +53,9 @@ typedef struct {
     MYFLT scale;
     MYFLT *input_buffer;
     MYFLT *inframe;
-    MYFLT *outframe; 
-    MYFLT *real; 
-    MYFLT *imag; 
+    MYFLT *outframe;
+    MYFLT *real;
+    MYFLT *imag;
     MYFLT *lastPhase;
     MYFLT **twiddle;
     MYFLT *window;
@@ -77,20 +78,20 @@ PVAnal_realloc_memories(PVAnal *self) {
     n8 = self->size >> 3;
     self->input_buffer = (MYFLT *)realloc(self->input_buffer, self->size * sizeof(MYFLT));
     self->inframe = (MYFLT *)realloc(self->inframe, self->size * sizeof(MYFLT));
-    self->outframe = (MYFLT *)realloc(self->outframe, self->size * sizeof(MYFLT));    
+    self->outframe = (MYFLT *)realloc(self->outframe, self->size * sizeof(MYFLT));
     for (i=0; i<self->size; i++)
         self->input_buffer[i] = self->inframe[i] = self->outframe[i] = 0.0;
-    self->lastPhase = (MYFLT *)realloc(self->lastPhase, self->hsize * sizeof(MYFLT)); 
-    self->real = (MYFLT *)realloc(self->real, self->hsize * sizeof(MYFLT)); 
-    self->imag = (MYFLT *)realloc(self->imag, self->hsize * sizeof(MYFLT)); 
-    self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); 
+    self->lastPhase = (MYFLT *)realloc(self->lastPhase, self->hsize * sizeof(MYFLT));
+    self->real = (MYFLT *)realloc(self->real, self->hsize * sizeof(MYFLT));
+    self->imag = (MYFLT *)realloc(self->imag, self->hsize * sizeof(MYFLT));
+    self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *));
     self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *));
     for (i=0; i<self->olaps; i++) {
         self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         for (j=0; j<self->hsize; j++)
             self->magn[i][j] = self->freq[i][j] = 0.0;
-    } 
+    }
     for (i=0; i<self->hsize; i++)
         self->lastPhase[i] = self->real[i] = self->imag[i] = 0.0;
     self->twiddle = (MYFLT **)realloc(self->twiddle, 4 * sizeof(MYFLT *));
@@ -113,7 +114,7 @@ PVAnal_process(PVAnal *self) {
     int i, k, mod;
     MYFLT real, imag, mag, phase, tmp;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->input_buffer[self->incount] = in[i];
         self->count[i] = self->incount;
@@ -156,14 +157,14 @@ PVAnal_process(PVAnal *self) {
 
 static void
 PVAnal_setProcMode(PVAnal *self)
-{        
-    self->proc_func_ptr = PVAnal_process;  
+{
+    self->proc_func_ptr = PVAnal_process;
 }
 
 static void
 PVAnal_compute_next_data_frame(PVAnal *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -176,7 +177,7 @@ PVAnal_traverse(PVAnal *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 PVAnal_clear(PVAnal *self)
 {
     pyo_CLEAR
@@ -193,9 +194,9 @@ PVAnal_dealloc(PVAnal* self)
     pyo_DEALLOC
     free(self->input_buffer);
     free(self->inframe);
-    free(self->outframe); 
-    free(self->real); 
-    free(self->imag); 
+    free(self->outframe);
+    free(self->real);
+    free(self->imag);
     free(self->lastPhase);
     for(i=0; i<4; i++) {
         free(self->twiddle[i]);
@@ -210,7 +211,7 @@ PVAnal_dealloc(PVAnal* self)
     free(self->freq);
     free(self->count);
     PVAnal_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -229,12 +230,12 @@ PVAnal_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = PVAnal_setProcMode;
 
     static char *kwlist[] = {"input", "size", "olaps", "wintype", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iii", kwlist, &inputtmp, &self->size, &self->olaps, &self->wintype))
         Py_RETURN_NONE;
 
     INIT_INPUT_STREAM
- 
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL);
@@ -244,7 +245,7 @@ PVAnal_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         while (k < self->size)
             k *= 2;
         self->size = k;
-        printf("FFT size must be a power-of-2, using the next power-of-2 greater than size : %d\n", self->size);
+        PySys_WriteStdout("FFT size must be a power-of-2, using the next power-of-2 greater than size : %d\n", self->size);
     }
 
     self->count = (int *)realloc(self->count, self->bufsize * sizeof(int));
@@ -265,7 +266,7 @@ static PyObject * PVAnal_stop(PVAnal *self) { STOP };
 
 static PyObject *
 PVAnal_setSize(PVAnal *self, PyObject *arg)
-{    
+{
     int k;
     if (PyLong_Check(arg) || PyInt_Check(arg)) {
         self->size = PyInt_AsLong(arg);
@@ -274,18 +275,18 @@ PVAnal_setSize(PVAnal *self, PyObject *arg)
             while (k < self->size)
                 k *= 2;
             self->size = k;
-            printf("FFT size must be a power-of-2, using the next power-of-2 greater than size : %d\n", self->size);
+            PySys_WriteStdout("FFT size must be a power-of-2, using the next power-of-2 greater than size : %d\n", self->size);
         }
         PVAnal_realloc_memories(self);
-    }    
-    
+    }
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
 static PyObject *
 PVAnal_setOverlaps(PVAnal *self, PyObject *arg)
-{    
+{
     int k;
     if (PyLong_Check(arg) || PyInt_Check(arg)) {
         self->olaps = PyInt_AsLong(arg);
@@ -294,23 +295,23 @@ PVAnal_setOverlaps(PVAnal *self, PyObject *arg)
             while (k < self->olaps)
                 k *= 2;
             self->olaps = k;
-            printf("FFT overlaps must be a power-of-2, using the next power-of-2 greater than olaps : %d\n", self->olaps);
+            PySys_WriteStdout("FFT overlaps must be a power-of-2, using the next power-of-2 greater than olaps : %d\n", self->olaps);
         }
         PVAnal_realloc_memories(self);
-    }    
-    
+    }
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
 static PyObject *
 PVAnal_setWinType(PVAnal *self, PyObject *arg)
-{    
+{
     if (PyLong_Check(arg) || PyInt_Check(arg)) {
         self->wintype = PyInt_AsLong(arg);
         gen_window(self->window, self->size, self->wintype);
-    }    
-    
+    }
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -336,8 +337,7 @@ static PyMethodDef PVAnal_methods[] = {
 };
 
 PyTypeObject PVAnalType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.PVAnal_base",                                   /*tp_name*/
 sizeof(PVAnal),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -345,7 +345,7 @@ sizeof(PVAnal),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 0,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -398,9 +398,9 @@ typedef struct {
     MYFLT *output_buffer;
     MYFLT *outputAccum;
     MYFLT *inframe;
-    MYFLT *outframe; 
-    MYFLT *real; 
-    MYFLT *imag; 
+    MYFLT *outframe;
+    MYFLT *real;
+    MYFLT *imag;
     MYFLT *sumPhase;
     MYFLT **twiddle;
     MYFLT *window;
@@ -421,15 +421,15 @@ PVSynth_realloc_memories(PVSynth *self) {
     n8 = self->size >> 3;
     self->output_buffer = (MYFLT *)realloc(self->output_buffer, self->size * sizeof(MYFLT));
     self->inframe = (MYFLT *)realloc(self->inframe, self->size * sizeof(MYFLT));
-    self->outframe = (MYFLT *)realloc(self->outframe, self->size * sizeof(MYFLT));    
+    self->outframe = (MYFLT *)realloc(self->outframe, self->size * sizeof(MYFLT));
     for (i=0; i<self->size; i++)
         self->output_buffer[i] = self->inframe[i] = self->outframe[i] = 0.0;
-    self->sumPhase = (MYFLT *)realloc(self->sumPhase, self->hsize * sizeof(MYFLT)); 
-    self->real = (MYFLT *)realloc(self->real, self->hsize * sizeof(MYFLT)); 
-    self->imag = (MYFLT *)realloc(self->imag, self->hsize * sizeof(MYFLT)); 
+    self->sumPhase = (MYFLT *)realloc(self->sumPhase, self->hsize * sizeof(MYFLT));
+    self->real = (MYFLT *)realloc(self->real, self->hsize * sizeof(MYFLT));
+    self->imag = (MYFLT *)realloc(self->imag, self->hsize * sizeof(MYFLT));
     for (i=0; i<self->hsize; i++)
         self->sumPhase[i] = self->real[i] = self->imag[i] = 0.0;
-    self->outputAccum = (MYFLT *)realloc(self->outputAccum, (self->size+self->hopsize) * sizeof(MYFLT)); 
+    self->outputAccum = (MYFLT *)realloc(self->outputAccum, (self->size+self->hopsize) * sizeof(MYFLT));
     for (i=0; i<(self->size+self->hopsize); i++)
         self->outputAccum[i] = 0.0;
     self->twiddle = (MYFLT **)realloc(self->twiddle, 4 * sizeof(MYFLT *));
@@ -461,14 +461,14 @@ PVSynth_process(PVSynth *self) {
         if (count[i] >= (self->size-1)) {
             for (k=0; k<self->hsize; k++) {
                 mag = magn[self->overcount][k];
-                tmp = freq[self->overcount][k];                
+                tmp = freq[self->overcount][k];
                 tmp = (tmp - k * self->scale) * self->factor;
                 self->sumPhase[k] += tmp;
                 phase = self->sumPhase[k];
                 self->real[k] = mag * MYCOS(phase);
                 self->imag[k] = mag * MYSIN(phase);
             }
-            
+
             self->inframe[0] = self->real[0];
             self->inframe[self->hsize] = 0.0;
             for (k=1; k<self->hsize; k++) {
@@ -509,34 +509,34 @@ PVSynth_setProcMode(PVSynth *self)
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
-    self->proc_func_ptr = PVSynth_process;  
+    self->proc_func_ptr = PVSynth_process;
 
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = PVSynth_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = PVSynth_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = PVSynth_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = PVSynth_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = PVSynth_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = PVSynth_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = PVSynth_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = PVSynth_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = PVSynth_postprocessing_revareva;
             break;
     }
@@ -545,7 +545,7 @@ PVSynth_setProcMode(PVSynth *self)
 static void
 PVSynth_compute_next_data_frame(PVSynth *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -559,7 +559,7 @@ PVSynth_traverse(PVSynth *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 PVSynth_clear(PVSynth *self)
 {
     pyo_CLEAR
@@ -577,9 +577,9 @@ PVSynth_dealloc(PVSynth* self)
     free(self->output_buffer);
     free(self->outputAccum);
     free(self->inframe);
-    free(self->outframe); 
-    free(self->real); 
-    free(self->imag); 
+    free(self->outframe);
+    free(self->real);
+    free(self->imag);
     free(self->sumPhase);
     for(i=0; i<4; i++) {
         free(self->twiddle[i]);
@@ -587,7 +587,7 @@ PVSynth_dealloc(PVSynth* self)
     free(self->twiddle);
     free(self->window);
     PVSynth_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -607,16 +607,13 @@ PVSynth_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = PVSynth_setProcMode;
 
     static char *kwlist[] = {"input", "wintype", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOO", kwlist, &inputtmp, &self->wintype, &multmp, &addtmp))
         Py_RETURN_NONE;
 
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVSynth \"input\" argument must be a PyoPVObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVSynth must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
     Py_INCREF(inputtmp);
     Py_XDECREF(self->input);
@@ -628,11 +625,11 @@ PVSynth_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
     self->size = PVStream_getFFTsize(self->input_stream);
     self->olaps = PVStream_getOlaps(self->input_stream);
- 
+
     if (multmp) {
         PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
     }
-    
+
     if (addtmp) {
         PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
     }
@@ -653,9 +650,8 @@ PVSynth_setInput(PVSynth *self, PyObject *arg)
 
     inputtmp = arg;
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVSynth \"input\" argument must be a PyoPVObject.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVSynth must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
 
     Py_INCREF(inputtmp);
@@ -665,19 +661,19 @@ PVSynth_setInput(PVSynth *self, PyObject *arg)
     Py_INCREF(input_streamtmp);
     Py_XDECREF(self->input_stream);
     self->input_stream = (PVStream *)input_streamtmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 PVSynth_setWinType(PVSynth *self, PyObject *arg)
-{    
+{
     if (PyLong_Check(arg) || PyInt_Check(arg)) {
         self->wintype = PyInt_AsLong(arg);
         gen_window(self->window, self->size, self->wintype);
-    }    
-    
+    }
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -685,10 +681,10 @@ PVSynth_setWinType(PVSynth *self, PyObject *arg)
 static PyObject * PVSynth_getServer(PVSynth* self) { GET_SERVER };
 static PyObject * PVSynth_getStream(PVSynth* self) { GET_STREAM };
 //static PyObject * PVSynth_getPVStream(PVSynth* self) { GET_PV_STREAM };
-static PyObject * PVSynth_setMul(PVSynth *self, PyObject *arg) { SET_MUL };	
-static PyObject * PVSynth_setAdd(PVSynth *self, PyObject *arg) { SET_ADD };	
-static PyObject * PVSynth_setSub(PVSynth *self, PyObject *arg) { SET_SUB };	
-static PyObject * PVSynth_setDiv(PVSynth *self, PyObject *arg) { SET_DIV };	
+static PyObject * PVSynth_setMul(PVSynth *self, PyObject *arg) { SET_MUL };
+static PyObject * PVSynth_setAdd(PVSynth *self, PyObject *arg) { SET_ADD };
+static PyObject * PVSynth_setSub(PVSynth *self, PyObject *arg) { SET_SUB };
+static PyObject * PVSynth_setDiv(PVSynth *self, PyObject *arg) { SET_DIV };
 
 static PyObject * PVSynth_play(PVSynth *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * PVSynth_out(PVSynth *self, PyObject *args, PyObject *kwds) { OUT };
@@ -733,7 +729,7 @@ static PyNumberMethods PVSynth_as_number = {
 (binaryfunc)PVSynth_add,                         /*nb_add*/
 (binaryfunc)PVSynth_sub,                         /*nb_subtract*/
 (binaryfunc)PVSynth_multiply,                    /*nb_multiply*/
-(binaryfunc)PVSynth_div,                         /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO  /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -747,16 +743,16 @@ static PyNumberMethods PVSynth_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)PVSynth_inplace_add,                 /*inplace_add*/
 (binaryfunc)PVSynth_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)PVSynth_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)PVSynth_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -765,15 +761,14 @@ static PyNumberMethods PVSynth_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)PVSynth_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)PVSynth_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject PVSynthType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.PVSynth_base",                                   /*tp_name*/
 sizeof(PVSynth),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -781,7 +776,7 @@ sizeof(PVSynth),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &PVSynth_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -978,41 +973,41 @@ PVAddSynth_setProcMode(PVAddSynth *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2];
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = PVAddSynth_process_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = PVAddSynth_process_a;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = PVAddSynth_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = PVAddSynth_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = PVAddSynth_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = PVAddSynth_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = PVAddSynth_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = PVAddSynth_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = PVAddSynth_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = PVAddSynth_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = PVAddSynth_postprocessing_revareva;
             break;
     }
@@ -1021,7 +1016,7 @@ PVAddSynth_setProcMode(PVAddSynth *self)
 static void
 PVAddSynth_compute_next_data_frame(PVAddSynth *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1036,7 +1031,7 @@ PVAddSynth_traverse(PVAddSynth *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 PVAddSynth_clear(PVAddSynth *self)
 {
     pyo_CLEAR
@@ -1057,7 +1052,7 @@ PVAddSynth_dealloc(PVAddSynth* self)
     free(self->amp);
     free(self->freq);
     PVAddSynth_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1082,16 +1077,13 @@ PVAddSynth_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = PVAddSynth_setProcMode;
 
     static char *kwlist[] = {"input", "pitch", "num", "first", "inc", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OiiiOO", kwlist, &inputtmp, &pitchtmp, &self->num, &self->first, &self->inc, &multmp, &addtmp))
         Py_RETURN_NONE;
 
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVAddSynth \"input\" argument must be a PyoPVObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVAddSynth must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
     Py_INCREF(inputtmp);
     Py_XDECREF(self->input);
@@ -1107,11 +1099,11 @@ PVAddSynth_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (pitchtmp) {
         PyObject_CallMethod((PyObject *)self, "setPitch", "O", pitchtmp);
     }
- 
+
     if (multmp) {
         PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
     }
-    
+
     if (addtmp) {
         PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
     }
@@ -1122,7 +1114,7 @@ PVAddSynth_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     for (i=0; i<8192; i++)
         self->table[i] = (MYFLT)(MYSIN(TWOPI * i / 8192.0));
     self->table[8192] = 0.0;
-    
+
     PVAddSynth_realloc_memories(self);
 
     (*self->mode_func_ptr)(self);
@@ -1137,9 +1129,8 @@ PVAddSynth_setInput(PVAddSynth *self, PyObject *arg)
 
     inputtmp = arg;
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVAddSynth \"input\" argument must be a PyoPVObject.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVAddSynth must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
 
     Py_INCREF(inputtmp);
@@ -1149,23 +1140,20 @@ PVAddSynth_setInput(PVAddSynth *self, PyObject *arg)
     Py_INCREF(input_streamtmp);
     Py_XDECREF(self->input_stream);
     self->input_stream = (PVStream *)input_streamtmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 PVAddSynth_setPitch(PVAddSynth *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->pitch);
@@ -1181,16 +1169,16 @@ PVAddSynth_setPitch(PVAddSynth *self, PyObject *arg)
         self->pitch_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
 
 static PyObject *
 PVAddSynth_setNum(PVAddSynth *self, PyObject *arg)
-{    
+{
     if (PyLong_Check(arg) || PyInt_Check(arg)) {
         self->num = PyInt_AsLong(arg);
         if (self->num < 1)
@@ -1198,15 +1186,15 @@ PVAddSynth_setNum(PVAddSynth *self, PyObject *arg)
         else if (self->num > self->hsize)
             self->num = self->hsize;
         self->update = 1;
-    }    
-    
+    }
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
 static PyObject *
 PVAddSynth_setFirst(PVAddSynth *self, PyObject *arg)
-{    
+{
     if (PyLong_Check(arg) || PyInt_Check(arg)) {
         self->first = PyInt_AsLong(arg);
         if (self->first < 0)
@@ -1214,15 +1202,15 @@ PVAddSynth_setFirst(PVAddSynth *self, PyObject *arg)
         else if (self->first > self->hsize)
             self->first = self->hsize;
         self->update = 1;
-    }    
-    
+    }
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
 static PyObject *
 PVAddSynth_setInc(PVAddSynth *self, PyObject *arg)
-{    
+{
     if (PyLong_Check(arg) || PyInt_Check(arg)) {
         self->inc = PyInt_AsLong(arg);
         if (self->inc < 1)
@@ -1230,18 +1218,18 @@ PVAddSynth_setInc(PVAddSynth *self, PyObject *arg)
         else if (self->inc > self->hsize)
             self->inc = self->hsize;
         self->update = 1;
-    }    
-    
+    }
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
 static PyObject * PVAddSynth_getServer(PVAddSynth* self) { GET_SERVER };
 static PyObject * PVAddSynth_getStream(PVAddSynth* self) { GET_STREAM };
-static PyObject * PVAddSynth_setMul(PVAddSynth *self, PyObject *arg) { SET_MUL };	
-static PyObject * PVAddSynth_setAdd(PVAddSynth *self, PyObject *arg) { SET_ADD };	
-static PyObject * PVAddSynth_setSub(PVAddSynth *self, PyObject *arg) { SET_SUB };	
-static PyObject * PVAddSynth_setDiv(PVAddSynth *self, PyObject *arg) { SET_DIV };	
+static PyObject * PVAddSynth_setMul(PVAddSynth *self, PyObject *arg) { SET_MUL };
+static PyObject * PVAddSynth_setAdd(PVAddSynth *self, PyObject *arg) { SET_ADD };
+static PyObject * PVAddSynth_setSub(PVAddSynth *self, PyObject *arg) { SET_SUB };
+static PyObject * PVAddSynth_setDiv(PVAddSynth *self, PyObject *arg) { SET_DIV };
 
 static PyObject * PVAddSynth_play(PVAddSynth *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * PVAddSynth_out(PVAddSynth *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1288,7 +1276,7 @@ static PyNumberMethods PVAddSynth_as_number = {
 (binaryfunc)PVAddSynth_add,                         /*nb_add*/
 (binaryfunc)PVAddSynth_sub,                         /*nb_subtract*/
 (binaryfunc)PVAddSynth_multiply,                    /*nb_multiply*/
-(binaryfunc)PVAddSynth_div,                         /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO  /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -1302,16 +1290,16 @@ static PyNumberMethods PVAddSynth_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)PVAddSynth_inplace_add,                 /*inplace_add*/
 (binaryfunc)PVAddSynth_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)PVAddSynth_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)PVAddSynth_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -1320,15 +1308,14 @@ static PyNumberMethods PVAddSynth_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)PVAddSynth_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)PVAddSynth_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject PVAddSynthType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.PVAddSynth_base",                                   /*tp_name*/
 sizeof(PVAddSynth),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -1336,7 +1323,7 @@ sizeof(PVAddSynth),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &PVAddSynth_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -1396,14 +1383,14 @@ PVTranspose_realloc_memories(PVTranspose *self) {
     self->hopsize = self->size / self->olaps;
     inputLatency = self->size - self->hopsize;
     self->overcount = 0;
-    self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); 
+    self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *));
     self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *));
     for (i=0; i<self->olaps; i++) {
         self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         for (j=0; j<self->hsize; j++)
             self->magn[i][j] = self->freq[i][j] = 0.0;
-    } 
+    }
     for (i=0; i<self->bufsize; i++)
         self->count[i] = inputLatency;
     PVStream_setFFTsize(self->pv_stream, self->size);
@@ -1492,24 +1479,24 @@ PVTranspose_process_a(PVTranspose *self) {
 
 static void
 PVTranspose_setProcMode(PVTranspose *self)
-{        
+{
     int procmode;
     procmode = self->modebuffer[0];
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = PVTranspose_process_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = PVTranspose_process_a;
             break;
-    } 
+    }
 }
 
 static void
 PVTranspose_compute_next_data_frame(PVTranspose *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -1519,20 +1506,20 @@ PVTranspose_traverse(PVTranspose *self, visitproc visit, void *arg)
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
     Py_VISIT(self->pv_stream);
-    Py_VISIT(self->transpo);    
-    Py_VISIT(self->transpo_stream);    
+    Py_VISIT(self->transpo);
+    Py_VISIT(self->transpo_stream);
     return 0;
 }
 
-static int 
+static int
 PVTranspose_clear(PVTranspose *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
     Py_CLEAR(self->pv_stream);
-    Py_CLEAR(self->transpo);    
-    Py_CLEAR(self->transpo_stream);    
+    Py_CLEAR(self->transpo);
+    Py_CLEAR(self->transpo_stream);
     return 0;
 }
 
@@ -1549,7 +1536,7 @@ PVTranspose_dealloc(PVTranspose* self)
     free(self->freq);
     free(self->count);
     PVTranspose_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1568,16 +1555,13 @@ PVTranspose_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = PVTranspose_setProcMode;
 
     static char *kwlist[] = {"input", "transpo", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, &inputtmp, &transpotmp))
         Py_RETURN_NONE;
 
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVTranspose \"input\" argument must be a PyoPVObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVTranspose must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
     Py_INCREF(inputtmp);
     Py_XDECREF(self->input);
@@ -1593,7 +1577,7 @@ PVTranspose_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (transpotmp) {
         PyObject_CallMethod((PyObject *)self, "setTranspo", "O", transpotmp);
     }
- 
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL);
@@ -1621,9 +1605,8 @@ PVTranspose_setInput(PVTranspose *self, PyObject *arg)
 
     inputtmp = arg;
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVTranspose \"input\" argument must be a PyoPVObject.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVTranspose must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
 
     Py_INCREF(inputtmp);
@@ -1633,23 +1616,20 @@ PVTranspose_setInput(PVTranspose *self, PyObject *arg)
     Py_INCREF(input_streamtmp);
     Py_XDECREF(self->input_stream);
     self->input_stream = (PVStream *)input_streamtmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 PVTranspose_setTranspo(PVTranspose *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->transpo);
@@ -1665,9 +1645,9 @@ PVTranspose_setTranspo(PVTranspose *self, PyObject *arg)
         self->transpo_stream = (Stream *)streamtmp;
 		self->modebuffer[0] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -1693,8 +1673,7 @@ static PyMethodDef PVTranspose_methods[] = {
 };
 
 PyTypeObject PVTransposeType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.PVTranspose_base",                                   /*tp_name*/
 sizeof(PVTranspose),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -1702,7 +1681,7 @@ sizeof(PVTranspose),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 0,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -1752,6 +1731,7 @@ typedef struct {
     int hopsize;
     int overcount;
     MYFLT *l_magn;
+    MYFLT *l_freq;
     MYFLT **magn;
     MYFLT **freq;
     int *count;
@@ -1765,9 +1745,10 @@ PVVerb_realloc_memories(PVVerb *self) {
     self->hopsize = self->size / self->olaps;
     inputLatency = self->size - self->hopsize;
     self->overcount = 0;
-    self->l_magn = (MYFLT *)realloc(self->l_magn, self->hsize * sizeof(MYFLT)); 
+    self->l_magn = (MYFLT *)realloc(self->l_magn, self->hsize * sizeof(MYFLT));
+    self->l_freq = (MYFLT *)realloc(self->l_freq, self->hsize * sizeof(MYFLT));
     for (i=0; i<self->hsize; i++)
-        self->l_magn[i] = 0.0;
+        self->l_magn[i] = self->l_freq[i] = 0.0;
     self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *));
     self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *));
     for (i=0; i<self->olaps; i++) {
@@ -1775,7 +1756,7 @@ PVVerb_realloc_memories(PVVerb *self) {
         self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         for (j=0; j<self->hsize; j++)
             self->magn[i][j] = self->freq[i][j] = 0.0;
-    } 
+    }
     for (i=0; i<self->bufsize; i++)
         self->count[i] = inputLatency;
     PVStream_setFFTsize(self->pv_stream, self->size);
@@ -1788,7 +1769,7 @@ PVVerb_realloc_memories(PVVerb *self) {
 static void
 PVVerb_process_ii(PVVerb *self) {
     int i, k;
-    MYFLT revtime, damp, mag, amp;
+    MYFLT revtime, damp, mag, amp, fre;
     MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream);
     MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream);
     int *count = PVStream_getCount((PVStream *)self->input_stream);
@@ -1819,11 +1800,15 @@ PVVerb_process_ii(PVVerb *self) {
             amp = 1.0;
             for (k=0; k<self->hsize; k++) {
                 mag = magn[self->overcount][k];
-                if (mag > self->l_magn[k])
+                fre = freq[self->overcount][k];
+                if (mag > self->l_magn[k]) {
                     self->magn[self->overcount][k] = self->l_magn[k] = mag;
-                else
+                    self->freq[self->overcount][k] = self->l_freq[k] = fre;
+                }
+                else {
                     self->magn[self->overcount][k] = self->l_magn[k] = mag + (self->l_magn[k] - mag) * revtime * amp;
-                self->freq[self->overcount][k] = freq[self->overcount][k];
+                    self->freq[self->overcount][k] = self->l_freq[k] = fre + (self->l_freq[k] - fre) * revtime * amp;
+                }
                 amp *= damp;
             }
             self->overcount++;
@@ -1836,7 +1821,7 @@ PVVerb_process_ii(PVVerb *self) {
 static void
 PVVerb_process_ai(PVVerb *self) {
     int i, k;
-    MYFLT revtime, damp, mag, amp;
+    MYFLT revtime, damp, mag, amp, fre;
     MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream);
     MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream);
     int *count = PVStream_getCount((PVStream *)self->input_stream);
@@ -1868,11 +1853,15 @@ PVVerb_process_ai(PVVerb *self) {
             amp = 1.0;
             for (k=0; k<self->hsize; k++) {
                 mag = magn[self->overcount][k];
-                if (mag > self->l_magn[k])
+                fre = freq[self->overcount][k];
+                if (mag > self->l_magn[k]) {
                     self->magn[self->overcount][k] = self->l_magn[k] = mag;
-                else
+                    self->freq[self->overcount][k] = self->l_freq[k] = fre;
+                }
+                else {
                     self->magn[self->overcount][k] = self->l_magn[k] = mag + (self->l_magn[k] - mag) * revtime * amp;
-                self->freq[self->overcount][k] = freq[self->overcount][k];
+                    self->freq[self->overcount][k] = self->l_freq[k] = fre + (self->l_freq[k] - fre) * revtime * amp;
+                }
                 amp *= damp;
             }
             self->overcount++;
@@ -1885,7 +1874,7 @@ PVVerb_process_ai(PVVerb *self) {
 static void
 PVVerb_process_ia(PVVerb *self) {
     int i, k;
-    MYFLT revtime, damp, mag, amp;
+    MYFLT revtime, damp, mag, amp, fre;
     MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream);
     MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream);
     int *count = PVStream_getCount((PVStream *)self->input_stream);
@@ -1917,11 +1906,15 @@ PVVerb_process_ia(PVVerb *self) {
             amp = 1.0;
             for (k=0; k<self->hsize; k++) {
                 mag = magn[self->overcount][k];
-                if (mag > self->l_magn[k])
+                fre = freq[self->overcount][k];
+                if (mag > self->l_magn[k]) {
                     self->magn[self->overcount][k] = self->l_magn[k] = mag;
-                else
+                    self->freq[self->overcount][k] = self->l_freq[k] = fre;
+                }
+                else {
                     self->magn[self->overcount][k] = self->l_magn[k] = mag + (self->l_magn[k] - mag) * revtime * amp;
-                self->freq[self->overcount][k] = freq[self->overcount][k];
+                    self->freq[self->overcount][k] = self->l_freq[k] = fre + (self->l_freq[k] - fre) * revtime * amp;
+                }
                 amp *= damp;
             }
             self->overcount++;
@@ -1934,7 +1927,7 @@ PVVerb_process_ia(PVVerb *self) {
 static void
 PVVerb_process_aa(PVVerb *self) {
     int i, k;
-    MYFLT revtime, damp, mag, amp;
+    MYFLT revtime, damp, mag, amp, fre;
     MYFLT **magn = PVStream_getMagn((PVStream *)self->input_stream);
     MYFLT **freq = PVStream_getFreq((PVStream *)self->input_stream);
     int *count = PVStream_getCount((PVStream *)self->input_stream);
@@ -1967,11 +1960,15 @@ PVVerb_process_aa(PVVerb *self) {
             amp = 1.0;
             for (k=0; k<self->hsize; k++) {
                 mag = magn[self->overcount][k];
-                if (mag > self->l_magn[k])
+                fre = freq[self->overcount][k];
+                if (mag > self->l_magn[k]) {
                     self->magn[self->overcount][k] = self->l_magn[k] = mag;
-                else
+                    self->freq[self->overcount][k] = self->l_freq[k] = fre;
+                }
+                else {
                     self->magn[self->overcount][k] = self->l_magn[k] = mag + (self->l_magn[k] - mag) * revtime * amp;
-                self->freq[self->overcount][k] = freq[self->overcount][k];
+                    self->freq[self->overcount][k] = self->l_freq[k] = fre + (self->l_freq[k] - fre) * revtime * amp;
+                }
                 amp *= damp;
             }
             self->overcount++;
@@ -1983,30 +1980,30 @@ PVVerb_process_aa(PVVerb *self) {
 
 static void
 PVVerb_setProcMode(PVVerb *self)
-{        
+{
     int procmode;
     procmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = PVVerb_process_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = PVVerb_process_ai;
             break;
-        case 10:    
+        case 10:
             self->proc_func_ptr = PVVerb_process_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = PVVerb_process_aa;
             break;
-    } 
+    }
 }
 
 static void
 PVVerb_compute_next_data_frame(PVVerb *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -2016,24 +2013,24 @@ PVVerb_traverse(PVVerb *self, visitproc visit, void *arg)
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
     Py_VISIT(self->pv_stream);
-    Py_VISIT(self->revtime);    
-    Py_VISIT(self->revtime_stream);    
-    Py_VISIT(self->damp);    
-    Py_VISIT(self->damp_stream);    
+    Py_VISIT(self->revtime);
+    Py_VISIT(self->revtime_stream);
+    Py_VISIT(self->damp);
+    Py_VISIT(self->damp_stream);
     return 0;
 }
 
-static int 
+static int
 PVVerb_clear(PVVerb *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
     Py_CLEAR(self->pv_stream);
-    Py_CLEAR(self->revtime);    
-    Py_CLEAR(self->revtime_stream);    
-    Py_CLEAR(self->damp);    
-    Py_CLEAR(self->damp_stream);    
+    Py_CLEAR(self->revtime);
+    Py_CLEAR(self->revtime_stream);
+    Py_CLEAR(self->damp);
+    Py_CLEAR(self->damp_stream);
     return 0;
 }
 
@@ -2049,9 +2046,10 @@ PVVerb_dealloc(PVVerb* self)
     free(self->magn);
     free(self->freq);
     free(self->l_magn);
+    free(self->l_freq);
     free(self->count);
     PVVerb_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2071,16 +2069,13 @@ PVVerb_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = PVVerb_setProcMode;
 
     static char *kwlist[] = {"input", "revtime", "damp", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &revtimetmp, &damptmp))
         Py_RETURN_NONE;
 
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVVerb \"input\" argument must be a PyoPVObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVVerb must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
     Py_INCREF(inputtmp);
     Py_XDECREF(self->input);
@@ -2100,7 +2095,7 @@ PVVerb_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (damptmp) {
         PyObject_CallMethod((PyObject *)self, "setDamp", "O", damptmp);
     }
- 
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL);
@@ -2128,9 +2123,8 @@ PVVerb_setInput(PVVerb *self, PyObject *arg)
 
     inputtmp = arg;
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVVerb \"input\" argument must be a PyoPVObject.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVVerb must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
 
     Py_INCREF(inputtmp);
@@ -2140,23 +2134,20 @@ PVVerb_setInput(PVVerb *self, PyObject *arg)
     Py_INCREF(input_streamtmp);
     Py_XDECREF(self->input_stream);
     self->input_stream = (PVStream *)input_streamtmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 PVVerb_setRevtime(PVVerb *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->revtime);
@@ -2172,9 +2163,9 @@ PVVerb_setRevtime(PVVerb *self, PyObject *arg)
         self->revtime_stream = (Stream *)streamtmp;
 		self->modebuffer[0] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -2183,14 +2174,11 @@ static PyObject *
 PVVerb_setDamp(PVVerb *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->damp);
@@ -2206,9 +2194,9 @@ PVVerb_setDamp(PVVerb *self, PyObject *arg)
         self->damp_stream = (Stream *)streamtmp;
 		self->modebuffer[1] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -2236,8 +2224,7 @@ static PyMethodDef PVVerb_methods[] = {
 };
 
 PyTypeObject PVVerbType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.PVVerb_base",                                   /*tp_name*/
 sizeof(PVVerb),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -2245,7 +2232,7 @@ sizeof(PVVerb),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 0,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -2289,6 +2276,7 @@ typedef struct {
     Stream *thresh_stream;
     PyObject *damp;
     Stream *damp_stream;
+    int inverse;
     int size;
     int olaps;
     int hsize;
@@ -2314,7 +2302,7 @@ PVGate_realloc_memories(PVGate *self) {
         self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         for (j=0; j<self->hsize; j++)
             self->magn[i][j] = self->freq[i][j] = 0.0;
-    } 
+    }
     for (i=0; i<self->bufsize; i++)
         self->count[i] = inputLatency;
     PVStream_setFFTsize(self->pv_stream, self->size);
@@ -2346,13 +2334,24 @@ PVGate_process_ii(PVGate *self) {
     for (i=0; i<self->bufsize; i++) {
         self->count[i] = count[i];
         if (count[i] >= (self->size-1)) {
-            for (k=0; k<self->hsize; k++) {
-                mag = magn[self->overcount][k];
-                if (mag < thresh)
-                    self->magn[self->overcount][k] = mag * damp;
-                else
-                    self->magn[self->overcount][k] = mag;
-                self->freq[self->overcount][k] = freq[self->overcount][k];
+            if (self->inverse == 0) {
+                for (k=0; k<self->hsize; k++) {
+                    mag = magn[self->overcount][k];
+                    if (mag < thresh)
+                        self->magn[self->overcount][k] = mag * damp;
+                    else
+                        self->magn[self->overcount][k] = mag;
+                    self->freq[self->overcount][k] = freq[self->overcount][k];
+                }
+            } else {
+                for (k=0; k<self->hsize; k++) {
+                    mag = magn[self->overcount][k];
+                    if (mag > thresh)
+                        self->magn[self->overcount][k] = mag * damp;
+                    else
+                        self->magn[self->overcount][k] = mag;
+                    self->freq[self->overcount][k] = freq[self->overcount][k];
+                }
             }
             self->overcount++;
             if (self->overcount >= self->olaps)
@@ -2384,13 +2383,24 @@ PVGate_process_ai(PVGate *self) {
         if (count[i] >= (self->size-1)) {
             thresh = rvt[i];
             thresh = MYPOW(10.0, thresh * 0.05);
-            for (k=0; k<self->hsize; k++) {
-                mag = magn[self->overcount][k];
-                if (mag < thresh)
-                    self->magn[self->overcount][k] = mag * damp;
-                else
-                    self->magn[self->overcount][k] = mag;
-                self->freq[self->overcount][k] = freq[self->overcount][k];
+            if (self->inverse == 0) {
+                for (k=0; k<self->hsize; k++) {
+                    mag = magn[self->overcount][k];
+                    if (mag < thresh)
+                        self->magn[self->overcount][k] = mag * damp;
+                    else
+                        self->magn[self->overcount][k] = mag;
+                    self->freq[self->overcount][k] = freq[self->overcount][k];
+                }
+            } else {
+                for (k=0; k<self->hsize; k++) {
+                    mag = magn[self->overcount][k];
+                    if (mag > thresh)
+                        self->magn[self->overcount][k] = mag * damp;
+                    else
+                        self->magn[self->overcount][k] = mag;
+                    self->freq[self->overcount][k] = freq[self->overcount][k];
+                }
             }
             self->overcount++;
             if (self->overcount >= self->olaps)
@@ -2422,13 +2432,24 @@ PVGate_process_ia(PVGate *self) {
         self->count[i] = count[i];
         if (count[i] >= (self->size-1)) {
             damp = dmp[i];
-            for (k=0; k<self->hsize; k++) {
-                mag = magn[self->overcount][k];
-                if (mag < thresh)
-                    self->magn[self->overcount][k] = mag * damp;
-                else
-                    self->magn[self->overcount][k] = mag;
-                self->freq[self->overcount][k] = freq[self->overcount][k];
+            if (self->inverse == 0) {
+                for (k=0; k<self->hsize; k++) {
+                    mag = magn[self->overcount][k];
+                    if (mag < thresh)
+                        self->magn[self->overcount][k] = mag * damp;
+                    else
+                        self->magn[self->overcount][k] = mag;
+                    self->freq[self->overcount][k] = freq[self->overcount][k];
+                }
+            } else {
+                for (k=0; k<self->hsize; k++) {
+                    mag = magn[self->overcount][k];
+                    if (mag > thresh)
+                        self->magn[self->overcount][k] = mag * damp;
+                    else
+                        self->magn[self->overcount][k] = mag;
+                    self->freq[self->overcount][k] = freq[self->overcount][k];
+                }
             }
             self->overcount++;
             if (self->overcount >= self->olaps)
@@ -2461,13 +2482,24 @@ PVGate_process_aa(PVGate *self) {
             thresh = rvt[i];
             thresh = MYPOW(10.0, thresh * 0.05);
             damp = dmp[i];
-            for (k=0; k<self->hsize; k++) {
-                mag = magn[self->overcount][k];
-                if (mag < thresh)
-                    self->magn[self->overcount][k] = mag * damp;
-                else
-                    self->magn[self->overcount][k] = mag;
-                self->freq[self->overcount][k] = freq[self->overcount][k];
+            if (self->inverse == 0) {
+                for (k=0; k<self->hsize; k++) {
+                    mag = magn[self->overcount][k];
+                    if (mag < thresh)
+                        self->magn[self->overcount][k] = mag * damp;
+                    else
+                        self->magn[self->overcount][k] = mag;
+                    self->freq[self->overcount][k] = freq[self->overcount][k];
+                }
+            } else {
+                for (k=0; k<self->hsize; k++) {
+                    mag = magn[self->overcount][k];
+                    if (mag > thresh)
+                        self->magn[self->overcount][k] = mag * damp;
+                    else
+                        self->magn[self->overcount][k] = mag;
+                    self->freq[self->overcount][k] = freq[self->overcount][k];
+                }
             }
             self->overcount++;
             if (self->overcount >= self->olaps)
@@ -2478,30 +2510,30 @@ PVGate_process_aa(PVGate *self) {
 
 static void
 PVGate_setProcMode(PVGate *self)
-{        
+{
     int procmode;
     procmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = PVGate_process_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = PVGate_process_ai;
             break;
-        case 10:    
+        case 10:
             self->proc_func_ptr = PVGate_process_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = PVGate_process_aa;
             break;
-    } 
+    }
 }
 
 static void
 PVGate_compute_next_data_frame(PVGate *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -2511,24 +2543,24 @@ PVGate_traverse(PVGate *self, visitproc visit, void *arg)
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
     Py_VISIT(self->pv_stream);
-    Py_VISIT(self->thresh);    
-    Py_VISIT(self->thresh_stream);    
-    Py_VISIT(self->damp);    
-    Py_VISIT(self->damp_stream);    
+    Py_VISIT(self->thresh);
+    Py_VISIT(self->thresh_stream);
+    Py_VISIT(self->damp);
+    Py_VISIT(self->damp_stream);
     return 0;
 }
 
-static int 
+static int
 PVGate_clear(PVGate *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
     Py_CLEAR(self->pv_stream);
-    Py_CLEAR(self->thresh);    
-    Py_CLEAR(self->thresh_stream);    
-    Py_CLEAR(self->damp);    
-    Py_CLEAR(self->damp_stream);    
+    Py_CLEAR(self->thresh);
+    Py_CLEAR(self->thresh_stream);
+    Py_CLEAR(self->damp);
+    Py_CLEAR(self->damp_stream);
     return 0;
 }
 
@@ -2545,7 +2577,7 @@ PVGate_dealloc(PVGate* self)
     free(self->freq);
     free(self->count);
     PVGate_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2560,21 +2592,19 @@ PVGate_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->damp = PyFloat_FromDouble(0.0);
     self->size = 1024;
     self->olaps = 4;
+    self->inverse = 0;
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, PVGate_compute_next_data_frame);
     self->mode_func_ptr = PVGate_setProcMode;
 
-    static char *kwlist[] = {"input", "thresh", "damp", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &threshtmp, &damptmp))
+    static char *kwlist[] = {"input", "thresh", "damp", "inverse", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOi", kwlist, &inputtmp, &threshtmp, &damptmp, &self->inverse))
         Py_RETURN_NONE;
 
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVGate \"input\" argument must be a PyoPVObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVGate must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
     Py_INCREF(inputtmp);
     Py_XDECREF(self->input);
@@ -2594,7 +2624,7 @@ PVGate_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (damptmp) {
         PyObject_CallMethod((PyObject *)self, "setDamp", "O", damptmp);
     }
- 
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL);
@@ -2622,9 +2652,8 @@ PVGate_setInput(PVGate *self, PyObject *arg)
 
     inputtmp = arg;
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVGate \"input\" argument must be a PyoPVObject.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVGate must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
 
     Py_INCREF(inputtmp);
@@ -2634,23 +2663,20 @@ PVGate_setInput(PVGate *self, PyObject *arg)
     Py_INCREF(input_streamtmp);
     Py_XDECREF(self->input_stream);
     self->input_stream = (PVStream *)input_streamtmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 PVGate_setThresh(PVGate *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->thresh);
@@ -2666,9 +2692,9 @@ PVGate_setThresh(PVGate *self, PyObject *arg)
         self->thresh_stream = (Stream *)streamtmp;
 		self->modebuffer[0] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -2677,14 +2703,11 @@ static PyObject *
 PVGate_setDamp(PVGate *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->damp);
@@ -2700,9 +2723,22 @@ PVGate_setDamp(PVGate *self, PyObject *arg)
         self->damp_stream = (Stream *)streamtmp;
 		self->modebuffer[1] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+PVGate_setInverse(PVGate *self, PyObject *arg)
+{
+    ASSERT_ARG_NOT_NULL
+
+	if (PyInt_Check(arg)) {
+        self->inverse = PyInt_AsLong(arg);
+    }
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -2724,14 +2760,14 @@ static PyMethodDef PVGate_methods[] = {
 {"setInput", (PyCFunction)PVGate_setInput, METH_O, "Sets a new input object."},
 {"setThresh", (PyCFunction)PVGate_setThresh, METH_O, "Sets the Threshold factor."},
 {"setDamp", (PyCFunction)PVGate_setDamp, METH_O, "Sets the damping factor."},
+{"setInverse", (PyCFunction)PVGate_setInverse, METH_O, "Sets the inverse mode."},
 {"play", (PyCFunction)PVGate_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
 {"stop", (PyCFunction)PVGate_stop, METH_NOARGS, "Stops computing."},
 {NULL}  /* Sentinel */
 };
 
 PyTypeObject PVGateType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.PVGate_base",                                   /*tp_name*/
 sizeof(PVGate),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -2739,7 +2775,7 @@ sizeof(PVGate),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 0,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -2801,14 +2837,14 @@ PVCross_realloc_memories(PVCross *self) {
     self->hopsize = self->size / self->olaps;
     inputLatency = self->size - self->hopsize;
     self->overcount = 0;
-    self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); 
+    self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *));
     self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *));
     for (i=0; i<self->olaps; i++) {
         self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         for (j=0; j<self->hsize; j++)
             self->magn[i][j] = self->freq[i][j] = 0.0;
-    } 
+    }
     for (i=0; i<self->bufsize; i++)
         self->count[i] = inputLatency;
     PVStream_setFFTsize(self->pv_stream, self->size);
@@ -2885,24 +2921,24 @@ PVCross_process_a(PVCross *self) {
 
 static void
 PVCross_setProcMode(PVCross *self)
-{        
+{
     int procmode;
     procmode = self->modebuffer[0];
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = PVCross_process_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = PVCross_process_a;
             break;
-    } 
+    }
 }
 
 static void
 PVCross_compute_next_data_frame(PVCross *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -2914,12 +2950,12 @@ PVCross_traverse(PVCross *self, visitproc visit, void *arg)
     Py_VISIT(self->input2);
     Py_VISIT(self->input2_stream);
     Py_VISIT(self->pv_stream);
-    Py_VISIT(self->fade);    
-    Py_VISIT(self->fade_stream);    
+    Py_VISIT(self->fade);
+    Py_VISIT(self->fade_stream);
     return 0;
 }
 
-static int 
+static int
 PVCross_clear(PVCross *self)
 {
     pyo_CLEAR
@@ -2928,8 +2964,8 @@ PVCross_clear(PVCross *self)
     Py_CLEAR(self->input2);
     Py_CLEAR(self->input2_stream);
     Py_CLEAR(self->pv_stream);
-    Py_CLEAR(self->fade);    
-    Py_CLEAR(self->fade_stream);    
+    Py_CLEAR(self->fade);
+    Py_CLEAR(self->fade_stream);
     return 0;
 }
 
@@ -2946,7 +2982,7 @@ PVCross_dealloc(PVCross* self)
     free(self->freq);
     free(self->count);
     PVCross_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2965,16 +3001,13 @@ PVCross_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = PVCross_setProcMode;
 
     static char *kwlist[] = {"input", "input2", "fade", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|O", kwlist, &inputtmp, &input2tmp, &fadetmp))
         Py_RETURN_NONE;
 
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVCross \"input\" argument must be a PyoPVObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVCross must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
     Py_INCREF(inputtmp);
     Py_XDECREF(self->input);
@@ -2985,11 +3018,8 @@ PVCross_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->input_stream = (PVStream *)input_streamtmp;
 
     if ( PyObject_HasAttrString((PyObject *)input2tmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVCross \"input2\" argument must be a PyoPVObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"input2\" argument of PVCross must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
     Py_INCREF(input2tmp);
     Py_XDECREF(self->input2);
@@ -3005,7 +3035,7 @@ PVCross_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (fadetmp) {
         PyObject_CallMethod((PyObject *)self, "setFade", "O", fadetmp);
     }
- 
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL);
@@ -3033,9 +3063,8 @@ PVCross_setInput(PVCross *self, PyObject *arg)
 
     inputtmp = arg;
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVCross \"input\" argument must be a PyoPVObject.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVCross must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
 
     Py_INCREF(inputtmp);
@@ -3045,10 +3074,10 @@ PVCross_setInput(PVCross *self, PyObject *arg)
     Py_INCREF(input_streamtmp);
     Py_XDECREF(self->input_stream);
     self->input_stream = (PVStream *)input_streamtmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 PVCross_setInput2(PVCross *self, PyObject *arg)
@@ -3057,9 +3086,8 @@ PVCross_setInput2(PVCross *self, PyObject *arg)
 
     inputtmp = arg;
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVCross \"input2\" argument must be a PyoPVObject.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        PyErr_SetString(PyExc_TypeError, "\"input2\" argument of PVCross must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
 
     Py_INCREF(inputtmp);
@@ -3069,23 +3097,20 @@ PVCross_setInput2(PVCross *self, PyObject *arg)
     Py_INCREF(input_streamtmp);
     Py_XDECREF(self->input2_stream);
     self->input2_stream = (PVStream *)input_streamtmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 PVCross_setFade(PVCross *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->fade);
@@ -3101,9 +3126,9 @@ PVCross_setFade(PVCross *self, PyObject *arg)
         self->fade_stream = (Stream *)streamtmp;
 		self->modebuffer[0] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -3131,8 +3156,7 @@ static PyMethodDef PVCross_methods[] = {
 };
 
 PyTypeObject PVCrossType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.PVCross_base",                                   /*tp_name*/
 sizeof(PVCross),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -3140,7 +3164,7 @@ sizeof(PVCross),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 0,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -3199,14 +3223,14 @@ PVMult_realloc_memories(PVMult *self) {
     self->hopsize = self->size / self->olaps;
     inputLatency = self->size - self->hopsize;
     self->overcount = 0;
-    self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); 
+    self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *));
     self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *));
     for (i=0; i<self->olaps; i++) {
         self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         for (j=0; j<self->hsize; j++)
             self->magn[i][j] = self->freq[i][j] = 0.0;
-    } 
+    }
     for (i=0; i<self->bufsize; i++)
         self->count[i] = inputLatency;
     PVStream_setFFTsize(self->pv_stream, self->size);
@@ -3255,7 +3279,7 @@ PVMult_setProcMode(PVMult *self)
 static void
 PVMult_compute_next_data_frame(PVMult *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -3270,7 +3294,7 @@ PVMult_traverse(PVMult *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 PVMult_clear(PVMult *self)
 {
     pyo_CLEAR
@@ -3295,7 +3319,7 @@ PVMult_dealloc(PVMult* self)
     free(self->freq);
     free(self->count);
     PVMult_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -3313,16 +3337,13 @@ PVMult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = PVMult_setProcMode;
 
     static char *kwlist[] = {"input", "input2", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &inputtmp, &input2tmp))
         Py_RETURN_NONE;
 
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVMult \"input\" argument must be a PyoPVObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVMult must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
     Py_INCREF(inputtmp);
     Py_XDECREF(self->input);
@@ -3333,11 +3354,8 @@ PVMult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->input_stream = (PVStream *)input_streamtmp;
 
     if ( PyObject_HasAttrString((PyObject *)input2tmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVMult \"input2\" argument must be a PyoPVObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"input2\" argument of PVMult must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
     Py_INCREF(input2tmp);
     Py_XDECREF(self->input2);
@@ -3349,7 +3367,7 @@ PVMult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
     self->size = PVStream_getFFTsize(self->input_stream);
     self->olaps = PVStream_getOlaps(self->input_stream);
- 
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL);
@@ -3377,9 +3395,8 @@ PVMult_setInput(PVMult *self, PyObject *arg)
 
     inputtmp = arg;
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVMult \"input\" argument must be a PyoPVObject.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVMult must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
 
     Py_INCREF(inputtmp);
@@ -3389,10 +3406,10 @@ PVMult_setInput(PVMult *self, PyObject *arg)
     Py_INCREF(input_streamtmp);
     Py_XDECREF(self->input_stream);
     self->input_stream = (PVStream *)input_streamtmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 PVMult_setInput2(PVMult *self, PyObject *arg)
@@ -3401,9 +3418,8 @@ PVMult_setInput2(PVMult *self, PyObject *arg)
 
     inputtmp = arg;
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVMult \"input2\" argument must be a PyoPVObject.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        PyErr_SetString(PyExc_TypeError, "\"input2\" argument of PVMult must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
 
     Py_INCREF(inputtmp);
@@ -3413,10 +3429,10 @@ PVMult_setInput2(PVMult *self, PyObject *arg)
     Py_INCREF(input_streamtmp);
     Py_XDECREF(self->input2_stream);
     self->input2_stream = (PVStream *)input_streamtmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef PVMult_members[] = {
 {"server", T_OBJECT_EX, offsetof(PVMult, server), 0, "Pyo server."},
@@ -3439,8 +3455,7 @@ static PyMethodDef PVMult_methods[] = {
 };
 
 PyTypeObject PVMultType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.PVMult_base",                                   /*tp_name*/
 sizeof(PVMult),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -3448,7 +3463,7 @@ sizeof(PVMult),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 0,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -3510,14 +3525,14 @@ PVMorph_realloc_memories(PVMorph *self) {
     self->hopsize = self->size / self->olaps;
     inputLatency = self->size - self->hopsize;
     self->overcount = 0;
-    self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); 
+    self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *));
     self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *));
     for (i=0; i<self->olaps; i++) {
         self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         for (j=0; j<self->hsize; j++)
             self->magn[i][j] = self->freq[i][j] = 0.0;
-    } 
+    }
     for (i=0; i<self->bufsize; i++)
         self->count[i] = inputLatency;
     PVStream_setFFTsize(self->pv_stream, self->size);
@@ -3604,24 +3619,24 @@ PVMorph_process_a(PVMorph *self) {
 
 static void
 PVMorph_setProcMode(PVMorph *self)
-{        
+{
     int procmode;
     procmode = self->modebuffer[0];
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = PVMorph_process_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = PVMorph_process_a;
             break;
-    } 
+    }
 }
 
 static void
 PVMorph_compute_next_data_frame(PVMorph *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -3633,12 +3648,12 @@ PVMorph_traverse(PVMorph *self, visitproc visit, void *arg)
     Py_VISIT(self->input2);
     Py_VISIT(self->input2_stream);
     Py_VISIT(self->pv_stream);
-    Py_VISIT(self->fade);    
-    Py_VISIT(self->fade_stream);    
+    Py_VISIT(self->fade);
+    Py_VISIT(self->fade_stream);
     return 0;
 }
 
-static int 
+static int
 PVMorph_clear(PVMorph *self)
 {
     pyo_CLEAR
@@ -3647,8 +3662,8 @@ PVMorph_clear(PVMorph *self)
     Py_CLEAR(self->input2);
     Py_CLEAR(self->input2_stream);
     Py_CLEAR(self->pv_stream);
-    Py_CLEAR(self->fade);    
-    Py_CLEAR(self->fade_stream);    
+    Py_CLEAR(self->fade);
+    Py_CLEAR(self->fade_stream);
     return 0;
 }
 
@@ -3665,7 +3680,7 @@ PVMorph_dealloc(PVMorph* self)
     free(self->freq);
     free(self->count);
     PVMorph_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -3684,16 +3699,13 @@ PVMorph_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = PVMorph_setProcMode;
 
     static char *kwlist[] = {"input", "input2", "fade", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|O", kwlist, &inputtmp, &input2tmp, &fadetmp))
         Py_RETURN_NONE;
 
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVMorph \"input\" argument must be a PyoPVObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVMorph must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
     Py_INCREF(inputtmp);
     Py_XDECREF(self->input);
@@ -3704,11 +3716,8 @@ PVMorph_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->input_stream = (PVStream *)input_streamtmp;
 
     if ( PyObject_HasAttrString((PyObject *)input2tmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVMorph \"input2\" argument must be a PyoPVObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"input2\" argument of PVMorph must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
     Py_INCREF(input2tmp);
     Py_XDECREF(self->input2);
@@ -3724,7 +3733,7 @@ PVMorph_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (fadetmp) {
         PyObject_CallMethod((PyObject *)self, "setFade", "O", fadetmp);
     }
- 
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL);
@@ -3752,9 +3761,8 @@ PVMorph_setInput(PVMorph *self, PyObject *arg)
 
     inputtmp = arg;
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVMorph \"input\" argument must be a PyoPVObject.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVMorph must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
 
     Py_INCREF(inputtmp);
@@ -3764,10 +3772,10 @@ PVMorph_setInput(PVMorph *self, PyObject *arg)
     Py_INCREF(input_streamtmp);
     Py_XDECREF(self->input_stream);
     self->input_stream = (PVStream *)input_streamtmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 PVMorph_setInput2(PVMorph *self, PyObject *arg)
@@ -3776,9 +3784,8 @@ PVMorph_setInput2(PVMorph *self, PyObject *arg)
 
     inputtmp = arg;
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVMorph \"input2\" argument must be a PyoPVObject.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        PyErr_SetString(PyExc_TypeError, "\"input2\" argument of PVMorph must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
 
     Py_INCREF(inputtmp);
@@ -3788,23 +3795,20 @@ PVMorph_setInput2(PVMorph *self, PyObject *arg)
     Py_INCREF(input_streamtmp);
     Py_XDECREF(self->input2_stream);
     self->input2_stream = (PVStream *)input_streamtmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 PVMorph_setFade(PVMorph *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->fade);
@@ -3820,9 +3824,9 @@ PVMorph_setFade(PVMorph *self, PyObject *arg)
         self->fade_stream = (Stream *)streamtmp;
 		self->modebuffer[0] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -3850,8 +3854,7 @@ static PyMethodDef PVMorph_methods[] = {
 };
 
 PyTypeObject PVMorphType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.PVMorph_base",                                   /*tp_name*/
 sizeof(PVMorph),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -3859,7 +3862,7 @@ sizeof(PVMorph),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 0,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -3921,14 +3924,14 @@ PVFilter_realloc_memories(PVFilter *self) {
     self->hopsize = self->size / self->olaps;
     inputLatency = self->size - self->hopsize;
     self->overcount = 0;
-    self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); 
+    self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *));
     self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *));
     for (i=0; i<self->olaps; i++) {
         self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         for (j=0; j<self->hsize; j++)
             self->magn[i][j] = self->freq[i][j] = 0.0;
-    } 
+    }
     for (i=0; i<self->bufsize; i++)
         self->count[i] = inputLatency;
     PVStream_setFFTsize(self->pv_stream, self->size);
@@ -4014,7 +4017,7 @@ PVFilter_process_a(PVFilter *self) {
     }
 
     factor = (MYFLT)tsize / self->hsize;
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->count[i] = count[i];
         if (count[i] >= (self->size-1)) {
@@ -4053,24 +4056,24 @@ PVFilter_process_a(PVFilter *self) {
 
 static void
 PVFilter_setProcMode(PVFilter *self)
-{        
+{
     int procmode;
     procmode = self->modebuffer[0];
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = PVFilter_process_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = PVFilter_process_a;
             break;
-    } 
+    }
 }
 
 static void
 PVFilter_compute_next_data_frame(PVFilter *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -4080,21 +4083,21 @@ PVFilter_traverse(PVFilter *self, visitproc visit, void *arg)
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
     Py_VISIT(self->pv_stream);
-    Py_VISIT(self->gain);    
-    Py_VISIT(self->gain_stream);    
+    Py_VISIT(self->gain);
+    Py_VISIT(self->gain_stream);
     Py_VISIT(self->table);
     return 0;
 }
 
-static int 
+static int
 PVFilter_clear(PVFilter *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
     Py_CLEAR(self->pv_stream);
-    Py_CLEAR(self->gain);    
-    Py_CLEAR(self->gain_stream);    
+    Py_CLEAR(self->gain);
+    Py_CLEAR(self->gain_stream);
     Py_CLEAR(self->table);
     return 0;
 }
@@ -4112,7 +4115,7 @@ PVFilter_dealloc(PVFilter* self)
     free(self->freq);
     free(self->count);
     PVFilter_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -4126,23 +4129,20 @@ PVFilter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->gain = PyFloat_FromDouble(1);
     self->size = 1024;
     self->olaps = 4;
-    self->mode = 0; /* 0 : index outside table range clipped to 0 
+    self->mode = 0; /* 0 : index outside table range clipped to 0
                        1 : index between 0 and hsize are scaled over table length */
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, PVFilter_compute_next_data_frame);
     self->mode_func_ptr = PVFilter_setProcMode;
 
     static char *kwlist[] = {"input", "table", "gain", "mode", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|Oi", kwlist, &inputtmp, &tabletmp, &gaintmp, &self->mode))
         Py_RETURN_NONE;
 
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVFilter \"input\" argument must be a PyoPVObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVFilter must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
     Py_INCREF(inputtmp);
     Py_XDECREF(self->input);
@@ -4161,7 +4161,7 @@ PVFilter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (gaintmp) {
         PyObject_CallMethod((PyObject *)self, "setGain", "O", gaintmp);
     }
- 
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL);
@@ -4189,9 +4189,8 @@ PVFilter_setInput(PVFilter *self, PyObject *arg)
 
     inputtmp = arg;
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVFilter \"input\" argument must be a PyoPVObject.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVFilter must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
 
     Py_INCREF(inputtmp);
@@ -4201,23 +4200,20 @@ PVFilter_setInput(PVFilter *self, PyObject *arg)
     Py_INCREF(input_streamtmp);
     Py_XDECREF(self->input_stream);
     self->input_stream = (PVStream *)input_streamtmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 PVFilter_setGain(PVFilter *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->gain);
@@ -4233,9 +4229,9 @@ PVFilter_setGain(PVFilter *self, PyObject *arg)
         self->gain_stream = (Stream *)streamtmp;
 		self->modebuffer[0] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -4251,19 +4247,16 @@ static PyObject *
 PVFilter_setTable(PVFilter *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
+
+    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 *
 PVFilter_setMode(PVFilter *self, PyObject *arg)
@@ -4277,10 +4270,10 @@ PVFilter_setMode(PVFilter *self, PyObject *arg)
         else
             self->mode = 1;
     }
-   
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef PVFilter_members[] = {
 {"server", T_OBJECT_EX, offsetof(PVFilter, server), 0, "Pyo server."},
@@ -4307,8 +4300,7 @@ static PyMethodDef PVFilter_methods[] = {
 };
 
 PyTypeObject PVFilterType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.PVFilter_base",                                   /*tp_name*/
 sizeof(PVFilter),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -4316,7 +4308,7 @@ sizeof(PVFilter),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 0,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -4383,22 +4375,22 @@ PVDelay_realloc_memories(PVDelay *self) {
     self->numFrames = (int)(self->maxdelay * self->sr / self->hopsize + 0.5);
     self->overcount = 0;
     self->framecount = 0;
-    self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); 
+    self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *));
     self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *));
     for (i=0; i<self->olaps; i++) {
         self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         for (j=0; j<self->hsize; j++)
             self->magn[i][j] = self->freq[i][j] = 0.0;
-    } 
-    self->magn_buf = (MYFLT **)realloc(self->magn_buf, self->numFrames * sizeof(MYFLT *)); 
+    }
+    self->magn_buf = (MYFLT **)realloc(self->magn_buf, self->numFrames * sizeof(MYFLT *));
     self->freq_buf = (MYFLT **)realloc(self->freq_buf, self->numFrames * sizeof(MYFLT *));
     for (i=0; i<self->numFrames; i++) {
         self->magn_buf[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         self->freq_buf[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         for (j=0; j<self->hsize; j++)
             self->magn_buf[i][j] = self->freq_buf[i][j] = 0.0;
-    } 
+    }
     for (i=0; i<self->bufsize; i++)
         self->count[i] = inputLatency;
     PVStream_setFFTsize(self->pv_stream, self->size);
@@ -4543,7 +4535,7 @@ PVDelay_process_scaled(PVDelay *self) {
 
 static void
 PVDelay_setProcMode(PVDelay *self)
-{        
+{
     if (self->mode == 0)
         self->proc_func_ptr = PVDelay_process_zero;
     else
@@ -4553,7 +4545,7 @@ PVDelay_setProcMode(PVDelay *self)
 static void
 PVDelay_compute_next_data_frame(PVDelay *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -4568,7 +4560,7 @@ PVDelay_traverse(PVDelay *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 PVDelay_clear(PVDelay *self)
 {
     pyo_CLEAR
@@ -4599,7 +4591,7 @@ PVDelay_dealloc(PVDelay* self)
     free(self->freq_buf);
     free(self->count);
     PVDelay_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -4619,16 +4611,13 @@ PVDelay_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = PVDelay_setProcMode;
 
     static char *kwlist[] = {"input", "deltable", "feedtable", "maxdelay", "mode", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_OOO_FI, kwlist, &inputtmp, &deltabletmp, &feedtabletmp, &self->maxdelay, &self->mode))
         Py_RETURN_NONE;
 
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVDelay \"input\" argument must be a PyoPVObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVDelay must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
     Py_INCREF(inputtmp);
     Py_XDECREF(self->input);
@@ -4646,7 +4635,7 @@ PVDelay_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
     Py_XDECREF(self->feedtable);
     self->feedtable = PyObject_CallMethod((PyObject *)feedtabletmp, "getTableStream", "");
- 
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL);
@@ -4675,9 +4664,8 @@ PVDelay_setInput(PVDelay *self, PyObject *arg)
 
     inputtmp = arg;
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVDelay \"input\" argument must be a PyoPVObject.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVDelay must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
 
     Py_INCREF(inputtmp);
@@ -4687,10 +4675,10 @@ PVDelay_setInput(PVDelay *self, PyObject *arg)
     Py_INCREF(input_streamtmp);
     Py_XDECREF(self->input_stream);
     self->input_stream = (PVStream *)input_streamtmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 PVDelay_getDeltable(PVDelay* self)
@@ -4703,19 +4691,16 @@ static PyObject *
 PVDelay_setDeltable(PVDelay *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
+
+    ASSERT_ARG_NOT_NULL
 
 	tmp = arg;
 	Py_DECREF(self->deltable);
     self->deltable = PyObject_CallMethod((PyObject *)tmp, "getTableStream", "");
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 PVDelay_getFeedtable(PVDelay* self)
@@ -4728,19 +4713,16 @@ static PyObject *
 PVDelay_setFeedtable(PVDelay *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
+
+    ASSERT_ARG_NOT_NULL
 
 	tmp = arg;
 	Py_DECREF(self->feedtable);
     self->feedtable = PyObject_CallMethod((PyObject *)tmp, "getTableStream", "");
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 PVDelay_setMode(PVDelay *self, PyObject *arg)
@@ -4756,10 +4738,10 @@ PVDelay_setMode(PVDelay *self, PyObject *arg)
     }
 
     (*self->mode_func_ptr)(self);
-   
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef PVDelay_members[] = {
 {"server", T_OBJECT_EX, offsetof(PVDelay, server), 0, "Pyo server."},
@@ -4787,8 +4769,7 @@ static PyMethodDef PVDelay_methods[] = {
 };
 
 PyTypeObject PVDelayType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.PVDelay_base",                                   /*tp_name*/
 sizeof(PVDelay),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -4796,7 +4777,7 @@ sizeof(PVDelay),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 0,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -4865,22 +4846,22 @@ PVBuffer_realloc_memories(PVBuffer *self) {
     self->numFrames = (int)(self->length * self->sr / self->hopsize + 0.5);
     self->overcount = 0;
     self->framecount = 0;
-    self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); 
+    self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *));
     self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *));
     for (i=0; i<self->olaps; i++) {
         self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         for (j=0; j<self->hsize; j++)
             self->magn[i][j] = self->freq[i][j] = 0.0;
-    } 
-    self->magn_buf = (MYFLT **)realloc(self->magn_buf, self->numFrames * sizeof(MYFLT *)); 
+    }
+    self->magn_buf = (MYFLT **)realloc(self->magn_buf, self->numFrames * sizeof(MYFLT *));
     self->freq_buf = (MYFLT **)realloc(self->freq_buf, self->numFrames * sizeof(MYFLT *));
     for (i=0; i<self->numFrames; i++) {
         self->magn_buf[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         self->freq_buf[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         for (j=0; j<self->hsize; j++)
             self->magn_buf[i][j] = self->freq_buf[i][j] = 0.0;
-    } 
+    }
     for (i=0; i<self->bufsize; i++)
         self->count[i] = inputLatency;
     PVStream_setFFTsize(self->pv_stream, self->size);
@@ -4997,15 +4978,15 @@ PVBuffer_process_a(PVBuffer *self) {
 
 static void
 PVBuffer_setProcMode(PVBuffer *self)
-{        
+{
     int procmode;
     procmode = self->modebuffer[0];
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = PVBuffer_process_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = PVBuffer_process_a;
             break;
     } }
@@ -5013,7 +4994,7 @@ PVBuffer_setProcMode(PVBuffer *self)
 static void
 PVBuffer_compute_next_data_frame(PVBuffer *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -5030,7 +5011,7 @@ PVBuffer_traverse(PVBuffer *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 PVBuffer_clear(PVBuffer *self)
 {
     pyo_CLEAR
@@ -5063,7 +5044,7 @@ PVBuffer_dealloc(PVBuffer* self)
     free(self->freq_buf);
     free(self->count);
     PVBuffer_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -5074,7 +5055,7 @@ PVBuffer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PVBuffer *self;
     self = (PVBuffer *)type->tp_alloc(type, 0);
 
-    self->pitch = PyFloat_FromDouble(1);    
+    self->pitch = PyFloat_FromDouble(1);
     self->size = 1024;
     self->olaps = 4;
     self->length = 1.0;
@@ -5083,16 +5064,13 @@ PVBuffer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = PVBuffer_setProcMode;
 
     static char *kwlist[] = {"input", "index", "pitch", "length", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_OO_OF, kwlist, &inputtmp, &indextmp, &pitchtmp, &self->length))
         Py_RETURN_NONE;
 
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVBuffer \"input\" argument must be a PyoPVObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVBuffer must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
     Py_INCREF(inputtmp);
     Py_XDECREF(self->input);
@@ -5112,7 +5090,7 @@ PVBuffer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (pitchtmp) {
         PyObject_CallMethod((PyObject *)self, "setPitch", "O", pitchtmp);
     }
- 
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL);
@@ -5130,9 +5108,9 @@ static PyObject * PVBuffer_getServer(PVBuffer* self) { GET_SERVER };
 static PyObject * PVBuffer_getStream(PVBuffer* self) { GET_STREAM };
 static PyObject * PVBuffer_getPVStream(PVBuffer* self) { GET_PV_STREAM };
 
-static PyObject * PVBuffer_play(PVBuffer *self, PyObject *args, PyObject *kwds) { 
+static PyObject * PVBuffer_play(PVBuffer *self, PyObject *args, PyObject *kwds) {
     self->framecount = 0;
-    PLAY 
+    PLAY
 };
 
 static PyObject * PVBuffer_stop(PVBuffer *self) { STOP };
@@ -5144,9 +5122,8 @@ PVBuffer_setInput(PVBuffer *self, PyObject *arg)
 
     inputtmp = arg;
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVBuffer \"input\" argument must be a PyoPVObject.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVBuffer must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
 
     Py_INCREF(inputtmp);
@@ -5156,31 +5133,24 @@ PVBuffer_setInput(PVBuffer *self, PyObject *arg)
     Py_INCREF(input_streamtmp);
     Py_XDECREF(self->input_stream);
     self->input_stream = (PVStream *)input_streamtmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 PVBuffer_setIndex(PVBuffer *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	int isNumber = PyNumber_Check(arg);
-	if (isNumber == 1) {
-		PySys_WriteStderr("TypeError: \"index\" attribute of PVBuffer must be a PyoObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
-	}
-	
+
+    ASSERT_ARG_NOT_NULL
+
 	tmp = arg;
+	if (PyObject_HasAttrString((PyObject *)tmp, "server") == 0) {
+        PyErr_SetString(PyExc_TypeError, "\"index\" argument of PVBuffer must be a PyoObject.\n");
+        Py_RETURN_NONE;
+	}
+
 	Py_INCREF(tmp);
 	Py_XDECREF(self->index);
 
@@ -5189,23 +5159,20 @@ PVBuffer_setIndex(PVBuffer *self, PyObject *arg)
     Py_INCREF(streamtmp);
     Py_XDECREF(self->index_stream);
     self->index_stream = (Stream *)streamtmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 PVBuffer_setPitch(PVBuffer *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->pitch);
@@ -5221,12 +5188,12 @@ PVBuffer_setPitch(PVBuffer *self, PyObject *arg)
         self->pitch_stream = (Stream *)streamtmp;
 		self->modebuffer[0] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef PVBuffer_members[] = {
 {"server", T_OBJECT_EX, offsetof(PVBuffer, server), 0, "Pyo server."},
@@ -5251,8 +5218,7 @@ static PyMethodDef PVBuffer_methods[] = {
 };
 
 PyTypeObject PVBufferType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.PVBuffer_base",                                   /*tp_name*/
 sizeof(PVBuffer),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -5260,7 +5226,7 @@ sizeof(PVBuffer),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 0,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -5320,14 +5286,14 @@ PVShift_realloc_memories(PVShift *self) {
     self->hopsize = self->size / self->olaps;
     inputLatency = self->size - self->hopsize;
     self->overcount = 0;
-    self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); 
+    self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *));
     self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *));
     for (i=0; i<self->olaps; i++) {
         self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         for (j=0; j<self->hsize; j++)
             self->magn[i][j] = self->freq[i][j] = 0.0;
-    } 
+    }
     for (i=0; i<self->bufsize; i++)
         self->count[i] = inputLatency;
     PVStream_setFFTsize(self->pv_stream, self->size);
@@ -5420,24 +5386,24 @@ PVShift_process_a(PVShift *self) {
 
 static void
 PVShift_setProcMode(PVShift *self)
-{        
+{
     int procmode;
     procmode = self->modebuffer[0];
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = PVShift_process_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = PVShift_process_a;
             break;
-    } 
+    }
 }
 
 static void
 PVShift_compute_next_data_frame(PVShift *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -5447,20 +5413,20 @@ PVShift_traverse(PVShift *self, visitproc visit, void *arg)
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
     Py_VISIT(self->pv_stream);
-    Py_VISIT(self->shift);    
-    Py_VISIT(self->shift_stream);    
+    Py_VISIT(self->shift);
+    Py_VISIT(self->shift_stream);
     return 0;
 }
 
-static int 
+static int
 PVShift_clear(PVShift *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
     Py_CLEAR(self->pv_stream);
-    Py_CLEAR(self->shift);    
-    Py_CLEAR(self->shift_stream);    
+    Py_CLEAR(self->shift);
+    Py_CLEAR(self->shift_stream);
     return 0;
 }
 
@@ -5477,7 +5443,7 @@ PVShift_dealloc(PVShift* self)
     free(self->freq);
     free(self->count);
     PVShift_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -5496,16 +5462,13 @@ PVShift_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = PVShift_setProcMode;
 
     static char *kwlist[] = {"input", "shift", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|O", kwlist, &inputtmp, &shifttmp))
         Py_RETURN_NONE;
 
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVShift \"input\" argument must be a PyoPVObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVShift must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
     Py_INCREF(inputtmp);
     Py_XDECREF(self->input);
@@ -5521,7 +5484,7 @@ PVShift_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (shifttmp) {
         PyObject_CallMethod((PyObject *)self, "setShift", "O", shifttmp);
     }
- 
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL);
@@ -5549,9 +5512,8 @@ PVShift_setInput(PVShift *self, PyObject *arg)
 
     inputtmp = arg;
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVShift \"input\" argument must be a PyoPVObject.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVShift must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
 
     Py_INCREF(inputtmp);
@@ -5561,23 +5523,20 @@ PVShift_setInput(PVShift *self, PyObject *arg)
     Py_INCREF(input_streamtmp);
     Py_XDECREF(self->input_stream);
     self->input_stream = (PVStream *)input_streamtmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 PVShift_setShift(PVShift *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->shift);
@@ -5593,9 +5552,9 @@ PVShift_setShift(PVShift *self, PyObject *arg)
         self->shift_stream = (Stream *)streamtmp;
 		self->modebuffer[0] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -5621,8 +5580,7 @@ static PyMethodDef PVShift_methods[] = {
 };
 
 PyTypeObject PVShiftType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.PVShift_base",                                   /*tp_name*/
 sizeof(PVShift),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -5630,7 +5588,7 @@ sizeof(PVShift),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 0,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -5665,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;
@@ -5696,7 +5719,7 @@ PVAmpMod_realloc_memories(PVAmpMod *self) {
     inputLatency = self->size - self->hopsize;
     self->overcount = 0;
     self->factor = 8192.0 / (self->sr / self->hopsize);
-    self->pointers = (MYFLT *)realloc(self->pointers, self->hsize * sizeof(MYFLT)); 
+    self->pointers = (MYFLT *)realloc(self->pointers, self->hsize * sizeof(MYFLT));
     for (i=0; i<self->hsize; i++)
         self->pointers[i] = 0.0;
     self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *));
@@ -5706,7 +5729,7 @@ PVAmpMod_realloc_memories(PVAmpMod *self) {
         self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         for (j=0; j<self->hsize; j++)
             self->magn[i][j] = self->freq[i][j] = 0.0;
-    } 
+    }
     for (i=0; i<self->bufsize; i++)
         self->count[i] = inputLatency;
     PVStream_setFFTsize(self->pv_stream, self->size);
@@ -5728,7 +5751,7 @@ PVAmpMod_process_ii(PVAmpMod *self) {
     bfreq = PyFloat_AS_DOUBLE(self->basefreq);
     spread = PyFloat_AS_DOUBLE(self->spread);
     spread *= 0.001;
-    spread += 1.0; 
+    spread += 1.0;
 
     if (self->size != size || self->olaps != olaps) {
         self->size = size;
@@ -5769,7 +5792,7 @@ PVAmpMod_process_ai(PVAmpMod *self) {
     MYFLT *bf = Stream_getData((Stream *)self->basefreq_stream);
     spread = PyFloat_AS_DOUBLE(self->spread);
     spread *= 0.001;
-    spread += 1.0; 
+    spread += 1.0;
 
     if (self->size != size || self->olaps != olaps) {
         self->size = size;
@@ -5822,7 +5845,7 @@ PVAmpMod_process_ia(PVAmpMod *self) {
         if (count[i] >= (self->size-1)) {
             spread = sp[i];
             spread *= 0.001;
-            spread += 1.0; 
+            spread += 1.0;
             for (k=0; k<self->hsize; k++) {
                 pos = self->pointers[k];
                 self->magn[self->overcount][k] = magn[self->overcount][k] * self->table[(int)pos];
@@ -5865,7 +5888,7 @@ PVAmpMod_process_aa(PVAmpMod *self) {
             bfreq = bf[i];
             spread = sp[i];
             spread *= 0.001;
-            spread += 1.0; 
+            spread += 1.0;
             for (k=0; k<self->hsize; k++) {
                 pos = self->pointers[k];
                 self->magn[self->overcount][k] = magn[self->overcount][k] * self->table[(int)pos];
@@ -5886,30 +5909,30 @@ PVAmpMod_process_aa(PVAmpMod *self) {
 
 static void
 PVAmpMod_setProcMode(PVAmpMod *self)
-{        
+{
     int procmode;
     procmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = PVAmpMod_process_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = PVAmpMod_process_ai;
             break;
-        case 10:    
+        case 10:
             self->proc_func_ptr = PVAmpMod_process_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = PVAmpMod_process_aa;
             break;
-    } 
+    }
 }
 
 static void
 PVAmpMod_compute_next_data_frame(PVAmpMod *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -5919,24 +5942,24 @@ PVAmpMod_traverse(PVAmpMod *self, visitproc visit, void *arg)
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
     Py_VISIT(self->pv_stream);
-    Py_VISIT(self->basefreq);    
-    Py_VISIT(self->basefreq_stream);    
-    Py_VISIT(self->spread);    
-    Py_VISIT(self->spread_stream);    
+    Py_VISIT(self->basefreq);
+    Py_VISIT(self->basefreq_stream);
+    Py_VISIT(self->spread);
+    Py_VISIT(self->spread_stream);
     return 0;
 }
 
-static int 
+static int
 PVAmpMod_clear(PVAmpMod *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
     Py_CLEAR(self->pv_stream);
-    Py_CLEAR(self->basefreq);    
-    Py_CLEAR(self->basefreq_stream);    
-    Py_CLEAR(self->spread);    
-    Py_CLEAR(self->spread_stream);    
+    Py_CLEAR(self->basefreq);
+    Py_CLEAR(self->basefreq_stream);
+    Py_CLEAR(self->spread);
+    Py_CLEAR(self->spread_stream);
     return 0;
 }
 
@@ -5955,13 +5978,13 @@ PVAmpMod_dealloc(PVAmpMod* self)
     free(self->pointers);
     free(self->count);
     PVAmpMod_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)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);
@@ -5974,17 +5997,14 @@ 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};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &basefreqtmp, &spreadtmp))
+    static char *kwlist[] = {"input", "basefreq", "spread", "shape", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOi", kwlist, &inputtmp, &basefreqtmp, &spreadtmp, &shape))
         Py_RETURN_NONE;
 
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVAmpMod \"input\" argument must be a PyoPVObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVAmpMod must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
     Py_INCREF(inputtmp);
     Py_XDECREF(self->input);
@@ -6004,7 +6024,7 @@ PVAmpMod_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (spreadtmp) {
         PyObject_CallMethod((PyObject *)self, "setSpread", "O", spreadtmp);
     }
- 
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL);
@@ -6012,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);
 
@@ -6037,9 +6055,8 @@ PVAmpMod_setInput(PVAmpMod *self, PyObject *arg)
 
     inputtmp = arg;
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVAmpMod \"input\" argument must be a PyoPVObject.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVAmpMod must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
 
     Py_INCREF(inputtmp);
@@ -6049,23 +6066,20 @@ PVAmpMod_setInput(PVAmpMod *self, PyObject *arg)
     Py_INCREF(input_streamtmp);
     Py_XDECREF(self->input_stream);
     self->input_stream = (PVStream *)input_streamtmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 PVAmpMod_setBasefreq(PVAmpMod *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->basefreq);
@@ -6081,9 +6095,9 @@ PVAmpMod_setBasefreq(PVAmpMod *self, PyObject *arg)
         self->basefreq_stream = (Stream *)streamtmp;
 		self->modebuffer[0] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -6092,14 +6106,11 @@ static PyObject *
 PVAmpMod_setSpread(PVAmpMod *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->spread);
@@ -6115,9 +6126,22 @@ PVAmpMod_setSpread(PVAmpMod *self, PyObject *arg)
         self->spread_stream = (Stream *)streamtmp;
 		self->modebuffer[1] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+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;
 }
@@ -6148,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."},
@@ -6155,8 +6180,7 @@ static PyMethodDef PVAmpMod_methods[] = {
 };
 
 PyTypeObject PVAmpModType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.PVAmpMod_base",                                   /*tp_name*/
 sizeof(PVAmpMod),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -6164,7 +6188,7 @@ sizeof(PVAmpMod),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 0,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -6232,7 +6256,7 @@ PVFreqMod_realloc_memories(PVFreqMod *self) {
     inputLatency = self->size - self->hopsize;
     self->overcount = 0;
     self->factor = 8192.0 / (self->sr / self->hopsize);
-    self->pointers = (MYFLT *)realloc(self->pointers, self->hsize * sizeof(MYFLT)); 
+    self->pointers = (MYFLT *)realloc(self->pointers, self->hsize * sizeof(MYFLT));
     for (i=0; i<self->hsize; i++)
         self->pointers[i] = 0.0;
     self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *));
@@ -6242,7 +6266,7 @@ PVFreqMod_realloc_memories(PVFreqMod *self) {
         self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         for (j=0; j<self->hsize; j++)
             self->magn[i][j] = self->freq[i][j] = 0.0;
-    } 
+    }
     for (i=0; i<self->bufsize; i++)
         self->count[i] = inputLatency;
     PVStream_setFFTsize(self->pv_stream, self->size);
@@ -6264,7 +6288,7 @@ PVFreqMod_process_ii(PVFreqMod *self) {
     bfreq = PyFloat_AS_DOUBLE(self->basefreq);
     spread = PyFloat_AS_DOUBLE(self->spread);
     spread *= 0.001;
-    spread += 1.0; 
+    spread += 1.0;
 
     if (self->modebuffer[2] == 0)
         depth = PyFloat_AS_DOUBLE(self->depth);
@@ -6322,7 +6346,7 @@ PVFreqMod_process_ai(PVFreqMod *self) {
     MYFLT *bf = Stream_getData((Stream *)self->basefreq_stream);
     spread = PyFloat_AS_DOUBLE(self->spread);
     spread *= 0.001;
-    spread += 1.0; 
+    spread += 1.0;
 
     if (self->modebuffer[2] == 0)
         depth = PyFloat_AS_DOUBLE(self->depth);
@@ -6401,7 +6425,7 @@ PVFreqMod_process_ia(PVFreqMod *self) {
         if (count[i] >= (self->size-1)) {
             spread = sp[i];
             spread *= 0.001;
-            spread += 1.0; 
+            spread += 1.0;
             freqPerBin = self->sr / self->size;
             for (k=0; k<self->hsize; k++) {
                 self->magn[self->overcount][k] = self->freq[self->overcount][k] = 0.0;
@@ -6461,7 +6485,7 @@ PVFreqMod_process_aa(PVFreqMod *self) {
             bfreq = bf[i];
             spread = sp[i];
             spread *= 0.001;
-            spread += 1.0; 
+            spread += 1.0;
             freqPerBin = self->sr / self->size;
             for (k=0; k<self->hsize; k++) {
                 self->magn[self->overcount][k] = self->freq[self->overcount][k] = 0.0;
@@ -6490,30 +6514,30 @@ PVFreqMod_process_aa(PVFreqMod *self) {
 
 static void
 PVFreqMod_setProcMode(PVFreqMod *self)
-{        
+{
     int procmode;
     procmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = PVFreqMod_process_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = PVFreqMod_process_ai;
             break;
-        case 10:    
+        case 10:
             self->proc_func_ptr = PVFreqMod_process_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = PVFreqMod_process_aa;
             break;
-    } 
+    }
 }
 
 static void
 PVFreqMod_compute_next_data_frame(PVFreqMod *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -6523,28 +6547,28 @@ PVFreqMod_traverse(PVFreqMod *self, visitproc visit, void *arg)
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
     Py_VISIT(self->pv_stream);
-    Py_VISIT(self->basefreq);    
-    Py_VISIT(self->basefreq_stream);    
-    Py_VISIT(self->spread);    
-    Py_VISIT(self->spread_stream);    
-    Py_VISIT(self->depth);    
-    Py_VISIT(self->depth_stream);    
+    Py_VISIT(self->basefreq);
+    Py_VISIT(self->basefreq_stream);
+    Py_VISIT(self->spread);
+    Py_VISIT(self->spread_stream);
+    Py_VISIT(self->depth);
+    Py_VISIT(self->depth_stream);
     return 0;
 }
 
-static int 
+static int
 PVFreqMod_clear(PVFreqMod *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
     Py_CLEAR(self->pv_stream);
-    Py_CLEAR(self->basefreq);    
-    Py_CLEAR(self->basefreq_stream);    
-    Py_CLEAR(self->spread);    
-    Py_CLEAR(self->spread_stream);    
-    Py_CLEAR(self->depth);    
-    Py_CLEAR(self->depth_stream);    
+    Py_CLEAR(self->basefreq);
+    Py_CLEAR(self->basefreq_stream);
+    Py_CLEAR(self->spread);
+    Py_CLEAR(self->spread_stream);
+    Py_CLEAR(self->depth);
+    Py_CLEAR(self->depth_stream);
     return 0;
 }
 
@@ -6563,13 +6587,13 @@ PVFreqMod_dealloc(PVFreqMod* self)
     free(self->pointers);
     free(self->count);
     PVFreqMod_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)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);
@@ -6583,17 +6607,14 @@ 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};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &basefreqtmp, &spreadtmp, &depthtmp))
+    static char *kwlist[] = {"input", "basefreq", "spread", "depth", "shape", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOi", kwlist, &inputtmp, &basefreqtmp, &spreadtmp, &depthtmp, &shape))
         Py_RETURN_NONE;
 
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVFreqMod \"input\" argument must be a PyoPVObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVFreqMod must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
     Py_INCREF(inputtmp);
     Py_XDECREF(self->input);
@@ -6617,7 +6638,7 @@ PVFreqMod_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (depthtmp) {
         PyObject_CallMethod((PyObject *)self, "setDepth", "O", depthtmp);
     }
- 
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL);
@@ -6625,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);
 
@@ -6650,9 +6669,8 @@ PVFreqMod_setInput(PVFreqMod *self, PyObject *arg)
 
     inputtmp = arg;
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVFreqMod \"input\" argument must be a PyoPVObject.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVFreqMod must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
 
     Py_INCREF(inputtmp);
@@ -6662,23 +6680,20 @@ PVFreqMod_setInput(PVFreqMod *self, PyObject *arg)
     Py_INCREF(input_streamtmp);
     Py_XDECREF(self->input_stream);
     self->input_stream = (PVStream *)input_streamtmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 PVFreqMod_setBasefreq(PVFreqMod *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->basefreq);
@@ -6694,9 +6709,9 @@ PVFreqMod_setBasefreq(PVFreqMod *self, PyObject *arg)
         self->basefreq_stream = (Stream *)streamtmp;
 		self->modebuffer[0] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -6705,14 +6720,11 @@ static PyObject *
 PVFreqMod_setSpread(PVFreqMod *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->spread);
@@ -6728,9 +6740,9 @@ PVFreqMod_setSpread(PVFreqMod *self, PyObject *arg)
         self->spread_stream = (Stream *)streamtmp;
 		self->modebuffer[1] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -6739,14 +6751,11 @@ static PyObject *
 PVFreqMod_setDepth(PVFreqMod *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->depth);
@@ -6762,9 +6771,22 @@ PVFreqMod_setDepth(PVFreqMod *self, PyObject *arg)
         self->depth_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+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;
 }
@@ -6797,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."},
@@ -6804,8 +6827,7 @@ static PyMethodDef PVFreqMod_methods[] = {
 };
 
 PyTypeObject PVFreqModType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.PVFreqMod_base",                                   /*tp_name*/
 sizeof(PVFreqMod),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -6813,7 +6835,7 @@ sizeof(PVFreqMod),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 0,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -6896,22 +6918,22 @@ PVBufLoops_realloc_memories(PVBufLoops *self) {
         self->speeds[i] = 1.0;
         self->pointers[i] = 0.0;
     }
-    self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); 
+    self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *));
     self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *));
     for (i=0; i<self->olaps; i++) {
         self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         for (j=0; j<self->hsize; j++)
             self->magn[i][j] = self->freq[i][j] = 0.0;
-    } 
-    self->magn_buf = (MYFLT **)realloc(self->magn_buf, self->numFrames * sizeof(MYFLT *)); 
+    }
+    self->magn_buf = (MYFLT **)realloc(self->magn_buf, self->numFrames * sizeof(MYFLT *));
     self->freq_buf = (MYFLT **)realloc(self->freq_buf, self->numFrames * sizeof(MYFLT *));
     for (i=0; i<self->numFrames; i++) {
         self->magn_buf[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         self->freq_buf[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         for (j=0; j<self->hsize; j++)
             self->magn_buf[i][j] = self->freq_buf[i][j] = 0.0;
-    } 
+    }
     for (i=0; i<self->bufsize; i++)
         self->count[i] = inputLatency;
     PVStream_setFFTsize(self->pv_stream, self->size);
@@ -6941,12 +6963,12 @@ PVBufLoops_setSpeeds(PVBufLoops *self, MYFLT low, MYFLT high) {
             for (i=0; i<self->hsize; i++)
                 self->speeds[i] = low + tmp * (1.0 - MYPOW(1.0-(float)i/self->hsize, 3.0));
             break;
-        case 3: /* random uniform */ 
+        case 3: /* random uniform */
             tmp = high - low;
             for (i=0; i<self->hsize; i++)
-                self->speeds[i] = RANDOM_UNIFORM * tmp + low; 
+                self->speeds[i] = RANDOM_UNIFORM * tmp + low;
             break;
-        case 4: /* random exponential min */ 
+        case 4: /* random exponential min */
             for (i=0; i<self->hsize; i++) {
                 tmp = -MYLOG(RANDOM_UNIFORM) * 0.05;
                 tmp = tmp < 0 ? 0.0 : tmp;
@@ -6954,15 +6976,15 @@ PVBufLoops_setSpeeds(PVBufLoops *self, MYFLT low, MYFLT high) {
                 self->speeds[i] = tmp * (high - low) + low;
             }
             break;
-        case 5: /* random exponential max */ 
+        case 5: /* random exponential max */
             for (i=0; i<self->hsize; i++) {
                 tmp = 1.0 - (-MYLOG(RANDOM_UNIFORM) * 0.05);
                 tmp = tmp < 0 ? 0.0 : tmp;
                 tmp = tmp > 1.0 ? 1.0 : tmp;
-                self->speeds[i] = tmp * (high - low) + low; 
+                self->speeds[i] = tmp * (high - low) + low;
             }
             break;
-        case 6: /* random bi-exponential */ 
+        case 6: /* random bi-exponential */
             for (i=0; i<self->hsize; i++) {
                 tmp = RANDOM_UNIFORM * 2.0;
                 if (tmp > 1.0)
@@ -6971,7 +6993,7 @@ PVBufLoops_setSpeeds(PVBufLoops *self, MYFLT low, MYFLT high) {
                     tmp = 0.5 * (MYLOG(tmp) * 0.05) + 0.5;
                 tmp = tmp < 0 ? 0.0 : tmp;
                 tmp = tmp > 1.0 ? 1.0 : tmp;
-                self->speeds[i] = tmp * (high - low) + low; 
+                self->speeds[i] = tmp * (high - low) + low;
             }
             break;
         default: /* linear */
@@ -7049,14 +7071,14 @@ PVBufLoops_process(PVBufLoops *self) {
 
 static void
 PVBufLoops_setProcMode(PVBufLoops *self)
-{        
+{
     self->proc_func_ptr = PVBufLoops_process;
 }
 
 static void
 PVBufLoops_compute_next_data_frame(PVBufLoops *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -7073,7 +7095,7 @@ PVBufLoops_traverse(PVBufLoops *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 PVBufLoops_clear(PVBufLoops *self)
 {
     pyo_CLEAR
@@ -7108,7 +7130,7 @@ PVBufLoops_dealloc(PVBufLoops* self)
     free(self->speeds);
     free(self->pointers);
     PVBufLoops_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -7123,7 +7145,7 @@ PVBufLoops_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->high = PyFloat_FromDouble(1.0);
     self->last_low = self->last_high = -1.0;
     self->mode = 0;
-    self->last_mode = -1;    
+    self->last_mode = -1;
     self->size = 1024;
     self->olaps = 4;
     self->length = 1.0;
@@ -7132,16 +7154,13 @@ PVBufLoops_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = PVBufLoops_setProcMode;
 
     static char *kwlist[] = {"input", "low", "high", "mode", "length", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_OOIF, kwlist, &inputtmp, &lowtmp, &hightmp, &self->mode, &self->length))
         Py_RETURN_NONE;
 
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVBufLoops \"input\" argument must be a PyoPVObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVBufLoops must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
     Py_INCREF(inputtmp);
     Py_XDECREF(self->input);
@@ -7161,7 +7180,7 @@ PVBufLoops_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (hightmp) {
         PyObject_CallMethod((PyObject *)self, "setHigh", "O", hightmp);
     }
- 
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL);
@@ -7179,12 +7198,12 @@ static PyObject * PVBufLoops_getServer(PVBufLoops* self) { GET_SERVER };
 static PyObject * PVBufLoops_getStream(PVBufLoops* self) { GET_STREAM };
 static PyObject * PVBufLoops_getPVStream(PVBufLoops* self) { GET_PV_STREAM };
 
-static PyObject * PVBufLoops_play(PVBufLoops *self, PyObject *args, PyObject *kwds) { 
+static PyObject * PVBufLoops_play(PVBufLoops *self, PyObject *args, PyObject *kwds) {
     int k;
     for (k=0; k<self->hsize; k++)
         self->pointers[k] = 0.0;
     self->framecount = 0;
-    PLAY 
+    PLAY
 };
 
 static PyObject * PVBufLoops_stop(PVBufLoops *self) { STOP };
@@ -7196,9 +7215,8 @@ PVBufLoops_setInput(PVBufLoops *self, PyObject *arg)
 
     inputtmp = arg;
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVBufLoops \"input\" argument must be a PyoPVObject.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVBufLoops must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
 
     Py_INCREF(inputtmp);
@@ -7208,23 +7226,20 @@ PVBufLoops_setInput(PVBufLoops *self, PyObject *arg)
     Py_INCREF(input_streamtmp);
     Py_XDECREF(self->input_stream);
     self->input_stream = (PVStream *)input_streamtmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 PVBufLoops_setLow(PVBufLoops *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->low);
@@ -7243,20 +7258,17 @@ PVBufLoops_setLow(PVBufLoops *self, PyObject *arg)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 PVBufLoops_setHigh(PVBufLoops *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->high);
@@ -7275,19 +7287,17 @@ PVBufLoops_setHigh(PVBufLoops *self, PyObject *arg)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 PVBufLoops_setMode(PVBufLoops *self, PyObject *arg)
 {
     int tmp;
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isInt = PyInt_Check(arg);
-	
+
 	if (isInt == 1) {
 		tmp = PyInt_AsLong(arg);
         if (tmp >= 0 && tmp < 7)
@@ -7296,7 +7306,7 @@ PVBufLoops_setMode(PVBufLoops *self, PyObject *arg)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 PVBufLoops_reset(PVBufLoops *self) {
@@ -7332,8 +7342,7 @@ static PyMethodDef PVBufLoops_methods[] = {
 };
 
 PyTypeObject PVBufLoopsType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.PVBufLoops_base",                                   /*tp_name*/
 sizeof(PVBufLoops),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -7341,7 +7350,7 @@ sizeof(PVBufLoops),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 0,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -7413,22 +7422,22 @@ PVBufTabLoops_realloc_memories(PVBufTabLoops *self) {
     for (i=0; i<self->hsize; i++) {
         self->pointers[i] = 0.0;
     }
-    self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); 
+    self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *));
     self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *));
     for (i=0; i<self->olaps; i++) {
         self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         for (j=0; j<self->hsize; j++)
             self->magn[i][j] = self->freq[i][j] = 0.0;
-    } 
-    self->magn_buf = (MYFLT **)realloc(self->magn_buf, self->numFrames * sizeof(MYFLT *)); 
+    }
+    self->magn_buf = (MYFLT **)realloc(self->magn_buf, self->numFrames * sizeof(MYFLT *));
     self->freq_buf = (MYFLT **)realloc(self->freq_buf, self->numFrames * sizeof(MYFLT *));
     for (i=0; i<self->numFrames; i++) {
         self->magn_buf[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         self->freq_buf[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         for (j=0; j<self->hsize; j++)
             self->magn_buf[i][j] = self->freq_buf[i][j] = 0.0;
-    } 
+    }
     for (i=0; i<self->bufsize; i++)
         self->count[i] = inputLatency;
     PVStream_setFFTsize(self->pv_stream, self->size);
@@ -7494,14 +7503,14 @@ PVBufTabLoops_process(PVBufTabLoops *self) {
 
 static void
 PVBufTabLoops_setProcMode(PVBufTabLoops *self)
-{        
+{
     self->proc_func_ptr = PVBufTabLoops_process;
 }
 
 static void
 PVBufTabLoops_compute_next_data_frame(PVBufTabLoops *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -7515,7 +7524,7 @@ PVBufTabLoops_traverse(PVBufTabLoops *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 PVBufTabLoops_clear(PVBufTabLoops *self)
 {
     pyo_CLEAR
@@ -7546,7 +7555,7 @@ PVBufTabLoops_dealloc(PVBufTabLoops* self)
     free(self->count);
     free(self->pointers);
     PVBufTabLoops_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -7565,16 +7574,13 @@ PVBufTabLoops_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = PVBufTabLoops_setProcMode;
 
     static char *kwlist[] = {"input", "speed", "length", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_OO_F, kwlist, &inputtmp, &speedtmp, &self->length))
         Py_RETURN_NONE;
 
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVBufTabLoops \"input\" argument must be a PyoPVObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVBufTabLoops must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
     Py_INCREF(inputtmp);
     Py_XDECREF(self->input);
@@ -7589,7 +7595,7 @@ PVBufTabLoops_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
     Py_XDECREF(self->speed);
     self->speed = PyObject_CallMethod((PyObject *)speedtmp, "getTableStream", "");
- 
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL);
@@ -7607,12 +7613,12 @@ static PyObject * PVBufTabLoops_getServer(PVBufTabLoops* self) { GET_SERVER };
 static PyObject * PVBufTabLoops_getStream(PVBufTabLoops* self) { GET_STREAM };
 static PyObject * PVBufTabLoops_getPVStream(PVBufTabLoops* self) { GET_PV_STREAM };
 
-static PyObject * PVBufTabLoops_play(PVBufTabLoops *self, PyObject *args, PyObject *kwds) { 
+static PyObject * PVBufTabLoops_play(PVBufTabLoops *self, PyObject *args, PyObject *kwds) {
     int k;
     for (k=0; k<self->hsize; k++)
         self->pointers[k] = 0.0;
     self->framecount = 0;
-    PLAY 
+    PLAY
 };
 
 static PyObject * PVBufTabLoops_stop(PVBufTabLoops *self) { STOP };
@@ -7624,9 +7630,8 @@ PVBufTabLoops_setInput(PVBufTabLoops *self, PyObject *arg)
 
     inputtmp = arg;
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVBufTabLoops \"input\" argument must be a PyoPVObject.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVBufTabLoops must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
 
     Py_INCREF(inputtmp);
@@ -7636,28 +7641,25 @@ PVBufTabLoops_setInput(PVBufTabLoops *self, PyObject *arg)
     Py_INCREF(input_streamtmp);
     Py_XDECREF(self->input_stream);
     self->input_stream = (PVStream *)input_streamtmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 PVBufTabLoops_setSpeed(PVBufTabLoops *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	tmp = arg;
 	Py_DECREF(self->speed);
     self->speed = PyObject_CallMethod((PyObject *)tmp, "getTableStream", "");
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 PVBufTabLoops_reset(PVBufTabLoops *self) {
@@ -7690,8 +7692,7 @@ static PyMethodDef PVBufTabLoops_methods[] = {
 };
 
 PyTypeObject PVBufTabLoopsType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.PVBufTabLoops_base",                                   /*tp_name*/
 sizeof(PVBufTabLoops),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -7699,7 +7700,7 @@ sizeof(PVBufTabLoops),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 0,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -7758,14 +7759,14 @@ PVMix_realloc_memories(PVMix *self) {
     self->hopsize = self->size / self->olaps;
     inputLatency = self->size - self->hopsize;
     self->overcount = 0;
-    self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *)); 
+    self->magn = (MYFLT **)realloc(self->magn, self->olaps * sizeof(MYFLT *));
     self->freq = (MYFLT **)realloc(self->freq, self->olaps * sizeof(MYFLT *));
     for (i=0; i<self->olaps; i++) {
         self->magn[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         self->freq[i] = (MYFLT *)malloc(self->hsize * sizeof(MYFLT));
         for (j=0; j<self->hsize; j++)
             self->magn[i][j] = self->freq[i][j] = 0.0;
-    } 
+    }
     for (i=0; i<self->bufsize; i++)
         self->count[i] = inputLatency;
     PVStream_setFFTsize(self->pv_stream, self->size);
@@ -7821,7 +7822,7 @@ PVMix_setProcMode(PVMix *self)
 static void
 PVMix_compute_next_data_frame(PVMix *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -7836,7 +7837,7 @@ PVMix_traverse(PVMix *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 PVMix_clear(PVMix *self)
 {
     pyo_CLEAR
@@ -7861,7 +7862,7 @@ PVMix_dealloc(PVMix* self)
     free(self->freq);
     free(self->count);
     PVMix_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -7879,16 +7880,13 @@ PVMix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = PVMix_setProcMode;
 
     static char *kwlist[] = {"input", "input2", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &inputtmp, &input2tmp))
         Py_RETURN_NONE;
 
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVMix \"input\" argument must be a PyoPVObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVMix must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
     Py_INCREF(inputtmp);
     Py_XDECREF(self->input);
@@ -7899,11 +7897,8 @@ PVMix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->input_stream = (PVStream *)input_streamtmp;
 
     if ( PyObject_HasAttrString((PyObject *)input2tmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVMix \"input2\" argument must be a PyoPVObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"input2\" argument of PVMix must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
     Py_INCREF(input2tmp);
     Py_XDECREF(self->input2);
@@ -7915,7 +7910,7 @@ PVMix_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
     self->size = PVStream_getFFTsize(self->input_stream);
     self->olaps = PVStream_getOlaps(self->input_stream);
- 
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     MAKE_NEW_PV_STREAM(self->pv_stream, &PVStreamType, NULL);
@@ -7943,9 +7938,8 @@ PVMix_setInput(PVMix *self, PyObject *arg)
 
     inputtmp = arg;
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVMix \"input\" argument must be a PyoPVObject.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        PyErr_SetString(PyExc_TypeError, "\"input\" argument of PVMix must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
 
     Py_INCREF(inputtmp);
@@ -7955,10 +7949,10 @@ PVMix_setInput(PVMix *self, PyObject *arg)
     Py_INCREF(input_streamtmp);
     Py_XDECREF(self->input_stream);
     self->input_stream = (PVStream *)input_streamtmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 PVMix_setInput2(PVMix *self, PyObject *arg)
@@ -7967,9 +7961,8 @@ PVMix_setInput2(PVMix *self, PyObject *arg)
 
     inputtmp = arg;
     if ( PyObject_HasAttrString((PyObject *)inputtmp, "pv_stream") == 0 ) {
-        PySys_WriteStderr("TypeError: PVMix \"input2\" argument must be a PyoPVObject.\n");
-        Py_INCREF(Py_None);
-        return Py_None;
+        PyErr_SetString(PyExc_TypeError, "\"input2\" argument of PVMix must be a PyoPVObject.\n");
+        Py_RETURN_NONE;
     }
 
     Py_INCREF(inputtmp);
@@ -7979,10 +7972,10 @@ PVMix_setInput2(PVMix *self, PyObject *arg)
     Py_INCREF(input_streamtmp);
     Py_XDECREF(self->input2_stream);
     self->input2_stream = (PVStream *)input_streamtmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef PVMix_members[] = {
 {"server", T_OBJECT_EX, offsetof(PVMix, server), 0, "Pyo server."},
@@ -8005,8 +7998,7 @@ static PyMethodDef PVMix_methods[] = {
 };
 
 PyTypeObject PVMixType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.PVMix_base",                                   /*tp_name*/
 sizeof(PVMix),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -8014,7 +8006,7 @@ sizeof(PVMix),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 0,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -8044,4 +8036,4 @@ PVMix_members,                                 /* tp_members */
 0,                          /* tp_init */
 0,                                              /* tp_alloc */
 PVMix_new,                                     /* tp_new */
-};
+};
\ No newline at end of file
diff --git a/src/objects/randommodule.c b/src/objects/randommodule.c
index b1e4e85..af31037 100644
--- a/src/objects/randommodule.c
+++ b/src/objects/randommodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include <math.h>
 #include "structmember.h"
 #include "pyomodule.h"
@@ -38,7 +39,7 @@ typedef struct {
     MYFLT oldValue;
     MYFLT diff;
     MYFLT time;
-    int modebuffer[5]; // need at least 2 slots for mul & add 
+    int modebuffer[5]; // need at least 2 slots for mul & add
 } Randi;
 
 static void
@@ -50,7 +51,7 @@ Randi_generate_iii(Randi *self) {
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
     MYFLT range = ma - mi;
     inc = fr / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->time += inc;
         if (self->time < 0.0)
@@ -58,7 +59,7 @@ Randi_generate_iii(Randi *self) {
         else if (self->time >= 1.0) {
             self->time -= 1.0;
             self->oldValue = self->value;
-            self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi;
+            self->value = range * RANDOM_UNIFORM + mi;
             self->diff = self->value - self->oldValue;
         }
         self->data[i] = self->oldValue + self->diff * self->time;
@@ -73,7 +74,7 @@ Randi_generate_aii(Randi *self) {
     MYFLT ma = PyFloat_AS_DOUBLE(self->max);
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
     inc = fr / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         range = ma - mi[i];
         self->time += inc;
@@ -82,7 +83,7 @@ Randi_generate_aii(Randi *self) {
         else if (self->time >= 1.0) {
             self->time -= 1.0;
             self->oldValue = self->value;
-            self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi[i];
+            self->value = range * RANDOM_UNIFORM + mi[i];
             self->diff = self->value - self->oldValue;
         }
         self->data[i] = self->oldValue + self->diff * self->time;
@@ -97,7 +98,7 @@ Randi_generate_iai(Randi *self) {
     MYFLT *ma = Stream_getData((Stream *)self->max_stream);
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
     inc = fr / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         range = ma[i] - mi;
         self->time += inc;
@@ -106,7 +107,7 @@ Randi_generate_iai(Randi *self) {
         else if (self->time >= 1.0) {
             self->time -= 1.0;
             self->oldValue = self->value;
-            self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi;
+            self->value = range * RANDOM_UNIFORM + mi;
             self->diff = self->value - self->oldValue;
         }
         self->data[i] = self->oldValue + self->diff * self->time;
@@ -121,7 +122,7 @@ Randi_generate_aai(Randi *self) {
     MYFLT *ma = Stream_getData((Stream *)self->max_stream);
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
     inc = fr / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         range = ma[i] - mi[i];
         self->time += inc;
@@ -130,7 +131,7 @@ Randi_generate_aai(Randi *self) {
         else if (self->time >= 1.0) {
             self->time -= 1.0;
             self->oldValue = self->value;
-            self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi[i];
+            self->value = range * RANDOM_UNIFORM + mi[i];
             self->diff = self->value - self->oldValue;
         }
         self->data[i] = self->oldValue + self->diff * self->time;
@@ -145,7 +146,7 @@ Randi_generate_iia(Randi *self) {
     MYFLT ma = PyFloat_AS_DOUBLE(self->max);
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
     MYFLT range = ma - mi;
-    
+
     for (i=0; i<self->bufsize; i++) {
         inc = fr[i] / self->sr;
         self->time += inc;
@@ -154,7 +155,7 @@ Randi_generate_iia(Randi *self) {
         else if (self->time >= 1.0) {
             self->time -= 1.0;
             self->oldValue = self->value;
-            self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi;
+            self->value = range * RANDOM_UNIFORM + mi;
             self->diff = self->value - self->oldValue;
         }
         self->data[i] = self->oldValue + self->diff * self->time;
@@ -168,7 +169,7 @@ Randi_generate_aia(Randi *self) {
     MYFLT *mi = Stream_getData((Stream *)self->min_stream);
     MYFLT ma = PyFloat_AS_DOUBLE(self->max);
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inc = fr[i] / self->sr;
         range = ma - mi[i];
@@ -178,7 +179,7 @@ Randi_generate_aia(Randi *self) {
         else if (self->time >= 1.0) {
             self->time -= 1.0;
             self->oldValue = self->value;
-            self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi[i];
+            self->value = range * RANDOM_UNIFORM + mi[i];
             self->diff = self->value - self->oldValue;
         }
         self->data[i] = self->oldValue + self->diff * self->time;
@@ -192,7 +193,7 @@ Randi_generate_iaa(Randi *self) {
     MYFLT mi = PyFloat_AS_DOUBLE(self->min);
     MYFLT *ma = Stream_getData((Stream *)self->max_stream);
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inc = fr[i] / self->sr;
         range = ma[i] - mi;
@@ -202,7 +203,7 @@ Randi_generate_iaa(Randi *self) {
         else if (self->time >= 1.0) {
             self->time -= 1.0;
             self->oldValue = self->value;
-            self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi;
+            self->value = range * RANDOM_UNIFORM + mi;
             self->diff = self->value - self->oldValue;
         }
         self->data[i] = self->oldValue + self->diff * self->time;
@@ -216,7 +217,7 @@ Randi_generate_aaa(Randi *self) {
     MYFLT *mi = Stream_getData((Stream *)self->min_stream);
     MYFLT *ma = Stream_getData((Stream *)self->max_stream);
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inc = fr[i] / self->sr;
         range = ma[i] - mi[i];
@@ -226,7 +227,7 @@ Randi_generate_aaa(Randi *self) {
         else if (self->time >= 1.0) {
             self->time -= 1.0;
             self->oldValue = self->value;
-            self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi[i];
+            self->value = range * RANDOM_UNIFORM + mi[i];
             self->diff = self->value - self->oldValue;
         }
         self->data[i] = self->oldValue + self->diff * self->time;
@@ -249,68 +250,68 @@ Randi_setProcMode(Randi *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Randi_generate_iii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Randi_generate_aii;
             break;
-        case 10:    
+        case 10:
             self->proc_func_ptr = Randi_generate_iai;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Randi_generate_aai;
             break;
-        case 100:    
+        case 100:
             self->proc_func_ptr = Randi_generate_iia;
             break;
-        case 101:    
+        case 101:
             self->proc_func_ptr = Randi_generate_aia;
             break;
-        case 110:    
+        case 110:
             self->proc_func_ptr = Randi_generate_iaa;
             break;
-        case 111:    
+        case 111:
             self->proc_func_ptr = Randi_generate_aaa;
-            break;            
-    } 
+            break;
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Randi_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Randi_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Randi_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Randi_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Randi_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Randi_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Randi_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Randi_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Randi_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 Randi_compute_next_data_frame(Randi *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -320,23 +321,23 @@ Randi_traverse(Randi *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->freq);
     Py_VISIT(self->freq_stream);
-    Py_VISIT(self->min);    
-    Py_VISIT(self->min_stream);    
-    Py_VISIT(self->max);    
-    Py_VISIT(self->max_stream);    
+    Py_VISIT(self->min);
+    Py_VISIT(self->min_stream);
+    Py_VISIT(self->max);
+    Py_VISIT(self->max_stream);
     return 0;
 }
 
-static int 
+static int
 Randi_clear(Randi *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->freq);
     Py_CLEAR(self->freq_stream);
-    Py_CLEAR(self->min);    
-    Py_CLEAR(self->min_stream);    
-    Py_CLEAR(self->max);    
-    Py_CLEAR(self->max_stream);    
+    Py_CLEAR(self->min);
+    Py_CLEAR(self->min_stream);
+    Py_CLEAR(self->max);
+    Py_CLEAR(self->max_stream);
     return 0;
 }
 
@@ -345,7 +346,7 @@ Randi_dealloc(Randi* self)
 {
     pyo_DEALLOC
     Randi_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -356,7 +357,7 @@ Randi_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *mintmp=NULL, *maxtmp=NULL, *freqtmp=NULL, *multmp=NULL, *addtmp=NULL;
     Randi *self;
     self = (Randi *)type->tp_alloc(type, 0);
-    
+
     self->min = PyFloat_FromDouble(0.);
     self->max = PyFloat_FromDouble(1.);
     self->freq = PyFloat_FromDouble(1.);
@@ -367,20 +368,20 @@ Randi_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
 	self->modebuffer[4] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Randi_compute_next_data_frame);
     self->mode_func_ptr = Randi_setProcMode;
 
     static char *kwlist[] = {"min", "max", "freq", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOO", kwlist, &mintmp, &maxtmp, &freqtmp, &multmp, &addtmp))
-        Py_RETURN_NONE; 
+        Py_RETURN_NONE;
 
     if (mintmp) {
         PyObject_CallMethod((PyObject *)self, "setMin", "O", mintmp);
     }
-    
+
     if (maxtmp) {
         PyObject_CallMethod((PyObject *)self, "setMax", "O", maxtmp);
     }
@@ -388,15 +389,15 @@ Randi_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    
+
     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);
 
     Server_generateSeed((Server *)self->server, RANDI_ID);
@@ -409,7 +410,7 @@ Randi_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         ma = PyFloat_AS_DOUBLE(self->max);
     else
         ma = Stream_getData((Stream *)self->max_stream)[0];
-    
+
     self->value = self->oldValue = (mi + ma) * 0.5;
 
     (*self->mode_func_ptr)(self);
@@ -419,10 +420,10 @@ Randi_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Randi_getServer(Randi* self) { GET_SERVER };
 static PyObject * Randi_getStream(Randi* self) { GET_STREAM };
-static PyObject * Randi_setMul(Randi *self, PyObject *arg) { SET_MUL };	
-static PyObject * Randi_setAdd(Randi *self, PyObject *arg) { SET_ADD };	
-static PyObject * Randi_setSub(Randi *self, PyObject *arg) { SET_SUB };	
-static PyObject * Randi_setDiv(Randi *self, PyObject *arg) { SET_DIV };	
+static PyObject * Randi_setMul(Randi *self, PyObject *arg) { SET_MUL };
+static PyObject * Randi_setAdd(Randi *self, PyObject *arg) { SET_ADD };
+static PyObject * Randi_setSub(Randi *self, PyObject *arg) { SET_SUB };
+static PyObject * Randi_setDiv(Randi *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Randi_play(Randi *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Randi_out(Randi *self, PyObject *args, PyObject *kwds) { OUT };
@@ -441,14 +442,11 @@ static PyObject *
 Randi_setMin(Randi *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->min);
@@ -464,25 +462,22 @@ Randi_setMin(Randi *self, PyObject *arg)
         self->min_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Randi_setMax(Randi *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->max);
@@ -498,25 +493,22 @@ Randi_setMax(Randi *self, PyObject *arg)
         self->max_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Randi_setFreq(Randi *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -532,12 +524,12 @@ Randi_setFreq(Randi *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[4] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Randi_members[] = {
 {"server", T_OBJECT_EX, offsetof(Randi, server), 0, "Pyo server."},
@@ -570,7 +562,7 @@ static PyNumberMethods Randi_as_number = {
 (binaryfunc)Randi_add,                         /*nb_add*/
 (binaryfunc)Randi_sub,                         /*nb_subtract*/
 (binaryfunc)Randi_multiply,                    /*nb_multiply*/
-(binaryfunc)Randi_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -584,16 +576,16 @@ static PyNumberMethods Randi_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)Randi_inplace_add,                 /*inplace_add*/
 (binaryfunc)Randi_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)Randi_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)Randi_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -602,15 +594,14 @@ static PyNumberMethods Randi_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)Randi_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)Randi_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject RandiType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Randi_base",                                   /*tp_name*/
 sizeof(Randi),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -618,7 +609,7 @@ sizeof(Randi),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &Randi_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -663,7 +654,7 @@ typedef struct {
     Stream *freq_stream;
     MYFLT value;
     MYFLT time;
-    int modebuffer[5]; // need at least 2 slots for mul & add 
+    int modebuffer[5]; // need at least 2 slots for mul & add
 } Randh;
 
 static void
@@ -675,14 +666,14 @@ Randh_generate_iii(Randh *self) {
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
     MYFLT range = ma - mi;
     inc = fr / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->time += inc;
         if (self->time < 0.0)
             self->time += 1.0;
         else if (self->time >= 1.0) {
             self->time -= 1.0;
-            self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi;
+            self->value = range * RANDOM_UNIFORM + mi;
         }
         self->data[i] = self->value;
     }
@@ -696,7 +687,7 @@ Randh_generate_aii(Randh *self) {
     MYFLT ma = PyFloat_AS_DOUBLE(self->max);
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
     inc = fr / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         range = ma - mi[i];
         self->time += inc;
@@ -704,7 +695,7 @@ Randh_generate_aii(Randh *self) {
             self->time += 1.0;
         else if (self->time >= 1.0) {
             self->time -= 1.0;
-            self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi[i];
+            self->value = range * RANDOM_UNIFORM + mi[i];
         }
         self->data[i] = self->value;
     }
@@ -718,7 +709,7 @@ Randh_generate_iai(Randh *self) {
     MYFLT *ma = Stream_getData((Stream *)self->max_stream);
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
     inc = fr / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         range = ma[i] - mi;
         self->time += inc;
@@ -726,7 +717,7 @@ Randh_generate_iai(Randh *self) {
             self->time += 1.0;
         else if (self->time >= 1.0) {
             self->time -= 1.0;
-            self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi;
+            self->value = range * RANDOM_UNIFORM + mi;
         }
         self->data[i] = self->value;
     }
@@ -740,7 +731,7 @@ Randh_generate_aai(Randh *self) {
     MYFLT *ma = Stream_getData((Stream *)self->max_stream);
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
     inc = fr / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         range = ma[i] - mi[i];
         self->time += inc;
@@ -748,7 +739,7 @@ Randh_generate_aai(Randh *self) {
             self->time += 1.0;
         else if (self->time >= 1.0) {
             self->time -= 1.0;
-            self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi[i];
+            self->value = range * RANDOM_UNIFORM + mi[i];
         }
         self->data[i] = self->value;
     }
@@ -762,7 +753,7 @@ Randh_generate_iia(Randh *self) {
     MYFLT ma = PyFloat_AS_DOUBLE(self->max);
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
     MYFLT range = ma - mi;
-    
+
     for (i=0; i<self->bufsize; i++) {
         inc = fr[i] / self->sr;
         self->time += inc;
@@ -770,7 +761,7 @@ Randh_generate_iia(Randh *self) {
             self->time += 1.0;
         else if (self->time >= 1.0) {
             self->time -= 1.0;
-            self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi;
+            self->value = range * RANDOM_UNIFORM + mi;
         }
         self->data[i] = self->value;
     }
@@ -783,7 +774,7 @@ Randh_generate_aia(Randh *self) {
     MYFLT *mi = Stream_getData((Stream *)self->min_stream);
     MYFLT ma = PyFloat_AS_DOUBLE(self->max);
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inc = fr[i] / self->sr;
         range = ma - mi[i];
@@ -792,7 +783,7 @@ Randh_generate_aia(Randh *self) {
             self->time += 1.0;
         else if (self->time >= 1.0) {
             self->time -= 1.0;
-            self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi[i];
+            self->value = range * RANDOM_UNIFORM + mi[i];
         }
         self->data[i] = self->value;
     }
@@ -805,7 +796,7 @@ Randh_generate_iaa(Randh *self) {
     MYFLT mi = PyFloat_AS_DOUBLE(self->min);
     MYFLT *ma = Stream_getData((Stream *)self->max_stream);
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inc = fr[i] / self->sr;
         range = ma[i] - mi;
@@ -814,7 +805,7 @@ Randh_generate_iaa(Randh *self) {
             self->time += 1.0;
         else if (self->time >= 1.0) {
             self->time -= 1.0;
-            self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi;
+            self->value = range * RANDOM_UNIFORM + mi;
         }
         self->data[i] = self->value;
     }
@@ -827,7 +818,7 @@ Randh_generate_aaa(Randh *self) {
     MYFLT *mi = Stream_getData((Stream *)self->min_stream);
     MYFLT *ma = Stream_getData((Stream *)self->max_stream);
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inc = fr[i] / self->sr;
         range = ma[i] - mi[i];
@@ -836,7 +827,7 @@ Randh_generate_aaa(Randh *self) {
             self->time += 1.0;
         else if (self->time >= 1.0) {
             self->time -= 1.0;
-            self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi[i];
+            self->value = range * RANDOM_UNIFORM + mi[i];
         }
         self->data[i] = self->value;
     }
@@ -858,68 +849,68 @@ Randh_setProcMode(Randh *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Randh_generate_iii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Randh_generate_aii;
             break;
-        case 10:    
+        case 10:
             self->proc_func_ptr = Randh_generate_iai;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Randh_generate_aai;
             break;
-        case 100:    
+        case 100:
             self->proc_func_ptr = Randh_generate_iia;
             break;
-        case 101:    
+        case 101:
             self->proc_func_ptr = Randh_generate_aia;
             break;
-        case 110:    
+        case 110:
             self->proc_func_ptr = Randh_generate_iaa;
             break;
-        case 111:    
+        case 111:
             self->proc_func_ptr = Randh_generate_aaa;
-            break;            
-    } 
+            break;
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Randh_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Randh_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Randh_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Randh_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Randh_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Randh_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Randh_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Randh_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Randh_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 Randh_compute_next_data_frame(Randh *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -929,23 +920,23 @@ Randh_traverse(Randh *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->freq);
     Py_VISIT(self->freq_stream);
-    Py_VISIT(self->min);    
-    Py_VISIT(self->min_stream);    
-    Py_VISIT(self->max);    
-    Py_VISIT(self->max_stream);    
+    Py_VISIT(self->min);
+    Py_VISIT(self->min_stream);
+    Py_VISIT(self->max);
+    Py_VISIT(self->max_stream);
     return 0;
 }
 
-static int 
+static int
 Randh_clear(Randh *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->freq);
     Py_CLEAR(self->freq_stream);
-    Py_CLEAR(self->min);    
-    Py_CLEAR(self->min_stream);    
-    Py_CLEAR(self->max);    
-    Py_CLEAR(self->max_stream);    
+    Py_CLEAR(self->min);
+    Py_CLEAR(self->min_stream);
+    Py_CLEAR(self->max);
+    Py_CLEAR(self->max_stream);
     return 0;
 }
 
@@ -954,7 +945,7 @@ Randh_dealloc(Randh* self)
 {
     pyo_DEALLOC
     Randh_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -965,7 +956,7 @@ Randh_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *mintmp=NULL, *maxtmp=NULL, *freqtmp=NULL, *multmp=NULL, *addtmp=NULL;
     Randh *self;
     self = (Randh *)type->tp_alloc(type, 0);
-    
+
     self->min = PyFloat_FromDouble(0.);
     self->max = PyFloat_FromDouble(1.);
     self->freq = PyFloat_FromDouble(1.);
@@ -976,38 +967,38 @@ Randh_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
 	self->modebuffer[4] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Randh_compute_next_data_frame);
     self->mode_func_ptr = Randh_setProcMode;
 
     static char *kwlist[] = {"min", "max", "freq", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOOO", kwlist, &mintmp, &maxtmp, &freqtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     if (mintmp) {
         PyObject_CallMethod((PyObject *)self, "setMin", "O", mintmp);
     }
-    
+
     if (maxtmp) {
         PyObject_CallMethod((PyObject *)self, "setMax", "O", maxtmp);
     }
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    
+
     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);
-    
+
     Server_generateSeed((Server *)self->server, RANDH_ID);
 
     if (self->modebuffer[2] == 0)
@@ -1018,9 +1009,9 @@ Randh_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         ma = PyFloat_AS_DOUBLE(self->max);
     else
         ma = Stream_getData((Stream *)self->max_stream)[0];
-    
+
     self->value = (mi + ma) * 0.5;
-    
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
@@ -1028,10 +1019,10 @@ Randh_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Randh_getServer(Randh* self) { GET_SERVER };
 static PyObject * Randh_getStream(Randh* self) { GET_STREAM };
-static PyObject * Randh_setMul(Randh *self, PyObject *arg) { SET_MUL };	
-static PyObject * Randh_setAdd(Randh *self, PyObject *arg) { SET_ADD };	
-static PyObject * Randh_setSub(Randh *self, PyObject *arg) { SET_SUB };	
-static PyObject * Randh_setDiv(Randh *self, PyObject *arg) { SET_DIV };	
+static PyObject * Randh_setMul(Randh *self, PyObject *arg) { SET_MUL };
+static PyObject * Randh_setAdd(Randh *self, PyObject *arg) { SET_ADD };
+static PyObject * Randh_setSub(Randh *self, PyObject *arg) { SET_SUB };
+static PyObject * Randh_setDiv(Randh *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Randh_play(Randh *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Randh_out(Randh *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1050,14 +1041,11 @@ static PyObject *
 Randh_setMin(Randh *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->min);
@@ -1073,25 +1061,22 @@ Randh_setMin(Randh *self, PyObject *arg)
         self->min_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Randh_setMax(Randh *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->max);
@@ -1107,25 +1092,22 @@ Randh_setMax(Randh *self, PyObject *arg)
         self->max_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Randh_setFreq(Randh *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -1141,12 +1123,12 @@ Randh_setFreq(Randh *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[4] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Randh_members[] = {
 {"server", T_OBJECT_EX, offsetof(Randh, server), 0, "Pyo server."},
@@ -1179,7 +1161,7 @@ static PyNumberMethods Randh_as_number = {
 (binaryfunc)Randh_add,                         /*nb_add*/
 (binaryfunc)Randh_sub,                         /*nb_subtract*/
 (binaryfunc)Randh_multiply,                    /*nb_multiply*/
-(binaryfunc)Randh_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -1193,16 +1175,16 @@ static PyNumberMethods Randh_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)Randh_inplace_add,                 /*inplace_add*/
 (binaryfunc)Randh_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)Randh_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)Randh_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -1211,15 +1193,14 @@ static PyNumberMethods Randh_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)Randh_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)Randh_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject RandhType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Randh_base",                                   /*tp_name*/
 sizeof(Randh),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -1227,7 +1208,7 @@ sizeof(Randh),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &Randh_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -1270,7 +1251,7 @@ typedef struct {
     MYFLT *choice;
     MYFLT value;
     MYFLT time;
-    int modebuffer[3]; // need at least 2 slots for mul & add 
+    int modebuffer[3]; // need at least 2 slots for mul & add
 } Choice;
 
 static void
@@ -1279,14 +1260,14 @@ Choice_generate_i(Choice *self) {
     MYFLT inc;
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
     inc = fr / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->time += inc;
         if (self->time < 0.0)
             self->time += 1.0;
         else if (self->time >= 1.0) {
             self->time -= 1.0;
-            self->value = self->choice[(int)((rand()/((MYFLT)(RAND_MAX))) * self->chSize)];
+            self->value = self->choice[(int)(RANDOM_UNIFORM * self->chSize)];
         }
         self->data[i] = self->value;
     }
@@ -1297,7 +1278,7 @@ Choice_generate_a(Choice *self) {
     int i;
     MYFLT inc;
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inc = fr[i] / self->sr;
         self->time += inc;
@@ -1305,7 +1286,7 @@ Choice_generate_a(Choice *self) {
             self->time += 1.0;
         else if (self->time >= 1.0) {
             self->time -= 1.0;
-            self->value = self->choice[(int)((rand()/((MYFLT)(RAND_MAX))) * self->chSize)];
+            self->value = self->choice[(int)(RANDOM_UNIFORM * self->chSize)];
         }
         self->data[i] = self->value;
     }
@@ -1327,50 +1308,50 @@ Choice_setProcMode(Choice *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2];
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Choice_generate_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Choice_generate_a;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Choice_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Choice_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Choice_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Choice_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Choice_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Choice_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Choice_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Choice_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Choice_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 Choice_compute_next_data_frame(Choice *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1383,7 +1364,7 @@ Choice_traverse(Choice *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Choice_clear(Choice *self)
 {
     pyo_CLEAR
@@ -1398,7 +1379,7 @@ Choice_dealloc(Choice* self)
     pyo_DEALLOC
     free(self->choice);
     Choice_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1408,23 +1389,23 @@ Choice_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *choicetmp=NULL, *freqtmp=NULL, *multmp=NULL, *addtmp=NULL;
     Choice *self;
     self = (Choice *)type->tp_alloc(type, 0);
-    
+
     self->freq = PyFloat_FromDouble(1.);
     self->value = 0.0;
     self->time = 1.0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Choice_compute_next_data_frame);
     self->mode_func_ptr = Choice_setProcMode;
 
     static char *kwlist[] = {"choice", "freq", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &choicetmp, &freqtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     if (choicetmp) {
         PyObject_CallMethod((PyObject *)self, "setChoice", "O", choicetmp);
     }
@@ -1432,17 +1413,17 @@ Choice_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    
+
     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);
-    
+
     Server_generateSeed((Server *)self->server, CHOICE_ID);
 
     (*self->mode_func_ptr)(self);
@@ -1452,10 +1433,10 @@ Choice_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Choice_getServer(Choice* self) { GET_SERVER };
 static PyObject * Choice_getStream(Choice* self) { GET_STREAM };
-static PyObject * Choice_setMul(Choice *self, PyObject *arg) { SET_MUL };	
-static PyObject * Choice_setAdd(Choice *self, PyObject *arg) { SET_ADD };	
-static PyObject * Choice_setSub(Choice *self, PyObject *arg) { SET_SUB };	
-static PyObject * Choice_setDiv(Choice *self, PyObject *arg) { SET_DIV };	
+static PyObject * Choice_setMul(Choice *self, PyObject *arg) { SET_MUL };
+static PyObject * Choice_setAdd(Choice *self, PyObject *arg) { SET_ADD };
+static PyObject * Choice_setSub(Choice *self, PyObject *arg) { SET_SUB };
+static PyObject * Choice_setDiv(Choice *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Choice_play(Choice *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Choice_out(Choice *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1475,38 +1456,35 @@ Choice_setChoice(Choice *self, PyObject *arg)
 {
     int i;
 	PyObject *tmp;
-	
+
 	if (! PyList_Check(arg)) {
         PyErr_SetString(PyExc_TypeError, "The choice attribute must be a list.");
 		Py_INCREF(Py_None);
 		return Py_None;
 	}
-    
+
     tmp = arg;
     self->chSize = PyList_Size(tmp);
     self->choice = (MYFLT *)realloc(self->choice, self->chSize * sizeof(MYFLT));
     for (i=0; i<self->chSize; i++) {
-        self->choice[i] = PyFloat_AS_DOUBLE(PyNumber_Float(PyList_GET_ITEM(tmp, i)));
+        self->choice[i] = PyFloat_AsDouble(PyList_GET_ITEM(tmp, i));
     }
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Choice_setFreq(Choice *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -1522,12 +1500,12 @@ Choice_setFreq(Choice *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Choice_members[] = {
 {"server", T_OBJECT_EX, offsetof(Choice, server), 0, "Pyo server."},
@@ -1557,7 +1535,7 @@ static PyNumberMethods Choice_as_number = {
 (binaryfunc)Choice_add,                         /*nb_add*/
 (binaryfunc)Choice_sub,                         /*nb_subtract*/
 (binaryfunc)Choice_multiply,                    /*nb_multiply*/
-(binaryfunc)Choice_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -1571,16 +1549,16 @@ static PyNumberMethods Choice_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)Choice_inplace_add,                 /*inplace_add*/
 (binaryfunc)Choice_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)Choice_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)Choice_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -1589,15 +1567,14 @@ static PyNumberMethods Choice_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)Choice_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)Choice_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject ChoiceType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Choice_base",                                   /*tp_name*/
 sizeof(Choice),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -1605,7 +1582,7 @@ sizeof(Choice),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &Choice_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -1648,7 +1625,7 @@ typedef struct {
     Stream *freq_stream;
     MYFLT value;
     MYFLT time;
-    int modebuffer[4]; // need at least 2 slots for mul & add 
+    int modebuffer[4]; // need at least 2 slots for mul & add
 } RandInt;
 
 static void
@@ -1658,14 +1635,14 @@ RandInt_generate_ii(RandInt *self) {
     MYFLT ma = PyFloat_AS_DOUBLE(self->max);
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
     inc = fr / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->time += inc;
         if (self->time < 0.0)
             self->time += 1.0;
         else if (self->time >= 1.0) {
             self->time -= 1.0;
-            self->value = (MYFLT)((int)(rand()/((MYFLT)(RAND_MAX)+1)*ma));
+            self->value = (MYFLT)((int)(RANDOM_UNIFORM * ma));
         }
         self->data[i] = self->value;
     }
@@ -1678,14 +1655,14 @@ RandInt_generate_ai(RandInt *self) {
     MYFLT *ma = Stream_getData((Stream *)self->max_stream);
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
     inc = fr / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->time += inc;
         if (self->time < 0.0)
             self->time += 1.0;
         else if (self->time >= 1.0) {
             self->time -= 1.0;
-            self->value = (MYFLT)((int)(rand()/((MYFLT)(RAND_MAX)+1)*ma[i]));
+            self->value = (MYFLT)((int)(RANDOM_UNIFORM * ma[i]));
         }
         self->data[i] = self->value;
     }
@@ -1697,7 +1674,7 @@ RandInt_generate_ia(RandInt *self) {
     MYFLT inc;
     MYFLT ma = PyFloat_AS_DOUBLE(self->max);
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inc = fr[i] / self->sr;
         self->time += inc;
@@ -1705,7 +1682,7 @@ RandInt_generate_ia(RandInt *self) {
             self->time += 1.0;
         else if (self->time >= 1.0) {
             self->time -= 1.0;
-            self->value = (MYFLT)((int)(rand()/((MYFLT)(RAND_MAX)+1)*ma));
+            self->value = (MYFLT)((int)(RANDOM_UNIFORM * ma));
         }
         self->data[i] = self->value;
     }
@@ -1717,7 +1694,7 @@ RandInt_generate_aa(RandInt *self) {
     MYFLT inc;
     MYFLT *ma = Stream_getData((Stream *)self->max_stream);
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inc = fr[i] / self->sr;
         self->time += inc;
@@ -1725,7 +1702,7 @@ RandInt_generate_aa(RandInt *self) {
             self->time += 1.0;
         else if (self->time >= 1.0) {
             self->time -= 1.0;
-            self->value = (MYFLT)((int)(rand()/((MYFLT)(RAND_MAX)+1)*ma[i]));
+            self->value = (MYFLT)((int)(RANDOM_UNIFORM * ma[i]));
         }
         self->data[i] = self->value;
     }
@@ -1747,56 +1724,56 @@ RandInt_setProcMode(RandInt *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = RandInt_generate_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = RandInt_generate_ai;
             break;
-        case 10:    
+        case 10:
             self->proc_func_ptr = RandInt_generate_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = RandInt_generate_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = RandInt_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = RandInt_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = RandInt_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = RandInt_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = RandInt_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = RandInt_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = RandInt_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = RandInt_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = RandInt_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 RandInt_compute_next_data_frame(RandInt *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1806,19 +1783,19 @@ RandInt_traverse(RandInt *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->freq);
     Py_VISIT(self->freq_stream);
-    Py_VISIT(self->max);    
-    Py_VISIT(self->max_stream);    
+    Py_VISIT(self->max);
+    Py_VISIT(self->max_stream);
     return 0;
 }
 
-static int 
+static int
 RandInt_clear(RandInt *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->freq);
     Py_CLEAR(self->freq_stream);
-    Py_CLEAR(self->max);    
-    Py_CLEAR(self->max_stream);    
+    Py_CLEAR(self->max);
+    Py_CLEAR(self->max_stream);
     return 0;
 }
 
@@ -1827,7 +1804,7 @@ RandInt_dealloc(RandInt* self)
 {
     pyo_DEALLOC
     RandInt_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1837,7 +1814,7 @@ RandInt_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *maxtmp=NULL, *freqtmp=NULL, *multmp=NULL, *addtmp=NULL;
     RandInt *self;
     self = (RandInt *)type->tp_alloc(type, 0);
-    
+
     self->max = PyFloat_FromDouble(100.);
     self->freq = PyFloat_FromDouble(1.);
     self->value = 0.0;
@@ -1846,32 +1823,32 @@ RandInt_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, RandInt_compute_next_data_frame);
     self->mode_func_ptr = RandInt_setProcMode;
 
     static char *kwlist[] = {"max", "freq", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &maxtmp, &freqtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
 
     if (maxtmp) {
         PyObject_CallMethod((PyObject *)self, "setMax", "O", maxtmp);
     }
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    
+
     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);
 
     Server_generateSeed((Server *)self->server, RANDINT_ID);
@@ -1883,10 +1860,10 @@ RandInt_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * RandInt_getServer(RandInt* self) { GET_SERVER };
 static PyObject * RandInt_getStream(RandInt* self) { GET_STREAM };
-static PyObject * RandInt_setMul(RandInt *self, PyObject *arg) { SET_MUL };	
-static PyObject * RandInt_setAdd(RandInt *self, PyObject *arg) { SET_ADD };	
-static PyObject * RandInt_setSub(RandInt *self, PyObject *arg) { SET_SUB };	
-static PyObject * RandInt_setDiv(RandInt *self, PyObject *arg) { SET_DIV };	
+static PyObject * RandInt_setMul(RandInt *self, PyObject *arg) { SET_MUL };
+static PyObject * RandInt_setAdd(RandInt *self, PyObject *arg) { SET_ADD };
+static PyObject * RandInt_setSub(RandInt *self, PyObject *arg) { SET_SUB };
+static PyObject * RandInt_setDiv(RandInt *self, PyObject *arg) { SET_DIV };
 
 static PyObject * RandInt_play(RandInt *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * RandInt_out(RandInt *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1905,14 +1882,11 @@ static PyObject *
 RandInt_setMax(RandInt *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->max);
@@ -1928,25 +1902,22 @@ RandInt_setMax(RandInt *self, PyObject *arg)
         self->max_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 RandInt_setFreq(RandInt *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -1962,12 +1933,12 @@ RandInt_setFreq(RandInt *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef RandInt_members[] = {
 {"server", T_OBJECT_EX, offsetof(RandInt, server), 0, "Pyo server."},
@@ -1998,7 +1969,7 @@ static PyNumberMethods RandInt_as_number = {
 (binaryfunc)RandInt_add,                         /*nb_add*/
 (binaryfunc)RandInt_sub,                         /*nb_subtract*/
 (binaryfunc)RandInt_multiply,                    /*nb_multiply*/
-(binaryfunc)RandInt_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -2012,16 +1983,16 @@ static PyNumberMethods RandInt_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)RandInt_inplace_add,                 /*inplace_add*/
 (binaryfunc)RandInt_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)RandInt_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)RandInt_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -2030,15 +2001,14 @@ static PyNumberMethods RandInt_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)RandInt_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)RandInt_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject RandIntType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.RandInt_base",                                   /*tp_name*/
 sizeof(RandInt),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -2046,7 +2016,7 @@ sizeof(RandInt),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &RandInt_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -2090,7 +2060,7 @@ typedef struct {
     MYFLT value;
     MYFLT time;
     MYFLT inc;
-    int modebuffer[4]; // need at least 2 slots for mul & add 
+    int modebuffer[4]; // need at least 2 slots for mul & add
 } RandDur;
 
 static void
@@ -2099,7 +2069,7 @@ RandDur_generate_ii(RandDur *self) {
     MYFLT range;
     MYFLT mi = PyFloat_AS_DOUBLE(self->min);
     MYFLT ma = PyFloat_AS_DOUBLE(self->max);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->time += self->inc;
         if (self->time < 0.0)
@@ -2111,7 +2081,7 @@ RandDur_generate_ii(RandDur *self) {
             range = ma - mi;
             if (range < 0.0)
                 range = 0.0;
-            self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi;
+            self->value = range * RANDOM_UNIFORM + mi;
             self->inc = (1.0 / self->value) / self->sr;
         }
         self->data[i] = self->value;
@@ -2124,7 +2094,7 @@ RandDur_generate_ai(RandDur *self) {
     MYFLT range, mi;
     MYFLT *min = Stream_getData((Stream *)self->min_stream);
     MYFLT ma = PyFloat_AS_DOUBLE(self->max);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->time += self->inc;
         if (self->time < 0.0)
@@ -2137,7 +2107,7 @@ RandDur_generate_ai(RandDur *self) {
             range = ma - mi;
             if (range < 0.0)
                 range = 0.0;
-            self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi;
+            self->value = range * RANDOM_UNIFORM + mi;
             self->inc = (1.0 / self->value) / self->sr;
         }
         self->data[i] = self->value;
@@ -2150,7 +2120,7 @@ RandDur_generate_ia(RandDur *self) {
     MYFLT range;
     MYFLT mi = PyFloat_AS_DOUBLE(self->min);
     MYFLT *ma = Stream_getData((Stream *)self->max_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->time += self->inc;
         if (self->time < 0.0)
@@ -2162,7 +2132,7 @@ RandDur_generate_ia(RandDur *self) {
             range = ma[i] - mi;
             if (range < 0.0)
                 range = 0.0;
-            self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi;
+            self->value = range * RANDOM_UNIFORM + mi;
             self->inc = (1.0 / self->value) / self->sr;
         }
         self->data[i] = self->value;
@@ -2175,7 +2145,7 @@ RandDur_generate_aa(RandDur *self) {
     MYFLT range, mi;
     MYFLT *min = Stream_getData((Stream *)self->min_stream);
     MYFLT *ma = Stream_getData((Stream *)self->max_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->time += self->inc;
         if (self->time < 0.0)
@@ -2188,7 +2158,7 @@ RandDur_generate_aa(RandDur *self) {
             range = ma[i] - mi;
             if (range < 0.0)
                 range = 0.0;
-            self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi;
+            self->value = range * RANDOM_UNIFORM + mi;
             self->inc = (1.0 / self->value) / self->sr;
         }
         self->data[i] = self->value;
@@ -2211,56 +2181,56 @@ RandDur_setProcMode(RandDur *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = RandDur_generate_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = RandDur_generate_ai;
             break;
-        case 10:    
+        case 10:
             self->proc_func_ptr = RandDur_generate_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = RandDur_generate_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = RandDur_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = RandDur_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = RandDur_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = RandDur_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = RandDur_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = RandDur_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = RandDur_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = RandDur_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = RandDur_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 RandDur_compute_next_data_frame(RandDur *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -2268,21 +2238,21 @@ static int
 RandDur_traverse(RandDur *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->min);    
-    Py_VISIT(self->min_stream);    
-    Py_VISIT(self->max);    
-    Py_VISIT(self->max_stream);    
+    Py_VISIT(self->min);
+    Py_VISIT(self->min_stream);
+    Py_VISIT(self->max);
+    Py_VISIT(self->max_stream);
     return 0;
 }
 
-static int 
+static int
 RandDur_clear(RandDur *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->min);    
-    Py_CLEAR(self->min_stream);    
-    Py_CLEAR(self->max);    
-    Py_CLEAR(self->max_stream);    
+    Py_CLEAR(self->min);
+    Py_CLEAR(self->min_stream);
+    Py_CLEAR(self->max);
+    Py_CLEAR(self->max_stream);
     return 0;
 }
 
@@ -2291,7 +2261,7 @@ RandDur_dealloc(RandDur* self)
 {
     pyo_DEALLOC
     RandDur_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2302,7 +2272,7 @@ RandDur_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *mintmp=NULL, *maxtmp=NULL, *multmp=NULL, *addtmp=NULL;
     RandDur *self;
     self = (RandDur *)type->tp_alloc(type, 0);
-    
+
     self->min = PyFloat_FromDouble(0.01);
     self->max = PyFloat_FromDouble(1.);
     self->value = self->inc = 0.0;
@@ -2311,34 +2281,34 @@ RandDur_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, RandDur_compute_next_data_frame);
     self->mode_func_ptr = RandDur_setProcMode;
 
     static char *kwlist[] = {"min", "max", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OOOO", kwlist, &mintmp, &maxtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     if (mintmp) {
         PyObject_CallMethod((PyObject *)self, "setMin", "O", mintmp);
     }
-    
+
     if (maxtmp) {
         PyObject_CallMethod((PyObject *)self, "setMax", "O", maxtmp);
     }
-    
+
     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);
-    
+
     Server_generateSeed((Server *)self->server, RANDDUR_ID);
 
     if (self->modebuffer[2] == 0)
@@ -2349,7 +2319,7 @@ RandDur_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         ma = PyFloat_AS_DOUBLE(self->max);
     else
         ma = Stream_getData((Stream *)self->max_stream)[0];
-    
+
     self->value = (mi + ma) * 0.5;
     if (self->value == 0.0)
         self->inc = 0.0;
@@ -2363,10 +2333,10 @@ RandDur_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * RandDur_getServer(RandDur* self) { GET_SERVER };
 static PyObject * RandDur_getStream(RandDur* self) { GET_STREAM };
-static PyObject * RandDur_setMul(RandDur *self, PyObject *arg) { SET_MUL };	
-static PyObject * RandDur_setAdd(RandDur *self, PyObject *arg) { SET_ADD };	
-static PyObject * RandDur_setSub(RandDur *self, PyObject *arg) { SET_SUB };	
-static PyObject * RandDur_setDiv(RandDur *self, PyObject *arg) { SET_DIV };	
+static PyObject * RandDur_setMul(RandDur *self, PyObject *arg) { SET_MUL };
+static PyObject * RandDur_setAdd(RandDur *self, PyObject *arg) { SET_ADD };
+static PyObject * RandDur_setSub(RandDur *self, PyObject *arg) { SET_SUB };
+static PyObject * RandDur_setDiv(RandDur *self, PyObject *arg) { SET_DIV };
 
 static PyObject * RandDur_play(RandDur *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * RandDur_out(RandDur *self, PyObject *args, PyObject *kwds) { OUT };
@@ -2385,14 +2355,11 @@ static PyObject *
 RandDur_setMin(RandDur *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->min);
@@ -2408,25 +2375,22 @@ RandDur_setMin(RandDur *self, PyObject *arg)
         self->min_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 RandDur_setMax(RandDur *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->max);
@@ -2442,12 +2406,12 @@ RandDur_setMax(RandDur *self, PyObject *arg)
         self->max_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef RandDur_members[] = {
     {"server", T_OBJECT_EX, offsetof(RandDur, server), 0, "Pyo server."},
@@ -2478,7 +2442,7 @@ static PyNumberMethods RandDur_as_number = {
     (binaryfunc)RandDur_add,                         /*nb_add*/
     (binaryfunc)RandDur_sub,                         /*nb_subtract*/
     (binaryfunc)RandDur_multiply,                    /*nb_multiply*/
-    (binaryfunc)RandDur_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -2492,16 +2456,16 @@ static PyNumberMethods RandDur_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)RandDur_inplace_add,                 /*inplace_add*/
     (binaryfunc)RandDur_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)RandDur_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)RandDur_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -2510,15 +2474,14 @@ static PyNumberMethods RandDur_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)RandDur_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)RandDur_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject RandDurType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.RandDur_base",                                   /*tp_name*/
     sizeof(RandDur),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -2526,7 +2489,7 @@ PyTypeObject RandDurType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &RandDur_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -2586,18 +2549,18 @@ typedef struct {
     int loopCountRec;
     int loopLen;
     int loopStop;
-    int modebuffer[5]; // need at least 2 slots for mul & add 
+    int modebuffer[5]; // need at least 2 slots for mul & add
 } Xnoise;
 
 // no parameter
 static MYFLT
 Xnoise_uniform(Xnoise *self) {
-    return RANDOM_UNIFORM;    
+    return RANDOM_UNIFORM;
 }
 
 static MYFLT
 Xnoise_linear_min(Xnoise *self) {
-    MYFLT a = RANDOM_UNIFORM;    
+    MYFLT a = RANDOM_UNIFORM;
     MYFLT b = RANDOM_UNIFORM;
     if (a < b) return a;
     else return b;
@@ -2605,7 +2568,7 @@ Xnoise_linear_min(Xnoise *self) {
 
 static MYFLT
 Xnoise_linear_max(Xnoise *self) {
-    MYFLT a = RANDOM_UNIFORM;    
+    MYFLT a = RANDOM_UNIFORM;
     MYFLT b = RANDOM_UNIFORM;
     if (a > b) return a;
     else return b;
@@ -2613,7 +2576,7 @@ Xnoise_linear_max(Xnoise *self) {
 
 static MYFLT
 Xnoise_triangle(Xnoise *self) {
-    MYFLT a = RANDOM_UNIFORM;    
+    MYFLT a = RANDOM_UNIFORM;
     MYFLT b = RANDOM_UNIFORM;
     return ((a + b) * 0.5);
 }
@@ -2622,7 +2585,7 @@ Xnoise_triangle(Xnoise *self) {
 static MYFLT
 Xnoise_expon_min(Xnoise *self) {
     if (self->xx1 <= 0.0) self->xx1 = 0.00001;
-    MYFLT val = -MYLOG(RANDOM_UNIFORM) / self->xx1;    
+    MYFLT val = -MYLOG(RANDOM_UNIFORM) / self->xx1;
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -2631,7 +2594,7 @@ Xnoise_expon_min(Xnoise *self) {
 static MYFLT
 Xnoise_expon_max(Xnoise *self) {
     if (self->xx1 <= 0.0) self->xx1 = 0.00001;
-    MYFLT val = 1.0 - (-MYLOG(RANDOM_UNIFORM) / self->xx1);    
+    MYFLT val = 1.0 - (-MYLOG(RANDOM_UNIFORM) / self->xx1);
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -2643,7 +2606,7 @@ Xnoise_biexpon(Xnoise *self) {
     MYFLT polar, val;
     if (self->xx1 <= 0.0) self->xx1 = 0.00001;
     MYFLT sum = RANDOM_UNIFORM * 2.0;
-    
+
     if (sum > 1.0) {
         polar = -1;
         sum = 2.0 - sum;
@@ -2665,14 +2628,14 @@ Xnoise_cauchy(Xnoise *self) {
         rnd = RANDOM_UNIFORM;
     }
     while (rnd == 0.5);
-    
-    if (rand() < (RAND_MAX / 2))
+
+    if (pyorand() < (PYO_RAND_MAX / 2))
         dir = -1;
     else
         dir = 1;
-    
+
     val = 0.5 * (MYTAN(rnd) * self->xx1 * dir) + 0.5;
-    
+
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -2683,10 +2646,10 @@ static MYFLT
 Xnoise_weibull(Xnoise *self) {
     MYFLT rnd, val;
     if (self->xx2 <= 0.0) self->xx2 = 0.00001;
-    
+
     rnd = 1.0 / (1.0 - RANDOM_UNIFORM);
     val = self->xx1 * MYPOW(MYLOG(rnd), (1.0 / self->xx2));
-    
+
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -2696,10 +2659,10 @@ Xnoise_weibull(Xnoise *self) {
 static MYFLT
 Xnoise_gaussian(Xnoise *self) {
     MYFLT rnd, val;
-    
+
     rnd = (RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM);
     val = (self->xx2 * (rnd - 3.0) * 0.33 + self->xx1);
-    
+
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -2727,8 +2690,8 @@ Xnoise_poisson(Xnoise *self) {
             }
         }
     }
-    val = self->poisson_buffer[rand() % self->poisson_tab] / 12.0 * self->xx2;
-    
+    val = self->poisson_buffer[pyorand() % self->poisson_tab] / 12.0 * self->xx2;
+
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -2737,77 +2700,77 @@ Xnoise_poisson(Xnoise *self) {
 // x1 = max value, x2 = max step
 static MYFLT
 Xnoise_walker(Xnoise *self) {
-    int modulo, dir;
-    
+    unsigned int modulo, dir;
+
     if (self->xx2 < 0.002) self->xx2 = 0.002;
-    
-    modulo = (int)(self->xx2 * 1000.0);
-    dir = rand() % 2;
-    
-    if (dir == 0)
-        self->walkerValue = self->walkerValue + (((rand() % modulo) - (modulo / 2)) * 0.001);
+
+    modulo = (unsigned int)(self->xx2 * 1000.0);
+    dir = pyorand() % 100;
+
+    if (dir < 50)
+        self->walkerValue += ((MYFLT)(pyorand() % modulo) * 0.001);
     else
-        self->walkerValue = self->walkerValue - (((rand() % modulo) - (modulo / 2)) * 0.001);
-        
+        self->walkerValue -= ((MYFLT)(pyorand() % modulo) * 0.001);
+
     if (self->walkerValue > self->xx1)
         self->walkerValue = self->xx1;
-    if (self->walkerValue < 0.0)
+    else if (self->walkerValue < 0.0)
         self->walkerValue = 0.0;
-    
+
     return self->walkerValue;
 }
 
 // x1 = max value, x2 = max step
 static MYFLT
 Xnoise_loopseg(Xnoise *self) {
-    int modulo, dir;
+    unsigned int modulo, dir;
 
     if (self->loopChoice == 0) {
-        
+
         self->loopCountPlay = self->loopTime = 0;
 
         if (self->xx2 < 0.002) self->xx2 = 0.002;
 
-        modulo = (int)(self->xx2 * 1000.0);
-        dir = rand() % 2;
-    
-        if (dir == 0)
-            self->walkerValue = self->walkerValue + (((rand() % modulo) - (modulo / 2)) * 0.001);
+        modulo = (unsigned int)(self->xx2 * 1000.0);
+        dir = pyorand() % 100;
+
+        if (dir < 50)
+            self->walkerValue += ((MYFLT)(pyorand() % modulo) * 0.001);
         else
-            self->walkerValue = self->walkerValue - (((rand() % modulo) - (modulo / 2)) * 0.001);
-    
+            self->walkerValue -= ((MYFLT)(pyorand() % modulo) * 0.001);
+
         if (self->walkerValue > self->xx1)
             self->walkerValue = self->xx1;
-        if (self->walkerValue < 0.0)
+        else if (self->walkerValue < 0.0)
             self->walkerValue = 0.0;
-        
+
         self->loop_buffer[self->loopCountRec++] = self->walkerValue;
-        
+
         if (self->loopCountRec < self->loopLen)
             self->loopChoice = 0;
         else {
             self->loopChoice = 1;
-            self->loopStop = (rand() % 4) + 1;
+            self->loopStop = (pyorand() % 4) + 1;
         }
     }
     else {
         self->loopCountRec = 0;
-        
+
         self->walkerValue = self->loop_buffer[self->loopCountPlay++];
-        
+
         if (self->loopCountPlay < self->loopLen)
             self->loopChoice = 1;
         else {
             self->loopCountPlay = 0;
             self->loopTime++;
         }
-        
+
         if (self->loopTime == self->loopStop) {
             self->loopChoice = 0;
-            self->loopLen = (rand() % 10) + 3;
+            self->loopLen = (pyorand() % 10) + 3;
         }
     }
-    
+
     return self->walkerValue;
 }
 
@@ -2840,7 +2803,7 @@ Xnoise_generate_aii(Xnoise *self) {
     self->xx2 = PyFloat_AS_DOUBLE(self->x2);
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
     inc = fr / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->time += inc;
         if (self->time < 0.0)
@@ -2862,7 +2825,7 @@ Xnoise_generate_iai(Xnoise *self) {
     MYFLT *x2 = Stream_getData((Stream *)self->x2_stream);
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
     inc = fr / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->time += inc;
         if (self->time < 0.0)
@@ -2884,7 +2847,7 @@ Xnoise_generate_aai(Xnoise *self) {
     MYFLT *x2 = Stream_getData((Stream *)self->x2_stream);
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
     inc = fr / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->time += inc;
         if (self->time < 0.0)
@@ -2906,7 +2869,7 @@ Xnoise_generate_iia(Xnoise *self) {
     self->xx1 = PyFloat_AS_DOUBLE(self->x1);
     self->xx2 = PyFloat_AS_DOUBLE(self->x2);
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inc = fr[i] / self->sr;
         self->time += inc;
@@ -2927,7 +2890,7 @@ Xnoise_generate_aia(Xnoise *self) {
     MYFLT *x1 = Stream_getData((Stream *)self->x1_stream);
     self->xx2 = PyFloat_AS_DOUBLE(self->x2);
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inc = fr[i] / self->sr;
         self->time += inc;
@@ -2949,7 +2912,7 @@ Xnoise_generate_iaa(Xnoise *self) {
     self->xx1 = PyFloat_AS_DOUBLE(self->x1);
     MYFLT *x2 = Stream_getData((Stream *)self->x2_stream);
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inc = fr[i] / self->sr;
         self->time += inc;
@@ -2971,7 +2934,7 @@ Xnoise_generate_aaa(Xnoise *self) {
     MYFLT *x1 = Stream_getData((Stream *)self->x1_stream);
     MYFLT *x2 = Stream_getData((Stream *)self->x2_stream);
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inc = fr[i] / self->sr;
         self->time += inc;
@@ -3001,7 +2964,7 @@ static void
 Xnoise_setRandomType(Xnoise *self)
 {
 
-    switch (self->type) {            
+    switch (self->type) {
         case 0:
             self->type_func_ptr = Xnoise_uniform;
             break;
@@ -3041,7 +3004,7 @@ Xnoise_setRandomType(Xnoise *self)
         case 12:
             self->type_func_ptr = Xnoise_loopseg;
             break;
-    }        
+    }
 }
 
 static void
@@ -3050,68 +3013,68 @@ Xnoise_setProcMode(Xnoise *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Xnoise_generate_iii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Xnoise_generate_aii;
             break;
-        case 10:    
+        case 10:
             self->proc_func_ptr = Xnoise_generate_iai;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Xnoise_generate_aai;
             break;
-        case 100:    
+        case 100:
             self->proc_func_ptr = Xnoise_generate_iia;
             break;
-        case 101:    
+        case 101:
             self->proc_func_ptr = Xnoise_generate_aia;
             break;
-        case 110:    
+        case 110:
             self->proc_func_ptr = Xnoise_generate_iaa;
             break;
-        case 111:    
+        case 111:
             self->proc_func_ptr = Xnoise_generate_aaa;
-            break;            
-    } 
+            break;
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Xnoise_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Xnoise_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Xnoise_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Xnoise_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Xnoise_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Xnoise_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Xnoise_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Xnoise_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Xnoise_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 Xnoise_compute_next_data_frame(Xnoise *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -3121,23 +3084,23 @@ Xnoise_traverse(Xnoise *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->freq);
     Py_VISIT(self->freq_stream);
-    Py_VISIT(self->x1);    
-    Py_VISIT(self->x1_stream);    
-    Py_VISIT(self->x2);    
-    Py_VISIT(self->x2_stream);    
+    Py_VISIT(self->x1);
+    Py_VISIT(self->x1_stream);
+    Py_VISIT(self->x2);
+    Py_VISIT(self->x2_stream);
     return 0;
 }
 
-static int 
+static int
 Xnoise_clear(Xnoise *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->freq);
     Py_CLEAR(self->freq_stream);
-    Py_CLEAR(self->x1);    
-    Py_CLEAR(self->x1_stream);    
-    Py_CLEAR(self->x2);    
-    Py_CLEAR(self->x2_stream);    
+    Py_CLEAR(self->x1);
+    Py_CLEAR(self->x1_stream);
+    Py_CLEAR(self->x2);
+    Py_CLEAR(self->x2_stream);
     return 0;
 }
 
@@ -3146,7 +3109,7 @@ Xnoise_dealloc(Xnoise* self)
 {
     pyo_DEALLOC
     Xnoise_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -3156,7 +3119,7 @@ Xnoise_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *freqtmp=NULL, *x1tmp=NULL, *x2tmp=NULL, *multmp=NULL, *addtmp=NULL;
     Xnoise *self;
     self = (Xnoise *)type->tp_alloc(type, 0);
-    
+
     self->x1 = PyFloat_FromDouble(0.5);
     self->x2 = PyFloat_FromDouble(0.5);
     self->freq = PyFloat_FromDouble(1.);
@@ -3168,9 +3131,9 @@ Xnoise_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
 	self->modebuffer[4] = 0;
-    
+
     INIT_OBJECT_COMMON
-    
+
     Server_generateSeed((Server *)self->server, XNOISE_ID);
 
     self->poisson_tab = 0;
@@ -3181,41 +3144,41 @@ Xnoise_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     for (i=0; i<15; i++) {
         self->loop_buffer[i] = 0.0;
     }
-    self->loopChoice = self->loopCountPlay = self->loopTime = self->loopCountRec = self->loopStop = 0;    
-    self->loopLen = (rand() % 10) + 3;
-    
+    self->loopChoice = self->loopCountPlay = self->loopTime = self->loopCountRec = self->loopStop = 0;
+    self->loopLen = (pyorand() % 10) + 3;
+
     Stream_setFunctionPtr(self->stream, Xnoise_compute_next_data_frame);
     self->mode_func_ptr = Xnoise_setProcMode;
 
     static char *kwlist[] = {"type", "freq", "x1", "x2", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|iOOOOO", kwlist, &self->type, &freqtmp, &x1tmp, &x2tmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     if (x1tmp) {
         PyObject_CallMethod((PyObject *)self, "setX1", "O", x1tmp);
     }
-    
+
     if (x2tmp) {
         PyObject_CallMethod((PyObject *)self, "setX2", "O", x2tmp);
     }
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    
+
     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);
 
     Xnoise_setRandomType(self);
-    
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
@@ -3223,10 +3186,10 @@ Xnoise_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Xnoise_getServer(Xnoise* self) { GET_SERVER };
 static PyObject * Xnoise_getStream(Xnoise* self) { GET_STREAM };
-static PyObject * Xnoise_setMul(Xnoise *self, PyObject *arg) { SET_MUL };	
-static PyObject * Xnoise_setAdd(Xnoise *self, PyObject *arg) { SET_ADD };	
-static PyObject * Xnoise_setSub(Xnoise *self, PyObject *arg) { SET_SUB };	
-static PyObject * Xnoise_setDiv(Xnoise *self, PyObject *arg) { SET_DIV };	
+static PyObject * Xnoise_setMul(Xnoise *self, PyObject *arg) { SET_MUL };
+static PyObject * Xnoise_setAdd(Xnoise *self, PyObject *arg) { SET_ADD };
+static PyObject * Xnoise_setSub(Xnoise *self, PyObject *arg) { SET_SUB };
+static PyObject * Xnoise_setDiv(Xnoise *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Xnoise_play(Xnoise *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Xnoise_out(Xnoise *self, PyObject *args, PyObject *kwds) { OUT };
@@ -3243,14 +3206,11 @@ static PyObject * Xnoise_inplace_div(Xnoise *self, PyObject *arg) { INPLACE_DIV
 
 static PyObject *
 Xnoise_setType(Xnoise *self, PyObject *arg)
-{	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+{
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyInt_Check(arg);
-	
+
 	if (isNumber == 1) {
 		self->type = PyInt_AsLong(arg);
         Xnoise_setRandomType(self);
@@ -3258,20 +3218,17 @@ Xnoise_setType(Xnoise *self, PyObject *arg)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Xnoise_setX1(Xnoise *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->x1);
@@ -3287,25 +3244,22 @@ Xnoise_setX1(Xnoise *self, PyObject *arg)
         self->x1_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Xnoise_setX2(Xnoise *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->x2);
@@ -3321,25 +3275,22 @@ Xnoise_setX2(Xnoise *self, PyObject *arg)
         self->x2_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Xnoise_setFreq(Xnoise *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -3355,12 +3306,12 @@ Xnoise_setFreq(Xnoise *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[4] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Xnoise_members[] = {
     {"server", T_OBJECT_EX, offsetof(Xnoise, server), 0, "Pyo server."},
@@ -3394,7 +3345,7 @@ static PyNumberMethods Xnoise_as_number = {
     (binaryfunc)Xnoise_add,                         /*nb_add*/
     (binaryfunc)Xnoise_sub,                         /*nb_subtract*/
     (binaryfunc)Xnoise_multiply,                    /*nb_multiply*/
-    (binaryfunc)Xnoise_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -3408,16 +3359,16 @@ static PyNumberMethods Xnoise_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Xnoise_inplace_add,                 /*inplace_add*/
     (binaryfunc)Xnoise_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Xnoise_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Xnoise_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -3426,15 +3377,14 @@ static PyNumberMethods Xnoise_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Xnoise_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Xnoise_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject XnoiseType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Xnoise_base",                                   /*tp_name*/
     sizeof(Xnoise),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -3442,7 +3392,7 @@ PyTypeObject XnoiseType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &Xnoise_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -3506,7 +3456,7 @@ typedef struct {
     int loopCountRec;
     int loopLen;
     int loopStop;
-    int modebuffer[5]; // need at least 2 slots for mul & add 
+    int modebuffer[5]; // need at least 2 slots for mul & add
 } XnoiseMidi;
 
 static MYFLT
@@ -3515,12 +3465,12 @@ XnoiseMidi_convert(XnoiseMidi *self) {
     MYFLT val;
 
     midival = (int)((self->value * (self->range_max-self->range_min)) + self->range_min);
-    
+
     if (midival < 0)
         midival = 0;
     else if (midival > 127)
         midival = 127;
-    
+
     if (self->scale == 0)
         val = (MYFLT)midival;
     else if (self->scale == 1)
@@ -3529,19 +3479,19 @@ XnoiseMidi_convert(XnoiseMidi *self) {
         val = MYPOW(1.0594630943593, midival - self->centralkey);
     else
         val = midival;
-    
+
     return val;
 }
 
 // no parameter
 static MYFLT
 XnoiseMidi_uniform(XnoiseMidi *self) {
-    return RANDOM_UNIFORM;    
+    return RANDOM_UNIFORM;
 }
 
 static MYFLT
 XnoiseMidi_linear_min(XnoiseMidi *self) {
-    MYFLT a = RANDOM_UNIFORM;    
+    MYFLT a = RANDOM_UNIFORM;
     MYFLT b = RANDOM_UNIFORM;
     if (a < b) return a;
     else return b;
@@ -3549,7 +3499,7 @@ XnoiseMidi_linear_min(XnoiseMidi *self) {
 
 static MYFLT
 XnoiseMidi_linear_max(XnoiseMidi *self) {
-    MYFLT a = RANDOM_UNIFORM;    
+    MYFLT a = RANDOM_UNIFORM;
     MYFLT b = RANDOM_UNIFORM;
     if (a > b) return a;
     else return b;
@@ -3557,7 +3507,7 @@ XnoiseMidi_linear_max(XnoiseMidi *self) {
 
 static MYFLT
 XnoiseMidi_triangle(XnoiseMidi *self) {
-    MYFLT a = RANDOM_UNIFORM;    
+    MYFLT a = RANDOM_UNIFORM;
     MYFLT b = RANDOM_UNIFORM;
     return ((a + b) * 0.5);
 }
@@ -3566,7 +3516,7 @@ XnoiseMidi_triangle(XnoiseMidi *self) {
 static MYFLT
 XnoiseMidi_expon_min(XnoiseMidi *self) {
     if (self->xx1 <= 0.0) self->xx1 = 0.00001;
-    MYFLT val = -MYLOG(RANDOM_UNIFORM) / self->xx1;    
+    MYFLT val = -MYLOG(RANDOM_UNIFORM) / self->xx1;
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -3575,7 +3525,7 @@ XnoiseMidi_expon_min(XnoiseMidi *self) {
 static MYFLT
 XnoiseMidi_expon_max(XnoiseMidi *self) {
     if (self->xx1 <= 0.0) self->xx1 = 0.00001;
-    MYFLT val = 1.0 - (-MYLOG(RANDOM_UNIFORM) / self->xx1);    
+    MYFLT val = 1.0 - (-MYLOG(RANDOM_UNIFORM) / self->xx1);
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -3587,16 +3537,16 @@ XnoiseMidi_biexpon(XnoiseMidi *self) {
     MYFLT polar, val;
     if (self->xx1 <= 0.0) self->xx1 = 0.00001;
     MYFLT sum = RANDOM_UNIFORM * 2.0;
-    
+
     if (sum > 1.0) {
         polar = -1;
         sum = 2.0 - sum;
     }
     else
         polar = 1;
-    
+
     val = 0.5 * (polar * MYLOG(sum) / self->xx1) + 0.5;
-    
+
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -3609,14 +3559,14 @@ XnoiseMidi_cauchy(XnoiseMidi *self) {
         rnd = RANDOM_UNIFORM;
     }
     while (rnd == 0.5);
-    
-    if (rand() < (RAND_MAX / 2))
+
+    if (pyorand() < (PYO_RAND_MAX / 2))
         dir = -1;
     else
         dir = 1;
-    
+
     val = 0.5 * (MYTAN(rnd) * self->xx1 * dir) + 0.5;
-    
+
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -3627,10 +3577,10 @@ static MYFLT
 XnoiseMidi_weibull(XnoiseMidi *self) {
     MYFLT rnd, val;
     if (self->xx2 <= 0.0) self->xx2 = 0.00001;
-    
+
     rnd = 1.0 / (1.0 - RANDOM_UNIFORM);
     val = self->xx1 * MYPOW(MYLOG(rnd), (1.0 / self->xx2));
-    
+
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -3640,10 +3590,10 @@ XnoiseMidi_weibull(XnoiseMidi *self) {
 static MYFLT
 XnoiseMidi_gaussian(XnoiseMidi *self) {
     MYFLT rnd, val;
-    
+
     rnd = (RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM);
     val = (self->xx2 * (rnd - 3.0) * 0.33 + self->xx1);
-    
+
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -3657,7 +3607,7 @@ XnoiseMidi_poisson(XnoiseMidi *self) {
     MYFLT val;
     if (self->xx1 < 0.1) self->xx1 = 0.1;
     if (self->xx2 < 0.1) self->xx2 = 0.1;
-    
+
     if (self->xx1 != self->lastPoissonX1) {
         self->lastPoissonX1 = self->xx1;
         self->poisson_tab = 0;
@@ -3671,8 +3621,8 @@ XnoiseMidi_poisson(XnoiseMidi *self) {
             }
         }
     }
-    val = self->poisson_buffer[rand() % self->poisson_tab] / 12.0 * self->xx2;
-    
+    val = self->poisson_buffer[pyorand() % self->poisson_tab] / 12.0 * self->xx2;
+
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -3681,77 +3631,77 @@ XnoiseMidi_poisson(XnoiseMidi *self) {
 // x1 = max value, x2 = max step
 static MYFLT
 XnoiseMidi_walker(XnoiseMidi *self) {
-    int modulo, dir;
-    
+    unsigned int modulo, dir;
+
     if (self->xx2 < 0.002) self->xx2 = 0.002;
-    
-    modulo = (int)(self->xx2 * 1000.0);
-    dir = rand() % 2;
-    
-    if (dir == 0)
-        self->walkerValue = self->walkerValue + (((rand() % modulo) - (modulo / 2)) * 0.001);
+
+    modulo = (unsigned int)(self->xx2 * 1000.0);
+    dir = pyorand() % 100;
+
+    if (dir < 50)
+        self->walkerValue += ((MYFLT)(pyorand() % modulo) * 0.001);
     else
-        self->walkerValue = self->walkerValue - (((rand() % modulo) - (modulo / 2)) * 0.001);
-    
+        self->walkerValue -= ((MYFLT)(pyorand() % modulo) * 0.001);
+
     if (self->walkerValue > self->xx1)
         self->walkerValue = self->xx1;
-    if (self->walkerValue < 0.0)
+    else if (self->walkerValue < 0.0)
         self->walkerValue = 0.0;
-    
+
     return self->walkerValue;
 }
 
 // x1 = max value, x2 = max step
 static MYFLT
 XnoiseMidi_loopseg(XnoiseMidi *self) {
-    int modulo, dir;
-    
+    unsigned int modulo, dir;
+
     if (self->loopChoice == 0) {
-        
+
         self->loopCountPlay = self->loopTime = 0;
-        
+
         if (self->xx2 < 0.002) self->xx2 = 0.002;
-        
-        modulo = (int)(self->xx2 * 1000.0);
-        dir = rand() % 2;
-        
-        if (dir == 0)
-            self->walkerValue = self->walkerValue + (((rand() % modulo) - (modulo / 2)) * 0.001);
+
+        modulo = (unsigned int)(self->xx2 * 1000.0);
+        dir = pyorand() % 100;
+
+        if (dir < 50)
+            self->walkerValue += ((MYFLT)(pyorand() % modulo) * 0.001);
         else
-            self->walkerValue = self->walkerValue - (((rand() % modulo) - (modulo / 2)) * 0.001);
-        
+            self->walkerValue -= ((MYFLT)(pyorand() % modulo) * 0.001);
+
         if (self->walkerValue > self->xx1)
             self->walkerValue = self->xx1;
-        if (self->walkerValue < 0.0)
+        else if (self->walkerValue < 0.0)
             self->walkerValue = 0.0;
-        
+
         self->loop_buffer[self->loopCountRec++] = self->walkerValue;
-        
+
         if (self->loopCountRec < self->loopLen)
             self->loopChoice = 0;
         else {
             self->loopChoice = 1;
-            self->loopStop = (rand() % 4) + 1;
+            self->loopStop = (pyorand() % 4) + 1;
         }
     }
     else {
         self->loopCountRec = 0;
-        
+
         self->walkerValue = self->loop_buffer[self->loopCountPlay++];
-        
+
         if (self->loopCountPlay < self->loopLen)
             self->loopChoice = 1;
         else {
             self->loopCountPlay = 0;
             self->loopTime++;
         }
-        
+
         if (self->loopTime == self->loopStop) {
             self->loopChoice = 0;
-            self->loopLen = (rand() % 10) + 3;
+            self->loopLen = (pyorand() % 10) + 3;
         }
     }
-    
+
     return self->walkerValue;
 }
 
@@ -3763,7 +3713,7 @@ XnoiseMidi_generate_iii(XnoiseMidi *self) {
     self->xx2 = PyFloat_AS_DOUBLE(self->x2);
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
     inc = fr / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->time += inc;
         if (self->time < 0.0)
@@ -3785,7 +3735,7 @@ XnoiseMidi_generate_aii(XnoiseMidi *self) {
     self->xx2 = PyFloat_AS_DOUBLE(self->x2);
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
     inc = fr / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->time += inc;
         if (self->time < 0.0)
@@ -3808,7 +3758,7 @@ XnoiseMidi_generate_iai(XnoiseMidi *self) {
     MYFLT *x2 = Stream_getData((Stream *)self->x2_stream);
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
     inc = fr / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->time += inc;
         if (self->time < 0.0)
@@ -3831,7 +3781,7 @@ XnoiseMidi_generate_aai(XnoiseMidi *self) {
     MYFLT *x2 = Stream_getData((Stream *)self->x2_stream);
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
     inc = fr / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->time += inc;
         if (self->time < 0.0)
@@ -3854,7 +3804,7 @@ XnoiseMidi_generate_iia(XnoiseMidi *self) {
     self->xx1 = PyFloat_AS_DOUBLE(self->x1);
     self->xx2 = PyFloat_AS_DOUBLE(self->x2);
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inc = fr[i] / self->sr;
         self->time += inc;
@@ -3876,7 +3826,7 @@ XnoiseMidi_generate_aia(XnoiseMidi *self) {
     MYFLT *x1 = Stream_getData((Stream *)self->x1_stream);
     self->xx2 = PyFloat_AS_DOUBLE(self->x2);
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inc = fr[i] / self->sr;
         self->time += inc;
@@ -3899,7 +3849,7 @@ XnoiseMidi_generate_iaa(XnoiseMidi *self) {
     self->xx1 = PyFloat_AS_DOUBLE(self->x1);
     MYFLT *x2 = Stream_getData((Stream *)self->x2_stream);
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inc = fr[i] / self->sr;
         self->time += inc;
@@ -3922,7 +3872,7 @@ XnoiseMidi_generate_aaa(XnoiseMidi *self) {
     MYFLT *x1 = Stream_getData((Stream *)self->x1_stream);
     MYFLT *x2 = Stream_getData((Stream *)self->x2_stream);
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inc = fr[i] / self->sr;
         self->time += inc;
@@ -3952,8 +3902,8 @@ static void XnoiseMidi_postprocessing_revareva(XnoiseMidi *self) { POST_PROCESSI
 static void
 XnoiseMidi_setRandomType(XnoiseMidi *self)
 {
-    
-    switch (self->type) {            
+
+    switch (self->type) {
         case 0:
             self->type_func_ptr = XnoiseMidi_uniform;
             break;
@@ -3993,7 +3943,7 @@ XnoiseMidi_setRandomType(XnoiseMidi *self)
         case 12:
             self->type_func_ptr = XnoiseMidi_loopseg;
             break;
-    }        
+    }
 }
 
 static void
@@ -4002,68 +3952,68 @@ XnoiseMidi_setProcMode(XnoiseMidi *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10 + self->modebuffer[4] * 100;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = XnoiseMidi_generate_iii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = XnoiseMidi_generate_aii;
             break;
-        case 10:    
+        case 10:
             self->proc_func_ptr = XnoiseMidi_generate_iai;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = XnoiseMidi_generate_aai;
             break;
-        case 100:    
+        case 100:
             self->proc_func_ptr = XnoiseMidi_generate_iia;
             break;
-        case 101:    
+        case 101:
             self->proc_func_ptr = XnoiseMidi_generate_aia;
             break;
-        case 110:    
+        case 110:
             self->proc_func_ptr = XnoiseMidi_generate_iaa;
             break;
-        case 111:    
+        case 111:
             self->proc_func_ptr = XnoiseMidi_generate_aaa;
-            break;            
-    } 
+            break;
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = XnoiseMidi_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = XnoiseMidi_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = XnoiseMidi_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = XnoiseMidi_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = XnoiseMidi_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = XnoiseMidi_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = XnoiseMidi_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = XnoiseMidi_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = XnoiseMidi_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 XnoiseMidi_compute_next_data_frame(XnoiseMidi *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -4073,23 +4023,23 @@ XnoiseMidi_traverse(XnoiseMidi *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->freq);
     Py_VISIT(self->freq_stream);
-    Py_VISIT(self->x1);    
-    Py_VISIT(self->x1_stream);    
-    Py_VISIT(self->x2);    
-    Py_VISIT(self->x2_stream);    
+    Py_VISIT(self->x1);
+    Py_VISIT(self->x1_stream);
+    Py_VISIT(self->x2);
+    Py_VISIT(self->x2_stream);
     return 0;
 }
 
-static int 
+static int
 XnoiseMidi_clear(XnoiseMidi *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->freq);
     Py_CLEAR(self->freq_stream);
-    Py_CLEAR(self->x1);    
-    Py_CLEAR(self->x1_stream);    
-    Py_CLEAR(self->x2);    
-    Py_CLEAR(self->x2_stream);    
+    Py_CLEAR(self->x1);
+    Py_CLEAR(self->x1_stream);
+    Py_CLEAR(self->x2);
+    Py_CLEAR(self->x2_stream);
     return 0;
 }
 
@@ -4098,7 +4048,7 @@ XnoiseMidi_dealloc(XnoiseMidi* self)
 {
     pyo_DEALLOC
     XnoiseMidi_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -4108,7 +4058,7 @@ XnoiseMidi_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *freqtmp=NULL, *x1tmp=NULL, *x2tmp=NULL, *rangetmp=NULL, *multmp=NULL, *addtmp=NULL;
     XnoiseMidi *self;
     self = (XnoiseMidi *)type->tp_alloc(type, 0);
-        
+
     self->x1 = PyFloat_FromDouble(0.5);
     self->x2 = PyFloat_FromDouble(0.5);
     self->freq = PyFloat_FromDouble(1.);
@@ -4124,7 +4074,7 @@ XnoiseMidi_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
 	self->modebuffer[4] = 0;
-    
+
     INIT_OBJECT_COMMON
 
     Server_generateSeed((Server *)self->server, XNOISEMIDI_ID);
@@ -4137,25 +4087,25 @@ XnoiseMidi_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     for (i=0; i<15; i++) {
         self->loop_buffer[i] = 0.0;
     }
-    self->loopChoice = self->loopCountPlay = self->loopTime = self->loopCountRec = self->loopStop = 0;    
-    self->loopLen = (rand() % 10) + 3;
-    
+    self->loopChoice = self->loopCountPlay = self->loopTime = self->loopCountRec = self->loopStop = 0;
+    self->loopLen = (pyorand() % 10) + 3;
+
     Stream_setFunctionPtr(self->stream, XnoiseMidi_compute_next_data_frame);
     self->mode_func_ptr = XnoiseMidi_setProcMode;
 
     static char *kwlist[] = {"type", "freq", "x1", "x2", "scale", "range", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|iOOOiOOO", kwlist, &self->type, &freqtmp, &x1tmp, &x2tmp, &self->scale, &rangetmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     if (x1tmp) {
         PyObject_CallMethod((PyObject *)self, "setX1", "O", x1tmp);
     }
-    
+
     if (x2tmp) {
         PyObject_CallMethod((PyObject *)self, "setX2", "O", x2tmp);
     }
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
@@ -4163,19 +4113,19 @@ XnoiseMidi_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (rangetmp) {
         PyObject_CallMethod((PyObject *)self, "setRange", "O", rangetmp);
     }
-    
+
     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);
-    
+
     XnoiseMidi_setRandomType(self);
-    
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
@@ -4183,10 +4133,10 @@ XnoiseMidi_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * XnoiseMidi_getServer(XnoiseMidi* self) { GET_SERVER };
 static PyObject * XnoiseMidi_getStream(XnoiseMidi* self) { GET_STREAM };
-static PyObject * XnoiseMidi_setMul(XnoiseMidi *self, PyObject *arg) { SET_MUL };	
-static PyObject * XnoiseMidi_setAdd(XnoiseMidi *self, PyObject *arg) { SET_ADD };	
-static PyObject * XnoiseMidi_setSub(XnoiseMidi *self, PyObject *arg) { SET_SUB };	
-static PyObject * XnoiseMidi_setDiv(XnoiseMidi *self, PyObject *arg) { SET_DIV };	
+static PyObject * XnoiseMidi_setMul(XnoiseMidi *self, PyObject *arg) { SET_MUL };
+static PyObject * XnoiseMidi_setAdd(XnoiseMidi *self, PyObject *arg) { SET_ADD };
+static PyObject * XnoiseMidi_setSub(XnoiseMidi *self, PyObject *arg) { SET_SUB };
+static PyObject * XnoiseMidi_setDiv(XnoiseMidi *self, PyObject *arg) { SET_DIV };
 
 static PyObject * XnoiseMidi_play(XnoiseMidi *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * XnoiseMidi_out(XnoiseMidi *self, PyObject *args, PyObject *kwds) { OUT };
@@ -4203,49 +4153,44 @@ static PyObject * XnoiseMidi_inplace_div(XnoiseMidi *self, PyObject *arg) { INPL
 
 static PyObject *
 XnoiseMidi_setType(XnoiseMidi *self, PyObject *arg)
-{	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+{
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyInt_Check(arg);
-	
+
 	if (isNumber == 1) {
 		self->type = PyInt_AsLong(arg);
         XnoiseMidi_setRandomType(self);
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 XnoiseMidi_setScale(XnoiseMidi *self, PyObject *arg)
-{	
+{
     int tmp;
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyInt_Check(arg);
-	
+
 	if (isNumber == 1) {
 		tmp = PyInt_AsLong(arg);
         if (tmp >= 0 && tmp <= 2)
             self->scale = tmp;
         else
-            printf("scale attribute must be an integer {0, 1, 2}\n");
+            PySys_WriteStdout("XnoiseMidi: scale attribute must be an integer {0, 1, 2}\n");
 	}
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 XnoiseMidi_setRange(XnoiseMidi *self, PyObject *args)
-{	
+{
 	if (args == NULL) {
 		Py_INCREF(Py_None);
 		return Py_None;
@@ -4261,20 +4206,17 @@ XnoiseMidi_setRange(XnoiseMidi *self, PyObject *args)
 
     Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 XnoiseMidi_setX1(XnoiseMidi *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->x1);
@@ -4290,25 +4232,22 @@ XnoiseMidi_setX1(XnoiseMidi *self, PyObject *arg)
         self->x1_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 XnoiseMidi_setX2(XnoiseMidi *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->x2);
@@ -4324,25 +4263,22 @@ XnoiseMidi_setX2(XnoiseMidi *self, PyObject *arg)
         self->x2_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 XnoiseMidi_setFreq(XnoiseMidi *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -4358,12 +4294,12 @@ XnoiseMidi_setFreq(XnoiseMidi *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[4] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef XnoiseMidi_members[] = {
     {"server", T_OBJECT_EX, offsetof(XnoiseMidi, server), 0, "Pyo server."},
@@ -4399,7 +4335,7 @@ static PyNumberMethods XnoiseMidi_as_number = {
     (binaryfunc)XnoiseMidi_add,                         /*nb_add*/
     (binaryfunc)XnoiseMidi_sub,                         /*nb_subtract*/
     (binaryfunc)XnoiseMidi_multiply,                    /*nb_multiply*/
-    (binaryfunc)XnoiseMidi_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -4413,16 +4349,16 @@ static PyNumberMethods XnoiseMidi_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)XnoiseMidi_inplace_add,                 /*inplace_add*/
     (binaryfunc)XnoiseMidi_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)XnoiseMidi_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)XnoiseMidi_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -4431,15 +4367,14 @@ static PyNumberMethods XnoiseMidi_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)XnoiseMidi_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)XnoiseMidi_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject XnoiseMidiType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.XnoiseMidi_base",                                   /*tp_name*/
     sizeof(XnoiseMidi),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -4447,7 +4382,7 @@ PyTypeObject XnoiseMidiType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &XnoiseMidi_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -4510,18 +4445,18 @@ typedef struct {
     int loopCountRec;
     int loopLen;
     int loopStop;
-    int modebuffer[6]; // need at least 2 slots for mul & add 
+    int modebuffer[6]; // need at least 2 slots for mul & add
 } XnoiseDur;
 
 // no parameter
 static MYFLT
 XnoiseDur_uniform(XnoiseDur *self) {
-    return RANDOM_UNIFORM;    
+    return RANDOM_UNIFORM;
 }
 
 static MYFLT
 XnoiseDur_linear_min(XnoiseDur *self) {
-    MYFLT a = RANDOM_UNIFORM;    
+    MYFLT a = RANDOM_UNIFORM;
     MYFLT b = RANDOM_UNIFORM;
     if (a < b) return a;
     else return b;
@@ -4529,7 +4464,7 @@ XnoiseDur_linear_min(XnoiseDur *self) {
 
 static MYFLT
 XnoiseDur_linear_max(XnoiseDur *self) {
-    MYFLT a = RANDOM_UNIFORM;    
+    MYFLT a = RANDOM_UNIFORM;
     MYFLT b = RANDOM_UNIFORM;
     if (a > b) return a;
     else return b;
@@ -4537,7 +4472,7 @@ XnoiseDur_linear_max(XnoiseDur *self) {
 
 static MYFLT
 XnoiseDur_triangle(XnoiseDur *self) {
-    MYFLT a = RANDOM_UNIFORM;    
+    MYFLT a = RANDOM_UNIFORM;
     MYFLT b = RANDOM_UNIFORM;
     return ((a + b) * 0.5);
 }
@@ -4546,7 +4481,7 @@ XnoiseDur_triangle(XnoiseDur *self) {
 static MYFLT
 XnoiseDur_expon_min(XnoiseDur *self) {
     if (self->xx1 <= 0.0) self->xx1 = 0.00001;
-    MYFLT val = -MYLOG(RANDOM_UNIFORM) / self->xx1;    
+    MYFLT val = -MYLOG(RANDOM_UNIFORM) / self->xx1;
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -4555,7 +4490,7 @@ XnoiseDur_expon_min(XnoiseDur *self) {
 static MYFLT
 XnoiseDur_expon_max(XnoiseDur *self) {
     if (self->xx1 <= 0.0) self->xx1 = 0.00001;
-    MYFLT val = 1.0 - (-MYLOG(RANDOM_UNIFORM) / self->xx1);    
+    MYFLT val = 1.0 - (-MYLOG(RANDOM_UNIFORM) / self->xx1);
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -4567,16 +4502,16 @@ XnoiseDur_biexpon(XnoiseDur *self) {
     MYFLT polar, val;
     if (self->xx1 <= 0.0) self->xx1 = 0.00001;
     MYFLT sum = RANDOM_UNIFORM * 2.0;
-    
+
     if (sum > 1.0) {
         polar = -1;
         sum = 2.0 - sum;
     }
     else
         polar = 1;
-    
+
     val = 0.5 * (polar * MYLOG(sum) / self->xx1) + 0.5;
-    
+
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -4589,14 +4524,14 @@ XnoiseDur_cauchy(XnoiseDur *self) {
         rnd = RANDOM_UNIFORM;
     }
     while (rnd == 0.5);
-    
-    if (rand() < (RAND_MAX / 2))
+
+    if (pyorand() < (PYO_RAND_MAX / 2))
         dir = -1;
     else
         dir = 1;
-    
+
     val = 0.5 * (MYTAN(rnd) * self->xx1 * dir) + 0.5;
-    
+
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -4607,10 +4542,10 @@ static MYFLT
 XnoiseDur_weibull(XnoiseDur *self) {
     MYFLT rnd, val;
     if (self->xx2 <= 0.0) self->xx2 = 0.00001;
-    
+
     rnd = 1.0 / (1.0 - RANDOM_UNIFORM);
     val = self->xx1 * MYPOW(MYLOG(rnd), (1.0 / self->xx2));
-    
+
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -4620,10 +4555,10 @@ XnoiseDur_weibull(XnoiseDur *self) {
 static MYFLT
 XnoiseDur_gaussian(XnoiseDur *self) {
     MYFLT rnd, val;
-    
+
     rnd = (RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM);
     val = (self->xx2 * (rnd - 3.0) * 0.33 + self->xx1);
-    
+
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -4637,7 +4572,7 @@ XnoiseDur_poisson(XnoiseDur *self) {
     MYFLT val;
     if (self->xx1 < 0.1) self->xx1 = 0.1;
     if (self->xx2 < 0.1) self->xx2 = 0.1;
-    
+
     if (self->xx1 != self->lastPoissonX1) {
         self->lastPoissonX1 = self->xx1;
         self->poisson_tab = 0;
@@ -4651,8 +4586,8 @@ XnoiseDur_poisson(XnoiseDur *self) {
             }
         }
     }
-    val = self->poisson_buffer[rand() % self->poisson_tab] / 12.0 * self->xx2;
-    
+    val = self->poisson_buffer[pyorand() % self->poisson_tab] / 12.0 * self->xx2;
+
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -4661,77 +4596,77 @@ XnoiseDur_poisson(XnoiseDur *self) {
 // x1 = max value, x2 = max step
 static MYFLT
 XnoiseDur_walker(XnoiseDur *self) {
-    int modulo, dir;
-    
+    unsigned int modulo, dir;
+
     if (self->xx2 < 0.002) self->xx2 = 0.002;
-    
-    modulo = (int)(self->xx2 * 1000.0);
-    dir = rand() % 2;
-    
-    if (dir == 0)
-        self->walkerValue = self->walkerValue + (((rand() % modulo) - (modulo / 2)) * 0.001);
+
+    modulo = (unsigned int)(self->xx2 * 1000.0);
+    dir = pyorand() % 100;
+
+    if (dir < 50)
+        self->walkerValue += ((MYFLT)(pyorand() % modulo) * 0.001);
     else
-        self->walkerValue = self->walkerValue - (((rand() % modulo) - (modulo / 2)) * 0.001);
-    
+        self->walkerValue -= ((MYFLT)(pyorand() % modulo) * 0.001);
+
     if (self->walkerValue > self->xx1)
         self->walkerValue = self->xx1;
-    if (self->walkerValue < 0.0)
+    else if (self->walkerValue < 0.0)
         self->walkerValue = 0.0;
-    
+
     return self->walkerValue;
 }
 
 // x1 = max value, x2 = max step
 static MYFLT
 XnoiseDur_loopseg(XnoiseDur *self) {
-    int modulo, dir;
-    
+    unsigned int modulo, dir;
+
     if (self->loopChoice == 0) {
-        
+
         self->loopCountPlay = self->loopTime = 0;
-        
+
         if (self->xx2 < 0.002) self->xx2 = 0.002;
-        
-        modulo = (int)(self->xx2 * 1000.0);
-        dir = rand() % 2;
-        
-        if (dir == 0)
-            self->walkerValue = self->walkerValue + (((rand() % modulo) - (modulo / 2)) * 0.001);
+
+        modulo = (unsigned int)(self->xx2 * 1000.0);
+        dir = pyorand() % 100;
+
+        if (dir < 50)
+            self->walkerValue += ((MYFLT)(pyorand() % modulo) * 0.001);
         else
-            self->walkerValue = self->walkerValue - (((rand() % modulo) - (modulo / 2)) * 0.001);
-        
+            self->walkerValue -= ((MYFLT)(pyorand() % modulo) * 0.001);
+
         if (self->walkerValue > self->xx1)
             self->walkerValue = self->xx1;
-        if (self->walkerValue < 0.0)
+        else if (self->walkerValue < 0.0)
             self->walkerValue = 0.0;
-        
+
         self->loop_buffer[self->loopCountRec++] = self->walkerValue;
-        
+
         if (self->loopCountRec < self->loopLen)
             self->loopChoice = 0;
         else {
             self->loopChoice = 1;
-            self->loopStop = (rand() % 4) + 1;
+            self->loopStop = (pyorand() % 4) + 1;
         }
     }
     else {
         self->loopCountRec = 0;
-        
+
         self->walkerValue = self->loop_buffer[self->loopCountPlay++];
-        
+
         if (self->loopCountPlay < self->loopLen)
             self->loopChoice = 1;
         else {
             self->loopCountPlay = 0;
             self->loopTime++;
         }
-        
+
         if (self->loopTime == self->loopStop) {
             self->loopChoice = 0;
-            self->loopLen = (rand() % 10) + 3;
+            self->loopLen = (pyorand() % 10) + 3;
         }
     }
-    
+
     return self->walkerValue;
 }
 
@@ -4739,7 +4674,7 @@ static void
 XnoiseDur_generate(XnoiseDur *self) {
     int i;
     MYFLT min, max;
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->time += self->inc;
         if (self->time < 0.0)
@@ -4787,8 +4722,8 @@ static void XnoiseDur_postprocessing_revareva(XnoiseDur *self) { POST_PROCESSING
 static void
 XnoiseDur_setRandomType(XnoiseDur *self)
 {
-    
-    switch (self->type) {            
+
+    switch (self->type) {
         case 0:
             self->type_func_ptr = XnoiseDur_uniform;
             break;
@@ -4828,7 +4763,7 @@ XnoiseDur_setRandomType(XnoiseDur *self)
         case 12:
             self->type_func_ptr = XnoiseDur_loopseg;
             break;
-    }        
+    }
 }
 
 static void
@@ -4836,44 +4771,44 @@ XnoiseDur_setProcMode(XnoiseDur *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = XnoiseDur_generate;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = XnoiseDur_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = XnoiseDur_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = XnoiseDur_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = XnoiseDur_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = XnoiseDur_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = XnoiseDur_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = XnoiseDur_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = XnoiseDur_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = XnoiseDur_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 XnoiseDur_compute_next_data_frame(XnoiseDur *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -4885,14 +4820,14 @@ XnoiseDur_traverse(XnoiseDur *self, visitproc visit, void *arg)
     Py_VISIT(self->min_stream);
     Py_VISIT(self->max);
     Py_VISIT(self->max_stream);
-    Py_VISIT(self->x1);    
-    Py_VISIT(self->x1_stream);    
-    Py_VISIT(self->x2);    
-    Py_VISIT(self->x2_stream);    
+    Py_VISIT(self->x1);
+    Py_VISIT(self->x1_stream);
+    Py_VISIT(self->x2);
+    Py_VISIT(self->x2_stream);
     return 0;
 }
 
-static int 
+static int
 XnoiseDur_clear(XnoiseDur *self)
 {
     pyo_CLEAR
@@ -4900,10 +4835,10 @@ XnoiseDur_clear(XnoiseDur *self)
     Py_CLEAR(self->min_stream);
     Py_CLEAR(self->max);
     Py_CLEAR(self->max_stream);
-    Py_CLEAR(self->x1);    
-    Py_CLEAR(self->x1_stream);    
-    Py_CLEAR(self->x2);    
-    Py_CLEAR(self->x2_stream);    
+    Py_CLEAR(self->x1);
+    Py_CLEAR(self->x1_stream);
+    Py_CLEAR(self->x2);
+    Py_CLEAR(self->x2_stream);
     return 0;
 }
 
@@ -4912,7 +4847,7 @@ XnoiseDur_dealloc(XnoiseDur* self)
 {
     pyo_DEALLOC
     XnoiseDur_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -4923,7 +4858,7 @@ XnoiseDur_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *mintmp=NULL, *maxtmp=NULL, *x1tmp=NULL, *x2tmp=NULL, *multmp=NULL, *addtmp=NULL;
     XnoiseDur *self;
     self = (XnoiseDur *)type->tp_alloc(type, 0);
-    
+
     self->x1 = PyFloat_FromDouble(0.5);
     self->x2 = PyFloat_FromDouble(0.5);
     self->min = PyFloat_FromDouble(0.0);
@@ -4936,11 +4871,11 @@ XnoiseDur_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[3] = 0;
 	self->modebuffer[4] = 0;
 	self->modebuffer[5] = 0;
-    
+
     INIT_OBJECT_COMMON
-    
+
     Server_generateSeed((Server *)self->server, XNOISEDUR_ID);
-    
+
     self->poisson_tab = 0;
     self->lastPoissonX1 = -99.0;
     for (i=0; i<2000; i++) {
@@ -4949,41 +4884,41 @@ XnoiseDur_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     for (i=0; i<15; i++) {
         self->loop_buffer[i] = 0.0;
     }
-    self->loopChoice = self->loopCountPlay = self->loopTime = self->loopCountRec = self->loopStop = 0;    
-    self->loopLen = (rand() % 10) + 3;
-    
+    self->loopChoice = self->loopCountPlay = self->loopTime = self->loopCountRec = self->loopStop = 0;
+    self->loopLen = (pyorand() % 10) + 3;
+
     Stream_setFunctionPtr(self->stream, XnoiseDur_compute_next_data_frame);
     self->mode_func_ptr = XnoiseDur_setProcMode;
 
     static char *kwlist[] = {"type", "min", "max", "x1", "x2", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|iOOOOOO", kwlist, &self->type, &mintmp, &maxtmp, &x1tmp, &x2tmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     if (x1tmp) {
         PyObject_CallMethod((PyObject *)self, "setX1", "O", x1tmp);
     }
-    
+
     if (x2tmp) {
         PyObject_CallMethod((PyObject *)self, "setX2", "O", x2tmp);
     }
-    
+
     if (mintmp) {
         PyObject_CallMethod((PyObject *)self, "setMin", "O", mintmp);
     }
-    
+
     if (maxtmp) {
         PyObject_CallMethod((PyObject *)self, "setMax", "O", maxtmp);
     }
-    
+
     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);
 
     if (self->modebuffer[2] == 0)
@@ -4994,15 +4929,15 @@ XnoiseDur_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         ma = PyFloat_AS_DOUBLE(self->max);
     else
         ma = Stream_getData((Stream *)self->max_stream)[0];
-    
+
     self->value = (mi + ma) * 0.5;
     if (self->value == 0.0)
         self->inc = 0.0;
     else
         self->inc = (1.0 / self->value) / self->sr;
-    
+
     XnoiseDur_setRandomType(self);
-    
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
@@ -5010,10 +4945,10 @@ XnoiseDur_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * XnoiseDur_getServer(XnoiseDur* self) { GET_SERVER };
 static PyObject * XnoiseDur_getStream(XnoiseDur* self) { GET_STREAM };
-static PyObject * XnoiseDur_setMul(XnoiseDur *self, PyObject *arg) { SET_MUL };	
-static PyObject * XnoiseDur_setAdd(XnoiseDur *self, PyObject *arg) { SET_ADD };	
-static PyObject * XnoiseDur_setSub(XnoiseDur *self, PyObject *arg) { SET_SUB };	
-static PyObject * XnoiseDur_setDiv(XnoiseDur *self, PyObject *arg) { SET_DIV };	
+static PyObject * XnoiseDur_setMul(XnoiseDur *self, PyObject *arg) { SET_MUL };
+static PyObject * XnoiseDur_setAdd(XnoiseDur *self, PyObject *arg) { SET_ADD };
+static PyObject * XnoiseDur_setSub(XnoiseDur *self, PyObject *arg) { SET_SUB };
+static PyObject * XnoiseDur_setDiv(XnoiseDur *self, PyObject *arg) { SET_DIV };
 
 static PyObject * XnoiseDur_play(XnoiseDur *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * XnoiseDur_out(XnoiseDur *self, PyObject *args, PyObject *kwds) { OUT };
@@ -5030,35 +4965,29 @@ static PyObject * XnoiseDur_inplace_div(XnoiseDur *self, PyObject *arg) { INPLAC
 
 static PyObject *
 XnoiseDur_setType(XnoiseDur *self, PyObject *arg)
-{	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+{
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyInt_Check(arg);
-	
+
 	if (isNumber == 1) {
 		self->type = PyInt_AsLong(arg);
         XnoiseDur_setRandomType(self);
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 XnoiseDur_setX1(XnoiseDur *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->x1);
@@ -5074,25 +5003,22 @@ XnoiseDur_setX1(XnoiseDur *self, PyObject *arg)
         self->x1_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 XnoiseDur_setX2(XnoiseDur *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->x2);
@@ -5108,25 +5034,22 @@ XnoiseDur_setX2(XnoiseDur *self, PyObject *arg)
         self->x2_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 XnoiseDur_setMin(XnoiseDur *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->min);
@@ -5142,25 +5065,22 @@ XnoiseDur_setMin(XnoiseDur *self, PyObject *arg)
         self->min_stream = (Stream *)streamtmp;
 		self->modebuffer[4] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 XnoiseDur_setMax(XnoiseDur *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->max);
@@ -5176,12 +5096,12 @@ XnoiseDur_setMax(XnoiseDur *self, PyObject *arg)
         self->max_stream = (Stream *)streamtmp;
 		self->modebuffer[5] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef XnoiseDur_members[] = {
     {"server", T_OBJECT_EX, offsetof(XnoiseDur, server), 0, "Pyo server."},
@@ -5217,7 +5137,7 @@ static PyNumberMethods XnoiseDur_as_number = {
     (binaryfunc)XnoiseDur_add,                         /*nb_add*/
     (binaryfunc)XnoiseDur_sub,                         /*nb_subtract*/
     (binaryfunc)XnoiseDur_multiply,                    /*nb_multiply*/
-    (binaryfunc)XnoiseDur_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -5231,16 +5151,16 @@ static PyNumberMethods XnoiseDur_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)XnoiseDur_inplace_add,                 /*inplace_add*/
     (binaryfunc)XnoiseDur_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)XnoiseDur_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)XnoiseDur_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -5249,15 +5169,14 @@ static PyNumberMethods XnoiseDur_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)XnoiseDur_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)XnoiseDur_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject XnoiseDurType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.XnoiseDur_base",                                   /*tp_name*/
     sizeof(XnoiseDur),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -5265,7 +5184,7 @@ PyTypeObject XnoiseDurType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &XnoiseDur_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -5312,7 +5231,7 @@ typedef struct {
     MYFLT time;
     MYFLT *trigsBuffer;
     TriggerStream *trig_stream;
-    int modebuffer[3]; // need at least 2 slots for mul & add 
+    int modebuffer[3]; // need at least 2 slots for mul & add
 } Urn;
 
 static void
@@ -5331,13 +5250,13 @@ Urn_choose(Urn *self) {
     int x = 0;
     int value = 0;
     int i, pick;
- 
-    pick = rand() % self->length;
+
+    pick = pyorand() % self->length;
     while (pick == self->lastvalue)
-        pick = rand() % self->length;
+        pick = pyorand() % self->length;
 
     for (i=0; i<self->length; i++) {
-        if (i != pick) 
+        if (i != pick)
             self->list[x++] = self->list[i];
         else
             value = self->list[i];
@@ -5354,7 +5273,7 @@ Urn_generate_i(Urn *self) {
     int i;
     MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
     MYFLT inc = fr / self->sr;
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->trigsBuffer[i] = 0.0;
         self->time += inc;
@@ -5377,7 +5296,7 @@ Urn_generate_a(Urn *self) {
     int i;
     MYFLT inc;
     MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->trigsBuffer[i] = 0.0;
         inc = fr[i] / self->sr;
@@ -5412,50 +5331,50 @@ Urn_setProcMode(Urn *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2];
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Urn_generate_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Urn_generate_a;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Urn_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Urn_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Urn_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Urn_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Urn_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Urn_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Urn_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Urn_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Urn_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 Urn_compute_next_data_frame(Urn *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -5465,17 +5384,17 @@ Urn_traverse(Urn *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->freq);
     Py_VISIT(self->freq_stream);
-    Py_VISIT(self->trig_stream);    
+    Py_VISIT(self->trig_stream);
     return 0;
 }
 
-static int 
+static int
 Urn_clear(Urn *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->freq);
     Py_CLEAR(self->freq_stream);
-    Py_CLEAR(self->trig_stream);    
+    Py_CLEAR(self->trig_stream);
     return 0;
 }
 
@@ -5486,7 +5405,7 @@ Urn_dealloc(Urn* self)
     free(self->list);
     free(self->trigsBuffer);
     Urn_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -5496,7 +5415,7 @@ Urn_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *freqtmp=NULL, *multmp=NULL, *addtmp=NULL;
     Urn *self;
     self = (Urn *)type->tp_alloc(type, 0);
-    
+
     self->freq = PyFloat_FromDouble(1.);
     self->max = 100;
     self->length = 0;
@@ -5506,36 +5425,36 @@ Urn_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Urn_compute_next_data_frame);
     self->mode_func_ptr = Urn_setProcMode;
 
     static char *kwlist[] = {"max", "freq", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|iOOO", kwlist, &self->max, &freqtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     if (freqtmp) {
         PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
     }
-    
+
     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->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT));
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->trigsBuffer[i] = 0.0;
-    }    
-    
+    }
+
     MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL);
     TriggerStream_setData(self->trig_stream, self->trigsBuffer);
 
@@ -5551,10 +5470,10 @@ Urn_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 static PyObject * Urn_getServer(Urn* self) { GET_SERVER };
 static PyObject * Urn_getStream(Urn* self) { GET_STREAM };
 static PyObject * Urn_getTriggerStream(Urn* self) { GET_TRIGGER_STREAM };
-static PyObject * Urn_setMul(Urn *self, PyObject *arg) { SET_MUL };	
-static PyObject * Urn_setAdd(Urn *self, PyObject *arg) { SET_ADD };	
-static PyObject * Urn_setSub(Urn *self, PyObject *arg) { SET_SUB };	
-static PyObject * Urn_setDiv(Urn *self, PyObject *arg) { SET_DIV };	
+static PyObject * Urn_setMul(Urn *self, PyObject *arg) { SET_MUL };
+static PyObject * Urn_setAdd(Urn *self, PyObject *arg) { SET_ADD };
+static PyObject * Urn_setSub(Urn *self, PyObject *arg) { SET_SUB };
+static PyObject * Urn_setDiv(Urn *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Urn_play(Urn *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Urn_out(Urn *self, PyObject *args, PyObject *kwds) { OUT };
@@ -5571,7 +5490,7 @@ static PyObject * Urn_inplace_div(Urn *self, PyObject *arg) { INPLACE_DIV };
 
 static PyObject *
 Urn_setMax(Urn *self, PyObject *arg)
-{	
+{
 	if (PyNumber_Check(arg) == 1)
 		self->max = PyInt_AsLong(arg);
 
@@ -5579,20 +5498,17 @@ Urn_setMax(Urn *self, PyObject *arg)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Urn_setFreq(Urn *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->freq);
@@ -5608,12 +5524,12 @@ Urn_setFreq(Urn *self, PyObject *arg)
         self->freq_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Urn_members[] = {
 {"server", T_OBJECT_EX, offsetof(Urn, server), 0, "Pyo server."},
@@ -5645,7 +5561,7 @@ static PyNumberMethods Urn_as_number = {
 (binaryfunc)Urn_add,                         /*nb_add*/
 (binaryfunc)Urn_sub,                         /*nb_subtract*/
 (binaryfunc)Urn_multiply,                    /*nb_multiply*/
-(binaryfunc)Urn_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -5659,16 +5575,16 @@ static PyNumberMethods Urn_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)Urn_inplace_add,                 /*inplace_add*/
 (binaryfunc)Urn_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)Urn_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)Urn_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -5677,15 +5593,14 @@ static PyNumberMethods Urn_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)Urn_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)Urn_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject UrnType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Urn_base",                                   /*tp_name*/
 sizeof(Urn),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -5693,7 +5608,7 @@ sizeof(Urn),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &Urn_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -5724,3 +5639,457 @@ Urn_members,                                 /* tp_members */
 0,                                              /* tp_alloc */
 Urn_new,                                     /* tp_new */
 };
+
+/****************/
+/**** LogiMap ***/
+/****************/
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *chaos;
+    PyObject *freq;
+    Stream *chaos_stream;
+    Stream *freq_stream;
+    MYFLT init;
+    MYFLT value;
+    MYFLT time;
+    int modebuffer[4]; // need at least 2 slots for mul & add
+} LogiMap;
+
+static void
+LogiMap_generate_ii(LogiMap *self) {
+    int i;
+    MYFLT inc;
+    MYFLT ch = PyFloat_AS_DOUBLE(self->chaos);
+    MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
+    inc = fr / self->sr;
+
+    if (ch <= 0.0)
+        ch = 0.001;
+    else if (ch >= 1.0)
+        ch = 0.999;
+
+    for (i=0; i<self->bufsize; i++) {
+        self->time += inc;
+        if (self->time >= 1.0) {
+            self->time -= 1.0;
+            self->value = (ch + 3) * self->value * (1.0 - self->value);
+        }
+        self->data[i] = self->value;
+    }
+}
+
+static void
+LogiMap_generate_ai(LogiMap *self) {
+    int i;
+    MYFLT inc, ch = 0.0;
+    MYFLT *chaos = Stream_getData((Stream *)self->chaos_stream);
+    MYFLT fr = PyFloat_AS_DOUBLE(self->freq);
+    inc = fr / self->sr;
+
+    for (i=0; i<self->bufsize; i++) {
+        self->time += inc;
+        if (self->time >= 1.0) {
+            self->time -= 1.0;
+            ch = chaos[i];
+            if (ch <= 0.0)
+                ch = 0.001;
+            else if (ch >= 1.0)
+                ch = 0.999;
+            self->value = (ch + 3) * self->value * (1.0 - self->value);
+        }
+        self->data[i] = self->value;
+    }
+}
+
+static void
+LogiMap_generate_ia(LogiMap *self) {
+    int i;
+    MYFLT inc;
+    MYFLT ch = PyFloat_AS_DOUBLE(self->chaos);
+    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
+
+    if (ch <= 0.0)
+        ch = 0.001;
+    else if (ch >= 1.0)
+        ch = 0.999;
+
+    for (i=0; i<self->bufsize; i++) {
+        inc = fr[i] / self->sr;
+        self->time += inc;
+        if (self->time >= 1.0) {
+            self->time -= 1.0;
+            self->value = (ch + 3) * self->value * (1.0 - self->value);
+        }
+        self->data[i] = self->value;
+    }
+}
+
+static void
+LogiMap_generate_aa(LogiMap *self) {
+    int i;
+    MYFLT inc, ch = 0.0;
+    MYFLT *chaos = Stream_getData((Stream *)self->chaos_stream);
+    MYFLT *fr = Stream_getData((Stream *)self->freq_stream);
+
+    for (i=0; i<self->bufsize; i++) {
+        inc = fr[i] / self->sr;
+        self->time += inc;
+        if (self->time >= 1.0) {
+            self->time -= 1.0;
+            ch = chaos[i];
+            if (ch <= 0.0)
+                ch = 0.001;
+            else if (ch >= 1.0)
+                ch = 0.999;
+            self->value = (ch + 3) * self->value * (1.0 - self->value);
+        }
+        self->data[i] = self->value;
+    }
+}
+
+static void LogiMap_postprocessing_ii(LogiMap *self) { POST_PROCESSING_II };
+static void LogiMap_postprocessing_ai(LogiMap *self) { POST_PROCESSING_AI };
+static void LogiMap_postprocessing_ia(LogiMap *self) { POST_PROCESSING_IA };
+static void LogiMap_postprocessing_aa(LogiMap *self) { POST_PROCESSING_AA };
+static void LogiMap_postprocessing_ireva(LogiMap *self) { POST_PROCESSING_IREVA };
+static void LogiMap_postprocessing_areva(LogiMap *self) { POST_PROCESSING_AREVA };
+static void LogiMap_postprocessing_revai(LogiMap *self) { POST_PROCESSING_REVAI };
+static void LogiMap_postprocessing_revaa(LogiMap *self) { POST_PROCESSING_REVAA };
+static void LogiMap_postprocessing_revareva(LogiMap *self) { POST_PROCESSING_REVAREVA };
+
+static void
+LogiMap_setProcMode(LogiMap *self)
+{
+    int procmode, muladdmode;
+    procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+	switch (procmode) {
+        case 0:
+            self->proc_func_ptr = LogiMap_generate_ii;
+            break;
+        case 1:
+            self->proc_func_ptr = LogiMap_generate_ai;
+            break;
+        case 10:
+            self->proc_func_ptr = LogiMap_generate_ia;
+            break;
+        case 11:
+            self->proc_func_ptr = LogiMap_generate_aa;
+            break;
+    }
+	switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = LogiMap_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = LogiMap_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = LogiMap_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = LogiMap_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = LogiMap_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = LogiMap_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = LogiMap_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = LogiMap_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = LogiMap_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+LogiMap_compute_next_data_frame(LogiMap *self)
+{
+    (*self->proc_func_ptr)(self);
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+LogiMap_traverse(LogiMap *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->freq);
+    Py_VISIT(self->freq_stream);
+    Py_VISIT(self->chaos);
+    Py_VISIT(self->chaos_stream);
+    return 0;
+}
+
+static int
+LogiMap_clear(LogiMap *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->freq);
+    Py_CLEAR(self->freq_stream);
+    Py_CLEAR(self->chaos);
+    Py_CLEAR(self->chaos_stream);
+    return 0;
+}
+
+static void
+LogiMap_dealloc(LogiMap* self)
+{
+    pyo_DEALLOC
+    LogiMap_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+LogiMap_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    MYFLT init;
+    PyObject *chaostmp=NULL, *freqtmp=NULL, *multmp=NULL, *addtmp=NULL;
+    LogiMap *self;
+    self = (LogiMap *)type->tp_alloc(type, 0);
+
+    self->chaos = PyFloat_FromDouble(0.6);
+    self->freq = PyFloat_FromDouble(1.);
+    self->time = 1.0;
+	self->modebuffer[0] = 0;
+	self->modebuffer[1] = 0;
+	self->modebuffer[2] = 0;
+	self->modebuffer[3] = 0;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, LogiMap_compute_next_data_frame);
+    self->mode_func_ptr = LogiMap_setProcMode;
+
+    static char *kwlist[] = {"chaos", "freq", "init", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__OOFOO, kwlist, &chaostmp, &freqtmp, &init, &multmp, &addtmp))
+        Py_RETURN_NONE;
+
+    if (chaostmp) {
+        PyObject_CallMethod((PyObject *)self, "setChaos", "O", chaostmp);
+    }
+
+    if (freqtmp) {
+        PyObject_CallMethod((PyObject *)self, "setFreq", "O", freqtmp);
+    }
+
+    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);
+
+    if (init <= 0)
+        init = 0.001;
+    else if (init >= 1.0)
+        init = 0.999;
+    self->value = self->init = init;
+
+    (*self->mode_func_ptr)(self);
+
+    return (PyObject *)self;
+}
+
+static PyObject * LogiMap_getServer(LogiMap* self) { GET_SERVER };
+static PyObject * LogiMap_getStream(LogiMap* self) { GET_STREAM };
+static PyObject * LogiMap_setMul(LogiMap *self, PyObject *arg) { SET_MUL };
+static PyObject * LogiMap_setAdd(LogiMap *self, PyObject *arg) { SET_ADD };
+static PyObject * LogiMap_setSub(LogiMap *self, PyObject *arg) { SET_SUB };
+static PyObject * LogiMap_setDiv(LogiMap *self, PyObject *arg) { SET_DIV };
+
+static PyObject * LogiMap_play(LogiMap *self, PyObject *args, PyObject *kwds) { 
+    self->value = self->init;
+    PLAY 
+};
+static PyObject * LogiMap_out(LogiMap *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * LogiMap_stop(LogiMap *self) { STOP };
+
+static PyObject * LogiMap_multiply(LogiMap *self, PyObject *arg) { MULTIPLY };
+static PyObject * LogiMap_inplace_multiply(LogiMap *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * LogiMap_add(LogiMap *self, PyObject *arg) { ADD };
+static PyObject * LogiMap_inplace_add(LogiMap *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * LogiMap_sub(LogiMap *self, PyObject *arg) { SUB };
+static PyObject * LogiMap_inplace_sub(LogiMap *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * LogiMap_div(LogiMap *self, PyObject *arg) { DIV };
+static PyObject * LogiMap_inplace_div(LogiMap *self, PyObject *arg) { INPLACE_DIV };
+
+static PyObject *
+LogiMap_setChaos(LogiMap *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->chaos);
+	if (isNumber == 1) {
+		self->chaos = PyNumber_Float(tmp);
+        self->modebuffer[2] = 0;
+	}
+	else {
+		self->chaos = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->chaos, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->chaos_stream);
+        self->chaos_stream = (Stream *)streamtmp;
+		self->modebuffer[2] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+LogiMap_setFreq(LogiMap *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->freq);
+	if (isNumber == 1) {
+		self->freq = PyNumber_Float(tmp);
+        self->modebuffer[3] = 0;
+	}
+	else {
+		self->freq = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->freq, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->freq_stream);
+        self->freq_stream = (Stream *)streamtmp;
+		self->modebuffer[3] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyMemberDef LogiMap_members[] = {
+{"server", T_OBJECT_EX, offsetof(LogiMap, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(LogiMap, stream), 0, "Stream object."},
+{"chaos", T_OBJECT_EX, offsetof(LogiMap, chaos), 0, "chaosimum possible value."},
+{"freq", T_OBJECT_EX, offsetof(LogiMap, freq), 0, "Polling frequency."},
+{"mul", T_OBJECT_EX, offsetof(LogiMap, mul), 0, "Mul factor."},
+{"add", T_OBJECT_EX, offsetof(LogiMap, add), 0, "Add factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyMethodDef LogiMap_methods[] = {
+{"getServer", (PyCFunction)LogiMap_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)LogiMap_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)LogiMap_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"out", (PyCFunction)LogiMap_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+{"stop", (PyCFunction)LogiMap_stop, METH_NOARGS, "Stops computing."},
+{"setChaos", (PyCFunction)LogiMap_setChaos, METH_O, "Sets the randomization degree."},
+{"setFreq", (PyCFunction)LogiMap_setFreq, METH_O, "Sets polling frequency."},
+{"setMul", (PyCFunction)LogiMap_setMul, METH_O, "Sets oscillator mul factor."},
+{"setAdd", (PyCFunction)LogiMap_setAdd, METH_O, "Sets oscillator add factor."},
+{"setSub", (PyCFunction)LogiMap_setSub, METH_O, "Sets inverse add factor."},
+{"setDiv", (PyCFunction)LogiMap_setDiv, METH_O, "Sets inverse mul factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyNumberMethods LogiMap_as_number = {
+(binaryfunc)LogiMap_add,                         /*nb_add*/
+(binaryfunc)LogiMap_sub,                         /*nb_subtract*/
+(binaryfunc)LogiMap_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)LogiMap_inplace_add,                 /*inplace_add*/
+(binaryfunc)LogiMap_inplace_sub,                 /*inplace_subtract*/
+(binaryfunc)LogiMap_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)LogiMap_div,                       /*nb_true_divide*/
+0,                                              /*nb_inplace_floor_divide*/
+(binaryfunc)LogiMap_inplace_div,                       /*nb_inplace_true_divide*/
+0,                                              /* nb_index */
+};
+
+PyTypeObject LogiMapType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.LogiMap_base",                                   /*tp_name*/
+sizeof(LogiMap),                                 /*tp_basicsize*/
+0,                                              /*tp_itemsize*/
+(destructor)LogiMap_dealloc,                     /*tp_dealloc*/
+0,                                              /*tp_print*/
+0,                                              /*tp_getattr*/
+0,                                              /*tp_setattr*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
+0,                                              /*tp_repr*/
+&LogiMap_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*/
+"LogiMap objects. Random generator based on the logistic equation.",           /* tp_doc */
+(traverseproc)LogiMap_traverse,                  /* tp_traverse */
+(inquiry)LogiMap_clear,                          /* tp_clear */
+0,                                              /* tp_richcompare */
+0,                                              /* tp_weaklistoffset */
+0,                                              /* tp_iter */
+0,                                              /* tp_iternext */
+LogiMap_methods,                                 /* tp_methods */
+LogiMap_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 */
+LogiMap_new,                                     /* tp_new */
+};
diff --git a/src/objects/recordmodule.c b/src/objects/recordmodule.c
index 1ce6d30..e6a3a46 100644
--- a/src/objects/recordmodule.c
+++ b/src/objects/recordmodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include "pyomodule.h"
 #include "streammodule.h"
@@ -50,16 +51,16 @@ Record_process(Record *self) {
     MYFLT *in;
 
     totlen = self->chnls*self->bufsize*self->buffering;
-    
+
     if (self->count == self->buffering) {
         self->count = 0;
         for (i=0; i<totlen; i++) {
             self->buffer[i] = 0.0;
         }
-    }    
+    }
 
     offset = self->bufsize * self->chnls * self->count;
-    
+
     for (j=0; j<self->listlen; j++) {
         chnl = j % self->chnls;
         in = Stream_getData((Stream *)PyList_GET_ITEM(self->input_stream_list, j));
@@ -68,21 +69,21 @@ Record_process(Record *self) {
         }
     }
     self->count++;
-    
+
     if (self->count == self->buffering)
         SF_WRITE(self->recfile, self->buffer, totlen);
 }
 
 static void
 Record_setProcMode(Record *self)
-{       
-    self->proc_func_ptr = Record_process;   
+{
+    self->proc_func_ptr = Record_process;
 }
 
 static void
 Record_compute_next_data_frame(Record *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -94,7 +95,7 @@ Record_traverse(Record *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Record_clear(Record *self)
 {
     pyo_CLEAR
@@ -111,7 +112,7 @@ Record_dealloc(Record* self)
     pyo_DEALLOC
     free(self->buffer);
     Record_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -120,23 +121,25 @@ Record_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     int i, buflen;
     int fileformat = 0;
     int sampletype = 0;
+    double quality = 0.4;
+    Py_ssize_t psize;
     PyObject *input_listtmp;
     Record *self;
     self = (Record *)type->tp_alloc(type, 0);
-    
+
     self->chnls = 2;
     self->buffering = 4;
     self->count = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Record_compute_next_data_frame);
     self->mode_func_ptr = Record_setProcMode;
 
-    static char *kwlist[] = {"input", "filename", "chnls", "fileformat", "sampletype", "buffering", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "Os|iiii", kwlist, &input_listtmp, &self->recpath, &self->chnls, &fileformat, &sampletype, &self->buffering))
+    static char *kwlist[] = {"input", "filename", "chnls", "fileformat", "sampletype", "buffering", "quality", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "Os#|iiiid", kwlist, &input_listtmp, &self->recpath, &psize, &self->chnls, &fileformat, &sampletype, &self->buffering, &quality))
         Py_RETURN_NONE;
-    
+
     Py_XDECREF(self->input_list);
     self->input_list = input_listtmp;
     self->listlen = PyList_Size(self->input_list);
@@ -148,7 +151,7 @@ Record_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     /* Prepare sfinfo */
     self->recinfo.samplerate = (int)self->sr;
     self->recinfo.channels = self->chnls;
-    
+
     switch (fileformat) {
         case 0:
             self->recinfo.format = SF_FORMAT_WAV;
@@ -200,21 +203,26 @@ Record_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
                 break;
         }
     }
-    
+
     /* Open the output file. */
-    if (! (self->recfile = sf_open(self->recpath, SFM_WRITE, &self->recinfo))) {   
-        printf ("Not able to open output file %s.\n", self->recpath);
+    if (! (self->recfile = sf_open(self->recpath, SFM_WRITE, &self->recinfo))) {
+        PySys_WriteStdout("Record: not able to open output file %s.\n", self->recpath);
         Py_RETURN_NONE;
-    }	
+    }
+
+    // Sets the encoding quality for FLAC and OGG compressed formats
+    if (fileformat == 5 || fileformat == 7) {
+        sf_command(self->recfile, SFC_SET_VBR_ENCODING_QUALITY, &quality, sizeof(double));
+    }
 
     buflen = self->bufsize * self->chnls * self->buffering;
     self->buffer = (MYFLT *)realloc(self->buffer, buflen * sizeof(MYFLT));
     for (i=0; i<buflen; i++) {
         self->buffer[i] = 0.;
-    }    
-    
+    }
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
@@ -224,8 +232,8 @@ static PyObject * Record_getServer(Record* self) { GET_SERVER };
 static PyObject * Record_getStream(Record* self) { GET_STREAM };
 
 static PyObject * Record_play(Record *self, PyObject *args, PyObject *kwds) { PLAY };
-static PyObject * Record_stop(Record *self) 
-{ 
+static PyObject * Record_stop(Record *self)
+{
     sf_close(self->recfile);
     STOP
 };
@@ -246,8 +254,7 @@ static PyMethodDef Record_methods[] = {
 };
 
 PyTypeObject RecordType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Record_base",                                   /*tp_name*/
 sizeof(Record),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -255,7 +262,7 @@ sizeof(Record),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 0,												/*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -307,9 +314,9 @@ typedef struct {
 static void
 ControlRec_process(ControlRec *self) {
     int i;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->dur > 0.0) {
         for (i=0; i<self->bufsize; i++) {
             if ((self->time % self->modulo) == 0 && self->count < self->size) {
@@ -319,7 +326,7 @@ ControlRec_process(ControlRec *self) {
             self->time++;
             if (self->count >= self->size)
                 PyObject_CallMethod((PyObject *)self, "stop", NULL);
-        }        
+        }
     }
     else {
         for (i=0; i<self->bufsize; i++) {
@@ -333,14 +340,14 @@ ControlRec_process(ControlRec *self) {
 
 static void
 ControlRec_setProcMode(ControlRec *self)
-{       
-    self->proc_func_ptr = ControlRec_process;   
+{
+    self->proc_func_ptr = ControlRec_process;
 }
 
 static void
 ControlRec_compute_next_data_frame(ControlRec *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -353,7 +360,7 @@ ControlRec_traverse(ControlRec *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 ControlRec_clear(ControlRec *self)
 {
     pyo_CLEAR
@@ -370,7 +377,7 @@ ControlRec_dealloc(ControlRec* self)
     if (self->buffer != NULL)
         free(self->buffer);
     ControlRec_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -381,33 +388,33 @@ ControlRec_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp;
     ControlRec *self;
     self = (ControlRec *)type->tp_alloc(type, 0);
-    
+
     self->dur = 0.0;
     self->rate = 1000;
     self->tmp_list = PyList_New(0);
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, ControlRec_compute_next_data_frame);
     self->mode_func_ptr = ControlRec_setProcMode;
 
     static char *kwlist[] = {"input", "rate", "dur", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_IF, kwlist, &inputtmp, &self->rate, &self->dur))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
 
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     if (self->dur > 0.0) {
         self->size = (long)(self->dur * self->rate + 1);
         self->buffer = (MYFLT *)realloc(self->buffer, self->size * sizeof(MYFLT));
         for (j=0; j<self->size; j++) {
             self->buffer[j] = 0.0;
-        }        
-    }    
+        }
+    }
     self->modulo = (int)(self->sr / self->rate);
-    
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
@@ -416,9 +423,9 @@ ControlRec_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 static PyObject * ControlRec_getServer(ControlRec* self) { GET_SERVER };
 static PyObject * ControlRec_getStream(ControlRec* self) { GET_STREAM };
 
-static PyObject * ControlRec_play(ControlRec *self, PyObject *args, PyObject *kwds) { 
+static PyObject * ControlRec_play(ControlRec *self, PyObject *args, PyObject *kwds) {
     self->count = self->time = 0;
-    PLAY 
+    PLAY
 };
 
 static PyObject * ControlRec_stop(ControlRec *self) { STOP };
@@ -428,7 +435,7 @@ ControlRec_getData(ControlRec *self) {
     int i;
     PyObject *data, *point;
     MYFLT time, timescl = 1.0 / self->rate;
-        
+
     if (self->dur > 0.0) {
         data = PyList_New(self->size);
         for (i=0; i<self->size; i++) {
@@ -437,7 +444,7 @@ ControlRec_getData(ControlRec *self) {
             PyTuple_SET_ITEM(point, 0, PyFloat_FromDouble(time));
             PyTuple_SET_ITEM(point, 1, PyFloat_FromDouble(self->buffer[i]));
             PyList_SetItem(data, i, point);
-        }        
+        }
     }
     else {
         Py_ssize_t size = PyList_Size(self->tmp_list);
@@ -448,7 +455,7 @@ ControlRec_getData(ControlRec *self) {
             PyTuple_SET_ITEM(point, 0, PyFloat_FromDouble(time));
             PyTuple_SET_ITEM(point, 1, PyList_GET_ITEM(self->tmp_list, i));
             PyList_SetItem(data, i, point);
-        }        
+        }
     }
 	return data;
 }
@@ -470,8 +477,7 @@ static PyMethodDef ControlRec_methods[] = {
 };
 
 PyTypeObject ControlRecType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.ControlRec_base",                                   /*tp_name*/
     sizeof(ControlRec),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -479,7 +485,7 @@ PyTypeObject ControlRecType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     0,												/*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -536,16 +542,16 @@ ControlRead_readframes_i(ControlRead *self) {
     MYFLT fpart;
     long i, mod;
     MYFLT invmodulo = 1.0 / self->modulo;
-    
+
     if (self->go == 0)
         PyObject_CallMethod((PyObject *)self, "stop", NULL);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->trigsBuffer[i] = 0.0;
         if (self->go == 1) {
             mod = self->time % self->modulo;
             fpart = mod * invmodulo;
-            self->data[i] = (*self->interp_func_ptr)(self->values, (int)self->count, fpart, (int)self->size);            
+            self->data[i] = (*self->interp_func_ptr)(self->values, (int)self->count, fpart, (int)self->size);
         }
         else {
             mod = -1;
@@ -581,44 +587,44 @@ ControlRead_setProcMode(ControlRead *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = ControlRead_readframes_i;
 
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = ControlRead_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = ControlRead_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = ControlRead_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = ControlRead_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = ControlRead_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = ControlRead_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = ControlRead_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = ControlRead_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = ControlRead_postprocessing_revareva;
             break;
-    } 
+    }
 }
 
 static void
 ControlRead_compute_next_data_frame(ControlRead *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -626,15 +632,15 @@ static int
 ControlRead_traverse(ControlRead *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->trig_stream);    
+    Py_VISIT(self->trig_stream);
     return 0;
 }
 
-static int 
+static int
 ControlRead_clear(ControlRead *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->trig_stream);    
+    Py_CLEAR(self->trig_stream);
     return 0;
 }
 
@@ -645,7 +651,7 @@ ControlRead_dealloc(ControlRead* self)
     free(self->values);
     free(self->trigsBuffer);
     ControlRead_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -655,74 +661,74 @@ ControlRead_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *valuestmp, *multmp=NULL, *addtmp=NULL;
     ControlRead *self;
     self = (ControlRead *)type->tp_alloc(type, 0);
-    
+
     self->loop = 0;
     self->rate = 1000;
     self->interp = 2;
     self->go = 1;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, ControlRead_compute_next_data_frame);
     self->mode_func_ptr = ControlRead_setProcMode;
 
     static char *kwlist[] = {"values", "rate", "loop", "interp", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iiiOO", kwlist, &valuestmp, &self->rate, &self->loop, &self->interp, &multmp, &addtmp))
         Py_RETURN_NONE;
 
     if (valuestmp) {
         PyObject_CallMethod((PyObject *)self, "setValues", "O", valuestmp);
     }
-    
+
     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->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT));
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->trigsBuffer[i] = 0.0;
-    }    
+    }
 
     MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL);
     TriggerStream_setData(self->trig_stream, self->trigsBuffer);
-    
+
     self->modulo = (int)(self->sr / self->rate);
 
     (*self->mode_func_ptr)(self);
-    
+
     SET_INTERP_POINTER
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * ControlRead_getServer(ControlRead* self) { GET_SERVER };
 static PyObject * ControlRead_getStream(ControlRead* self) { GET_STREAM };
 static PyObject * ControlRead_getTriggerStream(ControlRead* self) { GET_TRIGGER_STREAM };
-static PyObject * ControlRead_setMul(ControlRead *self, PyObject *arg) { SET_MUL };	
-static PyObject * ControlRead_setAdd(ControlRead *self, PyObject *arg) { SET_ADD };	
-static PyObject * ControlRead_setSub(ControlRead *self, PyObject *arg) { SET_SUB };	
-static PyObject * ControlRead_setDiv(ControlRead *self, PyObject *arg) { SET_DIV };	
+static PyObject * ControlRead_setMul(ControlRead *self, PyObject *arg) { SET_MUL };
+static PyObject * ControlRead_setAdd(ControlRead *self, PyObject *arg) { SET_ADD };
+static PyObject * ControlRead_setSub(ControlRead *self, PyObject *arg) { SET_SUB };
+static PyObject * ControlRead_setDiv(ControlRead *self, PyObject *arg) { SET_DIV };
 
-static PyObject * ControlRead_play(ControlRead *self, PyObject *args, PyObject *kwds) 
-{ 
+static PyObject * ControlRead_play(ControlRead *self, PyObject *args, PyObject *kwds)
+{
     self->count = self->time = 0;
     self->go = 1;
-    PLAY 
+    PLAY
 };
 
-static PyObject * ControlRead_stop(ControlRead *self) 
-{ 
+static PyObject * ControlRead_stop(ControlRead *self)
+{
     self->go = 0;
-    STOP 
+    STOP
 };
 
 static PyObject * ControlRead_multiply(ControlRead *self, PyObject *arg) { MULTIPLY };
@@ -738,33 +744,27 @@ static PyObject *
 ControlRead_setValues(ControlRead *self, PyObject *arg)
 {
     Py_ssize_t i;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
     self->size = PyList_Size(arg);
     self->values = (MYFLT *)realloc(self->values, self->size * sizeof(MYFLT));
     for (i=0; i<self->size; i++) {
-        self->values[i] = PyFloat_AS_DOUBLE(PyList_GET_ITEM(arg, i));
+        self->values[i] = PyFloat_AsDouble(PyList_GET_ITEM(arg, i));
     }
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 ControlRead_setRate(ControlRead *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
     self->rate = PyInt_AsLong(arg);
     self->modulo = (int)(self->sr / self->rate);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -772,13 +772,10 @@ ControlRead_setRate(ControlRead *self, PyObject *arg)
 static PyObject *
 ControlRead_setLoop(ControlRead *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
     self->loop = PyInt_AsLong(arg);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -786,19 +783,16 @@ ControlRead_setLoop(ControlRead *self, PyObject *arg)
 static PyObject *
 ControlRead_setInterp(ControlRead *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
     int isNumber = PyNumber_Check(arg);
-    
+
 	if (isNumber == 1) {
 		self->interp = PyInt_AsLong(PyNumber_Int(arg));
-    }  
-    
+    }
+
     SET_INTERP_POINTER
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -833,7 +827,7 @@ static PyNumberMethods ControlRead_as_number = {
     (binaryfunc)ControlRead_add,                      /*nb_add*/
     (binaryfunc)ControlRead_sub,                 /*nb_subtract*/
     (binaryfunc)ControlRead_multiply,                 /*nb_multiply*/
-    (binaryfunc)ControlRead_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -847,16 +841,16 @@ static PyNumberMethods ControlRead_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)ControlRead_inplace_add,              /*inplace_add*/
     (binaryfunc)ControlRead_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)ControlRead_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)ControlRead_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -865,15 +859,14 @@ static PyNumberMethods ControlRead_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)ControlRead_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)ControlRead_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject ControlReadType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.ControlRead_base",         /*tp_name*/
     sizeof(ControlRead),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -881,7 +874,7 @@ PyTypeObject ControlReadType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &ControlRead_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -934,10 +927,10 @@ static void
 NoteinRec_process(NoteinRec *self) {
     int i;
     MYFLT pit, vel;
-    
+
     MYFLT *inp = Stream_getData((Stream *)self->inputp_stream);
     MYFLT *inv = Stream_getData((Stream *)self->inputv_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         pit = inp[i];
         vel = inv[i];
@@ -954,14 +947,14 @@ NoteinRec_process(NoteinRec *self) {
 
 static void
 NoteinRec_setProcMode(NoteinRec *self)
-{       
-    self->proc_func_ptr = NoteinRec_process;   
+{
+    self->proc_func_ptr = NoteinRec_process;
 }
 
 static void
 NoteinRec_compute_next_data_frame(NoteinRec *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -978,7 +971,7 @@ NoteinRec_traverse(NoteinRec *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 NoteinRec_clear(NoteinRec *self)
 {
     pyo_CLEAR
@@ -997,7 +990,7 @@ NoteinRec_dealloc(NoteinRec* self)
 {
     pyo_DEALLOC
     NoteinRec_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1007,21 +1000,21 @@ NoteinRec_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputptmp, *inputp_streamtmp, *inputvtmp, *inputv_streamtmp;
     NoteinRec *self;
     self = (NoteinRec *)type->tp_alloc(type, 0);
-    
+
     self->tmp_list_p = PyList_New(0);
     self->tmp_list_v = PyList_New(0);
     self->tmp_list_t = PyList_New(0);
     self->last_pitch = self->last_vel = 0.0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, NoteinRec_compute_next_data_frame);
     self->mode_func_ptr = NoteinRec_setProcMode;
 
     static char *kwlist[] = {"inputp", "inputv", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &inputptmp, &inputvtmp))
         Py_RETURN_NONE;
-    
+
     Py_XDECREF(self->inputp);
     self->inputp = inputptmp;
     inputp_streamtmp = PyObject_CallMethod((PyObject *)self->inputp, "_getStream", NULL);
@@ -1035,20 +1028,20 @@ NoteinRec_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     Py_INCREF(inputv_streamtmp);
     Py_XDECREF(self->inputv_stream);
     self->inputv_stream = (Stream *)inputv_streamtmp;
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * NoteinRec_getServer(NoteinRec* self) { GET_SERVER };
 static PyObject * NoteinRec_getStream(NoteinRec* self) { GET_STREAM };
 
-static PyObject * NoteinRec_play(NoteinRec *self, PyObject *args, PyObject *kwds) { 
+static PyObject * NoteinRec_play(NoteinRec *self, PyObject *args, PyObject *kwds) {
     self->time = 0;
-    PLAY 
+    PLAY
 };
 
 static PyObject * NoteinRec_stop(NoteinRec *self) { STOP };
@@ -1057,10 +1050,10 @@ static PyObject *
 NoteinRec_getData(NoteinRec *self) {
     int i;
     PyObject *data, *point;
-    
+
     Py_ssize_t size = PyList_Size(self->tmp_list_p);
     data = PyList_New(size);
-    
+
     for (i=0; i<size; i++) {
         point = PyTuple_New(3);
         PyTuple_SET_ITEM(point, 0, PyList_GET_ITEM(self->tmp_list_t, i));
@@ -1089,8 +1082,7 @@ static PyMethodDef NoteinRec_methods[] = {
 };
 
 PyTypeObject NoteinRecType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.NoteinRec_base",                                   /*tp_name*/
     sizeof(NoteinRec),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -1098,7 +1090,7 @@ PyTypeObject NoteinRecType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     0,												/*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -1151,17 +1143,17 @@ typedef struct {
 static void
 NoteinRead_readframes_i(NoteinRead *self) {
     long i;
-    
+
     if (self->go == 0)
         PyObject_CallMethod((PyObject *)self, "stop", NULL);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->trigsBuffer[i] = 0.0;
         if (self->go == 1) {
             if (self->time >= self->timestamps[self->count]) {
                 self->value = self->values[self->count];
                 self->data[i] = self->value;
-                self->count++;            
+                self->count++;
             }
             else
                 self->data[i] = self->value;
@@ -1195,44 +1187,44 @@ NoteinRead_setProcMode(NoteinRead *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = NoteinRead_readframes_i;
 
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = NoteinRead_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = NoteinRead_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = NoteinRead_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = NoteinRead_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = NoteinRead_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = NoteinRead_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = NoteinRead_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = NoteinRead_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = NoteinRead_postprocessing_revareva;
             break;
-    } 
+    }
 }
 
 static void
 NoteinRead_compute_next_data_frame(NoteinRead *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1240,15 +1232,15 @@ static int
 NoteinRead_traverse(NoteinRead *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->trig_stream);    
+    Py_VISIT(self->trig_stream);
     return 0;
 }
 
-static int 
+static int
 NoteinRead_clear(NoteinRead *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->trig_stream);    
+    Py_CLEAR(self->trig_stream);
     return 0;
 }
 
@@ -1260,7 +1252,7 @@ NoteinRead_dealloc(NoteinRead* self)
     free(self->timestamps);
     free(self->trigsBuffer);
     NoteinRead_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1270,26 +1262,26 @@ NoteinRead_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *valuestmp, *timestampstmp, *multmp=NULL, *addtmp=NULL;
     NoteinRead *self;
     self = (NoteinRead *)type->tp_alloc(type, 0);
-    
+
     self->value = 0.0;
     self->loop = 0;
     self->go = 1;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, NoteinRead_compute_next_data_frame);
     self->mode_func_ptr = NoteinRead_setProcMode;
 
     static char *kwlist[] = {"values", "timestamps", "loop", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|iOO", kwlist, &valuestmp, &timestampstmp, &self->loop, &multmp, &addtmp))
         Py_RETURN_NONE;
 
     if (valuestmp) {
         PyObject_CallMethod((PyObject *)self, "setValues", "O", valuestmp);
     }
-    
+
     if (timestampstmp) {
         PyObject_CallMethod((PyObject *)self, "setTimestamps", "O", timestampstmp);
     }
@@ -1297,46 +1289,46 @@ NoteinRead_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
      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->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT));
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->trigsBuffer[i] = 0.0;
-    }    
+    }
 
     MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL);
     TriggerStream_setData(self->trig_stream, self->trigsBuffer);
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * NoteinRead_getServer(NoteinRead* self) { GET_SERVER };
 static PyObject * NoteinRead_getStream(NoteinRead* self) { GET_STREAM };
 static PyObject * NoteinRead_getTriggerStream(NoteinRead* self) { GET_TRIGGER_STREAM };
-static PyObject * NoteinRead_setMul(NoteinRead *self, PyObject *arg) { SET_MUL };	
-static PyObject * NoteinRead_setAdd(NoteinRead *self, PyObject *arg) { SET_ADD };	
-static PyObject * NoteinRead_setSub(NoteinRead *self, PyObject *arg) { SET_SUB };	
-static PyObject * NoteinRead_setDiv(NoteinRead *self, PyObject *arg) { SET_DIV };	
+static PyObject * NoteinRead_setMul(NoteinRead *self, PyObject *arg) { SET_MUL };
+static PyObject * NoteinRead_setAdd(NoteinRead *self, PyObject *arg) { SET_ADD };
+static PyObject * NoteinRead_setSub(NoteinRead *self, PyObject *arg) { SET_SUB };
+static PyObject * NoteinRead_setDiv(NoteinRead *self, PyObject *arg) { SET_DIV };
 
-static PyObject * NoteinRead_play(NoteinRead *self, PyObject *args, PyObject *kwds) 
-{ 
+static PyObject * NoteinRead_play(NoteinRead *self, PyObject *args, PyObject *kwds)
+{
     self->count = self->time = 0;
     self->go = 1;
-    PLAY 
+    PLAY
 };
 
-static PyObject * NoteinRead_stop(NoteinRead *self) 
-{ 
+static PyObject * NoteinRead_stop(NoteinRead *self)
+{
     self->go = 0;
-    STOP 
+    STOP
 };
 
 static PyObject * NoteinRead_multiply(NoteinRead *self, PyObject *arg) { MULTIPLY };
@@ -1352,52 +1344,43 @@ static PyObject *
 NoteinRead_setValues(NoteinRead *self, PyObject *arg)
 {
     Py_ssize_t i;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
     self->size = PyList_Size(arg);
     self->values = (MYFLT *)realloc(self->values, self->size * sizeof(MYFLT));
     for (i=0; i<self->size; i++) {
-        self->values[i] = PyFloat_AS_DOUBLE(PyList_GET_ITEM(arg, i));
+        self->values[i] = PyFloat_AsDouble(PyList_GET_ITEM(arg, i));
     }
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 NoteinRead_setTimestamps(NoteinRead *self, PyObject *arg)
 {
     Py_ssize_t i;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
     self->size = PyList_Size(arg);
     self->timestamps = (long *)realloc(self->timestamps, self->size * sizeof(long));
     for (i=0; i<self->size; i++) {
-        self->timestamps[i] = (long)(PyFloat_AS_DOUBLE(PyList_GET_ITEM(arg, i)) * self->sr);
+        self->timestamps[i] = (long)(PyFloat_AsDouble(PyList_GET_ITEM(arg, i)) * self->sr);
     }
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
-    
+
 static PyObject *
 NoteinRead_setLoop(NoteinRead *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
     self->loop = PyInt_AsLong(arg);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1431,7 +1414,7 @@ static PyNumberMethods NoteinRead_as_number = {
     (binaryfunc)NoteinRead_add,                      /*nb_add*/
     (binaryfunc)NoteinRead_sub,                 /*nb_subtract*/
     (binaryfunc)NoteinRead_multiply,                 /*nb_multiply*/
-    (binaryfunc)NoteinRead_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -1445,16 +1428,16 @@ static PyNumberMethods NoteinRead_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)NoteinRead_inplace_add,              /*inplace_add*/
     (binaryfunc)NoteinRead_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)NoteinRead_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)NoteinRead_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -1463,15 +1446,14 @@ static PyNumberMethods NoteinRead_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)NoteinRead_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)NoteinRead_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject NoteinReadType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.NoteinRead_base",         /*tp_name*/
     sizeof(NoteinRead),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -1479,7 +1461,7 @@ PyTypeObject NoteinReadType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &NoteinRead_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -1509,4 +1491,4 @@ PyTypeObject NoteinReadType = {
     0,      /* tp_init */
     0,                         /* tp_alloc */
     NoteinRead_new,                 /* tp_new */
-};
+};
\ No newline at end of file
diff --git a/src/objects/selectmodule.c b/src/objects/selectmodule.c
index 64906fb..98ffe3c 100644
--- a/src/objects/selectmodule.c
+++ b/src/objects/selectmodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include "pyomodule.h"
 #include "streammodule.h"
@@ -31,7 +32,7 @@ typedef struct {
     Stream *input_stream;
     long value;
     MYFLT last_value;
-    int modebuffer[2]; // need at least 2 slots for mul & add 
+    int modebuffer[2]; // need at least 2 slots for mul & add
 } Select;
 
 static void
@@ -40,14 +41,14 @@ Select_selector(Select *self) {
     int i;
 
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inval = in[i];
         if (inval == self->value && inval != self->last_value)
             val = 1;
         else
             val = 0;
-        
+
         self->last_value = inval;
         self->data[i] = val;
     }
@@ -67,47 +68,47 @@ static void
 Select_setProcMode(Select *self)
 {
     int muladdmode;
-    
+
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
     self->proc_func_ptr = Select_selector;
-    
+
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Select_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Select_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Select_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Select_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Select_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Select_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Select_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Select_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Select_postprocessing_revareva;
             break;
-    }  
-    
+    }
+
 }
 
 static void
 Select_compute_next_data_frame(Select *self)
 {
-    (*self->proc_func_ptr)(self);    
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -115,16 +116,16 @@ static int
 Select_traverse(Select *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->input);    
-    Py_VISIT(self->input_stream);    
+    Py_VISIT(self->input);
+    Py_VISIT(self->input_stream);
     return 0;
 }
 
-static int 
+static int
 Select_clear(Select *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->input);    
+    Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
     return 0;
 }
@@ -134,7 +135,7 @@ Select_dealloc(Select* self)
 {
     pyo_DEALLOC
     Select_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -144,7 +145,7 @@ Select_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     Select *self;
     self = (Select *)type->tp_alloc(type, 0);
-    
+
     self->value = 0;
     self->last_value = -99.0;
 	self->modebuffer[0] = 0;
@@ -155,7 +156,7 @@ Select_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = Select_setProcMode;
 
     static char *kwlist[] = {"input", "value", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOO", kwlist, &inputtmp, &self->value, &multmp, &addtmp))
         Py_RETURN_NONE;
 
@@ -164,24 +165,24 @@ Select_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     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 * Select_getServer(Select* self) { GET_SERVER };
 static PyObject * Select_getStream(Select* self) { GET_STREAM };
-static PyObject * Select_setMul(Select *self, PyObject *arg) { SET_MUL };	
-static PyObject * Select_setAdd(Select *self, PyObject *arg) { SET_ADD };	
-static PyObject * Select_setSub(Select *self, PyObject *arg) { SET_SUB };	
-static PyObject * Select_setDiv(Select *self, PyObject *arg) { SET_DIV };	
+static PyObject * Select_setMul(Select *self, PyObject *arg) { SET_MUL };
+static PyObject * Select_setAdd(Select *self, PyObject *arg) { SET_ADD };
+static PyObject * Select_setSub(Select *self, PyObject *arg) { SET_SUB };
+static PyObject * Select_setDiv(Select *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Select_play(Select *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Select_stop(Select *self) { STOP };
@@ -198,18 +199,15 @@ static PyObject * Select_inplace_div(Select *self, PyObject *arg) { INPLACE_DIV
 static PyObject *
 Select_setValue(Select *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	if (PyLong_Check(arg) || PyInt_Check(arg)) {	
+    ASSERT_ARG_NOT_NULL
+
+	if (PyLong_Check(arg) || PyInt_Check(arg)) {
 		self->value = PyLong_AsLong(arg);
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Select_members[] = {
 {"server", T_OBJECT_EX, offsetof(Select, server), 0, "Pyo server."},
@@ -236,7 +234,7 @@ static PyNumberMethods Select_as_number = {
     (binaryfunc)Select_add,                         /*nb_add*/
     (binaryfunc)Select_sub,                         /*nb_subtract*/
     (binaryfunc)Select_multiply,                    /*nb_multiply*/
-    (binaryfunc)Select_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -250,16 +248,16 @@ static PyNumberMethods Select_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Select_inplace_add,                 /*inplace_add*/
     (binaryfunc)Select_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Select_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Select_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -268,15 +266,14 @@ static PyNumberMethods Select_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Select_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Select_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject SelectType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Select_base",         /*tp_name*/
 sizeof(Select),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -284,7 +281,7 @@ sizeof(Select),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &Select_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -321,7 +318,7 @@ typedef struct {
     PyObject *input;
     Stream *input_stream;
     MYFLT last_value;
-    int modebuffer[2]; // need at least 2 slots for mul & add 
+    int modebuffer[2]; // need at least 2 slots for mul & add
 } Change;
 
 static void
@@ -330,7 +327,7 @@ Change_selector(Change *self) {
     int i;
 
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         inval = in[i];
         if (inval < (self->last_value - 0.00001) || inval > (self->last_value + 0.00001)) {
@@ -363,40 +360,40 @@ Change_setProcMode(Change *self)
     self->proc_func_ptr = Change_selector;
 
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Change_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Change_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Change_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Change_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Change_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Change_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Change_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Change_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Change_postprocessing_revareva;
             break;
-    }      
+    }
 }
 
 static void
 Change_compute_next_data_frame(Change *self)
 {
-    (*self->proc_func_ptr)(self);    
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -404,16 +401,16 @@ static int
 Change_traverse(Change *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->input);    
-    Py_VISIT(self->input_stream);    
+    Py_VISIT(self->input);
+    Py_VISIT(self->input_stream);
     return 0;
 }
 
-static int 
+static int
 Change_clear(Change *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->input);    
+    Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
     return 0;
 }
@@ -423,7 +420,7 @@ Change_dealloc(Change* self)
 {
     pyo_DEALLOC
     Change_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -443,7 +440,7 @@ Change_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = Change_setProcMode;
 
     static char *kwlist[] = {"input", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OOO", kwlist, &inputtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
 
@@ -452,24 +449,24 @@ Change_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     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 * Change_getServer(Change* self) { GET_SERVER };
 static PyObject * Change_getStream(Change* self) { GET_STREAM };
-static PyObject * Change_setMul(Change *self, PyObject *arg) { SET_MUL };	
-static PyObject * Change_setAdd(Change *self, PyObject *arg) { SET_ADD };	
-static PyObject * Change_setSub(Change *self, PyObject *arg) { SET_SUB };	
-static PyObject * Change_setDiv(Change *self, PyObject *arg) { SET_DIV };	
+static PyObject * Change_setMul(Change *self, PyObject *arg) { SET_MUL };
+static PyObject * Change_setAdd(Change *self, PyObject *arg) { SET_ADD };
+static PyObject * Change_setSub(Change *self, PyObject *arg) { SET_SUB };
+static PyObject * Change_setDiv(Change *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Change_play(Change *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Change_stop(Change *self) { STOP };
@@ -507,7 +504,7 @@ static PyNumberMethods Change_as_number = {
     (binaryfunc)Change_add,                         /*nb_add*/
     (binaryfunc)Change_sub,                         /*nb_subtract*/
     (binaryfunc)Change_multiply,                    /*nb_multiply*/
-    (binaryfunc)Change_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -521,16 +518,16 @@ static PyNumberMethods Change_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Change_inplace_add,                 /*inplace_add*/
     (binaryfunc)Change_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Change_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Change_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -539,15 +536,14 @@ static PyNumberMethods Change_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Change_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Change_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject ChangeType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Change_base",         /*tp_name*/
 sizeof(Change),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -555,7 +551,7 @@ sizeof(Change),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &Change_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -585,4 +581,4 @@ Change_members,             /* tp_members */
 0,      /* tp_init */
 0,                         /* tp_alloc */
 Change_new,                 /* tp_new */
-};
+};
\ No newline at end of file
diff --git a/src/objects/sfplayermodule.c b/src/objects/sfplayermodule.c
index 4e6c5ef..42408d9 100644
--- a/src/objects/sfplayermodule.c
+++ b/src/objects/sfplayermodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
@@ -52,30 +53,6 @@ typedef struct {
     MYFLT (*interp_func_ptr)(MYFLT *, int, MYFLT, int);
 } SfPlayer;
 
-MYFLT max_arr(MYFLT *a,int n)
-{
-    int i;
-    MYFLT m;
-    m=*a;
-    for (i=1; i<n; i++) {
-        if (m < *(a+i)) 
-            m = *(a+i);
-    }    
-    return m;
-}
-
-MYFLT min_arr(MYFLT *a,int n)
-{
-    int i;
-    MYFLT m;
-    m=*a;
-    for (i=1; i<n; i++) {
-        if (m > *(a+i)) 
-            m = *(a+i);
-    }    
-    return m;
-}
-
 static void
 SfPlayer_readframes_i(SfPlayer *self) {
     MYFLT sp, frac, bufpos, delta, startPos;
@@ -87,12 +64,12 @@ SfPlayer_readframes_i(SfPlayer *self) {
     else
         sp = Stream_getData((Stream *)self->speed_stream)[0];
     delta = MYFABS(sp) * self->srScale;
-    
+
     buflen = (int)(self->bufsize * delta + 0.5) + 64;
     totlen = self->sndChnls*buflen;
     MYFLT buffer[totlen];
     MYFLT buffer2[self->sndChnls][buflen];
-    
+
     if (sp > 0) { /* forward reading */
         if (self->pointerPos >= self->sndSize) {
             self->pointerPos -= self->sndSize - self->startPos;
@@ -100,19 +77,19 @@ SfPlayer_readframes_i(SfPlayer *self) {
                 PyObject_CallMethod((PyObject *)self, "stop", NULL);
                 for (i=0; i<(self->bufsize * self->sndChnls); i++) {
                     self->samplesBuffer[i] = 0.0;
-                }    
+                }
                 for (i=0; i<self->bufsize; i++) {
                     self->trigsBuffer[i] = 0.0;
                 }
                 return;
             }
-        }        
+        }
         index = (int)self->pointerPos;
         sf_seek(self->sf, index, SEEK_SET); /* sets position pointer in the file */
 
         /* fill a buffer with enough samples to satisfy speed reading */
         /* if not enough samples left in the file */
-        if ((index+buflen) > self->sndSize) {   
+        if ((index+buflen) > self->sndSize) {
             shortbuflen = self->sndSize - index;
             pad = (buflen-shortbuflen)*self->sndChnls;
             SF_READ(self->sf, buffer, shortbuflen*self->sndChnls);
@@ -128,16 +105,16 @@ SfPlayer_readframes_i(SfPlayer *self) {
                 for (i=0; i<(pad); i++) {
                     buffer[i+shortbuflen*self->sndChnls] = buftemp[i];
                 }
-            }    
+            }
         }
         else /* without zero padding */
             SF_READ(self->sf, buffer, totlen);
-    
+
         /* de-interleave samples */
         for (i=0; i<totlen; i++) {
             buffer2[i%self->sndChnls][(int)(i/self->sndChnls)] = buffer[i];
         }
-    
+
         /* fill samplesBuffer with samples */
         for (i=0; i<self->bufsize; i++) {
             self->trigsBuffer[i] = 0.0;
@@ -146,7 +123,7 @@ SfPlayer_readframes_i(SfPlayer *self) {
             frac = bufpos - bufindex;
             for (j=0; j<self->sndChnls; j++) {
                 self->samplesBuffer[i+(j*self->bufsize)] = (*self->interp_func_ptr)(buffer2[j], bufindex, frac, buflen);
-            }    
+            }
             self->pointerPos += delta;
         }
         if (self->pointerPos >= self->sndSize)
@@ -165,16 +142,16 @@ SfPlayer_readframes_i(SfPlayer *self) {
                 PyObject_CallMethod((PyObject *)self, "stop", NULL);
                 for (i=0; i<(self->bufsize * self->sndChnls); i++) {
                     self->samplesBuffer[i] = 0.0;
-                }    
+                }
                 for (i=0; i<self->bufsize; i++) {
                     self->trigsBuffer[i] = 0.0;
                 }
                 return;
             }
         }
-        
+
         index = (int)self->pointerPos + 1;
-        
+
         /* fill a buffer with enough samples to satisfy speed reading */
         /* if not enough samples to read in the file */
         if ((index-buflen) < 0) {
@@ -195,35 +172,35 @@ SfPlayer_readframes_i(SfPlayer *self) {
                     buffer[i] = buftemp[i];
                 }
             }
-            
+
             MYFLT buftemp2[shortbuflen*self->sndChnls];
             sf_seek(self->sf, 0, SEEK_SET); /* sets position pointer in the file */
             SF_READ(self->sf, buftemp2, shortbuflen*self->sndChnls);
             for (i=0; i<(shortbuflen*self->sndChnls); i++) {
                 buffer[i+padlen] = buftemp2[i];
-            }    
+            }
         }
         else /* without zero padding */
             sf_seek(self->sf, index-buflen, SEEK_SET); /* sets position pointer in the file */
             SF_READ(self->sf, buffer, totlen);
-        
+
         /* de-interleave samples */
         for (i=0; i<totlen; i++) {
             buffer2[i%self->sndChnls][(int)(i/self->sndChnls)] = buffer[i];
         }
-        
+
         /* reverse arrays */
         MYFLT swap;
         for (i=0; i<self->sndChnls; i++) {
             int a;
-            int b = buflen; 
+            int b = buflen;
             for (a=0; a<--b; a++) { //increment a and decrement b until they meet eachother
                 swap = buffer2[i][a];       //put what's in a into swap space
                 buffer2[i][a] = buffer2[i][b];    //put what's in b into a
                 buffer2[i][b] = swap;       //put what's in the swap (a) into b
             }
         }
-        
+
         /* fill stream buffer with samples */
         for (i=0; i<self->bufsize; i++) {
             self->trigsBuffer[i] = 0.0;
@@ -247,7 +224,7 @@ SfPlayer_readframes_i(SfPlayer *self) {
             self->samplesBuffer[i] = 0.0;
         }
     }
-}    
+}
 
 static void
 SfPlayer_setProcMode(SfPlayer *self)
@@ -258,26 +235,26 @@ SfPlayer_setProcMode(SfPlayer *self)
 static void
 SfPlayer_compute_next_data_frame(SfPlayer *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
 SfPlayer_traverse(SfPlayer *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->speed);    
-    Py_VISIT(self->speed_stream);    
-    Py_VISIT(self->trig_stream);    
+    Py_VISIT(self->speed);
+    Py_VISIT(self->speed_stream);
+    Py_VISIT(self->trig_stream);
     return 0;
 }
 
-static int 
+static int
 SfPlayer_clear(SfPlayer *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->speed);    
-    Py_CLEAR(self->speed_stream);    
-    Py_CLEAR(self->trig_stream);    
+    Py_CLEAR(self->speed);
+    Py_CLEAR(self->speed_stream);
+    Py_CLEAR(self->trig_stream);
     return 0;
 }
 
@@ -290,18 +267,19 @@ SfPlayer_dealloc(SfPlayer* self)
     free(self->trigsBuffer);
     free(self->samplesBuffer);
     SfPlayer_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
 SfPlayer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
+    Py_ssize_t psize;
     MYFLT offset = 0.;
     PyObject *speedtmp=NULL;
     SfPlayer *self;
     self = (SfPlayer *)type->tp_alloc(type, 0);
-    
+
     self->speed = PyFloat_FromDouble(1);
     self->loop = 0;
     self->interp = 2;
@@ -313,26 +291,26 @@ SfPlayer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = SfPlayer_setProcMode;
 
     static char *kwlist[] = {"path", "speed", "loop", "offset", "interp", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_S__OIFI, kwlist, &self->path, &speedtmp, &self->loop, &offset, &self->interp))
-        Py_RETURN_NONE; 
-    
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_P__OIFI, kwlist, &self->path, &psize, &speedtmp, &self->loop, &offset, &self->interp))
+        Py_RETURN_NONE;
+
     if (speedtmp) {
         PyObject_CallMethod((PyObject *)self, "setSpeed", "O", speedtmp);
     }
 
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     (*self->mode_func_ptr)(self);
 
     SET_INTERP_POINTER
-    
+
     /* Open the sound file. */
     self->info.format = 0;
     self->sf = sf_open(self->path, SFM_READ, &self->info);
     if (self->sf == NULL)
     {
-        printf("Failed to open the file.\n");
+        PySys_WriteStdout("SfPlayer: failed to open the file.\n");
     }
     self->sndSize = self->info.frames;
     self->sndSr = self->info.samplerate;
@@ -344,17 +322,17 @@ SfPlayer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
     for (i=0; i<self->bufsize; i++) {
         self->trigsBuffer[i] = 0.0;
-    }    
+    }
 
     MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL);
     TriggerStream_setData(self->trig_stream, self->trigsBuffer);
-    
+
     self->startPos = offset * self->sr * self->srScale;
     if (self->startPos < 0.0 || self->startPos >= self->sndSize)
         self->startPos = 0.0;
-    
+
     self->pointerPos = self->startPos;
-    
+
     return (PyObject *)self;
 }
 
@@ -363,7 +341,7 @@ static PyObject * SfPlayer_getStream(SfPlayer* self) { GET_STREAM };
 static PyObject * SfPlayer_getTriggerStream(SfPlayer* self) { GET_TRIGGER_STREAM };
 
 static PyObject * SfPlayer_play(SfPlayer *self, PyObject *args, PyObject *kwds)
-{ 
+{
     self->init = 1;
     self->pointerPos = self->startPos;
     PLAY
@@ -382,14 +360,11 @@ static PyObject *
 SfPlayer_setSpeed(SfPlayer *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->speed);
@@ -405,23 +380,25 @@ SfPlayer_setSpeed(SfPlayer *self, PyObject *arg)
         self->speed_stream = (Stream *)streamtmp;
 		self->modebuffer[0] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
-	Py_INCREF(Py_None);
-	return Py_None;
-}	
+
+	Py_RETURN_NONE;
+}
 
 static PyObject *
-SfPlayer_setSound(SfPlayer *self, PyObject *arg)
+SfPlayer_setSound(SfPlayer *self, PyObject *args)
 {
-    /* Need to perform a check to be sure that the new sound is of the same number of channels */
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-    self->path = PyString_AsString(arg);
+    /* Need to perform a check to be sure that the new 
+       sound is of the same number of channels. */
+    Py_ssize_t psize;
+
+    //ASSERT_ARG_NOT_NULL
+
+    if (! PyArg_ParseTuple(args, "s#", &self->path, &psize))
+        Py_RETURN_NONE;
+
+    //self->path = PY_STRING_AS_STRING(arg);
 
     sf_close(self->sf);
 
@@ -430,81 +407,68 @@ SfPlayer_setSound(SfPlayer *self, PyObject *arg)
     self->sf = sf_open(self->path, SFM_READ, &self->info);
     if (self->sf == NULL)
     {
-        printf("Failed to open the file.\n");
+        PySys_WriteStdout("SfPlayer: failed to open the file.\n");
     }
     self->sndSize = self->info.frames;
     self->sndSr = self->info.samplerate;
     //self->sndChnls = self->info.channels;
     self->srScale = self->sndSr / self->sr;
-    
+
     //self->samplesBuffer = (MYFLT *)realloc(self->samplesBuffer, self->bufsize * self->sndChnls * sizeof(MYFLT));
-    
+
     self->startPos = 0.0;
     self->pointerPos = self->startPos;
-    
-    Py_INCREF(Py_None);
-    return Py_None;
+
+    Py_RETURN_NONE;
 }
 
 static PyObject *
 SfPlayer_setLoop(SfPlayer *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
     self->loop = PyInt_AsLong(arg);
-    
-    Py_INCREF(Py_None);
-    return Py_None;
+
+    Py_RETURN_NONE;
 }
 
 static PyObject *
 SfPlayer_setOffset(SfPlayer *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
     int isNumber = PyNumber_Check(arg);
 
 	if (isNumber == 1) {
-		self->startPos = PyFloat_AsDouble(PyNumber_Float(arg)) * self->sr * self->srScale;
+		self->startPos = PyFloat_AsDouble(arg) * self->sr * self->srScale;
         if (self->startPos < 0.0 || self->startPos >= self->sndSize)
             self->startPos = 0.0;
-    }  
+    }
 
-    Py_INCREF(Py_None);
-    return Py_None;
+    Py_RETURN_NONE;
 }
 
 static PyObject *
 SfPlayer_setInterp(SfPlayer *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
     int isNumber = PyNumber_Check(arg);
-    
+
 	if (isNumber == 1) {
 		self->interp = PyInt_AsLong(PyNumber_Int(arg));
-    }  
+    }
 
     SET_INTERP_POINTER
-    
-    Py_INCREF(Py_None);
-    return Py_None;
+
+    Py_RETURN_NONE;
 }
 
 MYFLT *
 SfPlayer_getSamplesBuffer(SfPlayer *self)
 {
     return (MYFLT *)self->samplesBuffer;
-}    
+}
 
 static PyMemberDef SfPlayer_members[] = {
 {"server", T_OBJECT_EX, offsetof(SfPlayer, server), 0, "Pyo server."},
@@ -521,7 +485,7 @@ static PyMethodDef SfPlayer_methods[] = {
 {"play", (PyCFunction)SfPlayer_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
 {"out", (PyCFunction)SfPlayer_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
 {"stop", (PyCFunction)SfPlayer_stop, METH_NOARGS, "Stops computing."},
-{"setSound", (PyCFunction)SfPlayer_setSound, METH_O, "Sets sfplayer sound path."},
+{"setSound", (PyCFunction)SfPlayer_setSound, METH_VARARGS, "Sets sfplayer sound path."},
 {"setSpeed", (PyCFunction)SfPlayer_setSpeed, METH_O, "Sets sfplayer reading speed."},
 {"setLoop", (PyCFunction)SfPlayer_setLoop, METH_O, "Sets sfplayer loop mode (0 = no loop, 1 = loop)."},
 {"setOffset", (PyCFunction)SfPlayer_setOffset, METH_O, "Sets sfplayer start position."},
@@ -530,8 +494,7 @@ static PyMethodDef SfPlayer_methods[] = {
 };
 
 PyTypeObject SfPlayerType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.SfPlayer_base",         /*tp_name*/
 sizeof(SfPlayer),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -539,7 +502,7 @@ sizeof(SfPlayer),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 0,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -578,7 +541,7 @@ typedef struct {
     pyo_audio_HEAD
     SfPlayer *mainPlayer;
     int modebuffer[2];
-    int chnl; 
+    int chnl;
 } SfPlay;
 
 static void SfPlay_postprocessing_ii(SfPlay *self) { POST_PROCESSING_II };
@@ -596,33 +559,33 @@ SfPlay_setProcMode(SfPlay *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = SfPlay_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = SfPlay_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = SfPlay_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = SfPlay_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = SfPlay_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = SfPlay_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = SfPlay_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = SfPlay_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = SfPlay_postprocessing_revareva;
             break;
     }
@@ -637,7 +600,7 @@ SfPlay_compute_next_data_frame(SfPlay *self)
     tmp = SfPlayer_getSamplesBuffer((SfPlayer *)self->mainPlayer);
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = tmp[i + offset];
-    }    
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -649,11 +612,11 @@ SfPlay_traverse(SfPlay *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 SfPlay_clear(SfPlay *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->mainPlayer);    
+    Py_CLEAR(self->mainPlayer);
     return 0;
 }
 
@@ -662,7 +625,7 @@ SfPlay_dealloc(SfPlay* self)
 {
     pyo_DEALLOC
     SfPlay_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -672,45 +635,45 @@ SfPlay_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL;
     SfPlay *self;
     self = (SfPlay *)type->tp_alloc(type, 0);
-    
+
     self->chnl = 0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, SfPlay_compute_next_data_frame);
     self->mode_func_ptr = SfPlay_setProcMode;
 
     static char *kwlist[] = {"mainPlayer", "chnl", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOO", kwlist, &maintmp, &self->chnl, &multmp, &addtmp))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     Py_XDECREF(self->mainPlayer);
     Py_INCREF(maintmp);
     self->mainPlayer = (SfPlayer *)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 * SfPlay_getServer(SfPlay* self) { GET_SERVER };
 static PyObject * SfPlay_getStream(SfPlay* self) { GET_STREAM };
-static PyObject * SfPlay_setMul(SfPlay *self, PyObject *arg) { SET_MUL };	
-static PyObject * SfPlay_setAdd(SfPlay *self, PyObject *arg) { SET_ADD };	
-static PyObject * SfPlay_setSub(SfPlay *self, PyObject *arg) { SET_SUB };	
-static PyObject * SfPlay_setDiv(SfPlay *self, PyObject *arg) { SET_DIV };	
+static PyObject * SfPlay_setMul(SfPlay *self, PyObject *arg) { SET_MUL };
+static PyObject * SfPlay_setAdd(SfPlay *self, PyObject *arg) { SET_ADD };
+static PyObject * SfPlay_setSub(SfPlay *self, PyObject *arg) { SET_SUB };
+static PyObject * SfPlay_setDiv(SfPlay *self, PyObject *arg) { SET_DIV };
 
 static PyObject * SfPlay_play(SfPlay *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * SfPlay_out(SfPlay *self, PyObject *args, PyObject *kwds) { OUT };
@@ -750,7 +713,7 @@ static PyNumberMethods SfPlay_as_number = {
 (binaryfunc)SfPlay_add,                      /*nb_add*/
 (binaryfunc)SfPlay_sub,                 /*nb_subtract*/
 (binaryfunc)SfPlay_multiply,                 /*nb_multiply*/
-(binaryfunc)SfPlay_div,                   /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -764,16 +727,16 @@ static PyNumberMethods SfPlay_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
 (binaryfunc)SfPlay_inplace_add,              /*inplace_add*/
 (binaryfunc)SfPlay_inplace_sub,         /*inplace_subtract*/
 (binaryfunc)SfPlay_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)SfPlay_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -782,15 +745,14 @@ static PyNumberMethods SfPlay_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)SfPlay_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)SfPlay_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
 PyTypeObject SfPlayType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.SfPlay_base",         /*tp_name*/
 sizeof(SfPlay),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -798,7 +760,7 @@ sizeof(SfPlay),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &SfPlay_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -855,6 +817,8 @@ typedef struct {
     MYFLT *samplesBuffer;
     MYFLT *markers;
     int markers_size;
+    MYFLT x;
+    MYFLT (*type_func_ptr)();
     MYFLT (*interp_func_ptr)(MYFLT *, int, MYFLT, int);
 } SfMarkerShuffler;
 
@@ -862,6 +826,122 @@ typedef struct {
 static void SfMarkerShuffler_chooseNewMark(SfMarkerShuffler *self, int dir);
 /******************/
 
+// no parameter
+static MYFLT
+SfMarkerShuffler_uniform(SfMarkerShuffler *self) {
+    return RANDOM_UNIFORM;
+}
+
+static MYFLT
+SfMarkerShuffler_linear_min(SfMarkerShuffler *self) {
+    MYFLT a = RANDOM_UNIFORM;
+    MYFLT b = RANDOM_UNIFORM;
+    if (a < b) return a;
+    else return b;
+}
+
+static MYFLT
+SfMarkerShuffler_linear_max(SfMarkerShuffler *self) {
+    MYFLT a = RANDOM_UNIFORM;
+    MYFLT b = RANDOM_UNIFORM;
+    if (a > b) return a;
+    else return b;
+}
+
+static MYFLT
+SfMarkerShuffler_triangle(SfMarkerShuffler *self) {
+    MYFLT a = RANDOM_UNIFORM;
+    MYFLT b = RANDOM_UNIFORM;
+    return ((a + b) * 0.5);
+}
+
+// x1 = slope
+static MYFLT
+SfMarkerShuffler_expon_min(SfMarkerShuffler *self) {
+    if (self->x <= 0.0) self->x = 0.00001;
+    MYFLT val = -MYLOG(RANDOM_UNIFORM) / self->x;
+    if (val < 0.0) return 0.0;
+    else if (val > 1.0) return 1.0;
+    else return val;
+}
+
+static MYFLT
+SfMarkerShuffler_expon_max(SfMarkerShuffler *self) {
+    if (self->x <= 0.0) self->x = 0.00001;
+    MYFLT val = 1.0 - (-MYLOG(RANDOM_UNIFORM) / self->x);
+    if (val < 0.0) return 0.0;
+    else if (val > 1.0) return 1.0;
+    else return val;
+}
+
+// x1 = bandwidth
+static MYFLT
+SfMarkerShuffler_biexpon(SfMarkerShuffler *self) {
+    MYFLT polar, val;
+    if (self->x <= 0.0) self->x = 0.00001;
+    MYFLT sum = RANDOM_UNIFORM * 2.0;
+
+    if (sum > 1.0) {
+        polar = -1;
+        sum = 2.0 - sum;
+    }
+    else
+        polar = 1;
+
+    val = 0.5 * (polar * MYLOG(sum) / self->x) + 0.5;
+
+    if (val < 0.0) return 0.0;
+    else if (val > 1.0) return 1.0;
+    else return val;
+}
+
+static MYFLT
+SfMarkerShuffler_cauchy(SfMarkerShuffler *self) {
+    MYFLT rnd, val, dir;
+    do {
+        rnd = RANDOM_UNIFORM;
+    }
+    while (rnd == 0.5);
+
+    if (pyorand() < (PYO_RAND_MAX / 2))
+        dir = -1;
+    else
+        dir = 1;
+
+    val = 0.5 * (MYTAN(rnd) * self->x * dir) + 0.5;
+
+    if (val < 0.0) return 0.0;
+    else if (val > 1.0) return 1.0;
+    else return val;
+}
+
+// x = shape
+static MYFLT
+SfMarkerShuffler_weibull(SfMarkerShuffler *self) {
+    MYFLT rnd, val;
+    if (self->x <= 0.0) self->x = 0.00001;
+
+    rnd = 1.0 / (1.0 - RANDOM_UNIFORM);
+    val = 0.5 * MYPOW(MYLOG(rnd), (1.0 / self->x));
+
+    if (val < 0.0) return 0.0;
+    else if (val > 1.0) return 1.0;
+    else return val;
+}
+
+// x = bandwidth
+static MYFLT
+SfMarkerShuffler_gaussian(SfMarkerShuffler *self) {
+    MYFLT rnd, val;
+
+    rnd = (RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM);
+    val = (self->x * (rnd - 3.0) * 0.33 + 0.5);
+
+    if (val < 0.0) return 0.0;
+    else if (val > 1.0) return 1.0;
+    else return val;
+}
+
 static void
 SfMarkerShuffler_readframes_i(SfMarkerShuffler *self) {
     MYFLT sp, frac, bufpos, delta, tmp;
@@ -874,7 +954,7 @@ SfMarkerShuffler_readframes_i(SfMarkerShuffler *self) {
         sp = Stream_getData((Stream *)self->speed_stream)[0];
 
     delta = MYFABS(sp) * self->srScale;
-    
+
     buflen = (int)(self->bufsize * delta + 0.5) + 64;
     totlen = self->sndChnls*buflen;
     MYFLT buffer[totlen];
@@ -894,7 +974,7 @@ SfMarkerShuffler_readframes_i(SfMarkerShuffler *self) {
         }
         index = (int)self->pointerPos;
         sf_seek(self->sf, index, SEEK_SET); /* sets position pointer in the file */
-        
+
         /* fill a buffer with enough samples to satisfy speed reading */
         /* if not enough samples to read in the file */
         if ((index+buflen) > self->endPos) {
@@ -913,12 +993,12 @@ SfMarkerShuffler_readframes_i(SfMarkerShuffler *self) {
         }
         else /* without wraparound */
             SF_READ(self->sf, buffer, totlen);
-        
+
         /* de-interleave samples */
         for (i=0; i<totlen; i++) {
             buffer2[i%self->sndChnls][(int)(i/self->sndChnls)] = buffer[i];
         }
-        
+
         /* fill data with samples */
         for (i=0; i<self->bufsize; i++) {
             bufpos = self->pointerPos - index;
@@ -926,7 +1006,7 @@ SfMarkerShuffler_readframes_i(SfMarkerShuffler *self) {
             frac = bufpos - bufindex;
             for (j=0; j<self->sndChnls; j++) {
                 self->samplesBuffer[i+(j*self->bufsize)] = (*self->interp_func_ptr)(buffer2[j], bufindex, frac, buflen);
-            }    
+            }
             self->pointerPos += delta;
         }
         if (self->pointerPos >= self->endPos) {
@@ -940,9 +1020,9 @@ SfMarkerShuffler_readframes_i(SfMarkerShuffler *self) {
             self->lastDir = self->startPos = -1;
             SfMarkerShuffler_chooseNewMark((SfMarkerShuffler *)self, 0);
             self->pointerPos = self->startPos;
-        }    
+        }
         index = (int)self->pointerPos + 1;
-        
+
         /* fill a buffer with enough samples to satisfy speed reading */
         /* if not enough samples to read in the file */
         if ((index-buflen) < self->endPos) {
@@ -957,13 +1037,13 @@ SfMarkerShuffler_readframes_i(SfMarkerShuffler *self) {
             for (i=0; i<padlen; i++) {
                 buffer[i] = buftemp[i];
             }
-            
+
             MYFLT buftemp2[shortbuflen*self->sndChnls];
             sf_seek(self->sf, self->endPos, SEEK_SET); /* sets position pointer in the file */
             SF_READ(self->sf, buftemp2, shortbuflen*self->sndChnls);
             for (i=0; i<(shortbuflen*self->sndChnls); i++) {
                 buffer[i+padlen] = buftemp2[i];
-            }    
+            }
         }
         else { /* without wraparound */
             sf_seek(self->sf, index-buflen, SEEK_SET); /* sets position pointer in the file */
@@ -973,19 +1053,19 @@ SfMarkerShuffler_readframes_i(SfMarkerShuffler *self) {
         for (i=0; i<totlen; i++) {
             buffer2[i%self->sndChnls][(int)(i/self->sndChnls)] = buffer[i];
         }
-        
+
         /* reverse arrays */
         MYFLT swap;
         for (i=0; i<self->sndChnls; i++) {
             int a;
-            int b = buflen; 
+            int b = buflen;
             for (a=0; a<--b; a++) { //increment a and decrement b until they meet eachother
                 swap = buffer2[i][a];       //put what's in a into swap space
                 buffer2[i][a] = buffer2[i][b];    //put what's in b into a
                 buffer2[i][b] = swap;       //put what's in the swap (a) into b
             }
         }
-        
+
         /* fill stream buffer with samples */
         for (i=0; i<self->bufsize; i++) {
             bufpos = index - self->pointerPos;
@@ -1008,7 +1088,7 @@ SfMarkerShuffler_readframes_i(SfMarkerShuffler *self) {
             self->samplesBuffer[i] = 0.0;
         }
     }
-}    
+}
 
 static void
 SfMarkerShuffler_setProcMode(SfMarkerShuffler *self)
@@ -1019,42 +1099,42 @@ SfMarkerShuffler_setProcMode(SfMarkerShuffler *self)
 static void
 SfMarkerShuffler_compute_next_data_frame(SfMarkerShuffler *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static void
-SfMarkerShuffler_chooseNewMark(SfMarkerShuffler *self, int dir) 
+SfMarkerShuffler_chooseNewMark(SfMarkerShuffler *self, int dir)
 {
     int mark;
     if (dir == 1) {
         if (self->startPos == -1) {
-            mark = (int)(self->markers_size * (rand()/((MYFLT)(RAND_MAX)+1)));
-            self->startPos = self->markers[mark] * self->srScale;
-            self->endPos = self->markers[mark+1] * self->srScale;
+            mark = (int)(self->markers_size * (*self->type_func_ptr)(self) * 0.99);
+            self->startPos = self->markers[mark];
+            self->endPos = self->markers[mark+1];
         }
         else {
             self->startPos = self->nextStartPos;
             self->endPos = self->nextEndPos;
         }
-        
-        mark = (int)(self->markers_size * (rand()/((MYFLT)(RAND_MAX)+1)));
-        self->nextStartPos = self->markers[mark] * self->srScale;
-        self->nextEndPos = self->markers[mark+1] * self->srScale;
+
+        mark = (int)(self->markers_size * (*self->type_func_ptr)(self) * 0.99);
+        self->nextStartPos = self->markers[mark];
+        self->nextEndPos = self->markers[mark+1];
     }
     else {
         if (self->startPos == -1) {
-            mark = self->markers_size - (int)(self->markers_size * (rand()/((MYFLT)(RAND_MAX)+1)));
-            self->startPos = self->markers[mark] * self->srScale;
-            self->endPos = self->markers[mark-1] * self->srScale;
+            mark = self->markers_size - (int)(self->markers_size * (*self->type_func_ptr)(self) * 0.99);
+            self->startPos = self->markers[mark];
+            self->endPos = self->markers[mark-1];
         }
         else {
             self->startPos = self->nextStartPos;
             self->endPos = self->nextEndPos;
         }
-        
-        mark = self->markers_size - (int)(self->markers_size * (rand()/((MYFLT)(RAND_MAX)+1)));
-        self->nextStartPos = self->markers[mark] * self->srScale;
-        self->nextEndPos = self->markers[mark-1] * self->srScale;
+
+        mark = self->markers_size - (int)(self->markers_size * (*self->type_func_ptr)(self) * 0.99);
+        self->nextStartPos = self->markers[mark];
+        self->nextEndPos = self->markers[mark-1];
     }
 }
 
@@ -1067,7 +1147,7 @@ SfMarkerShuffler_setMarkers(SfMarkerShuffler *self, PyObject *markerstmp)
     self->markers[0] = 0.;
     for (i=0; i<len; i++) {
         self->markers[i+1] = PyFloat_AsDouble(PyList_GetItem(markerstmp, i));
-    }  
+    }
     self->markers[len+1] = self->sndSize;
     self->markers_size = (int)len+1;
 }
@@ -1076,17 +1156,17 @@ static int
 SfMarkerShuffler_traverse(SfMarkerShuffler *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->speed);    
-    Py_VISIT(self->speed_stream);    
+    Py_VISIT(self->speed);
+    Py_VISIT(self->speed_stream);
     return 0;
 }
 
-static int 
+static int
 SfMarkerShuffler_clear(SfMarkerShuffler *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->speed);    
-    Py_CLEAR(self->speed_stream);    
+    Py_CLEAR(self->speed);
+    Py_CLEAR(self->speed_stream);
     return 0;
 }
 
@@ -1099,40 +1179,44 @@ SfMarkerShuffler_dealloc(SfMarkerShuffler* self)
     free(self->samplesBuffer);
     free(self->markers);
     SfMarkerShuffler_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
 SfMarkerShuffler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
+    Py_ssize_t psize;
     PyObject *speedtmp=NULL, *markerstmp=NULL;
     SfMarkerShuffler *self;
     self = (SfMarkerShuffler *)type->tp_alloc(type, 0);
-    
+
     self->speed = PyFloat_FromDouble(1);
     self->interp = 2;
     self->startPos = -1;
     self->endPos = -1;
 	self->modebuffer[0] = 0;
     self->lastDir = 1;
+    self->x = 0.5;
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, SfMarkerShuffler_compute_next_data_frame);
     self->mode_func_ptr = SfMarkerShuffler_setProcMode;
 
     static char *kwlist[] = {"path", "markers", "speed", "interp", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "sO|Oi", kwlist, &self->path, &markerstmp, &speedtmp, &self->interp))
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "s#O|Oi", kwlist, &self->path, &psize, &markerstmp, &speedtmp, &self->interp))
         Py_RETURN_NONE;
 
     if (speedtmp) {
         PyObject_CallMethod((PyObject *)self, "setSpeed", "O", speedtmp);
     }
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     (*self->mode_func_ptr)(self);
-    
+
+    self->type_func_ptr = SfMarkerShuffler_uniform;
+
     if (self->interp == 0)
         self->interp = 2;
     if (self->interp == 1)
@@ -1143,13 +1227,13 @@ SfMarkerShuffler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         self->interp_func_ptr = cosine;
     else if (self->interp == 4)
         self->interp_func_ptr = cubic;
-    
+
     /* Open the sound file. */
     self->info.format = 0;
     self->sf = sf_open(self->path, SFM_READ, &self->info);
     if (self->sf == NULL)
     {
-        printf("Failed to open the file.\n");
+        PySys_WriteStdout("SfMarkerShuffler: failed to open the file.\n");
         Py_RETURN_NONE;
     }
     self->sndSize = self->info.frames;
@@ -1163,7 +1247,7 @@ SfMarkerShuffler_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->samplesBuffer = (MYFLT *)realloc(self->samplesBuffer, self->bufsize * self->sndChnls * sizeof(MYFLT));
 
     Server_generateSeed((Server *)self->server, SFMARKERSHUFFLER_ID);
-    
+
     return (PyObject *)self;
 }
 
@@ -1178,14 +1262,11 @@ static PyObject *
 SfMarkerShuffler_setSpeed(SfMarkerShuffler *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->speed);
@@ -1201,27 +1282,24 @@ SfMarkerShuffler_setSpeed(SfMarkerShuffler *self, PyObject *arg)
         self->speed_stream = (Stream *)streamtmp;
 		self->modebuffer[0] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 SfMarkerShuffler_setInterp(SfMarkerShuffler *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
     int isNumber = PyNumber_Check(arg);
-    
+
 	if (isNumber == 1) {
 		self->interp = PyInt_AsLong(PyNumber_Int(arg));
-    }  
-    
+    }
+
     if (self->interp == 0)
         self->interp = 2;
     if (self->interp == 1)
@@ -1232,16 +1310,81 @@ SfMarkerShuffler_setInterp(SfMarkerShuffler *self, PyObject *arg)
         self->interp_func_ptr = cosine;
     else if (self->interp == 4)
         self->interp_func_ptr = cubic;
-    
-    Py_INCREF(Py_None);
-    return Py_None;
+
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+SfMarkerShuffler_setRandomType(SfMarkerShuffler *self, PyObject *args, PyObject *kwds)
+{
+    int dist = 0;
+    MYFLT x = 0.5;
+
+    static char *kwlist[] = {"dist", "x", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__IF, kwlist, &dist, &x))
+        Py_RETURN_NONE;
+
+    if (dist < 0 || dist > 9) {
+        Py_RETURN_NONE;
+    }
+
+    if (x < 0.0)
+        self->x = 0.0;
+    else if (x >= 1.0)
+        self->x = 1.0;
+    else
+        self->x = x;
+
+    switch (dist) {
+        case 0:
+            self->type_func_ptr = SfMarkerShuffler_uniform;
+            break;
+        case 1:
+            self->type_func_ptr = SfMarkerShuffler_linear_min;
+            break;
+        case 2:
+            self->type_func_ptr = SfMarkerShuffler_linear_max;
+            break;
+        case 3:
+            self->type_func_ptr = SfMarkerShuffler_triangle;
+            break;
+        case 4:
+            self->type_func_ptr = SfMarkerShuffler_expon_min;
+            self->x *= 10.0;
+            break;
+        case 5:
+            self->type_func_ptr = SfMarkerShuffler_expon_max;
+            self->x *= 10.0;
+            break;
+        case 6:
+            self->type_func_ptr = SfMarkerShuffler_biexpon;
+            self->x *= 10.0;
+            break;
+        case 7:
+            self->type_func_ptr = SfMarkerShuffler_cauchy;
+            self->x *= 10.0;
+            self->x = 10.0 - self->x;
+            break;
+        case 8:
+            self->type_func_ptr = SfMarkerShuffler_weibull;
+            self->x = self->x * 5.0 + 0.1;
+            break;
+        case 9:
+            self->type_func_ptr = SfMarkerShuffler_gaussian;
+            self->x *= 10.0;
+            self->x = 10.0 - self->x;
+            break;
+    }
+
+    Py_RETURN_NONE;
 }
 
 MYFLT *
 SfMarkerShuffler_getSamplesBuffer(SfMarkerShuffler *self)
 {
     return (MYFLT *)self->samplesBuffer;
-}    
+}
 
 static PyMemberDef SfMarkerShuffler_members[] = {
 {"server", T_OBJECT_EX, offsetof(SfMarkerShuffler, server), 0, "Pyo server."},
@@ -1258,12 +1401,12 @@ static PyMethodDef SfMarkerShuffler_methods[] = {
 {"stop", (PyCFunction)SfMarkerShuffler_stop, METH_NOARGS, "Stops computing."},
 {"setSpeed", (PyCFunction)SfMarkerShuffler_setSpeed, METH_O, "Sets sfplayer reading speed."},
 {"setInterp", (PyCFunction)SfMarkerShuffler_setInterp, METH_O, "Sets sfplayer interpolation mode."},
+{"setRandomType", (PyCFunction)SfMarkerShuffler_setRandomType, METH_VARARGS|METH_KEYWORDS, "Sets sfplayer random type."},
 {NULL}  /* Sentinel */
 };
 
 PyTypeObject SfMarkerShufflerType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.SfMarkerShuffler_base",         /*tp_name*/
 sizeof(SfMarkerShuffler),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -1271,7 +1414,7 @@ sizeof(SfMarkerShuffler),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 0,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -1310,7 +1453,7 @@ typedef struct {
     pyo_audio_HEAD
     SfMarkerShuffler *mainPlayer;
     int modebuffer[2];
-    int chnl; 
+    int chnl;
 } SfMarkerShuffle;
 
 static void SfMarkerShuffle_postprocessing_ii(SfMarkerShuffle *self) { POST_PROCESSING_II };
@@ -1330,31 +1473,31 @@ SfMarkerShuffle_setProcMode(SfMarkerShuffle *self)
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = SfMarkerShuffle_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = SfMarkerShuffle_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = SfMarkerShuffle_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = SfMarkerShuffle_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = SfMarkerShuffle_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = SfMarkerShuffle_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = SfMarkerShuffle_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = SfMarkerShuffle_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = SfMarkerShuffle_postprocessing_revareva;
             break;
     }
@@ -1369,7 +1512,7 @@ SfMarkerShuffle_compute_next_data_frame(SfMarkerShuffle *self)
     tmp = SfMarkerShuffler_getSamplesBuffer((SfMarkerShuffler *)self->mainPlayer);
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = tmp[i + offset];
-    }    
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1381,11 +1524,11 @@ SfMarkerShuffle_traverse(SfMarkerShuffle *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 SfMarkerShuffle_clear(SfMarkerShuffle *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->mainPlayer);    
+    Py_CLEAR(self->mainPlayer);
     return 0;
 }
 
@@ -1394,7 +1537,7 @@ SfMarkerShuffle_dealloc(SfMarkerShuffle* self)
 {
     pyo_DEALLOC
     SfMarkerShuffle_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1404,45 +1547,45 @@ SfMarkerShuffle_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL;
     SfMarkerShuffle *self;
     self = (SfMarkerShuffle *)type->tp_alloc(type, 0);
-    
+
     self->chnl = 0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, SfMarkerShuffle_compute_next_data_frame);
     self->mode_func_ptr = SfMarkerShuffle_setProcMode;
 
     static char *kwlist[] = {"mainPlayer", "chnl", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOO", kwlist, &maintmp, &self->chnl, &multmp, &addtmp))
         Py_RETURN_NONE;
 
     Py_XDECREF(self->mainPlayer);
     Py_INCREF(maintmp);
     self->mainPlayer = (SfMarkerShuffler *)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 * SfMarkerShuffle_getServer(SfMarkerShuffle* self) { GET_SERVER };
 static PyObject * SfMarkerShuffle_getStream(SfMarkerShuffle* self) { GET_STREAM };
-static PyObject * SfMarkerShuffle_setMul(SfMarkerShuffle *self, PyObject *arg) { SET_MUL };	
-static PyObject * SfMarkerShuffle_setAdd(SfMarkerShuffle *self, PyObject *arg) { SET_ADD };	
-static PyObject * SfMarkerShuffle_setSub(SfMarkerShuffle *self, PyObject *arg) { SET_SUB };	
-static PyObject * SfMarkerShuffle_setDiv(SfMarkerShuffle *self, PyObject *arg) { SET_DIV };	
+static PyObject * SfMarkerShuffle_setMul(SfMarkerShuffle *self, PyObject *arg) { SET_MUL };
+static PyObject * SfMarkerShuffle_setAdd(SfMarkerShuffle *self, PyObject *arg) { SET_ADD };
+static PyObject * SfMarkerShuffle_setSub(SfMarkerShuffle *self, PyObject *arg) { SET_SUB };
+static PyObject * SfMarkerShuffle_setDiv(SfMarkerShuffle *self, PyObject *arg) { SET_DIV };
 
 static PyObject * SfMarkerShuffle_play(SfMarkerShuffle *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * SfMarkerShuffle_out(SfMarkerShuffle *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1482,7 +1625,7 @@ static PyNumberMethods SfMarkerShuffle_as_number = {
 (binaryfunc)SfMarkerShuffle_add,                      /*nb_add*/
 (binaryfunc)SfMarkerShuffle_sub,                 /*nb_subtract*/
 (binaryfunc)SfMarkerShuffle_multiply,                 /*nb_multiply*/
-(binaryfunc)SfMarkerShuffle_div,                   /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -1496,16 +1639,16 @@ static PyNumberMethods SfMarkerShuffle_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
 (binaryfunc)SfMarkerShuffle_inplace_add,              /*inplace_add*/
 (binaryfunc)SfMarkerShuffle_inplace_sub,         /*inplace_subtract*/
 (binaryfunc)SfMarkerShuffle_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)SfMarkerShuffle_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -1514,15 +1657,14 @@ static PyNumberMethods SfMarkerShuffle_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)SfMarkerShuffle_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)SfMarkerShuffle_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
 PyTypeObject SfMarkerShuffleType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.SfMarkerShuffle_base",         /*tp_name*/
 sizeof(SfMarkerShuffle),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -1530,7 +1672,7 @@ sizeof(SfMarkerShuffle),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &SfMarkerShuffle_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -1602,19 +1744,19 @@ SfMarkerLooper_readframes_i(SfMarkerLooper *self) {
     MYFLT sp, frac, bufpos, delta, tmp;
     int i, j, totlen, buflen, shortbuflen, bufindex;
     sf_count_t index;
-   
-    if (self->modebuffer[0] == 0) 
+
+    if (self->modebuffer[0] == 0)
         sp = PyFloat_AS_DOUBLE(self->speed);
     else
         sp = Stream_getData((Stream *)self->speed_stream)[0];
 
     delta = MYFABS(sp) * self->srScale;
-    
+
     buflen = (int)(self->bufsize * delta + 0.5) + 64;
     totlen = self->sndChnls*buflen;
     MYFLT buffer[totlen];
     MYFLT buffer2[self->sndChnls][buflen];
-    
+
     if (sp > 0) { /* reading forward */
         if (self->startPos == -1 || self->lastDir == 0) {
             self->lastDir = 1;
@@ -1629,13 +1771,13 @@ SfMarkerLooper_readframes_i(SfMarkerLooper *self) {
         }
         index = (int)self->pointerPos;
         sf_seek(self->sf, index, SEEK_SET); /* sets position pointer in the file */
-        
+
         /* fill a buffer with enough samples to satisfy speed reading */
         /* if not enough samples to read in the file */
         if ((index+buflen) > self->endPos) {
             shortbuflen = self->endPos - index;
             SF_READ(self->sf, buffer, shortbuflen*self->sndChnls);
-            
+
             /* wrap around and read new samples if loop */
             int pad = buflen - shortbuflen;
             int padlen = pad*self->sndChnls;
@@ -1648,12 +1790,12 @@ SfMarkerLooper_readframes_i(SfMarkerLooper *self) {
         }
         else /* without zero padding */
             SF_READ(self->sf, buffer, totlen);
-        
+
         /* de-interleave samples */
         for (i=0; i<totlen; i++) {
             buffer2[i%self->sndChnls][(int)(i/self->sndChnls)] = buffer[i];
         }
-        
+
         /* fill data with samples */
         for (i=0; i<self->bufsize; i++) {
             bufpos = self->pointerPos - index;
@@ -1661,7 +1803,7 @@ SfMarkerLooper_readframes_i(SfMarkerLooper *self) {
             frac = bufpos - bufindex;
             for (j=0; j<self->sndChnls; j++) {
                 self->samplesBuffer[i+(j*self->bufsize)] = (*self->interp_func_ptr)(buffer2[j], bufindex, frac, buflen);
-            }    
+            }
             self->pointerPos += delta;
         }
         if (self->pointerPos >= self->endPos) {
@@ -1675,16 +1817,16 @@ SfMarkerLooper_readframes_i(SfMarkerLooper *self) {
             self->lastDir = self->startPos = -1;
             SfMarkerLooper_chooseNewMark((SfMarkerLooper *)self, 0);
             self->pointerPos = self->startPos;
-        }    
+        }
         index = (int)self->pointerPos + 1;
-        
+
         /* fill a buffer with enough samples to satisfy speed reading */
         /* if not enough samples to read in the file */
         if ((index-buflen) < self->endPos) {
             shortbuflen = index - self->endPos;
             int pad = buflen - shortbuflen;
             int padlen = pad*self->sndChnls;
-            
+
             /* wrap around and read new samples if loop */
             MYFLT buftemp[padlen];
             sf_seek(self->sf, (int)self->nextStartPos-pad, SEEK_SET);
@@ -1692,13 +1834,13 @@ SfMarkerLooper_readframes_i(SfMarkerLooper *self) {
             for (i=0; i<padlen; i++) {
                 buffer[i] = buftemp[i];
             }
-            
+
             MYFLT buftemp2[shortbuflen*self->sndChnls];
             sf_seek(self->sf, self->endPos, SEEK_SET); /* sets position pointer in the file */
             SF_READ(self->sf, buftemp2, shortbuflen*self->sndChnls);
             for (i=0; i<(shortbuflen*self->sndChnls); i++) {
                 buffer[i+padlen] = buftemp2[i];
-            }    
+            }
         }
         else { /* without zero padding */
             sf_seek(self->sf, index-buflen, SEEK_SET); /* sets position pointer in the file */
@@ -1708,19 +1850,19 @@ SfMarkerLooper_readframes_i(SfMarkerLooper *self) {
         for (i=0; i<totlen; i++) {
             buffer2[i%self->sndChnls][(int)(i/self->sndChnls)] = buffer[i];
         }
-        
+
         /* reverse arrays */
         MYFLT swap;
         for (i=0; i<self->sndChnls; i++) {
             int a;
-            int b = buflen; 
+            int b = buflen;
             for (a=0; a<--b; a++) { //increment a and decrement b until they meet eachother
                 swap = buffer2[i][a];       //put what's in a into swap space
                 buffer2[i][a] = buffer2[i][b];    //put what's in b into a
                 buffer2[i][b] = swap;       //put what's in the swap (a) into b
             }
         }
-        
+
         /* fill stream buffer with samples */
         for (i=0; i<self->bufsize; i++) {
             bufpos = index - self->pointerPos;
@@ -1743,7 +1885,7 @@ SfMarkerLooper_readframes_i(SfMarkerLooper *self) {
             self->samplesBuffer[i] = 0.0;
         }
     }
-}    
+}
 
 static void
 SfMarkerLooper_setProcMode(SfMarkerLooper *self)
@@ -1754,14 +1896,14 @@ SfMarkerLooper_setProcMode(SfMarkerLooper *self)
 static void
 SfMarkerLooper_compute_next_data_frame(SfMarkerLooper *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static void
-SfMarkerLooper_chooseNewMark(SfMarkerLooper *self, int dir) 
+SfMarkerLooper_chooseNewMark(SfMarkerLooper *self, int dir)
 {
     int mark;
-    
+
     if (self->modebuffer[1] == 0)
         mark = (int)(PyFloat_AS_DOUBLE(self->mark));
     else
@@ -1770,33 +1912,33 @@ SfMarkerLooper_chooseNewMark(SfMarkerLooper *self, int dir)
     if (mark < 0 || mark >= self->markers_size) {
         mark = self->markers_size / 2;
     }
-    
+
     self->old_mark = mark;
 
     if (dir == 1) {
         if (self->startPos == -1) {
-            self->startPos = self->markers[mark] * self->srScale;
-            self->endPos = self->markers[mark+1] * self->srScale;
+            self->startPos = self->markers[mark];
+            self->endPos = self->markers[mark+1];
         }
         else {
             self->startPos = self->nextStartPos;
             self->endPos = self->nextEndPos;
         }
-        self->nextStartPos = self->markers[mark] * self->srScale;
-        self->nextEndPos = self->markers[mark+1] * self->srScale;
+        self->nextStartPos = self->markers[mark];
+        self->nextEndPos = self->markers[mark+1];
     }
     else {
         mark = self->markers_size - mark;
         if (self->startPos == -1) {
-            self->startPos = self->markers[mark] * self->srScale;
-            self->endPos = self->markers[mark-1] * self->srScale;
+            self->startPos = self->markers[mark];
+            self->endPos = self->markers[mark-1];
         }
         else {
             self->startPos = self->nextStartPos;
             self->endPos = self->nextEndPos;
         }
-        self->nextStartPos = self->markers[mark] * self->srScale;
-        self->nextEndPos = self->markers[mark-1] * self->srScale;
+        self->nextStartPos = self->markers[mark];
+        self->nextEndPos = self->markers[mark-1];
     }
 }
 
@@ -1809,7 +1951,7 @@ SfMarkerLooper_setMarkers(SfMarkerLooper *self, PyObject *markerstmp)
     self->markers[0] = 0.;
     for (i=0; i<len; i++) {
         self->markers[i+1] = PyFloat_AsDouble(PyList_GetItem(markerstmp, i));
-    }  
+    }
     self->markers[len+1] = self->sndSize;
     self->markers_size = (int)len+1;
 }
@@ -1818,21 +1960,21 @@ static int
 SfMarkerLooper_traverse(SfMarkerLooper *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->speed);    
-    Py_VISIT(self->speed_stream);    
-    Py_VISIT(self->mark);    
-    Py_VISIT(self->mark_stream);    
+    Py_VISIT(self->speed);
+    Py_VISIT(self->speed_stream);
+    Py_VISIT(self->mark);
+    Py_VISIT(self->mark_stream);
      return 0;
 }
 
-static int 
+static int
 SfMarkerLooper_clear(SfMarkerLooper *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->speed);    
-    Py_CLEAR(self->speed_stream);    
-    Py_CLEAR(self->mark);    
-    Py_CLEAR(self->mark_stream);    
+    Py_CLEAR(self->speed);
+    Py_CLEAR(self->speed_stream);
+    Py_CLEAR(self->mark);
+    Py_CLEAR(self->mark_stream);
     return 0;
 }
 
@@ -1845,17 +1987,18 @@ SfMarkerLooper_dealloc(SfMarkerLooper* self)
     free(self->samplesBuffer);
     free(self->markers);
     SfMarkerLooper_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
 SfMarkerLooper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
+    Py_ssize_t psize;
     PyObject *speedtmp=NULL, *marktmp=NULL, *markerstmp=NULL;
     SfMarkerLooper *self;
     self = (SfMarkerLooper *)type->tp_alloc(type, 0);
-    
+
     self->speed = PyFloat_FromDouble(1);
     self->mark = PyFloat_FromDouble(0);
     self->interp = 2;
@@ -1863,18 +2006,18 @@ SfMarkerLooper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->endPos = -1;
     self->old_mark = -1;
     self->lastDir = 1;
-    self->modebuffer[0] = 0;	
+    self->modebuffer[0] = 0;
     self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, SfMarkerLooper_compute_next_data_frame);
     self->mode_func_ptr = SfMarkerLooper_setProcMode;
 
     static char *kwlist[] = {"path", "markers", "speed", "mark", "interp", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "sO|OOi", kwlist, &self->path, &markerstmp, &speedtmp, &marktmp, &self->interp))
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "s#O|OOi", kwlist, &self->path, &psize, &markerstmp, &speedtmp, &marktmp, &self->interp))
         Py_RETURN_NONE;
-    
+
     if (speedtmp) {
         PyObject_CallMethod((PyObject *)self, "setSpeed", "O", speedtmp);
     }
@@ -1882,11 +2025,11 @@ SfMarkerLooper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (marktmp) {
         PyObject_CallMethod((PyObject *)self, "setMark", "O", marktmp);
     }
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     if (self->interp == 0)
         self->interp = 2;
     if (self->interp == 1)
@@ -1897,27 +2040,27 @@ SfMarkerLooper_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         self->interp_func_ptr = cosine;
     else if (self->interp == 4)
         self->interp_func_ptr = cubic;
-    
+
     /* Open the sound file. */
     self->info.format = 0;
     self->sf = sf_open(self->path, SFM_READ, &self->info);
     if (self->sf == NULL)
     {
-        printf("Failed to open the file.\n");
+        PySys_WriteStdout("SfMarkerLooper: failed to open the file.\n");
         Py_RETURN_NONE;
     }
     self->sndSize = self->info.frames;
     self->sndSr = self->info.samplerate;
     self->sndChnls = self->info.channels;
     self->srScale = self->sndSr / self->sr;
-    
+
     Py_INCREF(markerstmp);
     SfMarkerLooper_setMarkers((SfMarkerLooper *)self, markerstmp);
-    
+
     self->samplesBuffer = (MYFLT *)realloc(self->samplesBuffer, self->bufsize * self->sndChnls * sizeof(MYFLT));
-    
+
     Server_generateSeed((Server *)self->server, SFMARKERLOOPER_ID);
-    
+
     return (PyObject *)self;
 }
 
@@ -1932,14 +2075,11 @@ static PyObject *
 SfMarkerLooper_setSpeed(SfMarkerLooper *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->speed);
@@ -1955,23 +2095,20 @@ SfMarkerLooper_setSpeed(SfMarkerLooper *self, PyObject *arg)
         self->speed_stream = (Stream *)streamtmp;
 		self->modebuffer[0] = 1;
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 SfMarkerLooper_setMark(SfMarkerLooper *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->mark);
@@ -1990,22 +2127,19 @@ SfMarkerLooper_setMark(SfMarkerLooper *self, PyObject *arg)
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 SfMarkerLooper_setInterp(SfMarkerLooper *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
     int isNumber = PyNumber_Check(arg);
-    
+
 	if (isNumber == 1) {
 		self->interp = PyInt_AsLong(PyNumber_Int(arg));
-    }  
-    
+    }
+
     if (self->interp == 0)
         self->interp = 2;
     if (self->interp == 1)
@@ -2016,16 +2150,15 @@ SfMarkerLooper_setInterp(SfMarkerLooper *self, PyObject *arg)
         self->interp_func_ptr = cosine;
     else if (self->interp == 4)
         self->interp_func_ptr = cubic;
-    
-    Py_INCREF(Py_None);
-    return Py_None;
+
+    Py_RETURN_NONE;
 }
 
 MYFLT *
 SfMarkerLooper_getSamplesBuffer(SfMarkerLooper *self)
 {
     return (MYFLT *)self->samplesBuffer;
-}    
+}
 
 static PyMemberDef SfMarkerLooper_members[] = {
     {"server", T_OBJECT_EX, offsetof(SfMarkerLooper, server), 0, "Pyo server."},
@@ -2048,8 +2181,7 @@ static PyMethodDef SfMarkerLooper_methods[] = {
 };
 
 PyTypeObject SfMarkerLooperType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.SfMarkerLooper_base",         /*tp_name*/
     sizeof(SfMarkerLooper),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -2057,7 +2189,7 @@ PyTypeObject SfMarkerLooperType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     0,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -2096,7 +2228,7 @@ typedef struct {
     pyo_audio_HEAD
     SfMarkerLooper *mainPlayer;
     int modebuffer[2];
-    int chnl; 
+    int chnl;
 } SfMarkerLoop;
 
 static void SfMarkerLoop_postprocessing_ii(SfMarkerLoop *self) { POST_PROCESSING_II };
@@ -2114,33 +2246,33 @@ SfMarkerLoop_setProcMode(SfMarkerLoop *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = SfMarkerLoop_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = SfMarkerLoop_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = SfMarkerLoop_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = SfMarkerLoop_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = SfMarkerLoop_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = SfMarkerLoop_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = SfMarkerLoop_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = SfMarkerLoop_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = SfMarkerLoop_postprocessing_revareva;
             break;
     }
@@ -2155,7 +2287,7 @@ SfMarkerLoop_compute_next_data_frame(SfMarkerLoop *self)
     tmp = SfMarkerLooper_getSamplesBuffer((SfMarkerLooper *)self->mainPlayer);
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = tmp[i + offset];
-    }    
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -2167,11 +2299,11 @@ SfMarkerLoop_traverse(SfMarkerLoop *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 SfMarkerLoop_clear(SfMarkerLoop *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->mainPlayer);    
+    Py_CLEAR(self->mainPlayer);
     return 0;
 }
 
@@ -2180,7 +2312,7 @@ SfMarkerLoop_dealloc(SfMarkerLoop* self)
 {
     pyo_DEALLOC
     SfMarkerLoop_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2190,45 +2322,45 @@ SfMarkerLoop_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL;
     SfMarkerLoop *self;
     self = (SfMarkerLoop *)type->tp_alloc(type, 0);
-    
+
     self->chnl = 0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, SfMarkerLoop_compute_next_data_frame);
     self->mode_func_ptr = SfMarkerLoop_setProcMode;
 
     static char *kwlist[] = {"mainPlayer", "chnl", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOO", kwlist, &maintmp, &self->chnl, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     Py_XDECREF(self->mainPlayer);
     Py_INCREF(maintmp);
     self->mainPlayer = (SfMarkerLooper *)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 * SfMarkerLoop_getServer(SfMarkerLoop* self) { GET_SERVER };
 static PyObject * SfMarkerLoop_getStream(SfMarkerLoop* self) { GET_STREAM };
-static PyObject * SfMarkerLoop_setMul(SfMarkerLoop *self, PyObject *arg) { SET_MUL };	
-static PyObject * SfMarkerLoop_setAdd(SfMarkerLoop *self, PyObject *arg) { SET_ADD };	
-static PyObject * SfMarkerLoop_setSub(SfMarkerLoop *self, PyObject *arg) { SET_SUB };	
-static PyObject * SfMarkerLoop_setDiv(SfMarkerLoop *self, PyObject *arg) { SET_DIV };	
+static PyObject * SfMarkerLoop_setMul(SfMarkerLoop *self, PyObject *arg) { SET_MUL };
+static PyObject * SfMarkerLoop_setAdd(SfMarkerLoop *self, PyObject *arg) { SET_ADD };
+static PyObject * SfMarkerLoop_setSub(SfMarkerLoop *self, PyObject *arg) { SET_SUB };
+static PyObject * SfMarkerLoop_setDiv(SfMarkerLoop *self, PyObject *arg) { SET_DIV };
 
 static PyObject * SfMarkerLoop_play(SfMarkerLoop *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * SfMarkerLoop_out(SfMarkerLoop *self, PyObject *args, PyObject *kwds) { OUT };
@@ -2268,7 +2400,7 @@ static PyNumberMethods SfMarkerLoop_as_number = {
     (binaryfunc)SfMarkerLoop_add,                      /*nb_add*/
     (binaryfunc)SfMarkerLoop_sub,                 /*nb_subtract*/
     (binaryfunc)SfMarkerLoop_multiply,                 /*nb_multiply*/
-    (binaryfunc)SfMarkerLoop_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -2282,16 +2414,16 @@ static PyNumberMethods SfMarkerLoop_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)SfMarkerLoop_inplace_add,              /*inplace_add*/
     (binaryfunc)SfMarkerLoop_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)SfMarkerLoop_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)SfMarkerLoop_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -2300,15 +2432,14 @@ static PyNumberMethods SfMarkerLoop_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)SfMarkerLoop_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)SfMarkerLoop_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject SfMarkerLoopType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.SfMarkerLoop_base",         /*tp_name*/
     sizeof(SfMarkerLoop),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -2316,7 +2447,7 @@ PyTypeObject SfMarkerLoopType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &SfMarkerLoop_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -2346,4 +2477,4 @@ PyTypeObject SfMarkerLoopType = {
     0,      /* tp_init */
     0,                         /* tp_alloc */
     SfMarkerLoop_new,                 /* tp_new */
-};
+};
\ No newline at end of file
diff --git a/src/objects/sigmodule.c b/src/objects/sigmodule.c
index 93e295e..5cf05ff 100644
--- a/src/objects/sigmodule.c
+++ b/src/objects/sigmodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include "pyomodule.h"
 #include "streammodule.h"
@@ -47,33 +48,33 @@ Sig_setProcMode(Sig *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Sig_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Sig_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Sig_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Sig_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Sig_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Sig_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Sig_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Sig_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Sig_postprocessing_revareva;
             break;
     }
@@ -94,7 +95,7 @@ Sig_compute_next_data_frame(Sig *self)
         for (i=0; i<self->bufsize; i++) {
             self->data[i] = vals[i];
         }
-    }    
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -102,17 +103,17 @@ static int
 Sig_traverse(Sig *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->value);    
-    Py_VISIT(self->value_stream);    
+    Py_VISIT(self->value);
+    Py_VISIT(self->value_stream);
     return 0;
 }
 
-static int 
+static int
 Sig_clear(Sig *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->value);    
-    Py_CLEAR(self->value_stream);    
+    Py_CLEAR(self->value);
+    Py_CLEAR(self->value_stream);
     return 0;
 }
 
@@ -121,7 +122,7 @@ Sig_dealloc(Sig* self)
 {
     pyo_DEALLOC
     Sig_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -131,7 +132,7 @@ Sig_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *valuetmp=NULL, *multmp=NULL, *addtmp=NULL;
     Sig *self;
     self = (Sig *)type->tp_alloc(type, 0);
-    
+
     self->value = PyFloat_FromDouble(0.0);
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
@@ -142,28 +143,28 @@ Sig_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = Sig_setProcMode;
 
     static char *kwlist[] = {"value", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &valuetmp, &multmp, &addtmp))
-        Py_RETURN_NONE; 
+        Py_RETURN_NONE;
 
     if (valuetmp) {
         PyObject_CallMethod((PyObject *)self, "setValue", "O", valuetmp);
     }
-    
+
     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);
-    
+
     Sig_compute_next_data_frame((Sig *)self);
-    
+
     return (PyObject *)self;
 }
 
@@ -171,14 +172,11 @@ static PyObject *
 Sig_setValue(Sig *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
     Py_DECREF(self->value);
@@ -194,17 +192,17 @@ Sig_setValue(Sig *self, PyObject *arg)
         self->value_stream = (Stream *)streamtmp;
         self->modebuffer[2] = 1;
     }
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject * Sig_getServer(Sig* self) { GET_SERVER };
 static PyObject * Sig_getStream(Sig* self) { GET_STREAM };
-static PyObject * Sig_setMul(Sig *self, PyObject *arg) { SET_MUL };	
-static PyObject * Sig_setAdd(Sig *self, PyObject *arg) { SET_ADD };	
-static PyObject * Sig_setSub(Sig *self, PyObject *arg) { SET_SUB };	
-static PyObject * Sig_setDiv(Sig *self, PyObject *arg) { SET_DIV };	
+static PyObject * Sig_setMul(Sig *self, PyObject *arg) { SET_MUL };
+static PyObject * Sig_setAdd(Sig *self, PyObject *arg) { SET_ADD };
+static PyObject * Sig_setSub(Sig *self, PyObject *arg) { SET_SUB };
+static PyObject * Sig_setDiv(Sig *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Sig_play(Sig *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Sig_out(Sig *self, PyObject *args, PyObject *kwds) { OUT };
@@ -246,7 +244,7 @@ static PyNumberMethods Sig_as_number = {
 (binaryfunc)Sig_add,                      /*nb_add*/
 (binaryfunc)Sig_sub,                 /*nb_subtract*/
 (binaryfunc)Sig_multiply,                 /*nb_multiply*/
-(binaryfunc)Sig_div,                   /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -260,16 +258,16 @@ static PyNumberMethods Sig_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
 (binaryfunc)Sig_inplace_add,              /*inplace_add*/
 (binaryfunc)Sig_inplace_sub,         /*inplace_subtract*/
 (binaryfunc)Sig_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)Sig_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -278,15 +276,14 @@ static PyNumberMethods Sig_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)Sig_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)Sig_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
 PyTypeObject SigType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Sig_base",         /*tp_name*/
 sizeof(Sig),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -294,7 +291,7 @@ sizeof(Sig),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &Sig_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -333,33 +330,39 @@ typedef struct {
     pyo_audio_HEAD
     PyObject *value;
     Stream *value_stream;
-    MYFLT time;
+    PyObject *time;
+    Stream *time_stream;
     MYFLT lastValue;
     MYFLT currentValue;
     long timeStep;
     MYFLT stepVal;
     long timeCount;
-    int modebuffer[3];
+    int modebuffer[4];
 } SigTo;
 
 static void
 SigTo_generates_i(SigTo *self) {
     int i;
-    MYFLT value;
-    
+    MYFLT value, time;
+
     if (self->modebuffer[2] == 0) {
         value = PyFloat_AS_DOUBLE(self->value);
+        if (value != self->lastValue) {
+            if (self->modebuffer[3] == 0)
+                time = PyFloat_AS_DOUBLE(self->time);
+            else
+                time = Stream_getData((Stream *)self->time_stream)[0];
+            self->timeCount = 0;
+            self->lastValue = value;
+            self->timeStep = (long)(time * self->sr);
+            if (self->timeStep > 0)
+                self->stepVal = (value - self->currentValue) / self->timeStep;
+        }
         if (self->timeStep <= 0) {
             for (i=0; i<self->bufsize; i++)
                 self->data[i] = self->currentValue = self->lastValue = value;
         }
         else {
-            if (value != self->lastValue) {
-                self->timeCount = 0;
-                self->stepVal = (value - self->currentValue) / self->timeStep;
-                self->lastValue = value;
-            }    
-        
             for (i=0; i<self->bufsize; i++) {
                 if (self->timeCount == (self->timeStep - 1)) {
                     self->currentValue = value;
@@ -368,28 +371,29 @@ SigTo_generates_i(SigTo *self) {
                 else if (self->timeCount < self->timeStep) {
                     self->currentValue += self->stepVal;
                     self->timeCount++;
-                }    
+                }
                 self->data[i] = self->currentValue;
             }
         }
     }
-    else {
-        MYFLT *vals = Stream_getData((Stream *)self->value_stream);        
-        if (self->timeStep <= 0) {
-            for (i=0; i<self->bufsize; i++) {
-                value = vals[i];
-                self->data[i] = self->currentValue = self->lastValue = value;
-            }
-        }
-        else {
-            for (i=0; i<self->bufsize; i++) {
-                value = vals[i];
-                if (value != self->lastValue) {
-                    self->timeCount = 0;
+    else { 
+        MYFLT *vals = Stream_getData((Stream *)self->value_stream);
+        for (i=0; i<self->bufsize; i++) {
+            value = vals[i];
+            if (value != self->lastValue) {
+                if (self->modebuffer[3] == 0)
+                    time = PyFloat_AS_DOUBLE(self->time);
+                else
+                    time = Stream_getData((Stream *)self->time_stream)[i];
+                self->timeCount = 0;
+                self->lastValue = value;
+                self->timeStep = (long)(time * self->sr);
+                if (self->timeStep > 0)
                     self->stepVal = (value - self->currentValue) / self->timeStep;
-                    self->lastValue = value;
-                }    
-            
+            }
+            if (self->timeStep <= 0) {
+                self->data[i] = self->currentValue = self->lastValue = value;
+            } else {
                 if (self->timeCount == (self->timeStep - 1)) {
                     self->currentValue = value;
                     self->timeCount++;
@@ -397,7 +401,7 @@ SigTo_generates_i(SigTo *self) {
                 else if (self->timeCount < self->timeStep) {
                     self->currentValue += self->stepVal;
                     self->timeCount++;
-                }    
+                }
                 self->data[i] = self->currentValue;
             }
         }
@@ -421,33 +425,33 @@ SigTo_setProcMode(SigTo *self)
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
     self->proc_func_ptr = SigTo_generates_i;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = SigTo_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = SigTo_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = SigTo_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = SigTo_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = SigTo_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = SigTo_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = SigTo_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = SigTo_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = SigTo_postprocessing_revareva;
             break;
     }
@@ -456,7 +460,7 @@ SigTo_setProcMode(SigTo *self)
 static void
 SigTo_compute_next_data_frame(SigTo *self)
 {
-    (*self->proc_func_ptr)(self);  
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -464,17 +468,21 @@ static int
 SigTo_traverse(SigTo *self, visitproc visit, void *arg)
 {
     pyo_VISIT
-    Py_VISIT(self->value);    
-    Py_VISIT(self->value_stream);    
+    Py_VISIT(self->value);
+    Py_VISIT(self->value_stream);
+    Py_VISIT(self->time);
+    Py_VISIT(self->time_stream);
     return 0;
 }
 
-static int 
+static int
 SigTo_clear(SigTo *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->value);    
-    Py_CLEAR(self->value_stream);    
+    Py_CLEAR(self->value);
+    Py_CLEAR(self->value_stream);
+    Py_CLEAR(self->time);
+    Py_CLEAR(self->time_stream);
     return 0;
 }
 
@@ -483,7 +491,7 @@ SigTo_dealloc(SigTo* self)
 {
     pyo_DEALLOC
     SigTo_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -496,23 +504,24 @@ SigTo_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self = (SigTo *)type->tp_alloc(type, 0);
 
     self->value = PyFloat_FromDouble(0.0);
-    self->time = 0.025;
-    self->timeStep = (long)(self->time * self->sr);
+    self->time = PyFloat_FromDouble(0.025);
     self->timeCount = 0;
     self->stepVal = 0.0;
+    self->timeStep = 0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
-    
+	self->modebuffer[3] = 0;
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, SigTo_compute_next_data_frame);
     self->mode_func_ptr = SigTo_setProcMode;
 
     static char *kwlist[] = {"value", "time", "init", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_OFOO, kwlist, &valuetmp, &timetmp, &inittmp, &multmp, &addtmp))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     if (valuetmp) {
         PyObject_CallMethod((PyObject *)self, "setValue", "O", valuetmp);
     }
@@ -520,25 +529,25 @@ SigTo_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (timetmp) {
         PyObject_CallMethod((PyObject *)self, "setTime", "O", timetmp);
     }
-    
+
     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->lastValue = self->currentValue = inittmp;
-    
+
     (*self->mode_func_ptr)(self);
 
     for(i=0; i<self->bufsize; i++) {
         self->data[i] = self->currentValue;
     }
-    
+
     return (PyObject *)self;
 }
 
@@ -546,14 +555,11 @@ static PyObject *
 SigTo_setValue(SigTo *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
     Py_DECREF(self->value);
@@ -569,40 +575,44 @@ SigTo_setValue(SigTo *self, PyObject *arg)
         self->value_stream = (Stream *)streamtmp;
         self->modebuffer[2] = 1;
     }
-    
-	Py_INCREF(Py_None);
-	return Py_None;
-}	
+
+	Py_RETURN_NONE;
+}
 
 static PyObject *
 SigTo_setTime(SigTo *self, PyObject *arg)
 {
-	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
+    Py_DECREF(self->time);
 	if (isNumber == 1) {
-		self->time = PyFloat_AS_DOUBLE(PyNumber_Float(tmp));
-        self->timeStep = (long)(self->time * self->sr);
-	}
-    
-	Py_INCREF(Py_None);
-	return Py_None;
-}	
+		self->time = PyNumber_Float(tmp);
+        self->modebuffer[3] = 0;
+    }
+    else {
+		self->time = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->time, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->time_stream);
+        self->time_stream = (Stream *)streamtmp;
+        self->modebuffer[3] = 1;
+    }
+
+	Py_RETURN_NONE;
+}
 
 static PyObject * SigTo_getServer(SigTo* self) { GET_SERVER };
 static PyObject * SigTo_getStream(SigTo* self) { GET_STREAM };
-static PyObject * SigTo_setMul(SigTo *self, PyObject *arg) { SET_MUL };	
-static PyObject * SigTo_setAdd(SigTo *self, PyObject *arg) { SET_ADD };	
-static PyObject * SigTo_setSub(SigTo *self, PyObject *arg) { SET_SUB };	
-static PyObject * SigTo_setDiv(SigTo *self, PyObject *arg) { SET_DIV };	
+static PyObject * SigTo_setMul(SigTo *self, PyObject *arg) { SET_MUL };
+static PyObject * SigTo_setAdd(SigTo *self, PyObject *arg) { SET_ADD };
+static PyObject * SigTo_setSub(SigTo *self, PyObject *arg) { SET_SUB };
+static PyObject * SigTo_setDiv(SigTo *self, PyObject *arg) { SET_DIV };
 
 static PyObject * SigTo_play(SigTo *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * SigTo_stop(SigTo *self) { STOP };
@@ -620,6 +630,7 @@ static PyMemberDef SigTo_members[] = {
 {"server", T_OBJECT_EX, offsetof(SigTo, server), 0, "Pyo server."},
 {"stream", T_OBJECT_EX, offsetof(SigTo, stream), 0, "Stream object."},
 {"value", T_OBJECT_EX, offsetof(SigTo, value), 0, "Target value."},
+{"time", T_OBJECT_EX, offsetof(SigTo, time), 0, "Ramp time."},
 {"mul", T_OBJECT_EX, offsetof(SigTo, mul), 0, "Mul factor."},
 {"add", T_OBJECT_EX, offsetof(SigTo, add), 0, "Add factor."},
 {NULL}  /* Sentinel */
@@ -643,7 +654,7 @@ static PyNumberMethods SigTo_as_number = {
 (binaryfunc)SigTo_add,                      /*nb_add*/
 (binaryfunc)SigTo_sub,                 /*nb_subtract*/
 (binaryfunc)SigTo_multiply,                 /*nb_multiply*/
-(binaryfunc)SigTo_div,                   /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -657,16 +668,16 @@ static PyNumberMethods SigTo_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
 (binaryfunc)SigTo_inplace_add,              /*inplace_add*/
 (binaryfunc)SigTo_inplace_sub,         /*inplace_subtract*/
 (binaryfunc)SigTo_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)SigTo_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -675,15 +686,14 @@ static PyNumberMethods SigTo_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)SigTo_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)SigTo_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
 PyTypeObject SigToType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.SigTo_base",         /*tp_name*/
 sizeof(SigTo),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -691,7 +701,7 @@ sizeof(SigTo),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &SigTo_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -752,9 +762,9 @@ VarPort_generates_i(VarPort *self) {
         self->timeCount = 0;
         self->stepVal = (self->value - self->currentValue) / (self->timeStep+1);
         self->lastValue = self->value;
-    }    
-   
-    if (self->flag == 1) { 
+    }
+
+    if (self->flag == 1) {
         for (i=0; i<self->bufsize; i++) {
             if (self->timeCount >= self->timeStep)
                 self->currentValue = self->value;
@@ -771,7 +781,7 @@ VarPort_generates_i(VarPort *self) {
             self->data[i] = self->currentValue;
         }
     }
-    
+
     if (self->timeCount >= self->timeout && self->flag == 1) {
         self->flag = 0;
         if (self->callable != Py_None) {
@@ -788,7 +798,7 @@ VarPort_generates_i(VarPort *self) {
                 PyErr_Print();
                 return;
             }
-        }   
+        }
     }
 }
 
@@ -807,35 +817,35 @@ VarPort_setProcMode(VarPort *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = VarPort_generates_i;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = VarPort_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = VarPort_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = VarPort_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = VarPort_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = VarPort_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = VarPort_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = VarPort_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = VarPort_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = VarPort_postprocessing_revareva;
             break;
     }
@@ -844,7 +854,7 @@ VarPort_setProcMode(VarPort *self)
 static void
 VarPort_compute_next_data_frame(VarPort *self)
 {
-    (*self->proc_func_ptr)(self);  
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -857,7 +867,7 @@ VarPort_traverse(VarPort *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 VarPort_clear(VarPort *self)
 {
     pyo_CLEAR
@@ -871,7 +881,7 @@ VarPort_dealloc(VarPort* self)
 {
     pyo_DEALLOC
     VarPort_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -882,8 +892,8 @@ VarPort_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *valuetmp=NULL, *timetmp=NULL, *calltmp=NULL, *argtmp=NULL, *multmp=NULL, *addtmp=NULL;
     VarPort *self;
     self = (VarPort *)type->tp_alloc(type, 0);
-   
-    self->flag = 1; 
+
+    self->flag = 1;
     self->time = 0.025;
     self->timeStep = (long)(self->time * self->sr);
     self->timeout = (long)((self->time + 0.1) * self->sr);
@@ -900,22 +910,22 @@ VarPort_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->mode_func_ptr = VarPort_setProcMode;
 
     static char *kwlist[] = {"value", "time", "init", "callable", "arg", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_OFOOOO, kwlist, &valuetmp, &timetmp, &inittmp, &calltmp, &argtmp, &multmp, &addtmp))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     if (valuetmp) {
         PyObject_CallMethod((PyObject *)self, "setValue", "O", valuetmp);
     }
-    
+
     if (timetmp) {
         PyObject_CallMethod((PyObject *)self, "setTime", "O", timetmp);
     }
-    
+
     if (multmp) {
         PyObject_CallMethod((PyObject *)self, "setMul", "O", multmp);
     }
-    
+
     if (addtmp) {
         PyObject_CallMethod((PyObject *)self, "setAdd", "O", addtmp);
     }
@@ -931,17 +941,17 @@ VarPort_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         Py_INCREF(argtmp);
         self->arg = argtmp;
     }
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     self->lastValue = self->currentValue = inittmp;
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     for(i=0; i<self->bufsize; i++) {
         self->data[i] = self->currentValue;
     }
-    
+
     return (PyObject *)self;
 }
 
@@ -949,55 +959,69 @@ static PyObject *
 VarPort_setValue(VarPort *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	if (isNumber == 1)
-		self->value = PyFloat_AsDouble(PyNumber_Float(tmp));
+		self->value = PyFloat_AsDouble(tmp);
     else
         self->value = self->lastValue;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 VarPort_setTime(VarPort *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	if (isNumber == 1) {
-		self->time = PyFloat_AS_DOUBLE(PyNumber_Float(tmp));
+		self->time = PyFloat_AsDouble(tmp);
         self->timeStep = (long)(self->time * self->sr);
         self->timeout = (long)((self->time + 0.1) * self->sr);
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
+
+static PyObject *
+VarPort_setFunction(VarPort *self, PyObject *arg)
+{
+	PyObject *tmp;
+
+	if (! PyCallable_Check(arg)) {
+        PyErr_SetString(PyExc_TypeError, "The function attribute must be callable.");
+		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;
+}
 
 static PyObject * VarPort_getServer(VarPort* self) { GET_SERVER };
 static PyObject * VarPort_getStream(VarPort* self) { GET_STREAM };
-static PyObject * VarPort_setMul(VarPort *self, PyObject *arg) { SET_MUL };	
-static PyObject * VarPort_setAdd(VarPort *self, PyObject *arg) { SET_ADD };	
-static PyObject * VarPort_setSub(VarPort *self, PyObject *arg) { SET_SUB };	
-static PyObject * VarPort_setDiv(VarPort *self, PyObject *arg) { SET_DIV };	
+static PyObject * VarPort_setMul(VarPort *self, PyObject *arg) { SET_MUL };
+static PyObject * VarPort_setAdd(VarPort *self, PyObject *arg) { SET_ADD };
+static PyObject * VarPort_setSub(VarPort *self, PyObject *arg) { SET_SUB };
+static PyObject * VarPort_setDiv(VarPort *self, PyObject *arg) { SET_DIV };
 
 static PyObject * VarPort_play(VarPort *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * VarPort_stop(VarPort *self) { STOP };
@@ -1026,6 +1050,7 @@ static PyMethodDef VarPort_methods[] = {
     {"stop", (PyCFunction)VarPort_stop, METH_NOARGS, "Stops computing."},
     {"setValue", (PyCFunction)VarPort_setValue, METH_O, "Sets VarPort value."},
     {"setTime", (PyCFunction)VarPort_setTime, METH_O, "Sets ramp time in seconds."},
+    {"setFunction", (PyCFunction)VarPort_setFunction, METH_O, "Sets function to be called."},
     {"setMul", (PyCFunction)VarPort_setMul, METH_O, "Sets VarPort mul factor."},
     {"setAdd", (PyCFunction)VarPort_setAdd, METH_O, "Sets VarPort add factor."},
     {"setSub", (PyCFunction)VarPort_setSub, METH_O, "Sets inverse add factor."},
@@ -1037,7 +1062,7 @@ static PyNumberMethods VarPort_as_number = {
     (binaryfunc)VarPort_add,                      /*nb_add*/
     (binaryfunc)VarPort_sub,                 /*nb_subtract*/
     (binaryfunc)VarPort_multiply,                 /*nb_multiply*/
-    (binaryfunc)VarPort_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -1051,16 +1076,16 @@ static PyNumberMethods VarPort_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)VarPort_inplace_add,              /*inplace_add*/
     (binaryfunc)VarPort_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)VarPort_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)VarPort_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -1069,15 +1094,14 @@ static PyNumberMethods VarPort_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)VarPort_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)VarPort_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject VarPortType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.VarPort_base",         /*tp_name*/
     sizeof(VarPort),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -1085,7 +1109,7 @@ PyTypeObject VarPortType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &VarPort_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -1116,4 +1140,3 @@ PyTypeObject VarPortType = {
     0,                         /* tp_alloc */
     VarPort_new,                 /* tp_new */
 };
-
diff --git a/src/objects/tablemodule.c b/src/objects/tablemodule.c
index 0be9ea5..0dd4769 100644
--- a/src/objects/tablemodule.c
+++ b/src/objects/tablemodule.c
@@ -1,24 +1,26 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include <object.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
@@ -27,6 +29,12 @@
 #include "dummymodule.h"
 #include "sndfile.h"
 #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"
@@ -38,7 +46,7 @@
 static void
 TableStream_dealloc(TableStream* self)
 {
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -53,13 +61,13 @@ MYFLT *
 TableStream_getData(TableStream *self)
 {
     return (MYFLT *)self->data;
-}    
+}
 
 void
 TableStream_setData(TableStream *self, MYFLT *data)
 {
     self->data = data;
-}    
+}
 
 int
 TableStream_getSize(TableStream *self)
@@ -71,7 +79,7 @@ void
 TableStream_setSize(TableStream *self, int size)
 {
     self->size = size;
-}    
+}
 
 double
 TableStream_getSamplingRate(TableStream *self)
@@ -83,11 +91,31 @@ void
 TableStream_setSamplingRate(TableStream *self, double sr)
 {
     self->samplingRate = sr;
-}    
+}
+
+#if PY_MAJOR_VERSION < 3
+static Py_ssize_t TableStream_getReadBuffer(TableStream *self, Py_ssize_t index, const void **ptr) { TABLESTREAM_READ_WRITE_BUFFER };
+static Py_ssize_t TableStream_getWriteBuffer(TableStream *self, Py_ssize_t index, const void **ptr) { TABLESTREAM_READ_WRITE_BUFFER };
+static Py_ssize_t TableStream_getSegCount(TableStream *self, Py_ssize_t *lenp) { TABLESTREAM_SEG_COUNT };
+#endif
+static int TableStream_getBuffer(PyObject *obj, Py_buffer *view, int flags) {
+    TableStream *self = (TableStream *)obj;
+    TABLESTREAM_GET_BUFFER
+};
+
+static PyBufferProcs TableStream_as_buffer = {
+#if PY_MAJOR_VERSION < 3
+    (readbufferproc)TableStream_getReadBuffer,
+    (writebufferproc)TableStream_getWriteBuffer,
+    (segcountproc)TableStream_getSegCount,
+    (charbufferproc)NULL,
+#endif
+    (getbufferproc)TableStream_getBuffer,
+    (releasebufferproc)NULL,
+};
 
 PyTypeObject TableStreamType = {
-PyObject_HEAD_INIT(NULL)
-0, /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.TableStream", /*tp_name*/
 sizeof(TableStream), /*tp_basicsize*/
 0, /*tp_itemsize*/
@@ -95,7 +123,7 @@ sizeof(TableStream), /*tp_basicsize*/
 0, /*tp_print*/
 0, /*tp_getattr*/
 0, /*tp_setattr*/
-0, /*tp_compare*/
+0, /*tp_as_async (tp_compare in Python 2)*/
 0, /*tp_repr*/
 0, /*tp_as_number*/
 0, /*tp_as_sequence*/
@@ -105,8 +133,8 @@ sizeof(TableStream), /*tp_basicsize*/
 0, /*tp_str*/
 0, /*tp_getattro*/
 0, /*tp_setattro*/
-0, /*tp_as_buffer*/
-Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
+&TableStream_as_buffer,                         /*tp_as_buffer*/
+Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_NEWBUFFER, /*tp_flags*/
 "TableStream objects. For internal use only. Must never be instantiated by the user.", /* tp_doc */
 0, /* tp_traverse */
 0, /* tp_clear */
@@ -139,15 +167,15 @@ static void
 HarmTable_generate(HarmTable *self) {
     int i, j, ampsize;
     MYFLT factor, amplitude, val;
-    
+
     ampsize = PyList_Size(self->amplist);
     MYFLT array[ampsize];
     for(j=0; j<ampsize; j++) {
-        array[j] =  PyFloat_AS_DOUBLE(PyNumber_Float(PyList_GET_ITEM(self->amplist, j)));
-    }    
-    
+        array[j] =  PyFloat_AsDouble(PyList_GET_ITEM(self->amplist, j));
+    }
+
     factor = 1. / (self->size * 0.5) * PI;
-    
+
     for(i=0; i<self->size; i++) {
         val = 0;
         for(j=0; j<ampsize; j++) {
@@ -160,7 +188,7 @@ HarmTable_generate(HarmTable *self) {
     }
 
     val = self->data[0];
-    self->data[self->size] = val;  
+    self->data[self->size] = val;
 }
 
 static int
@@ -171,7 +199,7 @@ HarmTable_traverse(HarmTable *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 HarmTable_clear(HarmTable *self)
 {
     pyo_table_CLEAR
@@ -184,7 +212,7 @@ HarmTable_dealloc(HarmTable* self)
 {
     free(self->data);
     HarmTable_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -193,9 +221,9 @@ HarmTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *amplist=NULL;
     HarmTable *self;
     self = (HarmTable *)type->tp_alloc(type, 0);
-    
+
     self->server = PyServer_get_server();
-    
+
     self->amplist = PyList_New(0);
     PyList_Append(self->amplist, PyFloat_FromDouble(1.));
     self->size = 8192;
@@ -203,10 +231,10 @@ HarmTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL);
 
     static char *kwlist[] = {"list", "size", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|Oi", kwlist, &amplist, &self->size))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     if (amplist) {
         Py_INCREF(amplist);
         Py_DECREF(self->amplist);
@@ -231,12 +259,24 @@ static PyObject * HarmTable_reset(HarmTable *self) { TABLE_RESET };
 static PyObject * HarmTable_normalize(HarmTable *self) { NORMALIZE };
 static PyObject * HarmTable_removeDC(HarmTable *self) { REMOVE_DC };
 static PyObject * HarmTable_reverse(HarmTable *self) { REVERSE };
+static PyObject * HarmTable_invert(HarmTable *self) { INVERT };
+static PyObject * HarmTable_rectify(HarmTable *self) { RECTIFY };
+static PyObject * HarmTable_bipolarGain(HarmTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN };
+static PyObject * HarmTable_lowpass(HarmTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS };
+static PyObject * HarmTable_fadein(HarmTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN };
+static PyObject * HarmTable_fadeout(HarmTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT };
+static PyObject * HarmTable_pow(HarmTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER };
 static PyObject * HarmTable_copy(HarmTable *self, PyObject *arg) { COPY };
+static PyObject * HarmTable_copyData(HarmTable *self, PyObject *args, PyObject *kwds) { TABLE_COPYDATA };
+static PyObject * HarmTable_rotate(HarmTable *self, PyObject *args, PyObject *kwds) { TABLE_ROTATE };
 static PyObject * HarmTable_setTable(HarmTable *self, PyObject *arg) { SET_TABLE };
 static PyObject * HarmTable_getTable(HarmTable *self) { GET_TABLE };
-static PyObject * HarmTable_getViewTable(HarmTable *self) { GET_VIEW_TABLE };
+static PyObject * HarmTable_getViewTable(HarmTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE };
 static PyObject * HarmTable_put(HarmTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT };
 static PyObject * HarmTable_get(HarmTable *self, PyObject *args, PyObject *kwds) { TABLE_GET };
+static PyObject * HarmTable_add(HarmTable *self, PyObject *arg) { TABLE_ADD };
+static PyObject * HarmTable_sub(HarmTable *self, PyObject *arg) { TABLE_SUB };
+static PyObject * HarmTable_mul(HarmTable *self, PyObject *arg) { TABLE_MUL };
 
 static PyObject *
 HarmTable_setSize(HarmTable *self, PyObject *value)
@@ -245,19 +285,19 @@ HarmTable_setSize(HarmTable *self, PyObject *value)
         PyErr_SetString(PyExc_TypeError, "Cannot delete the size attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyInt_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The size attribute value must be an integer.");
         return PyInt_FromLong(-1);
     }
-    
-    self->size = PyInt_AsLong(value); 
+
+    self->size = PyInt_AsLong(value);
 
     self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
     TableStream_setSize(self->tablestream, self->size);
-    
+
     HarmTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -275,18 +315,18 @@ HarmTable_replace(HarmTable *self, PyObject *value)
         PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyList_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The amplitude list attribute value must be a list.");
         return PyInt_FromLong(-1);
     }
-    
+
     Py_INCREF(value);
     Py_DECREF(self->amplist);
-    self->amplist = value; 
-    
+    self->amplist = value;
+
     HarmTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -302,25 +342,36 @@ static PyMethodDef HarmTable_methods[] = {
 {"getServer", (PyCFunction)HarmTable_getServer, METH_NOARGS, "Returns server object."},
 {"setTable", (PyCFunction)HarmTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."},
 {"getTable", (PyCFunction)HarmTable_getTable, METH_NOARGS, "Returns a list of table samples."},
-{"getViewTable", (PyCFunction)HarmTable_getViewTable, METH_NOARGS, "Returns a list of pixel coordinates for drawing the table."},
+{"getViewTable", (PyCFunction)HarmTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."},
 {"getTableStream", (PyCFunction)HarmTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."},
 {"normalize", (PyCFunction)HarmTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"},
 {"reset", (PyCFunction)HarmTable_reset, METH_NOARGS, "Resets table samples to 0.0"},
 {"removeDC", (PyCFunction)HarmTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."},
-{"reverse", (PyCFunction)HarmTable_reverse, METH_NOARGS, "Reverse the table's data."},
+{"reverse", (PyCFunction)HarmTable_reverse, METH_NOARGS, "Reverse the table's data in time."},
+{"invert", (PyCFunction)HarmTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."},
+{"rectify", (PyCFunction)HarmTable_rectify, METH_NOARGS, "Positive rectification of the table's data."},
+{"bipolarGain", (PyCFunction)HarmTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."},
+{"lowpass", (PyCFunction)HarmTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."},
+{"fadein", (PyCFunction)HarmTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."},
+{"fadeout", (PyCFunction)HarmTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."},
+{"pow", (PyCFunction)HarmTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."},
 {"copy", (PyCFunction)HarmTable_copy, METH_O, "Copy data from table given in argument."},
+{"copyData", (PyCFunction)HarmTable_copyData, METH_VARARGS|METH_KEYWORDS, "Copy data from table given in argument."},
+{"rotate", (PyCFunction)HarmTable_rotate, METH_VARARGS|METH_KEYWORDS, "Rotate table around position as argument."},
 {"setData", (PyCFunction)HarmTable_setData, METH_O, "Sets the table from samples in a text file."},
 {"setSize", (PyCFunction)HarmTable_setSize, METH_O, "Sets the size of the table in samples"},
 {"getSize", (PyCFunction)HarmTable_getSize, METH_NOARGS, "Return the size of the table in samples"},
 {"put", (PyCFunction)HarmTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."},
 {"get", (PyCFunction)HarmTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."},
 {"replace", (PyCFunction)HarmTable_replace, METH_O, "Sets the harmonics amplitude list and generates a new waveform table."},
+{"add", (PyCFunction)HarmTable_add, METH_O, "Performs table addition."},
+{"sub", (PyCFunction)HarmTable_sub, METH_O, "Performs table substraction."},
+{"mul", (PyCFunction)HarmTable_mul, METH_O, "Performs table multiplication."},
 {NULL}  /* Sentinel */
 };
 
 PyTypeObject HarmTableType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.HarmTable_base",         /*tp_name*/
 sizeof(HarmTable),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -328,7 +379,7 @@ sizeof(HarmTable),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 0,                         /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -372,18 +423,18 @@ static void
 ChebyTable_generate(ChebyTable *self) {
     int i, j, ampsize, halfsize;
     MYFLT amplitude, val, ihalfsize, index, x;
-    
+
     ampsize = PyList_Size(self->amplist);
     if (ampsize > 12)
         ampsize = 12;
     MYFLT array[ampsize];
     for(j=0; j<ampsize; j++) {
-        array[j] =  PyFloat_AS_DOUBLE(PyNumber_Float(PyList_GET_ITEM(self->amplist, j)));
-    }    
-    
+        array[j] =  PyFloat_AsDouble(PyList_GET_ITEM(self->amplist, j));
+    }
+
     halfsize = self->size / 2;
     ihalfsize = 1.0 / halfsize;
-    
+
     x = 0.0;
     for(i=0; i<self->size; i++) {
         val = 0;
@@ -432,9 +483,9 @@ ChebyTable_generate(ChebyTable *self) {
         }
         self->data[i] = val;
     }
-    
+
     val = self->data[self->size-1];
-    self->data[self->size] = val;  
+    self->data[self->size] = val;
 }
 
 static int
@@ -445,7 +496,7 @@ ChebyTable_traverse(ChebyTable *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 ChebyTable_clear(ChebyTable *self)
 {
     pyo_table_CLEAR
@@ -458,7 +509,7 @@ ChebyTable_dealloc(ChebyTable* self)
 {
     free(self->data);
     ChebyTable_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -467,26 +518,26 @@ ChebyTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *amplist=NULL;
     ChebyTable *self;
     self = (ChebyTable *)type->tp_alloc(type, 0);
-    
+
     self->server = PyServer_get_server();
-    
+
     self->amplist = PyList_New(0);
     PyList_Append(self->amplist, PyFloat_FromDouble(1.));
     self->size = 8192;
-    
+
     MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL);
 
     static char *kwlist[] = {"list", "size", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|Oi", kwlist, &amplist, &self->size))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     if (amplist) {
         Py_INCREF(amplist);
         Py_DECREF(self->amplist);
         self->amplist = amplist;
     }
-    
+
     self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
     TableStream_setSize(self->tablestream, self->size);
     TableStream_setData(self->tablestream, self->data);
@@ -494,7 +545,7 @@ ChebyTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
     double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL));
     TableStream_setSamplingRate(self->tablestream, sr);
-    
+
     return (PyObject *)self;
 }
 
@@ -505,12 +556,24 @@ static PyObject * ChebyTable_normalize(ChebyTable *self) { NORMALIZE };
 static PyObject * ChebyTable_reset(ChebyTable *self) { TABLE_RESET };
 static PyObject * ChebyTable_removeDC(ChebyTable *self) { REMOVE_DC };
 static PyObject * ChebyTable_reverse(ChebyTable *self) { REVERSE };
+static PyObject * ChebyTable_invert(ChebyTable *self) { INVERT };
+static PyObject * ChebyTable_rectify(ChebyTable *self) { RECTIFY };
+static PyObject * ChebyTable_bipolarGain(ChebyTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN };
+static PyObject * ChebyTable_lowpass(ChebyTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS };
+static PyObject * ChebyTable_fadein(ChebyTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN };
+static PyObject * ChebyTable_fadeout(ChebyTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT };
+static PyObject * ChebyTable_pow(ChebyTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER };
 static PyObject * ChebyTable_copy(ChebyTable *self, PyObject *arg) { COPY };
+static PyObject * ChebyTable_copyData(ChebyTable *self, PyObject *args, PyObject *kwds) { TABLE_COPYDATA };
+static PyObject * ChebyTable_rotate(ChebyTable *self, PyObject *args, PyObject *kwds) { TABLE_ROTATE };
 static PyObject * ChebyTable_setTable(ChebyTable *self, PyObject *arg) { SET_TABLE };
 static PyObject * ChebyTable_getTable(ChebyTable *self) { GET_TABLE };
-static PyObject * ChebyTable_getViewTable(ChebyTable *self) { GET_VIEW_TABLE };
+static PyObject * ChebyTable_getViewTable(ChebyTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE };
 static PyObject * ChebyTable_put(ChebyTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT };
 static PyObject * ChebyTable_get(ChebyTable *self, PyObject *args, PyObject *kwds) { TABLE_GET };
+static PyObject * ChebyTable_add(ChebyTable *self, PyObject *arg) { TABLE_ADD };
+static PyObject * ChebyTable_sub(ChebyTable *self, PyObject *arg) { TABLE_SUB };
+static PyObject * ChebyTable_mul(ChebyTable *self, PyObject *arg) { TABLE_MUL };
 
 static PyObject *
 ChebyTable_setSize(ChebyTable *self, PyObject *value)
@@ -519,19 +582,19 @@ ChebyTable_setSize(ChebyTable *self, PyObject *value)
         PyErr_SetString(PyExc_TypeError, "Cannot delete the size attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyInt_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The size attribute value must be an integer.");
         return PyInt_FromLong(-1);
     }
-    
-    self->size = PyInt_AsLong(value); 
-    
+
+    self->size = PyInt_AsLong(value);
+
     self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
     TableStream_setSize(self->tablestream, self->size);
-    
+
     ChebyTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -549,18 +612,18 @@ ChebyTable_replace(ChebyTable *self, PyObject *value)
         PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyList_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The amplitude list attribute value must be a list.");
         return PyInt_FromLong(-1);
     }
-    
+
     Py_INCREF(value);
     Py_DECREF(self->amplist);
-    self->amplist = value; 
-    
+    self->amplist = value;
+
     ChebyTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -576,7 +639,7 @@ ChebyTable_getNormTable(ChebyTable *self, PyObject *value)
     long sym = PyInt_AS_LONG(value);
     MYFLT samps[halfsize];
     PyObject *samples = PyList_New(halfsize);
-    
+
     if (sym == 0) {
         for (i=0; i<self->size; i++) {
             if (self->data[i] > maxval)
@@ -620,18 +683,18 @@ ChebyTable_getNormTable(ChebyTable *self, PyObject *value)
         if (val > maxval)
             maxval = val;
     }
-    
+
     for (i=0; i<halfsize; i++) {
         val = samps[i];
         if (val == -1.0)
             samps[i] = maxval;
     }
-    
+
     last = samps[0];
     for (i=1; i<halfsize; i++) {
         last = samps[i] = samps[i] + (last - samps[i]) * 0.95;
     }
-    
+
     for (i=0; i<halfsize; i++) {
         PyList_SET_ITEM(samples, i, PyFloat_FromDouble(samps[i]));
     }
@@ -648,27 +711,38 @@ static PyMemberDef ChebyTable_members[] = {
 static PyMethodDef ChebyTable_methods[] = {
 {"getServer", (PyCFunction)ChebyTable_getServer, METH_NOARGS, "Returns server object."},
 {"copy", (PyCFunction)ChebyTable_copy, METH_O, "Copy data from table given in argument."},
+{"copyData", (PyCFunction)ChebyTable_copyData, METH_VARARGS|METH_KEYWORDS, "Copy data from table given in argument."},
+{"rotate", (PyCFunction)ChebyTable_rotate, METH_VARARGS|METH_KEYWORDS, "Rotate table around position as argument."},
 {"setTable", (PyCFunction)ChebyTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."},
 {"getTable", (PyCFunction)ChebyTable_getTable, METH_NOARGS, "Returns a list of table samples."},
-{"getViewTable", (PyCFunction)ChebyTable_getViewTable, METH_NOARGS, "Returns a list of pixel coordinates for drawing the table."},
+{"getViewTable", (PyCFunction)ChebyTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."},
 {"getTableStream", (PyCFunction)ChebyTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."},
 {"setData", (PyCFunction)ChebyTable_setData, METH_O, "Sets the table from samples in a text file."},
 {"normalize", (PyCFunction)ChebyTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"},
 {"reset", (PyCFunction)ChebyTable_reset, METH_NOARGS, "Resets table samples to 0.0"},
 {"removeDC", (PyCFunction)ChebyTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."},
 {"reverse", (PyCFunction)ChebyTable_reverse, METH_NOARGS, "Reverse the table's data."},
+{"invert", (PyCFunction)ChebyTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."},
+{"rectify", (PyCFunction)ChebyTable_rectify, METH_NOARGS, "Positive rectification of the table's data."},
+{"bipolarGain", (PyCFunction)ChebyTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."},
+{"lowpass", (PyCFunction)ChebyTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."},
+{"fadein", (PyCFunction)ChebyTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."},
+{"fadeout", (PyCFunction)ChebyTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."},
+{"pow", (PyCFunction)ChebyTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."},
 {"setSize", (PyCFunction)ChebyTable_setSize, METH_O, "Sets the size of the table in samples"},
 {"getSize", (PyCFunction)ChebyTable_getSize, METH_NOARGS, "Return the size of the table in samples"},
 {"put", (PyCFunction)ChebyTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."},
 {"get", (PyCFunction)ChebyTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."},
 {"replace", (PyCFunction)ChebyTable_replace, METH_O, "Sets the harmonics amplitude list and generates a new waveform table."},
 {"getNormTable", (PyCFunction)ChebyTable_getNormTable, METH_O, "Computes and returns the normalization function for the current polynomial"},
+{"add", (PyCFunction)ChebyTable_add, METH_O, "Performs table addition."},
+{"sub", (PyCFunction)ChebyTable_sub, METH_O, "Performs table substraction."},
+{"mul", (PyCFunction)ChebyTable_mul, METH_O, "Performs table multiplication."},
 {NULL}  /* Sentinel */
 };
 
 PyTypeObject ChebyTableType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.ChebyTable_base",         /*tp_name*/
 sizeof(ChebyTable),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -676,7 +750,7 @@ sizeof(ChebyTable),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 0,                         /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -719,15 +793,15 @@ static void
 HannTable_generate(HannTable *self) {
     int i, halfSize;
     MYFLT val;
-    
+
     halfSize = self->size / 2 - 1;
-    
+
     for(i=0; i<self->size; i++) {
         val = 0.5 + (MYCOS(TWOPI * (i - halfSize) / self->size) * 0.5);
         self->data[i] = val;
     }
     val = self->data[0];
-    self->data[self->size] = val;  
+    self->data[self->size] = val;
 }
 
 static int
@@ -737,7 +811,7 @@ HannTable_traverse(HannTable *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 HannTable_clear(HannTable *self)
 {
     pyo_table_CLEAR
@@ -749,7 +823,7 @@ HannTable_dealloc(HannTable* self)
 {
     free(self->data);
     HannTable_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -757,18 +831,18 @@ HannTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     HannTable *self;
     self = (HannTable *)type->tp_alloc(type, 0);
-    
+
     self->server = PyServer_get_server();
-    
+
     self->size = 8192;
-    
+
     MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL);
- 
+
     static char *kwlist[] = {"size", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &self->size))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
     TableStream_setSize(self->tablestream, self->size);
 	TableStream_setData(self->tablestream, self->data);
@@ -776,7 +850,7 @@ HannTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
     double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL));
     TableStream_setSamplingRate(self->tablestream, sr);
-   
+
     return (PyObject *)self;
 }
 
@@ -787,12 +861,24 @@ static PyObject * HannTable_normalize(HannTable *self) { NORMALIZE };
 static PyObject * HannTable_reset(HannTable *self) { TABLE_RESET };
 static PyObject * HannTable_removeDC(HannTable *self) { REMOVE_DC };
 static PyObject * HannTable_reverse(HannTable *self) { REVERSE };
+static PyObject * HannTable_invert(HannTable *self) { INVERT };
+static PyObject * HannTable_rectify(HannTable *self) { RECTIFY };
+static PyObject * HannTable_bipolarGain(HannTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN };
+static PyObject * HannTable_lowpass(HannTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS };
+static PyObject * HannTable_fadein(HannTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN };
+static PyObject * HannTable_fadeout(HannTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT };
+static PyObject * HannTable_pow(HannTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER };
 static PyObject * HannTable_copy(HannTable *self, PyObject *arg) { COPY };
+static PyObject * HannTable_copyData(HannTable *self, PyObject *args, PyObject *kwds) { TABLE_COPYDATA };
+static PyObject * HannTable_rotate(HannTable *self, PyObject *args, PyObject *kwds) { TABLE_ROTATE };
 static PyObject * HannTable_setTable(HannTable *self, PyObject *arg) { SET_TABLE };
 static PyObject * HannTable_getTable(HannTable *self) { GET_TABLE };
-static PyObject * HannTable_getViewTable(HannTable *self) { GET_VIEW_TABLE };
+static PyObject * HannTable_getViewTable(HannTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE };
 static PyObject * HannTable_put(HannTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT };
 static PyObject * HannTable_get(HannTable *self, PyObject *args, PyObject *kwds) { TABLE_GET };
+static PyObject * HannTable_add(HannTable *self, PyObject *arg) { TABLE_ADD };
+static PyObject * HannTable_sub(HannTable *self, PyObject *arg) { TABLE_SUB };
+static PyObject * HannTable_mul(HannTable *self, PyObject *arg) { TABLE_MUL };
 
 static PyObject *
 HannTable_setSize(HannTable *self, PyObject *value)
@@ -801,19 +887,19 @@ HannTable_setSize(HannTable *self, PyObject *value)
         PyErr_SetString(PyExc_TypeError, "Cannot delete the size attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyInt_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The size attribute value must be an integer.");
         return PyInt_FromLong(-1);
     }
-    
-    self->size = PyInt_AsLong(value); 
-    
+
+    self->size = PyInt_AsLong(value);
+
     self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
     TableStream_setSize(self->tablestream, self->size);
-    
+
     HannTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -833,25 +919,36 @@ static PyMemberDef HannTable_members[] = {
 static PyMethodDef HannTable_methods[] = {
 {"getServer", (PyCFunction)HannTable_getServer, METH_NOARGS, "Returns server object."},
 {"copy", (PyCFunction)HannTable_copy, METH_O, "Copy data from table given in argument."},
+{"copyData", (PyCFunction)HannTable_copyData, METH_VARARGS|METH_KEYWORDS, "Copy data from table given in argument."},
+{"rotate", (PyCFunction)HannTable_rotate, METH_VARARGS|METH_KEYWORDS, "Rotate table around position as argument."},
 {"setTable", (PyCFunction)HannTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."},
 {"getTable", (PyCFunction)HannTable_getTable, METH_NOARGS, "Returns a list of table samples."},
-{"getViewTable", (PyCFunction)HannTable_getViewTable, METH_NOARGS, "Returns a list of pixel coordinates for drawing the table."},
+{"getViewTable", (PyCFunction)HannTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."},
 {"getTableStream", (PyCFunction)HannTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."},
 {"setData", (PyCFunction)HannTable_setData, METH_O, "Sets the table from samples in a text file."},
 {"normalize", (PyCFunction)HannTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"},
 {"reset", (PyCFunction)HannTable_reset, METH_NOARGS, "Resets table samples to 0.0"},
 {"removeDC", (PyCFunction)HannTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."},
 {"reverse", (PyCFunction)HannTable_reverse, METH_NOARGS, "Reverse the table's data."},
+{"invert", (PyCFunction)HannTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."},
+{"rectify", (PyCFunction)HannTable_rectify, METH_NOARGS, "Positive rectification of the table's data."},
+{"bipolarGain", (PyCFunction)HannTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."},
+{"lowpass", (PyCFunction)HannTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."},
+{"fadein", (PyCFunction)HannTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."},
+{"fadeout", (PyCFunction)HannTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."},
+{"pow", (PyCFunction)HannTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."},
 {"setSize", (PyCFunction)HannTable_setSize, METH_O, "Sets the size of the table in samples"},
 {"getSize", (PyCFunction)HannTable_getSize, METH_NOARGS, "Return the size of the table in samples"},
 {"put", (PyCFunction)HannTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."},
 {"get", (PyCFunction)HannTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."},
+{"add", (PyCFunction)HannTable_add, METH_O, "Performs table addition."},
+{"sub", (PyCFunction)HannTable_sub, METH_O, "Performs table substraction."},
+{"mul", (PyCFunction)HannTable_mul, METH_O, "Performs table multiplication."},
 {NULL}  /* Sentinel */
 };
 
 PyTypeObject HannTableType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.HannTable_base",         /*tp_name*/
 sizeof(HannTable),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -859,7 +956,7 @@ sizeof(HannTable),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 0,                         /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -904,11 +1001,11 @@ static void
 SincTable_generate(SincTable *self) {
     int i, half, halfMinusOne;
     MYFLT scl, val;
-    
+
     half = self->size / 2;
-    
+
     if (self->windowed) {
-        halfMinusOne = half - 1;    
+        halfMinusOne = half - 1;
         for(i=0; i<self->size; i++) {
             scl = (MYFLT)(i - half) / half * self->freq;
             if (scl == 0.0)
@@ -927,9 +1024,9 @@ SincTable_generate(SincTable *self) {
             else
                 val = (MYSIN(scl) / scl);
             self->data[i] = val;
-        }        
+        }
     }
-    self->data[self->size] = self->data[0];  
+    self->data[self->size] = self->data[0];
 }
 
 static int
@@ -939,7 +1036,7 @@ SincTable_traverse(SincTable *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 SincTable_clear(SincTable *self)
 {
     pyo_table_CLEAR
@@ -951,7 +1048,7 @@ SincTable_dealloc(SincTable* self)
 {
     free(self->data);
     SincTable_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -959,28 +1056,28 @@ SincTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     SincTable *self;
     self = (SincTable *)type->tp_alloc(type, 0);
-    
+
     self->server = PyServer_get_server();
-    
+
     self->size = 8192;
     self->freq = TWOPI;
     self->windowed = 0;
-    
+
     MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL);
 
     static char *kwlist[] = {"freq", "windowed", "size", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__FII, kwlist, &self->freq, &self->windowed, &self->size))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
     TableStream_setSize(self->tablestream, self->size);
 	TableStream_setData(self->tablestream, self->data);
     SincTable_generate(self);
-    
+
     double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL));
     TableStream_setSamplingRate(self->tablestream, sr);
-    
+
     return (PyObject *)self;
 }
 
@@ -991,26 +1088,38 @@ static PyObject * SincTable_normalize(SincTable *self) { NORMALIZE };
 static PyObject * SincTable_reset(SincTable *self) { TABLE_RESET };
 static PyObject * SincTable_removeDC(SincTable *self) { REMOVE_DC };
 static PyObject * SincTable_reverse(SincTable *self) { REVERSE };
+static PyObject * SincTable_invert(SincTable *self) { INVERT };
+static PyObject * SincTable_rectify(SincTable *self) { RECTIFY };
+static PyObject * SincTable_bipolarGain(SincTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN };
+static PyObject * SincTable_lowpass(SincTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS };
+static PyObject * SincTable_fadein(SincTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN };
+static PyObject * SincTable_fadeout(SincTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT };
+static PyObject * SincTable_pow(SincTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER };
 static PyObject * SincTable_copy(SincTable *self, PyObject *arg) { COPY };
+static PyObject * SincTable_copyData(SincTable *self, PyObject *args, PyObject *kwds) { TABLE_COPYDATA };
+static PyObject * SincTable_rotate(SincTable *self, PyObject *args, PyObject *kwds) { TABLE_ROTATE };
 static PyObject * SincTable_setTable(SincTable *self, PyObject *arg) { SET_TABLE };
 static PyObject * SincTable_getTable(SincTable *self) { GET_TABLE };
-static PyObject * SincTable_getViewTable(SincTable *self) { GET_VIEW_TABLE };
+static PyObject * SincTable_getViewTable(SincTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE };
 static PyObject * SincTable_put(SincTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT };
 static PyObject * SincTable_get(SincTable *self, PyObject *args, PyObject *kwds) { TABLE_GET };
+static PyObject * SincTable_add(SincTable *self, PyObject *arg) { TABLE_ADD };
+static PyObject * SincTable_sub(SincTable *self, PyObject *arg) { TABLE_SUB };
+static PyObject * SincTable_mul(SincTable *self, PyObject *arg) { TABLE_MUL };
 
 static PyObject *
 SincTable_setFreq(SincTable *self, PyObject *value)
 {
-    
+
     if (! PyNumber_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The freq attribute value must be a number.");
         return PyInt_FromLong(-1);
     }
-    
-    self->freq = PyFloat_AsDouble(PyNumber_Float(value)); 
-    
+
+    self->freq = PyFloat_AsDouble(value);
+
     SincTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1018,16 +1127,16 @@ SincTable_setFreq(SincTable *self, PyObject *value)
 static PyObject *
 SincTable_setWindowed(SincTable *self, PyObject *value)
 {
-    
+
     if (! PyInt_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The windowed attribute value must be a boolean.");
         return PyInt_FromLong(-1);
     }
-    
-    self->windowed = PyInt_AsLong(value); 
-    
+
+    self->windowed = PyInt_AsLong(value);
+
     SincTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1039,19 +1148,19 @@ SincTable_setSize(SincTable *self, PyObject *value)
         PyErr_SetString(PyExc_TypeError, "Cannot delete the size attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyInt_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The size attribute value must be an integer.");
         return PyInt_FromLong(-1);
     }
-    
-    self->size = PyInt_AsLong(value); 
-    
+
+    self->size = PyInt_AsLong(value);
+
     self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
     TableStream_setSize(self->tablestream, self->size);
-    
+
     SincTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1071,27 +1180,38 @@ static PyMemberDef SincTable_members[] = {
 static PyMethodDef SincTable_methods[] = {
     {"getServer", (PyCFunction)SincTable_getServer, METH_NOARGS, "Returns server object."},
     {"copy", (PyCFunction)SincTable_copy, METH_O, "Copy data from table given in argument."},
+    {"copyData", (PyCFunction)SincTable_copyData, METH_VARARGS|METH_KEYWORDS, "Copy data from table given in argument."},
+    {"rotate", (PyCFunction)SincTable_rotate, METH_VARARGS|METH_KEYWORDS, "Rotate table around position as argument."},
     {"setTable", (PyCFunction)SincTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."},
     {"getTable", (PyCFunction)SincTable_getTable, METH_NOARGS, "Returns a list of table samples."},
-    {"getViewTable", (PyCFunction)SincTable_getViewTable, METH_NOARGS, "Returns a list of pixel coordinates for drawing the table."},
+    {"getViewTable", (PyCFunction)SincTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."},
     {"getTableStream", (PyCFunction)SincTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."},
     {"setData", (PyCFunction)SincTable_setData, METH_O, "Sets the table from samples in a text file."},
     {"normalize", (PyCFunction)SincTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"},
     {"reset", (PyCFunction)SincTable_reset, METH_NOARGS, "Resets table samples to 0.0"},
     {"removeDC", (PyCFunction)SincTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."},
     {"reverse", (PyCFunction)SincTable_reverse, METH_NOARGS, "Reverse the table's data."},
+    {"invert", (PyCFunction)SincTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."},
+    {"rectify", (PyCFunction)SincTable_rectify, METH_NOARGS, "Positive rectification of the table's data."},
+    {"bipolarGain", (PyCFunction)SincTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."},
+    {"lowpass", (PyCFunction)SincTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."},
+    {"fadein", (PyCFunction)SincTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."},
+    {"fadeout", (PyCFunction)SincTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."},
+    {"pow", (PyCFunction)SincTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."},
     {"setSize", (PyCFunction)SincTable_setSize, METH_O, "Sets the size of the table in samples"},
     {"getSize", (PyCFunction)SincTable_getSize, METH_NOARGS, "Return the size of the table in samples"},
     {"setFreq", (PyCFunction)SincTable_setFreq, METH_O, "Sets the frequency, in radians, of the sinc function."},
     {"setWindowed", (PyCFunction)SincTable_setWindowed, METH_O, "If True, an hanning window is applied on the function."},
     {"put", (PyCFunction)SincTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."},
     {"get", (PyCFunction)SincTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."},
+    {"add", (PyCFunction)SincTable_add, METH_O, "Performs table addition."},
+    {"sub", (PyCFunction)SincTable_sub, METH_O, "Performs table substraction."},
+    {"mul", (PyCFunction)SincTable_mul, METH_O, "Performs table multiplication."},
     {NULL}  /* Sentinel */
 };
 
 PyTypeObject SincTableType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.SincTable_base",         /*tp_name*/
     sizeof(SincTable),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -1099,7 +1219,7 @@ PyTypeObject SincTableType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     0,                         /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -1152,7 +1272,7 @@ WinTable_traverse(WinTable *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 WinTable_clear(WinTable *self)
 {
     pyo_table_CLEAR
@@ -1164,7 +1284,7 @@ WinTable_dealloc(WinTable* self)
 {
     free(self->data);
     WinTable_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1172,19 +1292,19 @@ WinTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     WinTable *self;
     self = (WinTable *)type->tp_alloc(type, 0);
-    
+
     self->server = PyServer_get_server();
-    
+
     self->size = 8192;
     self->type = 2;
-    
+
     MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL);
 
     static char *kwlist[] = {"type", "size", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|ii", kwlist, &self->type, &self->size))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
     TableStream_setSize(self->tablestream, self->size);
 	TableStream_setData(self->tablestream, self->data);
@@ -1192,7 +1312,7 @@ WinTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
     double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL));
     TableStream_setSamplingRate(self->tablestream, sr);
-    
+
     return (PyObject *)self;
 }
 
@@ -1203,12 +1323,24 @@ static PyObject * WinTable_normalize(WinTable *self) { NORMALIZE };
 static PyObject * WinTable_reset(WinTable *self) { TABLE_RESET };
 static PyObject * WinTable_removeDC(WinTable *self) { REMOVE_DC };
 static PyObject * WinTable_reverse(WinTable *self) { REVERSE };
+static PyObject * WinTable_invert(WinTable *self) { INVERT };
+static PyObject * WinTable_rectify(WinTable *self) { RECTIFY };
+static PyObject * WinTable_bipolarGain(WinTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN };
+static PyObject * WinTable_lowpass(WinTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS };
+static PyObject * WinTable_fadein(WinTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN };
+static PyObject * WinTable_fadeout(WinTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT };
+static PyObject * WinTable_pow(WinTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER };
 static PyObject * WinTable_copy(WinTable *self, PyObject *arg) { COPY };
+static PyObject * WinTable_copyData(WinTable *self, PyObject *args, PyObject *kwds) { TABLE_COPYDATA };
+static PyObject * WinTable_rotate(WinTable *self, PyObject *args, PyObject *kwds) { TABLE_ROTATE };
 static PyObject * WinTable_setTable(WinTable *self, PyObject *arg) { SET_TABLE };
 static PyObject * WinTable_getTable(WinTable *self) { GET_TABLE };
-static PyObject * WinTable_getViewTable(WinTable *self) { GET_VIEW_TABLE };
+static PyObject * WinTable_getViewTable(WinTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE };
 static PyObject * WinTable_put(WinTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT };
 static PyObject * WinTable_get(WinTable *self, PyObject *args, PyObject *kwds) { TABLE_GET };
+static PyObject * WinTable_add(WinTable *self, PyObject *arg) { TABLE_ADD };
+static PyObject * WinTable_sub(WinTable *self, PyObject *arg) { TABLE_SUB };
+static PyObject * WinTable_mul(WinTable *self, PyObject *arg) { TABLE_MUL };
 
 static PyObject *
 WinTable_setSize(WinTable *self, PyObject *value)
@@ -1217,19 +1349,19 @@ WinTable_setSize(WinTable *self, PyObject *value)
         PyErr_SetString(PyExc_TypeError, "Cannot delete the size attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyInt_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The size attribute value must be an integer.");
         return PyInt_FromLong(-1);
     }
-    
-    self->size = PyInt_AsLong(value); 
-    
+
+    self->size = PyInt_AsLong(value);
+
     self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
     TableStream_setSize(self->tablestream, self->size);
-    
+
     WinTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1247,16 +1379,16 @@ WinTable_setType(WinTable *self, PyObject *value)
         PyErr_SetString(PyExc_TypeError, "Cannot delete the type attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyInt_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The type attribute value must be an integer.");
         return PyInt_FromLong(-1);
     }
-    
+
     self->type = PyInt_AsLong(value);
-    
+
     WinTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1270,26 +1402,37 @@ static PyMemberDef WinTable_members[] = {
 static PyMethodDef WinTable_methods[] = {
 {"getServer", (PyCFunction)WinTable_getServer, METH_NOARGS, "Returns server object."},
 {"copy", (PyCFunction)WinTable_copy, METH_O, "Copy data from table given in argument."},
+{"copyData", (PyCFunction)WinTable_copyData, METH_VARARGS|METH_KEYWORDS, "Copy data from table given in argument."},
+{"rotate", (PyCFunction)WinTable_rotate, METH_VARARGS|METH_KEYWORDS, "Rotate table around position as argument."},
 {"setTable", (PyCFunction)WinTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."},
 {"getTable", (PyCFunction)WinTable_getTable, METH_NOARGS, "Returns a list of table samples."},
-{"getViewTable", (PyCFunction)WinTable_getViewTable, METH_NOARGS, "Returns a list of pixel coordinates for drawing the table."},
+{"getViewTable", (PyCFunction)WinTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."},
 {"getTableStream", (PyCFunction)WinTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."},
 {"setData", (PyCFunction)WinTable_setData, METH_O, "Sets the table from samples in a text file."},
 {"normalize", (PyCFunction)WinTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"},
 {"reset", (PyCFunction)WinTable_reset, METH_NOARGS, "Resets table samples to 0.0"},
 {"removeDC", (PyCFunction)WinTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."},
 {"reverse", (PyCFunction)WinTable_reverse, METH_NOARGS, "Reverse the table's data."},
+{"invert", (PyCFunction)WinTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."},
+{"rectify", (PyCFunction)WinTable_rectify, METH_NOARGS, "Positive rectification of the table's data."},
+{"bipolarGain", (PyCFunction)WinTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."},
+{"lowpass", (PyCFunction)WinTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."},
+{"fadein", (PyCFunction)WinTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."},
+{"fadeout", (PyCFunction)WinTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."},
+{"pow", (PyCFunction)WinTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."},
 {"setSize", (PyCFunction)WinTable_setSize, METH_O, "Sets the size of the table in samples"},
 {"getSize", (PyCFunction)WinTable_getSize, METH_NOARGS, "Return the size of the table in samples"},
 {"setType", (PyCFunction)WinTable_setType, METH_O, "Sets the type of the table."},
 {"put", (PyCFunction)WinTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."},
 {"get", (PyCFunction)WinTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."},
+{"add", (PyCFunction)WinTable_add, METH_O, "Performs table addition."},
+{"sub", (PyCFunction)WinTable_sub, METH_O, "Performs table substraction."},
+{"mul", (PyCFunction)WinTable_mul, METH_O, "Performs table multiplication."},
 {NULL}  /* Sentinel */
 };
 
 PyTypeObject WinTableType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.WinTable_base",         /*tp_name*/
 sizeof(WinTable),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -1297,7 +1440,7 @@ sizeof(WinTable),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 0,                         /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -1340,7 +1483,7 @@ static void
 ParaTable_generate(ParaTable *self) {
     int i, sizeMinusOne;
     MYFLT rdur, rdur2, level, slope, curve;
-    
+
     sizeMinusOne = self->size - 1;
     rdur = 1.0 / sizeMinusOne;
     rdur2 = rdur * rdur;
@@ -1354,8 +1497,8 @@ ParaTable_generate(ParaTable *self) {
         slope += curve;
     }
 
-    self->data[sizeMinusOne] = self->data[0];  
-    self->data[self->size] = self->data[0];  
+    self->data[sizeMinusOne] = self->data[0];
+    self->data[self->size] = self->data[0];
 }
 
 static int
@@ -1365,7 +1508,7 @@ ParaTable_traverse(ParaTable *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 ParaTable_clear(ParaTable *self)
 {
     pyo_table_CLEAR
@@ -1377,7 +1520,7 @@ ParaTable_dealloc(ParaTable* self)
 {
     free(self->data);
     ParaTable_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1385,18 +1528,18 @@ ParaTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     ParaTable *self;
     self = (ParaTable *)type->tp_alloc(type, 0);
-    
+
     self->server = PyServer_get_server();
-    
+
     self->size = 8192;
-    
+
     MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL);
- 
+
     static char *kwlist[] = {"size", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwlist, &self->size))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
     TableStream_setSize(self->tablestream, self->size);
 	TableStream_setData(self->tablestream, self->data);
@@ -1404,7 +1547,7 @@ ParaTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
     double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL));
     TableStream_setSamplingRate(self->tablestream, sr);
-   
+
     return (PyObject *)self;
 }
 
@@ -1415,12 +1558,24 @@ static PyObject * ParaTable_normalize(ParaTable *self) { NORMALIZE };
 static PyObject * ParaTable_reset(ParaTable *self) { TABLE_RESET };
 static PyObject * ParaTable_removeDC(ParaTable *self) { REMOVE_DC };
 static PyObject * ParaTable_reverse(ParaTable *self) { REVERSE };
+static PyObject * ParaTable_invert(ParaTable *self) { INVERT };
+static PyObject * ParaTable_rectify(ParaTable *self) { RECTIFY };
+static PyObject * ParaTable_bipolarGain(ParaTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN };
+static PyObject * ParaTable_lowpass(ParaTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS };
+static PyObject * ParaTable_fadein(ParaTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN };
+static PyObject * ParaTable_fadeout(ParaTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT };
+static PyObject * ParaTable_pow(ParaTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER };
 static PyObject * ParaTable_copy(ParaTable *self, PyObject *arg) { COPY };
+static PyObject * ParaTable_copyData(ParaTable *self, PyObject *args, PyObject *kwds) { TABLE_COPYDATA };
+static PyObject * ParaTable_rotate(ParaTable *self, PyObject *args, PyObject *kwds) { TABLE_ROTATE };
 static PyObject * ParaTable_setTable(ParaTable *self, PyObject *arg) { SET_TABLE };
 static PyObject * ParaTable_getTable(ParaTable *self) { GET_TABLE };
-static PyObject * ParaTable_getViewTable(ParaTable *self) { GET_VIEW_TABLE };
+static PyObject * ParaTable_getViewTable(ParaTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE };
 static PyObject * ParaTable_put(ParaTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT };
 static PyObject * ParaTable_get(ParaTable *self, PyObject *args, PyObject *kwds) { TABLE_GET };
+static PyObject * ParaTable_add(ParaTable *self, PyObject *arg) { TABLE_ADD };
+static PyObject * ParaTable_sub(ParaTable *self, PyObject *arg) { TABLE_SUB };
+static PyObject * ParaTable_mul(ParaTable *self, PyObject *arg) { TABLE_MUL };
 
 static PyObject *
 ParaTable_setSize(ParaTable *self, PyObject *value)
@@ -1429,19 +1584,19 @@ ParaTable_setSize(ParaTable *self, PyObject *value)
         PyErr_SetString(PyExc_TypeError, "Cannot delete the size attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyInt_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The size attribute value must be an integer.");
         return PyInt_FromLong(-1);
     }
-    
-    self->size = PyInt_AsLong(value); 
-    
+
+    self->size = PyInt_AsLong(value);
+
     self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
     TableStream_setSize(self->tablestream, self->size);
-    
+
     ParaTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1461,25 +1616,36 @@ static PyMemberDef ParaTable_members[] = {
 static PyMethodDef ParaTable_methods[] = {
     {"getServer", (PyCFunction)ParaTable_getServer, METH_NOARGS, "Returns server object."},
     {"copy", (PyCFunction)ParaTable_copy, METH_O, "Copy data from table given in argument."},
+    {"copyData", (PyCFunction)ParaTable_copyData, METH_VARARGS|METH_KEYWORDS, "Copy data from table given in argument."},
+    {"rotate", (PyCFunction)ParaTable_rotate, METH_VARARGS|METH_KEYWORDS, "Rotate table around position as argument."},
     {"setTable", (PyCFunction)ParaTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."},
     {"getTable", (PyCFunction)ParaTable_getTable, METH_NOARGS, "Returns a list of table samples."},
-    {"getViewTable", (PyCFunction)ParaTable_getViewTable, METH_NOARGS, "Returns a list of pixel coordinates for drawing the table."},
+    {"getViewTable", (PyCFunction)ParaTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."},
     {"getTableStream", (PyCFunction)ParaTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."},
     {"setData", (PyCFunction)ParaTable_setData, METH_O, "Sets the table from samples in a text file."},
     {"normalize", (PyCFunction)ParaTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"},
     {"reset", (PyCFunction)ParaTable_reset, METH_NOARGS, "Resets table samples to 0.0"},
     {"removeDC", (PyCFunction)ParaTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."},
     {"reverse", (PyCFunction)ParaTable_reverse, METH_NOARGS, "Reverse the table's data."},
+    {"invert", (PyCFunction)ParaTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."},
+    {"rectify", (PyCFunction)ParaTable_rectify, METH_NOARGS, "Positive rectification of the table's data."},
+    {"bipolarGain", (PyCFunction)ParaTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."},
+    {"lowpass", (PyCFunction)ParaTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."},
+    {"fadein", (PyCFunction)ParaTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."},
+    {"fadeout", (PyCFunction)ParaTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."},
+    {"pow", (PyCFunction)ParaTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."},
     {"setSize", (PyCFunction)ParaTable_setSize, METH_O, "Sets the size of the table in samples"},
     {"getSize", (PyCFunction)ParaTable_getSize, METH_NOARGS, "Return the size of the table in samples"},
     {"put", (PyCFunction)ParaTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."},
     {"get", (PyCFunction)ParaTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."},
+    {"add", (PyCFunction)ParaTable_add, METH_O, "Performs table addition."},
+    {"sub", (PyCFunction)ParaTable_sub, METH_O, "Performs table substraction."},
+    {"mul", (PyCFunction)ParaTable_mul, METH_O, "Performs table multiplication."},
     {NULL}  /* Sentinel */
 };
 
 PyTypeObject ParaTableType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.ParaTable_base",         /*tp_name*/
     sizeof(ParaTable),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -1487,7 +1653,7 @@ PyTypeObject ParaTableType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     0,                         /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -1534,19 +1700,19 @@ LinTable_generate(LinTable *self) {
     PyObject *tup, *tup2;
     int x1, y1;
     MYFLT x2, y2, diff;
-    
+
     y1 = 0;
     y2 = 0.0;
 
     listsize = PyList_Size(self->pointslist);
-    
+
     for(i=0; i<(listsize-1); i++) {
         tup = PyList_GET_ITEM(self->pointslist, i);
         x1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup, 0)));
-        x2 = PyFloat_AsDouble(PyNumber_Float(PyTuple_GET_ITEM(tup, 1)));
+        x2 = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 1));
         tup2 = PyList_GET_ITEM(self->pointslist, i+1);
         y1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup2, 0)));
-        y2 = PyFloat_AsDouble(PyNumber_Float(PyTuple_GET_ITEM(tup2, 1)));
+        y2 = PyFloat_AsDouble(PyTuple_GET_ITEM(tup2, 1));
         steps = y1 - x1;
         if (steps <= 0)
             continue;
@@ -1565,7 +1731,7 @@ LinTable_generate(LinTable *self) {
     else {
         self->data[self->size-1] = y2;
         self->data[self->size] = y2;
-    }    
+    }
 }
 
 static int
@@ -1576,7 +1742,7 @@ LinTable_traverse(LinTable *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 LinTable_clear(LinTable *self)
 {
     pyo_table_CLEAR
@@ -1589,7 +1755,7 @@ LinTable_dealloc(LinTable* self)
 {
     free(self->data);
     LinTable_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1598,19 +1764,19 @@ LinTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *pointslist=NULL;
     LinTable *self;
     self = (LinTable *)type->tp_alloc(type, 0);
-    
+
     self->server = PyServer_get_server();
-    
+
     self->pointslist = PyList_New(0);
     self->size = 8192;
-    
+
     MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL);
 
     static char *kwlist[] = {"list", "size", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|Oi", kwlist, &pointslist, &self->size))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     if (pointslist) {
         Py_INCREF(pointslist);
         Py_DECREF(self->pointslist);
@@ -1620,7 +1786,7 @@ LinTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         PyList_Append(self->pointslist, PyTuple_Pack(2, PyInt_FromLong(0), PyFloat_FromDouble(0.)));
         PyList_Append(self->pointslist, PyTuple_Pack(2, PyInt_FromLong(self->size), PyFloat_FromDouble(1.)));
     }
-    
+
     self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
     TableStream_setSize(self->tablestream, self->size);
     TableStream_setData(self->tablestream, self->data);
@@ -1628,7 +1794,7 @@ LinTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
     double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL));
     TableStream_setSamplingRate(self->tablestream, sr);
-    
+
     return (PyObject *)self;
 }
 
@@ -1639,12 +1805,24 @@ static PyObject * LinTable_normalize(LinTable *self) { NORMALIZE };
 static PyObject * LinTable_reset(LinTable *self) { TABLE_RESET };
 static PyObject * LinTable_removeDC(LinTable *self) { REMOVE_DC };
 static PyObject * LinTable_reverse(LinTable *self) { REVERSE };
+static PyObject * LinTable_invert(LinTable *self) { INVERT };
+static PyObject * LinTable_rectify(LinTable *self) { RECTIFY };
+static PyObject * LinTable_bipolarGain(LinTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN };
+static PyObject * LinTable_lowpass(LinTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS };
+static PyObject * LinTable_fadein(LinTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN };
+static PyObject * LinTable_fadeout(LinTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT };
+static PyObject * LinTable_pow(LinTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER };
 static PyObject * LinTable_copy(LinTable *self, PyObject *arg) { COPY };
+static PyObject * LinTable_copyData(LinTable *self, PyObject *args, PyObject *kwds) { TABLE_COPYDATA };
+static PyObject * LinTable_rotate(LinTable *self, PyObject *args, PyObject *kwds) { TABLE_ROTATE };
 static PyObject * LinTable_setTable(LinTable *self, PyObject *arg) { SET_TABLE };
 static PyObject * LinTable_getTable(LinTable *self) { GET_TABLE };
-static PyObject * LinTable_getViewTable(LinTable *self) { GET_VIEW_TABLE };
+static PyObject * LinTable_getViewTable(LinTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE };
 static PyObject * LinTable_put(LinTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT };
 static PyObject * LinTable_get(LinTable *self, PyObject *args, PyObject *kwds) { TABLE_GET };
+static PyObject * LinTable_add(LinTable *self, PyObject *arg) { TABLE_ADD };
+static PyObject * LinTable_sub(LinTable *self, PyObject *arg) { TABLE_SUB };
+static PyObject * LinTable_mul(LinTable *self, PyObject *arg) { TABLE_MUL };
 
 static PyObject *
 LinTable_setSize(LinTable *self, PyObject *value)
@@ -1658,37 +1836,37 @@ LinTable_setSize(LinTable *self, PyObject *value)
         PyErr_SetString(PyExc_TypeError, "Cannot delete the size attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyInt_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The size attribute value must be an integer.");
         return PyInt_FromLong(-1);
     }
 
     old_size = self->size;
-    self->size = PyInt_AsLong(value); 
-    
+    self->size = PyInt_AsLong(value);
+
     factor = (MYFLT)(self->size) / old_size;
-    
+
     self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
     TableStream_setSize(self->tablestream, self->size);
 
     Py_ssize_t listsize = PyList_Size(self->pointslist);
 
     PyObject *listtemp = PyList_New(0);
-    
+
     for(i=0; i<(listsize); i++) {
         tup = PyList_GET_ITEM(self->pointslist, i);
         x1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup, 0)));
         x2 = PyNumber_Float(PyTuple_GET_ITEM(tup, 1));
         PyList_Append(listtemp, PyTuple_Pack(2, PyInt_FromLong((int)(x1*factor)), x2));
     }
-    
+
     Py_INCREF(listtemp);
     Py_DECREF(self->pointslist);
     self->pointslist = listtemp;
-    
+
     LinTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1713,18 +1891,18 @@ LinTable_replace(LinTable *self, PyObject *value)
         PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyList_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The amplitude list attribute value must be a list of tuples.");
         return PyInt_FromLong(-1);
     }
-    
+
     Py_INCREF(value);
     Py_DECREF(self->pointslist);
-    self->pointslist = value; 
-    
+    self->pointslist = value;
+
     LinTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1739,27 +1917,38 @@ static PyMemberDef LinTable_members[] = {
 static PyMethodDef LinTable_methods[] = {
 {"getServer", (PyCFunction)LinTable_getServer, METH_NOARGS, "Returns server object."},
 {"copy", (PyCFunction)LinTable_copy, METH_O, "Copy data from table given in argument."},
+{"copyData", (PyCFunction)LinTable_copyData, METH_VARARGS|METH_KEYWORDS, "Copy data from table given in argument."},
+{"rotate", (PyCFunction)LinTable_rotate, METH_VARARGS|METH_KEYWORDS, "Rotate table around position as argument."},
 {"setTable", (PyCFunction)LinTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."},
 {"getTable", (PyCFunction)LinTable_getTable, METH_NOARGS, "Returns a list of table samples."},
-{"getViewTable", (PyCFunction)LinTable_getViewTable, METH_NOARGS, "Returns a list of pixel coordinates for drawing the table."},
+{"getViewTable", (PyCFunction)LinTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."},
 {"getTableStream", (PyCFunction)LinTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."},
 {"setData", (PyCFunction)LinTable_setData, METH_O, "Sets the table from samples in a text file."},
 {"normalize", (PyCFunction)LinTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"},
 {"reset", (PyCFunction)LinTable_reset, METH_NOARGS, "Resets table samples to 0.0"},
 {"removeDC", (PyCFunction)LinTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."},
 {"reverse", (PyCFunction)LinTable_reverse, METH_NOARGS, "Reverse the table's data."},
+{"invert", (PyCFunction)LinTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."},
+{"rectify", (PyCFunction)LinTable_rectify, METH_NOARGS, "Positive rectification of the table's data."},
+{"bipolarGain", (PyCFunction)LinTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."},
+{"lowpass", (PyCFunction)LinTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."},
+{"fadein", (PyCFunction)LinTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."},
+{"fadeout", (PyCFunction)LinTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."},
+{"pow", (PyCFunction)LinTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."},
 {"setSize", (PyCFunction)LinTable_setSize, METH_O, "Sets the size of the table in samples"},
 {"getSize", (PyCFunction)LinTable_getSize, METH_NOARGS, "Return the size of the table in samples"},
 {"put", (PyCFunction)LinTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."},
 {"get", (PyCFunction)LinTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."},
 {"getPoints", (PyCFunction)LinTable_getPoints, METH_NOARGS, "Return the list of points."},
 {"replace", (PyCFunction)LinTable_replace, METH_O, "Sets the harmonics amplitude list and generates a new waveform table."},
+{"add", (PyCFunction)LinTable_add, METH_O, "Performs table addition."},
+{"sub", (PyCFunction)LinTable_sub, METH_O, "Performs table substraction."},
+{"mul", (PyCFunction)LinTable_mul, METH_O, "Performs table multiplication."},
 {NULL}  /* Sentinel */
 };
 
 PyTypeObject LinTableType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.LinTable_base",         /*tp_name*/
 sizeof(LinTable),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -1767,7 +1956,7 @@ sizeof(LinTable),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 0,                         /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -1814,19 +2003,19 @@ LogTable_generate(LogTable *self) {
     PyObject *tup, *tup2;
     int x1, y1;
     MYFLT x2, y2, diff, range, logrange, logmin, ratio, low, high;
-    
+
     y1 = 0;
     y2 = 0.0;
-    
+
     listsize = PyList_Size(self->pointslist);
-    
+
     for(i=0; i<(listsize-1); i++) {
         tup = PyList_GET_ITEM(self->pointslist, i);
         x1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup, 0)));
-        x2 = PyFloat_AsDouble(PyNumber_Float(PyTuple_GET_ITEM(tup, 1)));
+        x2 = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 1));
         tup2 = PyList_GET_ITEM(self->pointslist, i+1);
         y1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup2, 0)));
-        y2 = PyFloat_AsDouble(PyNumber_Float(PyTuple_GET_ITEM(tup2, 1)));
+        y2 = PyFloat_AsDouble(PyTuple_GET_ITEM(tup2, 1));
         if (x2 <= 0)
             x2 = 0.000001;
         if (y2 <= 0)
@@ -1856,7 +2045,7 @@ LogTable_generate(LogTable *self) {
             for(j=0; j<steps; j++) {
                 ratio = ((x2 + diff * j) - low) / range;
                 self->data[x1+j] = MYPOW(10, ratio * logrange + logmin);
-            }            
+            }
         }
     }
     if (y1 < (self->size-1)) {
@@ -1869,7 +2058,7 @@ LogTable_generate(LogTable *self) {
     else {
         self->data[self->size-1] = y2;
         self->data[self->size] = y2;
-    }    
+    }
 }
 
 static int
@@ -1880,7 +2069,7 @@ LogTable_traverse(LogTable *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 LogTable_clear(LogTable *self)
 {
     pyo_table_CLEAR
@@ -1893,7 +2082,7 @@ LogTable_dealloc(LogTable* self)
 {
     free(self->data);
     LogTable_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1902,19 +2091,19 @@ LogTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *pointslist=NULL;
     LogTable *self;
     self = (LogTable *)type->tp_alloc(type, 0);
-    
+
     self->server = PyServer_get_server();
-    
+
     self->pointslist = PyList_New(0);
     self->size = 8192;
-    
+
     MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL);
-    
+
     static char *kwlist[] = {"list", "size", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|Oi", kwlist, &pointslist, &self->size))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     if (pointslist) {
         Py_INCREF(pointslist);
         Py_DECREF(self->pointslist);
@@ -1924,15 +2113,15 @@ LogTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         PyList_Append(self->pointslist, PyTuple_Pack(2, PyInt_FromLong(0), PyFloat_FromDouble(0.)));
         PyList_Append(self->pointslist, PyTuple_Pack(2, PyInt_FromLong(self->size), PyFloat_FromDouble(1.)));
     }
-    
+
     self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
     TableStream_setSize(self->tablestream, self->size);
     TableStream_setData(self->tablestream, self->data);
     LogTable_generate(self);
-    
+
     double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL));
     TableStream_setSamplingRate(self->tablestream, sr);
-    
+
     return (PyObject *)self;
 }
 
@@ -1943,12 +2132,24 @@ static PyObject * LogTable_normalize(LogTable *self) { NORMALIZE };
 static PyObject * LogTable_reset(LogTable *self) { TABLE_RESET };
 static PyObject * LogTable_removeDC(LogTable *self) { REMOVE_DC };
 static PyObject * LogTable_reverse(LogTable *self) { REVERSE };
+static PyObject * LogTable_invert(LogTable *self) { INVERT };
+static PyObject * LogTable_rectify(LogTable *self) { RECTIFY };
+static PyObject * LogTable_bipolarGain(LogTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN };
+static PyObject * LogTable_lowpass(LogTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS };
+static PyObject * LogTable_fadein(LogTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN };
+static PyObject * LogTable_fadeout(LogTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT };
+static PyObject * LogTable_pow(LogTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER };
 static PyObject * LogTable_copy(LogTable *self, PyObject *arg) { COPY };
+static PyObject * LogTable_copyData(LogTable *self, PyObject *args, PyObject *kwds) { TABLE_COPYDATA };
+static PyObject * LogTable_rotate(LogTable *self, PyObject *args, PyObject *kwds) { TABLE_ROTATE };
 static PyObject * LogTable_setTable(LogTable *self, PyObject *arg) { SET_TABLE };
 static PyObject * LogTable_getTable(LogTable *self) { GET_TABLE };
-static PyObject * LogTable_getViewTable(LogTable *self) { GET_VIEW_TABLE };
+static PyObject * LogTable_getViewTable(LogTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE };
 static PyObject * LogTable_put(LogTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT };
 static PyObject * LogTable_get(LogTable *self, PyObject *args, PyObject *kwds) { TABLE_GET };
+static PyObject * LogTable_add(LogTable *self, PyObject *arg) { TABLE_ADD };
+static PyObject * LogTable_sub(LogTable *self, PyObject *arg) { TABLE_SUB };
+static PyObject * LogTable_mul(LogTable *self, PyObject *arg) { TABLE_MUL };
 
 static PyObject *
 LogTable_setSize(LogTable *self, PyObject *value)
@@ -1957,42 +2158,42 @@ LogTable_setSize(LogTable *self, PyObject *value)
     PyObject *tup, *x2;
     int old_size, x1;
     MYFLT factor;
-    
+
     if (value == NULL) {
         PyErr_SetString(PyExc_TypeError, "Cannot delete the size attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyInt_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The size attribute value must be an integer.");
         return PyInt_FromLong(-1);
     }
-    
+
     old_size = self->size;
-    self->size = PyInt_AsLong(value); 
-    
+    self->size = PyInt_AsLong(value);
+
     factor = (MYFLT)(self->size) / old_size;
-    
+
     self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
     TableStream_setSize(self->tablestream, self->size);
-    
+
     Py_ssize_t listsize = PyList_Size(self->pointslist);
-    
+
     PyObject *listtemp = PyList_New(0);
-    
+
     for(i=0; i<(listsize); i++) {
         tup = PyList_GET_ITEM(self->pointslist, i);
         x1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup, 0)));
         x2 = PyNumber_Float(PyTuple_GET_ITEM(tup, 1));
         PyList_Append(listtemp, PyTuple_Pack(2, PyInt_FromLong((int)(x1*factor)), x2));
     }
-    
+
     Py_INCREF(listtemp);
     Py_DECREF(self->pointslist);
     self->pointslist = listtemp;
-    
+
     LogTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -2017,18 +2218,18 @@ LogTable_replace(LogTable *self, PyObject *value)
         PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyList_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The amplitude list attribute value must be a list of tuples.");
         return PyInt_FromLong(-1);
     }
-    
+
     Py_INCREF(value);
     Py_DECREF(self->pointslist);
-    self->pointslist = value; 
-    
+    self->pointslist = value;
+
     LogTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -2043,27 +2244,38 @@ static PyMemberDef LogTable_members[] = {
 static PyMethodDef LogTable_methods[] = {
     {"getServer", (PyCFunction)LogTable_getServer, METH_NOARGS, "Returns server object."},
     {"copy", (PyCFunction)LogTable_copy, METH_O, "Copy data from table given in argument."},
+    {"copyData", (PyCFunction)LogTable_copyData, METH_VARARGS|METH_KEYWORDS, "Copy data from table given in argument."},
+    {"rotate", (PyCFunction)LogTable_rotate, METH_VARARGS|METH_KEYWORDS, "Rotate table around position as argument."},
     {"setTable", (PyCFunction)LogTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."},
     {"getTable", (PyCFunction)LogTable_getTable, METH_NOARGS, "Returns a list of table samples."},
-    {"getViewTable", (PyCFunction)LogTable_getViewTable, METH_NOARGS, "Returns a list of pixel coordinates for drawing the table."},
+    {"getViewTable", (PyCFunction)LogTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."},
     {"getTableStream", (PyCFunction)LogTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."},
     {"setData", (PyCFunction)LogTable_setData, METH_O, "Sets the table from samples in a text file."},
     {"normalize", (PyCFunction)LogTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"},
     {"reset", (PyCFunction)LogTable_reset, METH_NOARGS, "Resets table samples to 0.0"},
     {"removeDC", (PyCFunction)LogTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."},
     {"reverse", (PyCFunction)LogTable_reverse, METH_NOARGS, "Reverse the table's data."},
+    {"invert", (PyCFunction)LogTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."},
+    {"rectify", (PyCFunction)LogTable_rectify, METH_NOARGS, "Positive rectification of the table's data."},
+    {"bipolarGain", (PyCFunction)LogTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."},
+    {"lowpass", (PyCFunction)LogTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."},
+    {"fadein", (PyCFunction)LogTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."},
+    {"fadeout", (PyCFunction)LogTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."},
+    {"pow", (PyCFunction)LogTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."},
     {"setSize", (PyCFunction)LogTable_setSize, METH_O, "Sets the size of the table in samples"},
     {"getSize", (PyCFunction)LogTable_getSize, METH_NOARGS, "Return the size of the table in samples"},
     {"put", (PyCFunction)LogTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."},
     {"get", (PyCFunction)LogTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."},
     {"getPoints", (PyCFunction)LogTable_getPoints, METH_NOARGS, "Return the list of points."},
     {"replace", (PyCFunction)LogTable_replace, METH_O, "Sets the harmonics amplitude list and generates a new waveform table."},
+    {"add", (PyCFunction)LogTable_add, METH_O, "Performs table addition."},
+    {"sub", (PyCFunction)LogTable_sub, METH_O, "Performs table substraction."},
+    {"mul", (PyCFunction)LogTable_mul, METH_O, "Performs table multiplication."},
     {NULL}  /* Sentinel */
 };
 
 PyTypeObject LogTableType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.LogTable_base",         /*tp_name*/
     sizeof(LogTable),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -2071,7 +2283,7 @@ PyTypeObject LogTableType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     0,                         /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -2118,20 +2330,20 @@ CosTable_generate(CosTable *self) {
     PyObject *tup, *tup2;
     int x1, y1;
     MYFLT x2, y2, mu, mu2;
-        
+
     y1 = 0;
     y2 = 0.0;
-    
+
     listsize = PyList_Size(self->pointslist);
-    
+
     for(i=0; i<(listsize-1); i++) {
         tup = PyList_GET_ITEM(self->pointslist, i);
         x1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup, 0)));
-        x2 = PyFloat_AsDouble(PyNumber_Float(PyTuple_GET_ITEM(tup, 1)));        
+        x2 = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 1));
         tup2 = PyList_GET_ITEM(self->pointslist, i+1);
         y1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup2, 0)));
-        y2 = PyFloat_AsDouble(PyNumber_Float(PyTuple_GET_ITEM(tup2, 1)));
-        
+        y2 = PyFloat_AsDouble(PyTuple_GET_ITEM(tup2, 1));
+
         steps = y1 - x1;
         if (steps <= 0)
             continue;
@@ -2151,7 +2363,7 @@ CosTable_generate(CosTable *self) {
     else {
         self->data[self->size-1] = y2;
         self->data[self->size] = y2;
-    }    
+    }
 }
 
 static int
@@ -2162,7 +2374,7 @@ CosTable_traverse(CosTable *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 CosTable_clear(CosTable *self)
 {
     pyo_table_CLEAR
@@ -2175,7 +2387,7 @@ CosTable_dealloc(CosTable* self)
 {
     free(self->data);
     CosTable_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2184,19 +2396,19 @@ CosTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *pointslist=NULL;
     CosTable *self;
     self = (CosTable *)type->tp_alloc(type, 0);
-    
+
     self->server = PyServer_get_server();
-    
+
     self->pointslist = PyList_New(0);
     self->size = 8192;
-    
+
     MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL);
 
     static char *kwlist[] = {"list", "size", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|Oi", kwlist, &pointslist, &self->size))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     if (pointslist) {
         Py_INCREF(pointslist);
         Py_DECREF(self->pointslist);
@@ -2206,7 +2418,7 @@ CosTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         PyList_Append(self->pointslist, PyTuple_Pack(2, PyInt_FromLong(0), PyFloat_FromDouble(0.)));
         PyList_Append(self->pointslist, PyTuple_Pack(2, PyInt_FromLong(self->size), PyFloat_FromDouble(1.)));
     }
-    
+
     self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
     TableStream_setSize(self->tablestream, self->size);
     TableStream_setData(self->tablestream, self->data);
@@ -2214,7 +2426,7 @@ CosTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
     double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL));
     TableStream_setSamplingRate(self->tablestream, sr);
-    
+
     return (PyObject *)self;
 }
 
@@ -2225,12 +2437,24 @@ static PyObject * CosTable_normalize(CosTable *self) { NORMALIZE };
 static PyObject * CosTable_reset(CosTable *self) { TABLE_RESET };
 static PyObject * CosTable_removeDC(CosTable *self) { REMOVE_DC };
 static PyObject * CosTable_reverse(CosTable *self) { REVERSE };
+static PyObject * CosTable_invert(CosTable *self) { INVERT };
+static PyObject * CosTable_rectify(CosTable *self) { RECTIFY };
+static PyObject * CosTable_bipolarGain(CosTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN };
+static PyObject * CosTable_lowpass(CosTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS };
+static PyObject * CosTable_fadein(CosTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN };
+static PyObject * CosTable_fadeout(CosTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT };
+static PyObject * CosTable_pow(CosTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER };
 static PyObject * CosTable_copy(CosTable *self, PyObject *arg) { COPY };
+static PyObject * CosTable_copyData(CosTable *self, PyObject *args, PyObject *kwds) { TABLE_COPYDATA };
+static PyObject * CosTable_rotate(CosTable *self, PyObject *args, PyObject *kwds) { TABLE_ROTATE };
 static PyObject * CosTable_setTable(CosTable *self, PyObject *arg) { SET_TABLE };
 static PyObject * CosTable_getTable(CosTable *self) { GET_TABLE };
-static PyObject * CosTable_getViewTable(CosTable *self) { GET_VIEW_TABLE };
+static PyObject * CosTable_getViewTable(CosTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE };
 static PyObject * CosTable_put(CosTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT };
 static PyObject * CosTable_get(CosTable *self, PyObject *args, PyObject *kwds) { TABLE_GET };
+static PyObject * CosTable_add(CosTable *self, PyObject *arg) { TABLE_ADD };
+static PyObject * CosTable_sub(CosTable *self, PyObject *arg) { TABLE_SUB };
+static PyObject * CosTable_mul(CosTable *self, PyObject *arg) { TABLE_MUL };
 
 static PyObject *
 CosTable_setSize(CosTable *self, PyObject *value)
@@ -2239,42 +2463,42 @@ CosTable_setSize(CosTable *self, PyObject *value)
     PyObject *tup, *x2;
     int old_size, x1;
     MYFLT factor;
-    
+
     if (value == NULL) {
         PyErr_SetString(PyExc_TypeError, "Cannot delete the size attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyInt_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The size attribute value must be an integer.");
         return PyInt_FromLong(-1);
     }
-    
+
     old_size = self->size;
-    self->size = PyInt_AsLong(value); 
-    
+    self->size = PyInt_AsLong(value);
+
     factor = (MYFLT)(self->size) / old_size;
-    
+
     self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
     TableStream_setSize(self->tablestream, self->size);
-    
+
     Py_ssize_t listsize = PyList_Size(self->pointslist);
-    
+
     PyObject *listtemp = PyList_New(0);
-    
+
     for(i=0; i<(listsize); i++) {
         tup = PyList_GET_ITEM(self->pointslist, i);
         x1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup, 0)));
         x2 = PyNumber_Float(PyTuple_GET_ITEM(tup, 1));
         PyList_Append(listtemp, PyTuple_Pack(2, PyInt_FromLong((int)(x1*factor)), x2));
     }
-    
+
     Py_INCREF(listtemp);
     Py_DECREF(self->pointslist);
     self->pointslist = listtemp;
-    
+
     CosTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -2299,18 +2523,18 @@ CosTable_replace(CosTable *self, PyObject *value)
         PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyList_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The amplitude list attribute value must be a list of tuples.");
         return PyInt_FromLong(-1);
     }
-    
+
     Py_INCREF(value);
     Py_DECREF(self->pointslist);
-    self->pointslist = value; 
-    
+    self->pointslist = value;
+
     CosTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -2325,27 +2549,38 @@ static PyMemberDef CosTable_members[] = {
 static PyMethodDef CosTable_methods[] = {
 {"getServer", (PyCFunction)CosTable_getServer, METH_NOARGS, "Returns server object."},
 {"copy", (PyCFunction)CosTable_copy, METH_O, "Copy data from table given in argument."},
+{"copyData", (PyCFunction)CosTable_copyData, METH_VARARGS|METH_KEYWORDS, "Copy data from table given in argument."},
+{"rotate", (PyCFunction)CosTable_rotate, METH_VARARGS|METH_KEYWORDS, "Rotate table around position as argument."},
 {"setTable", (PyCFunction)CosTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."},
 {"getTable", (PyCFunction)CosTable_getTable, METH_NOARGS, "Returns a list of table samples."},
-{"getViewTable", (PyCFunction)CosTable_getViewTable, METH_NOARGS, "Returns a list of pixel coordinates for drawing the table."},
+{"getViewTable", (PyCFunction)CosTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."},
 {"getTableStream", (PyCFunction)CosTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."},
 {"setData", (PyCFunction)CosTable_setData, METH_O, "Sets the table from samples in a text file."},
 {"normalize", (PyCFunction)CosTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"},
 {"reset", (PyCFunction)CosTable_reset, METH_NOARGS, "Resets table samples to 0.0"},
 {"removeDC", (PyCFunction)CosTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."},
 {"reverse", (PyCFunction)CosTable_reverse, METH_NOARGS, "Reverse the table's data."},
+{"invert", (PyCFunction)CosTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."},
+{"rectify", (PyCFunction)CosTable_rectify, METH_NOARGS, "Positive rectification of the table's data."},
+{"bipolarGain", (PyCFunction)CosTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."},
+{"lowpass", (PyCFunction)CosTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."},
+{"fadein", (PyCFunction)CosTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."},
+{"fadeout", (PyCFunction)CosTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."},
+{"pow", (PyCFunction)CosTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."},
 {"setSize", (PyCFunction)CosTable_setSize, METH_O, "Sets the size of the table in samples"},
 {"getSize", (PyCFunction)CosTable_getSize, METH_NOARGS, "Return the size of the table in samples"},
 {"put", (PyCFunction)CosTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."},
 {"get", (PyCFunction)CosTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."},
 {"getPoints", (PyCFunction)CosTable_getPoints, METH_NOARGS, "Return the list of points."},
 {"replace", (PyCFunction)CosTable_replace, METH_O, "Sets the harmonics amplitude list and generates a new waveform table."},
+{"add", (PyCFunction)CosTable_add, METH_O, "Performs table addition."},
+{"sub", (PyCFunction)CosTable_sub, METH_O, "Performs table substraction."},
+{"mul", (PyCFunction)CosTable_mul, METH_O, "Performs table multiplication."},
 {NULL}  /* Sentinel */
 };
 
 PyTypeObject CosTableType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.CosTable_base",         /*tp_name*/
 sizeof(CosTable),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -2353,7 +2588,7 @@ sizeof(CosTable),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 0,                         /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -2400,19 +2635,19 @@ CosLogTable_generate(CosLogTable *self) {
     PyObject *tup, *tup2;
     int x1, y1;
     MYFLT x2, y2, range, logrange, logmin, ratio, low, high, mu;
-    
+
     y1 = 0;
     y2 = 0.0;
-    
+
     listsize = PyList_Size(self->pointslist);
-    
+
     for(i=0; i<(listsize-1); i++) {
         tup = PyList_GET_ITEM(self->pointslist, i);
         x1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup, 0)));
-        x2 = PyFloat_AsDouble(PyNumber_Float(PyTuple_GET_ITEM(tup, 1)));
+        x2 = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 1));
         tup2 = PyList_GET_ITEM(self->pointslist, i+1);
         y1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup2, 0)));
-        y2 = PyFloat_AsDouble(PyNumber_Float(PyTuple_GET_ITEM(tup2, 1)));
+        y2 = PyFloat_AsDouble(PyTuple_GET_ITEM(tup2, 1));
         if (x2 <= 0)
             x2 = 0.000001;
         if (y2 <= 0)
@@ -2425,7 +2660,7 @@ CosLogTable_generate(CosLogTable *self) {
             low = x2;
             high = y2;
         }
-        
+
         steps = y1 - x1;
         range = high - low;
         logrange = MYLOG10(high) - MYLOG10(low);
@@ -2444,7 +2679,7 @@ CosLogTable_generate(CosLogTable *self) {
                 mu = x2 *(1.0-mu) + y2*mu;
                 ratio = (mu - low) / range;
                 self->data[x1+j] = MYPOW(10, ratio * logrange + logmin);
-            }            
+            }
         }
     }
     if (y1 < (self->size-1)) {
@@ -2457,7 +2692,7 @@ CosLogTable_generate(CosLogTable *self) {
     else {
         self->data[self->size-1] = y2;
         self->data[self->size] = y2;
-    }    
+    }
 }
 
 static int
@@ -2468,7 +2703,7 @@ CosLogTable_traverse(CosLogTable *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 CosLogTable_clear(CosLogTable *self)
 {
     pyo_table_CLEAR
@@ -2481,7 +2716,7 @@ CosLogTable_dealloc(CosLogTable* self)
 {
     free(self->data);
     CosLogTable_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2490,19 +2725,19 @@ CosLogTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *pointslist=NULL;
     CosLogTable *self;
     self = (CosLogTable *)type->tp_alloc(type, 0);
-    
+
     self->server = PyServer_get_server();
-    
+
     self->pointslist = PyList_New(0);
     self->size = 8192;
-    
+
     MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL);
-    
+
     static char *kwlist[] = {"list", "size", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "|Oi", kwlist, &pointslist, &self->size))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     if (pointslist) {
         Py_INCREF(pointslist);
         Py_DECREF(self->pointslist);
@@ -2512,15 +2747,15 @@ CosLogTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         PyList_Append(self->pointslist, PyTuple_Pack(2, PyInt_FromLong(0), PyFloat_FromDouble(0.)));
         PyList_Append(self->pointslist, PyTuple_Pack(2, PyInt_FromLong(self->size), PyFloat_FromDouble(1.)));
     }
-    
+
     self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
     TableStream_setSize(self->tablestream, self->size);
     TableStream_setData(self->tablestream, self->data);
     CosLogTable_generate(self);
-    
+
     double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL));
     TableStream_setSamplingRate(self->tablestream, sr);
-    
+
     return (PyObject *)self;
 }
 
@@ -2531,12 +2766,24 @@ static PyObject * CosLogTable_normalize(CosLogTable *self) { NORMALIZE };
 static PyObject * CosLogTable_reset(CosLogTable *self) { TABLE_RESET };
 static PyObject * CosLogTable_removeDC(CosLogTable *self) { REMOVE_DC };
 static PyObject * CosLogTable_reverse(CosLogTable *self) { REVERSE };
+static PyObject * CosLogTable_invert(CosLogTable *self) { INVERT };
+static PyObject * CosLogTable_rectify(CosLogTable *self) { RECTIFY };
+static PyObject * CosLogTable_bipolarGain(CosLogTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN };
+static PyObject * CosLogTable_lowpass(CosLogTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS };
+static PyObject * CosLogTable_fadein(CosLogTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN };
+static PyObject * CosLogTable_fadeout(CosLogTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT };
+static PyObject * CosLogTable_pow(CosLogTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER };
 static PyObject * CosLogTable_copy(CosLogTable *self, PyObject *arg) { COPY };
+static PyObject * CosLogTable_copyData(CosLogTable *self, PyObject *args, PyObject *kwds) { TABLE_COPYDATA };
+static PyObject * CosLogTable_rotate(CosLogTable *self, PyObject *args, PyObject *kwds) { TABLE_ROTATE };
 static PyObject * CosLogTable_setTable(CosLogTable *self, PyObject *arg) { SET_TABLE };
 static PyObject * CosLogTable_getTable(CosLogTable *self) { GET_TABLE };
-static PyObject * CosLogTable_getViewTable(CosLogTable *self) { GET_VIEW_TABLE };
+static PyObject * CosLogTable_getViewTable(CosLogTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE };
 static PyObject * CosLogTable_put(CosLogTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT };
 static PyObject * CosLogTable_get(CosLogTable *self, PyObject *args, PyObject *kwds) { TABLE_GET };
+static PyObject * CosLogTable_add(CosLogTable *self, PyObject *arg) { TABLE_ADD };
+static PyObject * CosLogTable_sub(CosLogTable *self, PyObject *arg) { TABLE_SUB };
+static PyObject * CosLogTable_mul(CosLogTable *self, PyObject *arg) { TABLE_MUL };
 
 static PyObject *
 CosLogTable_setSize(CosLogTable *self, PyObject *value)
@@ -2545,42 +2792,42 @@ CosLogTable_setSize(CosLogTable *self, PyObject *value)
     PyObject *tup, *x2;
     int old_size, x1;
     MYFLT factor;
-    
+
     if (value == NULL) {
         PyErr_SetString(PyExc_TypeError, "Cannot delete the size attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyInt_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The size attribute value must be an integer.");
         return PyInt_FromLong(-1);
     }
-    
+
     old_size = self->size;
-    self->size = PyInt_AsLong(value); 
-    
+    self->size = PyInt_AsLong(value);
+
     factor = (MYFLT)(self->size) / old_size;
-    
+
     self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
     TableStream_setSize(self->tablestream, self->size);
-    
+
     Py_ssize_t listsize = PyList_Size(self->pointslist);
-    
+
     PyObject *listtemp = PyList_New(0);
-    
+
     for(i=0; i<(listsize); i++) {
         tup = PyList_GET_ITEM(self->pointslist, i);
         x1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup, 0)));
         x2 = PyNumber_Float(PyTuple_GET_ITEM(tup, 1));
         PyList_Append(listtemp, PyTuple_Pack(2, PyInt_FromLong((int)(x1*factor)), x2));
     }
-    
+
     Py_INCREF(listtemp);
     Py_DECREF(self->pointslist);
     self->pointslist = listtemp;
-    
+
     CosLogTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -2605,18 +2852,18 @@ CosLogTable_replace(CosLogTable *self, PyObject *value)
         PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyList_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The amplitude list attribute value must be a list of tuples.");
         return PyInt_FromLong(-1);
     }
-    
+
     Py_INCREF(value);
     Py_DECREF(self->pointslist);
-    self->pointslist = value; 
-    
+    self->pointslist = value;
+
     CosLogTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -2631,27 +2878,38 @@ static PyMemberDef CosLogTable_members[] = {
 static PyMethodDef CosLogTable_methods[] = {
     {"getServer", (PyCFunction)CosLogTable_getServer, METH_NOARGS, "Returns server object."},
     {"copy", (PyCFunction)CosLogTable_copy, METH_O, "Copy data from table given in argument."},
+    {"copyData", (PyCFunction)CosLogTable_copyData, METH_VARARGS|METH_KEYWORDS, "Copy data from table given in argument."},
+    {"rotate", (PyCFunction)CosLogTable_rotate, METH_VARARGS|METH_KEYWORDS, "Rotate table around position as argument."},
     {"setTable", (PyCFunction)CosLogTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."},
     {"getTable", (PyCFunction)CosLogTable_getTable, METH_NOARGS, "Returns a list of table samples."},
-    {"getViewTable", (PyCFunction)CosLogTable_getViewTable, METH_NOARGS, "Returns a list of pixel coordinates for drawing the table."},
+    {"getViewTable", (PyCFunction)CosLogTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."},
     {"getTableStream", (PyCFunction)CosLogTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."},
     {"setData", (PyCFunction)CosLogTable_setData, METH_O, "Sets the table from samples in a text file."},
     {"normalize", (PyCFunction)CosLogTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"},
     {"reset", (PyCFunction)CosLogTable_reset, METH_NOARGS, "Resets table samples to 0.0"},
     {"removeDC", (PyCFunction)CosLogTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."},
     {"reverse", (PyCFunction)CosLogTable_reverse, METH_NOARGS, "Reverse the table's data."},
+    {"invert", (PyCFunction)CosLogTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."},
+    {"rectify", (PyCFunction)CosLogTable_rectify, METH_NOARGS, "Positive rectification of the table's data."},
+    {"bipolarGain", (PyCFunction)CosLogTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."},
+    {"lowpass", (PyCFunction)CosLogTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."},
+    {"fadein", (PyCFunction)CosLogTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."},
+    {"fadeout", (PyCFunction)CosLogTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."},
+    {"pow", (PyCFunction)CosLogTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."},
     {"setSize", (PyCFunction)CosLogTable_setSize, METH_O, "Sets the size of the table in samples"},
     {"getSize", (PyCFunction)CosLogTable_getSize, METH_NOARGS, "Return the size of the table in samples"},
     {"put", (PyCFunction)CosLogTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."},
     {"get", (PyCFunction)CosLogTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."},
     {"getPoints", (PyCFunction)CosLogTable_getPoints, METH_NOARGS, "Return the list of points."},
     {"replace", (PyCFunction)CosLogTable_replace, METH_O, "Sets the harmonics amplitude list and generates a new waveform table."},
+    {"add", (PyCFunction)CosLogTable_add, METH_O, "Performs table addition."},
+    {"sub", (PyCFunction)CosLogTable_sub, METH_O, "Performs table substraction."},
+    {"mul", (PyCFunction)CosLogTable_mul, METH_O, "Performs table multiplication."},
     {NULL}  /* Sentinel */
 };
 
 PyTypeObject CosLogTableType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.CosLogTable_base",         /*tp_name*/
     sizeof(CosLogTable),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -2659,7 +2917,7 @@ PyTypeObject CosLogTableType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     0,                         /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -2707,24 +2965,24 @@ CurveTable_generate(CurveTable *self) {
     Py_ssize_t listsize;
     PyObject *tup;
     int x1, x2;
-    MYFLT y0, y1, y2, y3; 
+    MYFLT y0, y1, y2, y3;
     MYFLT m0, m1, mu, mu2, mu3;
     MYFLT a0, a1, a2, a3;
 
     for (i=0; i<self->size; i++) {
         self->data[i] = 0.0;
     }
-    
+
     listsize = PyList_Size(self->pointslist);
     int times[listsize+2];
     MYFLT values[listsize+2];
-    
+
     for (i=0; i<listsize; i++) {
         tup = PyList_GET_ITEM(self->pointslist, i);
         times[i+1] = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup, 0)));
-        values[i+1] = PyFloat_AsDouble(PyNumber_Float(PyTuple_GET_ITEM(tup, 1)));        
+        values[i+1] = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 1));
     }
-    
+
     // sets imaginary points
     times[0] = times[1] - times[2];
     if (values[1] < values[2])
@@ -2738,12 +2996,12 @@ CurveTable_generate(CurveTable *self) {
         values[endP] = values[endP-1] + values[endP-2];
     else
         values[endP] = values[endP-1] - values[endP-2];
-    
+
     for(i=1; i<listsize; i++) {
         x1 = times[i];
-        x2 = times[i+1];   
+        x2 = times[i+1];
         y0 = values[i-1]; y1 = values[i]; y2 = values[i+1]; y3 = values[i+2];
-        
+
         steps = x2 - x1;
         if (steps <= 0)
             continue;
@@ -2759,11 +3017,11 @@ CurveTable_generate(CurveTable *self) {
             a1 = mu3 - 2.0*mu2 + mu;
             a2 = mu3 - mu2;
             a3 = -2.0*mu3 + 3.0*mu2;
-            
+
             self->data[x1+j] = (a0*y1 + a1*m0 + a2*m1 + a3*y2);
         }
     }
-    
+
     self->data[self->size] = self->data[self->size-1];
 }
 
@@ -2775,7 +3033,7 @@ CurveTable_traverse(CurveTable *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 CurveTable_clear(CurveTable *self)
 {
     pyo_table_CLEAR
@@ -2788,30 +3046,30 @@ CurveTable_dealloc(CurveTable* self)
 {
     free(self->data);
     CurveTable_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
 CurveTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     PyObject *pointslist=NULL;
-    CurveTable *self;    
+    CurveTable *self;
     self = (CurveTable *)type->tp_alloc(type, 0);
-    
+
     self->server = PyServer_get_server();
-    
+
     self->pointslist = PyList_New(0);
     self->size = 8192;
     self->tension = 0.0;
     self->bias = 0.0;
-    
+
     MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL);
 
     static char *kwlist[] = {"list", "tension", "bias", "size", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__OFFI, kwlist, &pointslist, &self->tension, &self->bias, &self->size))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     if (pointslist) {
         Py_INCREF(pointslist);
         Py_DECREF(self->pointslist);
@@ -2821,7 +3079,7 @@ CurveTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         PyList_Append(self->pointslist, PyTuple_Pack(2, PyInt_FromLong(0), PyFloat_FromDouble(0.)));
         PyList_Append(self->pointslist, PyTuple_Pack(2, PyInt_FromLong(self->size), PyFloat_FromDouble(1.)));
     }
-    
+
     self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
     TableStream_setSize(self->tablestream, self->size);
     TableStream_setData(self->tablestream, self->data);
@@ -2829,7 +3087,7 @@ CurveTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
     double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL));
     TableStream_setSamplingRate(self->tablestream, sr);
-    
+
     return (PyObject *)self;
 }
 
@@ -2840,51 +3098,63 @@ static PyObject * CurveTable_normalize(CurveTable * self) { NORMALIZE };
 static PyObject * CurveTable_reset(CurveTable * self) { TABLE_RESET };
 static PyObject * CurveTable_removeDC(CurveTable *self) { REMOVE_DC };
 static PyObject * CurveTable_reverse(CurveTable *self) { REVERSE };
+static PyObject * CurveTable_invert(CurveTable *self) { INVERT };
+static PyObject * CurveTable_rectify(CurveTable *self) { RECTIFY };
+static PyObject * CurveTable_bipolarGain(CurveTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN };
+static PyObject * CurveTable_lowpass(CurveTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS };
+static PyObject * CurveTable_fadein(CurveTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN };
+static PyObject * CurveTable_fadeout(CurveTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT };
+static PyObject * CurveTable_pow(CurveTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER };
 static PyObject * CurveTable_copy(CurveTable *self, PyObject *arg) { COPY };
+static PyObject * CurveTable_copyData(CurveTable *self, PyObject *args, PyObject *kwds) { TABLE_COPYDATA };
+static PyObject * CurveTable_rotate(CurveTable *self, PyObject *args, PyObject *kwds) { TABLE_ROTATE };
 static PyObject * CurveTable_setTable(CurveTable *self, PyObject *arg) { SET_TABLE };
 static PyObject * CurveTable_getTable(CurveTable *self) { GET_TABLE };
-static PyObject * CurveTable_getViewTable(CurveTable *self) { GET_VIEW_TABLE };
+static PyObject * CurveTable_getViewTable(CurveTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE };
 static PyObject * CurveTable_put(CurveTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT };
 static PyObject * CurveTable_get(CurveTable *self, PyObject *args, PyObject *kwds) { TABLE_GET };
+static PyObject * CurveTable_add(CurveTable *self, PyObject *arg) { TABLE_ADD };
+static PyObject * CurveTable_sub(CurveTable *self, PyObject *arg) { TABLE_SUB };
+static PyObject * CurveTable_mul(CurveTable *self, PyObject *arg) { TABLE_MUL };
 
 static PyObject *
 CurveTable_setTension(CurveTable *self, PyObject *value)
-{    
+{
     if (value == NULL) {
         PyErr_SetString(PyExc_TypeError, "Cannot delete the tension attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyNumber_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The tension attribute value must be a float.");
         return PyInt_FromLong(-1);
     }
-    
-    self->tension = PyFloat_AsDouble(PyNumber_Float(value)); 
+
+    self->tension = PyFloat_AsDouble(value);
 
     CurveTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
 static PyObject *
 CurveTable_setBias(CurveTable *self, PyObject *value)
-{    
+{
     if (value == NULL) {
         PyErr_SetString(PyExc_TypeError, "Cannot delete the bias attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyNumber_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The bias attribute value must be a float.");
         return PyInt_FromLong(-1);
     }
-    
-    self->bias = PyFloat_AsDouble(PyNumber_Float(value)); 
-    
+
+    self->bias = PyFloat_AsDouble(value);
+
     CurveTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -2896,42 +3166,42 @@ CurveTable_setSize(CurveTable *self, PyObject *value)
     PyObject *tup, *x2;
     int old_size, x1;
     MYFLT factor;
-    
+
     if (value == NULL) {
         PyErr_SetString(PyExc_TypeError, "Cannot delete the size attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyInt_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The size attribute value must be an integer.");
         return PyInt_FromLong(-1);
     }
-    
+
     old_size = self->size;
-    self->size = PyInt_AsLong(value); 
-    
+    self->size = PyInt_AsLong(value);
+
     factor = (MYFLT)(self->size) / old_size;
-    
+
     self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
     TableStream_setSize(self->tablestream, self->size);
-    
+
     Py_ssize_t listsize = PyList_Size(self->pointslist);
-    
+
     PyObject *listtemp = PyList_New(0);
-    
+
     for(i=0; i<(listsize); i++) {
         tup = PyList_GET_ITEM(self->pointslist, i);
         x1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup, 0)));
         x2 = PyNumber_Float(PyTuple_GET_ITEM(tup, 1));
         PyList_Append(listtemp, PyTuple_Pack(2, PyInt_FromLong((int)(x1*factor)), x2));
     }
-    
+
     Py_INCREF(listtemp);
     Py_DECREF(self->pointslist);
     self->pointslist = listtemp;
-    
+
     CurveTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -2956,18 +3226,18 @@ CurveTable_replace(CurveTable *self, PyObject *value)
         PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyList_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The amplitude list attribute value must be a list of tuples.");
         return PyInt_FromLong(-1);
     }
-    
+
     Py_INCREF(value);
     Py_DECREF(self->pointslist);
-    self->pointslist = value; 
-    
+    self->pointslist = value;
+
     CurveTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -2982,9 +3252,11 @@ static PyMemberDef CurveTable_members[] = {
 static PyMethodDef CurveTable_methods[] = {
 {"getServer", (PyCFunction)CurveTable_getServer, METH_NOARGS, "Returns server object."},
 {"copy", (PyCFunction)CurveTable_copy, METH_O, "Copy data from table given in argument."},
+{"copyData", (PyCFunction)CurveTable_copyData, METH_VARARGS|METH_KEYWORDS, "Copy data from table given in argument."},
+{"rotate", (PyCFunction)CurveTable_rotate, METH_VARARGS|METH_KEYWORDS, "Rotate table around position as argument."},
 {"setTable", (PyCFunction)CurveTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."},
 {"getTable", (PyCFunction)CurveTable_getTable, METH_NOARGS, "Returns a list of table samples."},
-{"getViewTable", (PyCFunction)CurveTable_getViewTable, METH_NOARGS, "Returns a list of pixel coordinates for drawing the table."},
+{"getViewTable", (PyCFunction)CurveTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."},
 {"getTableStream", (PyCFunction)CurveTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."},
 {"setData", (PyCFunction)CurveTable_setData, METH_O, "Sets the table from samples in a text file."},
 {"setSize", (PyCFunction)CurveTable_setSize, METH_O, "Sets the size of the table in samples"},
@@ -2999,12 +3271,21 @@ static PyMethodDef CurveTable_methods[] = {
 {"reset", (PyCFunction)CurveTable_reset, METH_NOARGS, "Resets table samples to 0.0"},
 {"removeDC", (PyCFunction)CurveTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."},
 {"reverse", (PyCFunction)CurveTable_reverse, METH_NOARGS, "Reverse the table's data."},
+{"invert", (PyCFunction)CurveTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."},
+{"rectify", (PyCFunction)CurveTable_rectify, METH_NOARGS, "Positive rectification of the table's data."},
+{"bipolarGain", (PyCFunction)CurveTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."},
+{"lowpass", (PyCFunction)CurveTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."},
+{"fadein", (PyCFunction)CurveTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."},
+{"fadeout", (PyCFunction)CurveTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."},
+{"pow", (PyCFunction)CurveTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."},
+{"add", (PyCFunction)CurveTable_add, METH_O, "Performs table addition."},
+{"sub", (PyCFunction)CurveTable_sub, METH_O, "Performs table substraction."},
+{"mul", (PyCFunction)CurveTable_mul, METH_O, "Performs table multiplication."},
 {NULL}  /* Sentinel */
 };
 
 PyTypeObject CurveTableType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.CurveTable_base",         /*tp_name*/
 sizeof(CurveTable),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -3012,7 +3293,7 @@ sizeof(CurveTable),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 0,                         /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -3060,29 +3341,29 @@ ExpTable_generate(ExpTable *self) {
     Py_ssize_t listsize;
     PyObject *tup;
     int x1, x2;
-    MYFLT y1, y2, range, inc, pointer, scl; 
-    
+    MYFLT y1, y2, range, inc, pointer, scl;
+
     for (i=0; i<self->size; i++) {
         self->data[i] = 0.0;
     }
-    
+
     listsize = PyList_Size(self->pointslist);
     int times[listsize];
     MYFLT values[listsize];
-    
+
     for (i=0; i<listsize; i++) {
         tup = PyList_GET_ITEM(self->pointslist, i);
         times[i] = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup, 0)));
-        values[i] = PyFloat_AsDouble(PyNumber_Float(PyTuple_GET_ITEM(tup, 1)));        
+        values[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 1));
     }
 
     y1 = y2 = 0.0;
     for(i=0; i<(listsize-1); i++) {
         x1 = times[i];
-        x2 = times[i+1];   
-        y1 = values[i]; 
+        x2 = times[i+1];
+        y1 = values[i];
         y2 = values[i+1];
-        
+
         range = y2 - y1;
         steps = x2 - x1;
         if (steps <= 0)
@@ -3104,16 +3385,16 @@ ExpTable_generate(ExpTable *self) {
                     pointer += inc;
                 }
             }
-        }    
+        }
         else {
             for(j=0; j<steps; j++) {
                 scl = MYPOW(pointer, self->exp);
                 self->data[x1+j] = scl * range + y1;
                 pointer += inc;
             }
-        }    
+        }
     }
-    
+
     self->data[self->size] = y2;
 }
 
@@ -3125,7 +3406,7 @@ ExpTable_traverse(ExpTable *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 ExpTable_clear(ExpTable *self)
 {
     pyo_table_CLEAR
@@ -3138,30 +3419,30 @@ ExpTable_dealloc(ExpTable* self)
 {
     free(self->data);
     ExpTable_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
 ExpTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     PyObject *pointslist=NULL;
-    ExpTable *self;    
+    ExpTable *self;
     self = (ExpTable *)type->tp_alloc(type, 0);
-    
+
     self->server = PyServer_get_server();
-    
+
     self->pointslist = PyList_New(0);
     self->size = 8192;
     self->exp = 10.0;
     self->inverse = 1;
-    
+
     MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL);
 
     static char *kwlist[] = {"list", "exp", "inverse", "size", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__OFII, kwlist, &pointslist, &self->exp, &self->inverse, &self->size))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     if (pointslist) {
         Py_INCREF(pointslist);
         Py_DECREF(self->pointslist);
@@ -3171,7 +3452,7 @@ ExpTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         PyList_Append(self->pointslist, PyTuple_Pack(2, PyInt_FromLong(0), PyFloat_FromDouble(0.)));
         PyList_Append(self->pointslist, PyTuple_Pack(2, PyInt_FromLong(self->size), PyFloat_FromDouble(1.)));
     }
-    
+
     self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
     TableStream_setSize(self->tablestream, self->size);
     TableStream_setData(self->tablestream, self->data);
@@ -3179,7 +3460,7 @@ ExpTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
     double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL));
     TableStream_setSamplingRate(self->tablestream, sr);
-    
+
     return (PyObject *)self;
 }
 
@@ -3190,51 +3471,63 @@ static PyObject * ExpTable_normalize(ExpTable * self) { NORMALIZE };
 static PyObject * ExpTable_reset(ExpTable * self) { TABLE_RESET };
 static PyObject * ExpTable_removeDC(ExpTable *self) { REMOVE_DC };
 static PyObject * ExpTable_reverse(ExpTable *self) { REVERSE };
+static PyObject * ExpTable_invert(ExpTable *self) { INVERT };
+static PyObject * ExpTable_rectify(ExpTable *self) { RECTIFY };
+static PyObject * ExpTable_bipolarGain(ExpTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN };
+static PyObject * ExpTable_lowpass(ExpTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS };
+static PyObject * ExpTable_fadein(ExpTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN };
+static PyObject * ExpTable_fadeout(ExpTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT };
+static PyObject * ExpTable_pow(ExpTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER };
 static PyObject * ExpTable_copy(ExpTable *self, PyObject *arg) { COPY };
+static PyObject * ExpTable_copyData(ExpTable *self, PyObject *args, PyObject *kwds) { TABLE_COPYDATA };
+static PyObject * ExpTable_rotate(ExpTable *self, PyObject *args, PyObject *kwds) { TABLE_ROTATE };
 static PyObject * ExpTable_setTable(ExpTable *self, PyObject *arg) { SET_TABLE };
 static PyObject * ExpTable_getTable(ExpTable *self) { GET_TABLE };
-static PyObject * ExpTable_getViewTable(ExpTable *self) { GET_VIEW_TABLE };
+static PyObject * ExpTable_getViewTable(ExpTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE };
 static PyObject * ExpTable_put(ExpTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT };
 static PyObject * ExpTable_get(ExpTable *self, PyObject *args, PyObject *kwds) { TABLE_GET };
+static PyObject * ExpTable_add(ExpTable *self, PyObject *arg) { TABLE_ADD };
+static PyObject * ExpTable_sub(ExpTable *self, PyObject *arg) { TABLE_SUB };
+static PyObject * ExpTable_mul(ExpTable *self, PyObject *arg) { TABLE_MUL };
 
 static PyObject *
 ExpTable_setExp(ExpTable *self, PyObject *value)
-{    
+{
     if (value == NULL) {
         PyErr_SetString(PyExc_TypeError, "Cannot delete the exp attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyNumber_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The exp attribute value must be a float.");
         return PyInt_FromLong(-1);
     }
-    
-    self->exp = PyFloat_AsDouble(PyNumber_Float(value)); 
-    
+
+    self->exp = PyFloat_AsDouble(value);
+
     ExpTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
 static PyObject *
 ExpTable_setInverse(ExpTable *self, PyObject *value)
-{    
+{
     if (value == NULL) {
         PyErr_SetString(PyExc_TypeError, "Cannot delete the inverse attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyInt_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The inverse attribute value must be a boolean (True or False or 0 or 1).");
         return PyInt_FromLong(-1);
     }
-    
-    self->inverse = PyInt_AsLong(value); 
-    
+
+    self->inverse = PyInt_AsLong(value);
+
     ExpTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -3246,42 +3539,42 @@ ExpTable_setSize(ExpTable *self, PyObject *value)
     PyObject *tup, *x2;
     int old_size, x1;
     MYFLT factor;
-    
+
     if (value == NULL) {
         PyErr_SetString(PyExc_TypeError, "Cannot delete the size attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyInt_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The size attribute value must be an integer.");
         return PyInt_FromLong(-1);
     }
-    
+
     old_size = self->size;
-    self->size = PyInt_AsLong(value); 
-    
+    self->size = PyInt_AsLong(value);
+
     factor = (MYFLT)(self->size) / old_size;
-    
+
     self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
     TableStream_setSize(self->tablestream, self->size);
-    
+
     Py_ssize_t listsize = PyList_Size(self->pointslist);
-    
+
     PyObject *listtemp = PyList_New(0);
-    
+
     for(i=0; i<(listsize); i++) {
         tup = PyList_GET_ITEM(self->pointslist, i);
         x1 = PyInt_AsLong(PyNumber_Long(PyTuple_GET_ITEM(tup, 0)));
         x2 = PyNumber_Float(PyTuple_GET_ITEM(tup, 1));
         PyList_Append(listtemp, PyTuple_Pack(2, PyInt_FromLong((int)(x1*factor)), x2));
     }
-    
+
     Py_INCREF(listtemp);
     Py_DECREF(self->pointslist);
     self->pointslist = listtemp;
-    
+
     ExpTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -3306,18 +3599,18 @@ ExpTable_replace(ExpTable *self, PyObject *value)
         PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyList_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The amplitude list attribute value must be a list of tuples.");
         return PyInt_FromLong(-1);
     }
-    
+
     Py_INCREF(value);
     Py_DECREF(self->pointslist);
-    self->pointslist = value; 
-    
+    self->pointslist = value;
+
     ExpTable_generate(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -3331,9 +3624,11 @@ static PyMemberDef ExpTable_members[] = {
 static PyMethodDef ExpTable_methods[] = {
 {"getServer", (PyCFunction)ExpTable_getServer, METH_NOARGS, "Returns server object."},
 {"copy", (PyCFunction)ExpTable_copy, METH_O, "Copy data from table given in argument."},
+{"copyData", (PyCFunction)ExpTable_copyData, METH_VARARGS|METH_KEYWORDS, "Copy data from table given in argument."},
+{"rotate", (PyCFunction)ExpTable_rotate, METH_VARARGS|METH_KEYWORDS, "Rotate table around position as argument."},
 {"setTable", (PyCFunction)ExpTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."},
 {"getTable", (PyCFunction)ExpTable_getTable, METH_NOARGS, "Returns a list of table samples."},
-{"getViewTable", (PyCFunction)ExpTable_getViewTable, METH_NOARGS, "Returns a list of pixel coordinates for drawing the table."},
+{"getViewTable", (PyCFunction)ExpTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."},
 {"getTableStream", (PyCFunction)ExpTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."},
 {"setData", (PyCFunction)ExpTable_setData, METH_O, "Sets the table from samples in a text file."},
 {"setSize", (PyCFunction)ExpTable_setSize, METH_O, "Sets the size of the table in samples"},
@@ -3348,12 +3643,21 @@ static PyMethodDef ExpTable_methods[] = {
 {"reset", (PyCFunction)ExpTable_reset, METH_NOARGS, "Resets table samples to 0.0"},
 {"removeDC", (PyCFunction)ExpTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."},
 {"reverse", (PyCFunction)ExpTable_reverse, METH_NOARGS, "Reverse the table's data."},
+{"invert", (PyCFunction)ExpTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."},
+{"rectify", (PyCFunction)ExpTable_rectify, METH_NOARGS, "Positive rectification of the table's data."},
+{"bipolarGain", (PyCFunction)ExpTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."},
+{"lowpass", (PyCFunction)ExpTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."},
+{"fadein", (PyCFunction)ExpTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."},
+{"fadeout", (PyCFunction)ExpTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."},
+{"pow", (PyCFunction)ExpTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."},
+{"add", (PyCFunction)ExpTable_add, METH_O, "Performs table addition."},
+{"sub", (PyCFunction)ExpTable_sub, METH_O, "Performs table substraction."},
+{"mul", (PyCFunction)ExpTable_mul, METH_O, "Performs table multiplication."},
 {NULL}  /* Sentinel */
 };
 
 PyTypeObject ExpTableType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.ExpTable_base",         /*tp_name*/
 sizeof(ExpTable),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -3361,7 +3665,7 @@ sizeof(ExpTable),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 0,                         /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -3415,12 +3719,12 @@ SndTable_loadSound(SndTable *self) {
     unsigned int i, num, num_items, num_chnls, snd_size, start, stop;
     unsigned int num_count = 0;
     MYFLT *tmp;
-        
+
     info.format = 0;
     sf = sf_open(self->path, SFM_READ, &info);
     if (sf == NULL)
     {
-        printf("SndTable failed to open the file.\n");
+        PySys_WriteStdout("SndTable failed to open the file.\n");
         return;
     }
     snd_size = info.frames;
@@ -3436,24 +3740,24 @@ SndTable_loadSound(SndTable *self) {
         start = 0;
     else
         start = (unsigned int)(self->start * self->sndSr);
-    
+
     self->size = stop - start;
     num_items = self->size * num_chnls;
-    
+
     /* Allocate space for the data to be read, then read it. */
     self->data = (MYFLT *)realloc(self->data, (self->size + 1) * sizeof(MYFLT));
 
     /* For sound longer than 1 minute, load 30 sec chunks. */
-    if (self->size > (self->sndSr * 60 * num_chnls)) {
+    if (self->size > (int)(self->sndSr * 60 * num_chnls)) {
         tmp = (MYFLT *)malloc(self->sndSr * 30 * num_chnls * sizeof(MYFLT));
         sf_seek(sf, start, SEEK_SET);
         num_items = self->sndSr * 30 * num_chnls;
         do {
             num = SF_READ(sf, tmp, num_items);
             for (i=0; i<num; i++) {
-                if ((i % num_chnls) == self->chnl) {
+                if ((int)(i % num_chnls) == self->chnl) {
                     self->data[(int)(num_count++)] = tmp[i];
-                }  
+                }
             }
         } while (num == num_items);
         sf_close(sf);
@@ -3465,13 +3769,13 @@ SndTable_loadSound(SndTable *self) {
         num = SF_READ(sf, tmp, num_items);
         sf_close(sf);
         for (i=0; i<num_items; i++) {
-            if ((i % num_chnls) == self->chnl) {
+            if ((int)(i % num_chnls) == self->chnl) {
                 self->data[(int)(i/num_chnls)] = tmp[i];
-            }    
+            }
         }
     }
 
-    self->data[self->size] = self->data[0];  
+    self->data[self->size] = self->data[0];
 
     self->start = 0.0;
     self->stop = -1.0;
@@ -3488,46 +3792,46 @@ SndTable_appendSound(SndTable *self) {
     unsigned int i, num_items, num_chnls, snd_size, start, stop, to_load_size, cross_in_samps, cross_point, index, real_index;
     MYFLT *tmp, *tmp_data;
     MYFLT cross_amp;
-    
+
     info.format = 0;
     sf = sf_open(self->path, SFM_READ, &info);
     if (sf == NULL)
     {
-        printf("SndTable failed to open the file.\n");
+        PySys_WriteStdout("SndTable failed to open the file.\n");
         return;
     }
     snd_size = info.frames;
     self->sndSr = info.samplerate;
     num_chnls = info.channels;
-    
+
     if (self->stop <= 0 || self->stop <= self->start || (self->stop*self->sndSr) > snd_size)
         stop = snd_size;
     else
         stop = (unsigned int)(self->stop * self->sndSr);
-    
+
     if (self->start < 0 || (self->start*self->sndSr) > snd_size)
         start = 0;
     else
         start = (unsigned int)(self->start * self->sndSr);
-    
+
     to_load_size = stop - start;
     num_items = to_load_size * num_chnls;
     cross_in_samps = (unsigned int)(self->crossfade * self->sr);
     if (cross_in_samps >= to_load_size)
         cross_in_samps = to_load_size - 1;
-    if (cross_in_samps >= self->size)
+    if ((int)cross_in_samps >= self->size)
         cross_in_samps = self->size - 1;
-    
+
     /* Allocate space for the data to be read, then read it. */
     tmp = (MYFLT *)malloc(num_items * sizeof(MYFLT));
     tmp_data = (MYFLT *)malloc(self->size * sizeof(MYFLT));
-    
+
     sf_seek(sf, start, SEEK_SET);
     SF_READ(sf, tmp, num_items);
     sf_close(sf);
 
     if (cross_in_samps != 0) {
-        for (i=0; i<self->size; i++) {
+        for (i=0; i<(unsigned int)self->size; i++) {
             tmp_data[i] = self->data[i];
         }
     }
@@ -3535,7 +3839,7 @@ SndTable_appendSound(SndTable *self) {
     cross_point = self->size - cross_in_samps;
     self->size = self->size + to_load_size - cross_in_samps;
     self->data = (MYFLT *)realloc(self->data, (self->size + 1) * sizeof(MYFLT));
-    
+
     if (cross_in_samps != 0) {
         for (i=0; i<cross_point; i++) {
             self->data[i] = tmp_data[i];
@@ -3544,16 +3848,16 @@ SndTable_appendSound(SndTable *self) {
 
     if (self->crossfade == 0.0) {
         for (i=0; i<num_items; i++) {
-            if ((i % num_chnls) == self->chnl) {
+            if ((int)(i % num_chnls) == self->chnl) {
                 index = (int)(i/num_chnls);
                 real_index = cross_point + index;
                 self->data[real_index] = tmp[i];
-            }    
+            }
         }
     }
     else {
         for (i=0; i<num_items; i++) {
-            if ((i % num_chnls) == self->chnl) {
+            if ((int)(i % num_chnls) == self->chnl) {
                 index = (int)(i/num_chnls);
                 real_index = cross_point + index;
                 if (index < cross_in_samps) {
@@ -3562,12 +3866,12 @@ SndTable_appendSound(SndTable *self) {
                 }
                 else
                     self->data[real_index] = tmp[i];
-            }    
-        }        
+            }
+        }
     }
-    
-    self->data[self->size] = self->data[0];  
-    
+
+    self->data[self->size] = self->data[0];
+
     self->start = 0.0;
     self->stop = -1.0;
     free(tmp);
@@ -3581,68 +3885,68 @@ static void
 SndTable_prependSound(SndTable *self) {
     SNDFILE *sf;
     SF_INFO info;
-    unsigned int i, num_items, num_chnls, snd_size, start, stop, to_load_size, cross_in_samps, cross_point; 
+    unsigned int i, num_items, num_chnls, snd_size, start, stop, to_load_size, cross_in_samps, cross_point;
     unsigned int index = 0;
     MYFLT *tmp, *tmp_data;
     MYFLT cross_amp;
-    
+
     info.format = 0;
     sf = sf_open(self->path, SFM_READ, &info);
     if (sf == NULL)
     {
-        printf("SndTable failed to open the file.\n");
+        PySys_WriteStdout("SndTable failed to open the file.\n");
         return;
     }
     snd_size = info.frames;
     self->sndSr = info.samplerate;
     num_chnls = info.channels;
-    
+
     if (self->stop <= 0 || self->stop <= self->start || (self->stop*self->sndSr) > snd_size)
         stop = snd_size;
     else
         stop = (unsigned int)(self->stop * self->sndSr);
-    
+
     if (self->start < 0 || (self->start*self->sndSr) > snd_size)
         start = 0;
     else
         start = (unsigned int)(self->start * self->sndSr);
-    
+
     to_load_size = stop - start;
     num_items = to_load_size * num_chnls;
     cross_in_samps = (unsigned int)(self->crossfade * self->sr);
     if (cross_in_samps >= to_load_size)
         cross_in_samps = to_load_size - 1;
-    if (cross_in_samps >= self->size)
+    if ((int)cross_in_samps >= self->size)
         cross_in_samps = self->size - 1;
-    
+
     /* Allocate space for the data to be read, then read it. */
     tmp = (MYFLT *)malloc(num_items * sizeof(MYFLT));
     tmp_data = (MYFLT *)malloc(self->size * sizeof(MYFLT));
-    
+
     sf_seek(sf, start, SEEK_SET);
     SF_READ(sf, tmp, num_items);
     sf_close(sf);
-    
-    for (i=0; i<self->size; i++) {
+
+    for (i=0; i<(unsigned int)self->size; i++) {
         tmp_data[i] = self->data[i];
     }
-    
+
     cross_point = to_load_size - cross_in_samps;
     self->size = self->size + to_load_size - cross_in_samps;
     self->data = (MYFLT *)realloc(self->data, (self->size + 1) * sizeof(MYFLT));
-    
+
     if (self->crossfade == 0.0) {
         for (i=0; i<num_items; i++) {
-            if ((i % num_chnls) == self->chnl) {
+            if ((int)(i % num_chnls) == self->chnl) {
                 index = (int)(i/num_chnls);
                 self->data[index] = tmp[i];
-            }    
+            }
         }
-        
+
     }
     else {
         for (i=0; i<num_items; i++) {
-            if ((i % num_chnls) == self->chnl) {
+            if ((int)(i % num_chnls) == self->chnl) {
                 index = (int)(i/num_chnls);
                 if (index >= cross_point) {
                     cross_amp = MYSQRT((index-cross_point) / (MYFLT)cross_in_samps);
@@ -3650,16 +3954,16 @@ SndTable_prependSound(SndTable *self) {
                 }
                 else
                     self->data[index] = tmp[i];
-            }    
-        }        
+            }
+        }
     }
-    
-    for (i=(index+1); i<self->size; i++) {
+
+    for (i=(index+1); i<(unsigned int)self->size; i++) {
         self->data[i] = tmp_data[i - cross_point];
     }
-        
-    self->data[self->size] = self->data[0];  
-    
+
+    self->data[self->size] = self->data[0];
+
     self->start = 0.0;
     self->stop = -1.0;
     free(tmp);
@@ -3674,40 +3978,40 @@ SndTable_insertSound(SndTable *self) {
     SNDFILE *sf;
     SF_INFO info;
     unsigned int i, num_items, num_chnls, snd_size, start, stop, to_load_size;
-    unsigned int cross_in_samps, cross_point, insert_point, index; 
-    unsigned int read_point = 0; 
+    unsigned int cross_in_samps, cross_point, insert_point, index;
+    unsigned int read_point = 0;
     unsigned int real_index = 0;
     MYFLT *tmp, *tmp_data;
     MYFLT cross_amp;
-    
+
     info.format = 0;
     sf = sf_open(self->path, SFM_READ, &info);
     if (sf == NULL)
     {
-        printf("SndTable failed to open the file.\n");
+        PySys_WriteStdout("SndTable failed to open the file.\n");
         return;
     }
     snd_size = info.frames;
     self->sndSr = info.samplerate;
     num_chnls = info.channels;
-    
+
     if (self->stop <= 0 || self->stop <= self->start || (self->stop*self->sndSr) > snd_size)
         stop = snd_size;
     else
         stop = (unsigned int)(self->stop * self->sndSr);
-    
+
     if (self->start < 0 || (self->start*self->sndSr) > snd_size)
         start = 0;
     else
         start = (unsigned int)(self->start * self->sndSr);
-    
+
     to_load_size = stop - start;
     num_items = to_load_size * num_chnls;
-    
+
     insert_point = (unsigned int)(self->insertPos * self->sr);
-    if (insert_point >= self->size)
+    if ((int)insert_point >= self->size)
         insert_point = self->size - 1;
-    
+
     cross_in_samps = (unsigned int)(self->crossfade * self->sr);
     if (cross_in_samps >= (to_load_size/2))
         cross_in_samps = (to_load_size/2) - 5;
@@ -3719,36 +4023,36 @@ SndTable_insertSound(SndTable *self) {
     /* Allocate space for the data to be read, then read it. */
     tmp = (MYFLT *)malloc(num_items * sizeof(MYFLT));
     tmp_data = (MYFLT *)malloc(self->size * sizeof(MYFLT));
-    
+
     sf_seek(sf, start, SEEK_SET);
     SF_READ(sf, tmp, num_items);
     sf_close(sf);
-    
-    for (i=0; i<self->size; i++) {
+
+    for (i=0; i<(unsigned int)self->size; i++) {
         tmp_data[i] = self->data[i];
     }
-    
+
     self->size = self->size + to_load_size - (cross_in_samps * 2);
     self->data = (MYFLT *)realloc(self->data, (self->size + 1) * sizeof(MYFLT));
-    
+
     cross_point = insert_point - cross_in_samps;
-    
+
     for (i=0; i<cross_point; i++) {
         self->data[i] = tmp_data[i];
     }
-    
+
     if (self->crossfade == 0.0) {
         for (i=0; i<num_items; i++) {
-            if ((i % num_chnls) == self->chnl) {
+            if ((int)(i % num_chnls) == self->chnl) {
                 index = (int)(i/num_chnls);
                 self->data[index+cross_point] = tmp[i];
-            }    
+            }
         }
-        
+
     }
     else {
         for (i=0; i<num_items; i++) {
-            if ((i % num_chnls) == self->chnl) {
+            if ((int)(i % num_chnls) == self->chnl) {
                 index = (int)(i/num_chnls);
                 real_index = index + cross_point;
                 if (index <= cross_in_samps) {
@@ -3762,18 +4066,18 @@ SndTable_insertSound(SndTable *self) {
                 }
                 else
                     self->data[real_index] = tmp[i];
-            }    
-        }        
+            }
+        }
     }
-    
+
     read_point++;
-    for (i=(real_index+1); i<self->size; i++) {
+    for (i=(real_index+1); i<(unsigned int)self->size; i++) {
         self->data[i] = tmp_data[read_point];
         read_point++;
     }
-    
-    self->data[self->size] = self->data[0];  
-    
+
+    self->data[self->size] = self->data[0];
+
     self->start = 0.0;
     self->stop = -1.0;
     free(tmp);
@@ -3790,7 +4094,7 @@ SndTable_traverse(SndTable *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 SndTable_clear(SndTable *self)
 {
     pyo_table_CLEAR
@@ -3802,17 +4106,18 @@ SndTable_dealloc(SndTable* self)
 {
     free(self->data);
     SndTable_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
 SndTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
+    Py_ssize_t psize;
     SndTable *self;
-    
+
     self = (SndTable *)type->tp_alloc(type, 0);
-    
+
     self->server = PyServer_get_server();
     self->sr = (MYFLT)PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL));
 
@@ -3824,10 +4129,10 @@ SndTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL);
 
     static char *kwlist[] = {"path", "chnl", "start", "stop", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_S_IFF, kwlist, &self->path, &self->chnl, &self->start, &self->stop))
-        return PyInt_FromLong(-1); 
-    
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_P_IFF, kwlist, &self->path, &psize, &self->chnl, &self->start, &self->stop))
+        return PyInt_FromLong(-1);
+
     if (strcmp(self->path, "") == 0) {
         self->size = (int)self->sr;
         self->data = (MYFLT *)realloc(self->data, (self->size + 1) * sizeof(MYFLT));
@@ -3845,7 +4150,7 @@ SndTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     else {
         SndTable_loadSound(self);
     }
-    
+
     return (PyObject *)self;
 }
 
@@ -3856,25 +4161,57 @@ static PyObject * SndTable_normalize(SndTable *self) { NORMALIZE };
 static PyObject * SndTable_reset(SndTable *self) { TABLE_RESET };
 static PyObject * SndTable_removeDC(SndTable *self) { REMOVE_DC };
 static PyObject * SndTable_reverse(SndTable *self) { REVERSE };
+static PyObject * SndTable_invert(SndTable *self) { INVERT };
+static PyObject * SndTable_rectify(SndTable *self) { RECTIFY };
+static PyObject * SndTable_bipolarGain(SndTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN };
+static PyObject * SndTable_lowpass(SndTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS };
+static PyObject * SndTable_fadein(SndTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN };
+static PyObject * SndTable_fadeout(SndTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT };
+static PyObject * SndTable_pow(SndTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER };
 static PyObject * SndTable_copy(SndTable *self, PyObject *arg) { COPY };
+static PyObject * SndTable_copyData(SndTable *self, PyObject *args, PyObject *kwds) { TABLE_COPYDATA };
+static PyObject * SndTable_rotate(SndTable *self, PyObject *args, PyObject *kwds) { TABLE_ROTATE };
 static PyObject * SndTable_setTable(SndTable *self, PyObject *arg) { SET_TABLE };
 static PyObject * SndTable_getTable(SndTable *self) { GET_TABLE };
 static PyObject * SndTable_put(SndTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT };
 static PyObject * SndTable_get(SndTable *self, PyObject *args, PyObject *kwds) { TABLE_GET };
+static PyObject * SndTable_add(SndTable *self, PyObject *arg) { TABLE_ADD };
+static PyObject * SndTable_sub(SndTable *self, PyObject *arg) { TABLE_SUB };
+static PyObject * SndTable_mul(SndTable *self, PyObject *arg) { TABLE_MUL };
 
-static PyObject * 
-SndTable_getViewTable(SndTable *self, PyObject *args, PyObject *kwds) { 
-    int i, j, y, w, h, h2, step;
+static PyObject *
+SndTable_getViewTable(SndTable *self, PyObject *args, PyObject *kwds) {
+    int i, j, y, w, h, h2, step, size;
     int count = 0;
-    MYFLT absin;
-    PyObject *samples;
+    int yOffset = 0;
+    MYFLT absin, fstep;
+    MYFLT begin = 0.0;
+    MYFLT end = -1.0;
+    PyObject *samples, *tuple;
     PyObject *sizetmp = NULL;
 
-    static char *kwlist[] = {"size", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &sizetmp))
-        return PyInt_FromLong(-1); 
-    
+    static char *kwlist[] = {"size", "begin", "end", "yOffset", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__OFFI, kwlist, &sizetmp, &begin, &end, &yOffset))
+        return PyInt_FromLong(-1);
+
+    if (end <= 0.0)
+        end = self->size;
+    else {
+        end = end * self->sr;
+        if (end > self->size)
+            end = self->size;
+    }
+
+    if (begin < 0.0)
+        begin = 0;
+    else {
+        begin = begin * self->sr;
+        if (begin >= end)
+            begin = 0;
+    }
+    size = (int)(end - begin);
+
     if (sizetmp) {
         if (PyTuple_Check(sizetmp)) {
             w = PyInt_AsLong(PyTuple_GET_ITEM(sizetmp, 0));
@@ -3894,38 +4231,67 @@ SndTable_getViewTable(SndTable *self, PyObject *args, PyObject *kwds) {
         h = 200;
     }
     h2 = h/2;
-    step = (int)(self->size / (MYFLT)(w));
-    
-    samples = PyList_New(w*4);
-    for(i=0; i<w; i++) {
-        absin = 0.0;
-        for (j=0; j<step; j++) {
-            if (MYFABS(self->data[count++]) > absin)
-                absin = self->data[count];
+    step = (int)(size / (MYFLT)(w));
+    fstep = (MYFLT)(w) / (size-1);
+
+    if (step == 0) {
+        samples = PyList_New(size);
+        for (i=0; i<size; i++) {
+            tuple = PyTuple_New(2);
+            PyTuple_SetItem(tuple, 0, PyInt_FromLong((int)(i*fstep)));
+            PyTuple_SetItem(tuple, 1, PyInt_FromLong(-self->data[i+(int)(begin)]*h2+h2+yOffset));
+            PyList_SetItem(samples, i, tuple);
+        }
+    }
+    else if (step < 32) {
+        samples = PyList_New(w);
+        for(i=0; i<w; i++) {
+            absin = 0.0;
+            for (j=0; j<step; j++) {
+                absin += -self->data[(int)(begin)+count];
+                count++;
+            }
+            y = (int)(absin / step * h2);
+            tuple = PyTuple_New(2);
+            PyTuple_SetItem(tuple, 0, PyInt_FromLong(i));
+            PyTuple_SetItem(tuple, 1, PyInt_FromLong(h2+y+yOffset));
+            PyList_SetItem(samples, i, tuple);
+        }
+    }
+    else {
+        samples = PyList_New(w*2);
+        for(i=0; i<w; i++) {
+            absin = 0.0;
+            for (j=0; j<step; j++) {
+                if (MYFABS(self->data[(int)(begin)+count]) > absin)
+                    absin = -self->data[(int)(begin)+count];
+                count++;
+            }
+            y = (int)(absin * h2);
+            tuple = PyTuple_New(2);
+            PyTuple_SetItem(tuple, 0, PyInt_FromLong(i));
+            PyTuple_SetItem(tuple, 1, PyInt_FromLong(h2-y+yOffset));
+            PyList_SetItem(samples, i*2, tuple);
+            tuple = PyTuple_New(2);
+            PyTuple_SetItem(tuple, 0, PyInt_FromLong(i));
+            PyTuple_SetItem(tuple, 1, PyInt_FromLong(h2+y+yOffset));
+            PyList_SetItem(samples, i*2+1, tuple);
         }
-        y = (int)(absin * h2);
-        PyList_SetItem(samples, i*4, PyInt_FromLong(i));
-        PyList_SetItem(samples, i*4+1, PyInt_FromLong(h2-y));
-        PyList_SetItem(samples, i*4+2, PyInt_FromLong(i));
-        PyList_SetItem(samples, i*4+3, PyInt_FromLong(h2+y));
     }
     return samples;
 };
 
-static PyObject * 
-SndTable_getEnvelope(SndTable *self, PyObject *arg) { 
+static PyObject *
+SndTable_getEnvelope(SndTable *self, PyObject *arg) {
     int i, j, step, points;
     long count;
     MYFLT absin, last;
     PyObject *samples;
 
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
 	int isInt = PyInt_Check(arg);
-    
+
     if (isInt) {
         count = 0;
         points = PyInt_AsLong(arg);
@@ -3951,68 +4317,71 @@ SndTable_getEnvelope(SndTable *self, PyObject *arg) {
 
 static PyObject *
 SndTable_setSound(SndTable *self, PyObject *args, PyObject *kwds)
-{    
+{
+    Py_ssize_t psize;
     static char *kwlist[] = {"path", "chnl", "start", "stop", NULL};
-    
+
     MYFLT stoptmp = -1.0;
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_S_IFF, kwlist, &self->path, &self->chnl, &self->start, &stoptmp)) {
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_P_IFF, kwlist, &self->path, &psize, &self->chnl, &self->start, &stoptmp)) {
         Py_INCREF(Py_None);
         return Py_None;
-    }    
-    
+    }
+
     self->stop = stoptmp;
     SndTable_loadSound(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
 static PyObject *
 SndTable_append(SndTable *self, PyObject *args, PyObject *kwds)
-{    
+{
+    Py_ssize_t psize;
     static char *kwlist[] = {"path", "crossfade", "chnl", "start", "stop", NULL};
-    
+
     MYFLT stoptmp = -1.0;
     MYFLT crosstmp = 0.0;
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_S_FIFF, kwlist, &self->path, &crosstmp, &self->chnl, &self->start, &stoptmp)) {
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_P_FIFF, kwlist, &self->path, &psize, &crosstmp, &self->chnl, &self->start, &stoptmp)) {
         Py_INCREF(Py_None);
         return Py_None;
-    }    
-    
+    }
+
     self->stop = stoptmp;
     if (crosstmp < 0.0)
         self->crossfade = 0.0;
     else
         self->crossfade = crosstmp;
-    
+
     SndTable_appendSound(self);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
 
 static PyObject *
 SndTable_insert(SndTable *self, PyObject *args, PyObject *kwds)
-{    
+{
+    Py_ssize_t psize;
     static char *kwlist[] = {"path", "pos", "crossfade", "chnl", "start", "stop", NULL};
-    
+
     MYFLT stoptmp = -1.0;
     MYFLT crosstmp = 0.0;
     MYFLT postmp = 0.0;
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_S_FFIFF, kwlist, &self->path, &postmp, &crosstmp, &self->chnl, &self->start, &stoptmp)) {
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_P_FFIFF, kwlist, &self->path, &psize, &postmp, &crosstmp, &self->chnl, &self->start, &stoptmp)) {
         Py_INCREF(Py_None);
         return Py_None;
-    }    
-    
+    }
+
     self->stop = stoptmp;
     if (crosstmp < 0.0)
         self->crossfade = 0.0;
     else
         self->crossfade = crosstmp;
-    
+
     if (postmp <= 0.0)
         SndTable_prependSound(self);
     else if (postmp >= ((self->size-1) / self->sndSr))
@@ -4021,7 +4390,7 @@ SndTable_insert(SndTable *self, PyObject *args, PyObject *kwds)
         self->insertPos = postmp;
         SndTable_insertSound(self);
     }
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -4031,7 +4400,7 @@ SndTable_setSize(SndTable *self, PyObject *value)
 {
     Py_ssize_t i;
 
-    self->size = PyInt_AsLong(value); 
+    self->size = PyInt_AsLong(value);
 
     self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
 
@@ -4043,7 +4412,7 @@ SndTable_setSize(SndTable *self, PyObject *value)
     self->stop = -1.0;
     TableStream_setSize(self->tablestream, self->size);
     TableStream_setData(self->tablestream, self->data);
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -4070,6 +4439,8 @@ static PyMemberDef SndTable_members[] = {
 static PyMethodDef SndTable_methods[] = {
 {"getServer", (PyCFunction)SndTable_getServer, METH_NOARGS, "Returns server object."},
 {"copy", (PyCFunction)SndTable_copy, METH_O, "Copy data from table given in argument."},
+{"copyData", (PyCFunction)SndTable_copyData, METH_VARARGS|METH_KEYWORDS, "Copy data from table given in argument."},
+{"rotate", (PyCFunction)SndTable_rotate, METH_VARARGS|METH_KEYWORDS, "Rotate table around position as argument."},
 {"setTable", (PyCFunction)SndTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."},
 {"getTable", (PyCFunction)SndTable_getTable, METH_NOARGS, "Returns a list of table samples."},
 {"getViewTable", (PyCFunction)SndTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."},
@@ -4080,6 +4451,13 @@ static PyMethodDef SndTable_methods[] = {
 {"reset", (PyCFunction)SndTable_reset, METH_NOARGS, "Resets table samples to 0.0"},
 {"removeDC", (PyCFunction)SndTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."},
 {"reverse", (PyCFunction)SndTable_reverse, METH_NOARGS, "Reverse the table's data."},
+{"invert", (PyCFunction)SndTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."},
+{"rectify", (PyCFunction)SndTable_rectify, METH_NOARGS, "Positive rectification of the table's data."},
+{"bipolarGain", (PyCFunction)SndTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."},
+{"lowpass", (PyCFunction)SndTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."},
+{"fadein", (PyCFunction)SndTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."},
+{"fadeout", (PyCFunction)SndTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."},
+{"pow", (PyCFunction)SndTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."},
 {"put", (PyCFunction)SndTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."},
 {"get", (PyCFunction)SndTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."},
 {"setSound", (PyCFunction)SndTable_setSound, METH_VARARGS|METH_KEYWORDS, "Load a new sound in the table."},
@@ -4088,12 +4466,14 @@ static PyMethodDef SndTable_methods[] = {
 {"setSize", (PyCFunction)SndTable_setSize, METH_O, "Sets the size of the table in samples"},
 {"getSize", (PyCFunction)SndTable_getSize, METH_NOARGS, "Return the size of the table in samples."},
 {"getRate", (PyCFunction)SndTable_getRate, METH_NOARGS, "Return the frequency (in cps) that reads the sound without pitch transposition."},
+{"add", (PyCFunction)SndTable_add, METH_O, "Performs table addition."},
+{"sub", (PyCFunction)SndTable_sub, METH_O, "Performs table substraction."},
+{"mul", (PyCFunction)SndTable_mul, METH_O, "Performs table multiplication."},
 {NULL}  /* Sentinel */
 };
 
 PyTypeObject SndTableType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.SndTable_base",         /*tp_name*/
 sizeof(SndTable),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -4101,7 +4481,7 @@ sizeof(SndTable),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 0,                         /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -4132,7 +4512,7 @@ SndTable_members,             /* tp_members */
 0,                         /* tp_alloc */
 SndTable_new,                 /* tp_new */
 0,               /* tp_free */
-0,               /* tp_is_gc */    
+0,               /* tp_is_gc */
 0,               /* tp_bases */
 0,               /* tp_mro */
 0,               /* tp_cache */
@@ -4148,9 +4528,14 @@ typedef struct {
     pyo_table_HEAD
     MYFLT length;
     MYFLT feedback;
+    MYFLT sr;
     int pointer;
 } NewTable;
 
+void NewTable_resetRecordingPointer(NewTable *self) { self->pointer = 0; }
+
+MYFLT NewTable_getFeedback(NewTable *self) { return self->feedback; }
+
 static PyObject *
 NewTable_recordChunk(NewTable *self, MYFLT *data, int datasize)
 {
@@ -4187,7 +4572,7 @@ NewTable_traverse(NewTable *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 NewTable_clear(NewTable *self)
 {
     pyo_table_CLEAR
@@ -4199,7 +4584,7 @@ NewTable_dealloc(NewTable* self)
 {
     free(self->data);
     NewTable_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -4209,36 +4594,36 @@ NewTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inittmp=NULL;
     NewTable *self;
     self = (NewTable *)type->tp_alloc(type, 0);
-    
+
     self->server = PyServer_get_server();
-    
+
     self->pointer = 0;
     self->feedback = 0.0;
-    
+
     MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL);
 
     static char *kwlist[] = {"length", "init", "feedback", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_F_OF, kwlist, &self->length, &inittmp, &self->feedback))
-        Py_RETURN_NONE; 
+        Py_RETURN_NONE;
 
-    double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL));
-    self->size = (int)(self->length * sr + 0.5);
+    self->sr = (MYFLT)PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL));
+    self->size = (int)(self->length * self->sr + 0.5);
     self->data = (MYFLT *)realloc(self->data, (self->size + 1) * sizeof(MYFLT));
 
     for (i=0; i<(self->size+1); i++) {
         self->data[i] = 0.;
     }
-    
+
     TableStream_setSize(self->tablestream, self->size);
 
     if (inittmp && inittmp != Py_None) {
         PyObject_CallMethod((PyObject *)self, "setTable", "O", inittmp);
     }
-    
+
     TableStream_setData(self->tablestream, self->data);
-    TableStream_setSamplingRate(self->tablestream, sr);
-    
+    TableStream_setSamplingRate(self->tablestream, self->sr);
+
     return (PyObject *)self;
 }
 
@@ -4249,25 +4634,57 @@ static PyObject * NewTable_normalize(NewTable *self) { NORMALIZE };
 static PyObject * NewTable_reset(NewTable *self) { TABLE_RESET };
 static PyObject * NewTable_removeDC(NewTable *self) { REMOVE_DC };
 static PyObject * NewTable_reverse(NewTable *self) { REVERSE };
+static PyObject * NewTable_invert(NewTable *self) { INVERT };
+static PyObject * NewTable_rectify(NewTable *self) { RECTIFY };
+static PyObject * NewTable_bipolarGain(NewTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN };
+static PyObject * NewTable_lowpass(NewTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS };
+static PyObject * NewTable_fadein(NewTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN };
+static PyObject * NewTable_fadeout(NewTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT };
+static PyObject * NewTable_pow(NewTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER };
 static PyObject * NewTable_copy(NewTable *self, PyObject *arg) { COPY };
+static PyObject * NewTable_copyData(NewTable *self, PyObject *args, PyObject *kwds) { TABLE_COPYDATA };
+static PyObject * NewTable_rotate(NewTable *self, PyObject *args, PyObject *kwds) { TABLE_ROTATE };
 static PyObject * NewTable_setTable(NewTable *self, PyObject *arg) { SET_TABLE };
 static PyObject * NewTable_getTable(NewTable *self) { GET_TABLE };
 static PyObject * NewTable_put(NewTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT };
 static PyObject * NewTable_get(NewTable *self, PyObject *args, PyObject *kwds) { TABLE_GET };
+static PyObject * NewTable_add(NewTable *self, PyObject *arg) { TABLE_ADD };
+static PyObject * NewTable_sub(NewTable *self, PyObject *arg) { TABLE_SUB };
+static PyObject * NewTable_mul(NewTable *self, PyObject *arg) { TABLE_MUL };
 
-static PyObject * 
-NewTable_getViewTable(NewTable *self, PyObject *args, PyObject *kwds) { 
-    int i, j, y, w, h, h2, step;
+static PyObject *
+NewTable_getViewTable(NewTable *self, PyObject *args, PyObject *kwds) {
+    int i, j, y, w, h, h2, step, size;
     int count = 0;
-    MYFLT absin;
-    PyObject *samples;
+    int yOffset = 0;
+    MYFLT absin, fstep;
+    MYFLT begin = 0.0;
+    MYFLT end = -1.0;
+    PyObject *samples, *tuple;
     PyObject *sizetmp = NULL;
-    
-    static char *kwlist[] = {"size", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &sizetmp))
-        return PyInt_FromLong(-1); 
-    
+
+    static char *kwlist[] = {"size", "begin", "end", "yOffset", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__OFFI, kwlist, &sizetmp, &begin, &end, &yOffset))
+        return PyInt_FromLong(-1);
+
+    if (end <= 0.0)
+        end = self->size;
+    else {
+        end = end * self->sr;
+        if (end > self->size)
+            end = self->size;
+    }
+
+    if (begin < 0.0)
+        begin = 0;
+    else {
+        begin = begin * self->sr;
+        if (begin >= end)
+            begin = 0;
+    }
+    size = (int)(end - begin);
+
     if (sizetmp) {
         if (PyTuple_Check(sizetmp)) {
             w = PyInt_AsLong(PyTuple_GET_ITEM(sizetmp, 0));
@@ -4287,20 +4704,52 @@ NewTable_getViewTable(NewTable *self, PyObject *args, PyObject *kwds) {
         h = 200;
     }
     h2 = h/2;
-    step = (int)(self->size / (MYFLT)(w));
-    
-    samples = PyList_New(w*4);
-    for(i=0; i<w; i++) {
-        absin = 0.0;
-        for (j=0; j<step; j++) {
-            if (MYFABS(self->data[count++]) > absin)
-                absin = self->data[count];
+    step = (int)(size / (MYFLT)(w));
+    fstep = (MYFLT)(w) / (size-1);
+
+    if (step == 0) {
+        samples = PyList_New(size);
+        for (i=0; i<size; i++) {
+            tuple = PyTuple_New(2);
+            PyTuple_SetItem(tuple, 0, PyInt_FromLong((int)(i*fstep)));
+            PyTuple_SetItem(tuple, 1, PyInt_FromLong(-self->data[i+(int)(begin)]*h2+h2+yOffset));
+            PyList_SetItem(samples, i, tuple);
+        }
+    }
+    else if (step < 32) {
+        samples = PyList_New(w);
+        for(i=0; i<w; i++) {
+            absin = 0.0;
+            for (j=0; j<step; j++) {
+                absin += -self->data[(int)(begin)+count];
+                count++;
+            }
+            y = (int)(absin / step * h2);
+            tuple = PyTuple_New(2);
+            PyTuple_SetItem(tuple, 0, PyInt_FromLong(i));
+            PyTuple_SetItem(tuple, 1, PyInt_FromLong(h2+y+yOffset));
+            PyList_SetItem(samples, i, tuple);
+        }
+    }
+    else {
+        samples = PyList_New(w*2);
+        for(i=0; i<w; i++) {
+            absin = 0.0;
+            for (j=0; j<step; j++) {
+                if (MYFABS(self->data[(int)(begin)+count]) > absin)
+                    absin = -self->data[(int)(begin)+count];
+                count++;
+            }
+            y = (int)(absin * h2);
+            tuple = PyTuple_New(2);
+            PyTuple_SetItem(tuple, 0, PyInt_FromLong(i));
+            PyTuple_SetItem(tuple, 1, PyInt_FromLong(h2-y+yOffset));
+            PyList_SetItem(samples, i*2, tuple);
+            tuple = PyTuple_New(2);
+            PyTuple_SetItem(tuple, 0, PyInt_FromLong(i));
+            PyTuple_SetItem(tuple, 1, PyInt_FromLong(h2+y+yOffset));
+            PyList_SetItem(samples, i*2+1, tuple);
         }
-        y = (int)(absin * h2);
-        PyList_SetItem(samples, i*4, PyInt_FromLong(i));
-        PyList_SetItem(samples, i*4+1, PyInt_FromLong(h2-y));
-        PyList_SetItem(samples, i*4+2, PyInt_FromLong(i));
-        PyList_SetItem(samples, i*4+3, PyInt_FromLong(h2+y));
     }
     return samples;
 };
@@ -4330,15 +4779,15 @@ NewTable_setFeedback(NewTable *self, PyObject *value)
     MYFLT feed;
 
     if (PyNumber_Check(value)) {
-        feed = PyFloat_AsDouble(PyNumber_Float(value));
+        feed = PyFloat_AsDouble(value);
         if (feed < -1.0)
             feed = -1.0;
         else if (feed > 1.0)
             feed = 1.0;
         self->feedback = feed;
     }
-        
-    Py_RETURN_NONE;    
+
+    Py_RETURN_NONE;
 }
 
 static PyMemberDef NewTable_members[] = {
@@ -4356,21 +4805,32 @@ static PyMethodDef NewTable_methods[] = {
 {"setFeedback", (PyCFunction)NewTable_setFeedback, METH_O, "Feedback sets the amount of old data to mix with a new recording."},
 {"setData", (PyCFunction)NewTable_setData, METH_O, "Sets the table from samples in a text file."},
 {"copy", (PyCFunction)NewTable_copy, METH_O, "Copy data from table given in argument."},
+{"copyData", (PyCFunction)NewTable_copyData, METH_VARARGS|METH_KEYWORDS, "Copy data from table given in argument."},
+{"rotate", (PyCFunction)NewTable_rotate, METH_VARARGS|METH_KEYWORDS, "Rotate table around position as argument."},
 {"normalize", (PyCFunction)NewTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"},
 {"reset", (PyCFunction)NewTable_reset, METH_NOARGS, "Resets table samples to 0.0"},
 {"removeDC", (PyCFunction)NewTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."},
 {"reverse", (PyCFunction)NewTable_reverse, METH_NOARGS, "Reverse the table's data."},
+{"invert", (PyCFunction)NewTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."},
+{"rectify", (PyCFunction)NewTable_rectify, METH_NOARGS, "Positive rectification of the table's data."},
+{"bipolarGain", (PyCFunction)NewTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."},
+{"lowpass", (PyCFunction)NewTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."},
+{"fadein", (PyCFunction)NewTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."},
+{"fadeout", (PyCFunction)NewTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."},
+{"pow", (PyCFunction)NewTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."},
 {"put", (PyCFunction)NewTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."},
 {"get", (PyCFunction)NewTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."},
 {"getSize", (PyCFunction)NewTable_getSize, METH_NOARGS, "Return the size of the table in samples."},
 {"getLength", (PyCFunction)NewTable_getLength, METH_NOARGS, "Return the length of the table in seconds."},
 {"getRate", (PyCFunction)NewTable_getRate, METH_NOARGS, "Return the frequency (in cps) that reads the sound without pitch transposition."},
+{"add", (PyCFunction)NewTable_add, METH_O, "Performs table addition."},
+{"sub", (PyCFunction)NewTable_sub, METH_O, "Performs table substraction."},
+{"mul", (PyCFunction)NewTable_mul, METH_O, "Performs table multiplication."},
 {NULL}  /* Sentinel */
 };
 
 PyTypeObject NewTableType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.NewTable_base",         /*tp_name*/
 sizeof(NewTable),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -4378,7 +4838,7 @@ sizeof(NewTable),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 0,                         /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -4415,7 +4875,6 @@ NewTable_new,                 /* tp_new */
 /***********************/
 typedef struct {
     pyo_table_HEAD
-    int pointer;
 } DataTable;
 
 static void
@@ -4431,7 +4890,7 @@ DataTable_traverse(DataTable *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 DataTable_clear(DataTable *self)
 {
     pyo_table_CLEAR
@@ -4443,7 +4902,7 @@ DataTable_dealloc(DataTable* self)
 {
     free(self->data);
     DataTable_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -4453,35 +4912,33 @@ DataTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inittmp=NULL;
     DataTable *self;
     self = (DataTable *)type->tp_alloc(type, 0);
-    
+
     self->server = PyServer_get_server();
-    
-    self->pointer = 0;
-    
+
     MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL);
 
     static char *kwlist[] = {"size", "init", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "i|O", kwlist, &self->size, &inittmp))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     self->data = (MYFLT *)realloc(self->data, (self->size + 1) * sizeof(MYFLT));
-    
+
     for (i=0; i<(self->size+1); i++) {
         self->data[i] = 0.;
     }
-    
+
     TableStream_setSize(self->tablestream, self->size);
-    
+
     if (inittmp) {
         PyObject_CallMethod((PyObject *)self, "setTable", "O", inittmp);
     }
-    
+
     TableStream_setData(self->tablestream, self->data);
 
     double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL));
     TableStream_setSamplingRate(self->tablestream, sr);
-    
+
     return (PyObject *)self;
 }
 
@@ -4492,12 +4949,24 @@ static PyObject * DataTable_normalize(DataTable *self) { NORMALIZE };
 static PyObject * DataTable_reset(DataTable *self) { TABLE_RESET };
 static PyObject * DataTable_removeDC(DataTable *self) { REMOVE_DC };
 static PyObject * DataTable_reverse(DataTable *self) { REVERSE };
+static PyObject * DataTable_invert(DataTable *self) { INVERT };
+static PyObject * DataTable_rectify(DataTable *self) { RECTIFY };
+static PyObject * DataTable_bipolarGain(DataTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN };
+static PyObject * DataTable_lowpass(DataTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS };
+static PyObject * DataTable_fadein(DataTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN };
+static PyObject * DataTable_fadeout(DataTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT };
+static PyObject * DataTable_pow(DataTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER };
 static PyObject * DataTable_copy(DataTable *self, PyObject *arg) { COPY };
+static PyObject * DataTable_copyData(DataTable *self, PyObject *args, PyObject *kwds) { TABLE_COPYDATA };
+static PyObject * DataTable_rotate(DataTable *self, PyObject *args, PyObject *kwds) { TABLE_ROTATE };
 static PyObject * DataTable_setTable(DataTable *self, PyObject *arg) { SET_TABLE };
 static PyObject * DataTable_getTable(DataTable *self) { GET_TABLE };
-static PyObject * DataTable_getViewTable(DataTable *self) { GET_VIEW_TABLE };
+static PyObject * DataTable_getViewTable(DataTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE };
 static PyObject * DataTable_put(DataTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT };
 static PyObject * DataTable_get(DataTable *self, PyObject *args, PyObject *kwds) { TABLE_GET };
+static PyObject * DataTable_add(DataTable *self, PyObject *arg) { TABLE_ADD };
+static PyObject * DataTable_sub(DataTable *self, PyObject *arg) { TABLE_SUB };
+static PyObject * DataTable_mul(DataTable *self, PyObject *arg) { TABLE_MUL };
 
 static PyObject *
 DataTable_getSize(DataTable *self)
@@ -4521,25 +4990,36 @@ static PyMemberDef DataTable_members[] = {
 static PyMethodDef DataTable_methods[] = {
     {"getServer", (PyCFunction)DataTable_getServer, METH_NOARGS, "Returns server object."},
     {"copy", (PyCFunction)DataTable_copy, METH_O, "Copy data from table given in argument."},
+    {"copyData", (PyCFunction)DataTable_copyData, METH_VARARGS|METH_KEYWORDS, "Copy data from table given in argument."},
+    {"rotate", (PyCFunction)DataTable_rotate, METH_VARARGS|METH_KEYWORDS, "Rotate table around position as argument."},
     {"setTable", (PyCFunction)DataTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."},
     {"getTable", (PyCFunction)DataTable_getTable, METH_NOARGS, "Returns a list of table samples."},
-    {"getViewTable", (PyCFunction)DataTable_getViewTable, METH_NOARGS, "Returns a list of pixel coordinates for drawing the table."},
+    {"getViewTable", (PyCFunction)DataTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."},
     {"getTableStream", (PyCFunction)DataTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."},
     {"setData", (PyCFunction)DataTable_setData, METH_O, "Sets the table from samples in a text file."},
     {"normalize", (PyCFunction)DataTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"},
     {"reset", (PyCFunction)DataTable_reset, METH_NOARGS, "Resets table samples to 0.0"},
     {"removeDC", (PyCFunction)DataTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."},
     {"reverse", (PyCFunction)DataTable_reverse, METH_NOARGS, "Reverse the table's data."},
+    {"invert", (PyCFunction)DataTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."},
+    {"rectify", (PyCFunction)DataTable_rectify, METH_NOARGS, "Positive rectification of the table's data."},
+    {"bipolarGain", (PyCFunction)DataTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."},
+    {"lowpass", (PyCFunction)DataTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."},
+    {"fadein", (PyCFunction)DataTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."},
+    {"fadeout", (PyCFunction)DataTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."},
+    {"pow", (PyCFunction)DataTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."},
     {"put", (PyCFunction)DataTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."},
     {"get", (PyCFunction)DataTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."},
     {"getSize", (PyCFunction)DataTable_getSize, METH_NOARGS, "Return the size of the table in samples."},
     {"getRate", (PyCFunction)DataTable_getRate, METH_NOARGS, "Return the frequency (in cps) that reads the sound without pitch transposition."},
+    {"add", (PyCFunction)DataTable_add, METH_O, "Performs table addition."},
+    {"sub", (PyCFunction)DataTable_sub, METH_O, "Performs table substraction."},
+    {"mul", (PyCFunction)DataTable_mul, METH_O, "Performs table multiplication."},
     {NULL}  /* Sentinel */
 };
 
 PyTypeObject DataTableType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.DataTable_base",         /*tp_name*/
     sizeof(DataTable),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -4547,7 +5027,7 @@ PyTypeObject DataTableType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     0,                         /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -4579,215 +5059,861 @@ PyTypeObject DataTableType = {
     DataTable_new,                 /* tp_new */
 };
 
-/******************************/
-/* TableRec object definition */
-/******************************/
+/***********************/
+/* AtanTable structure */
+/***********************/
 typedef struct {
-    pyo_audio_HEAD
-    PyObject *input;
-    Stream *input_stream;
-    NewTable *table;
-    int pointer;
-    int active;
-    MYFLT fadetime;
-    MYFLT fadeInSample;
-    MYFLT *trigsBuffer;
-    TriggerStream *trig_stream;
-    MYFLT *time_buffer_streams;
-    MYFLT *buffer;
-} TableRec;
+    pyo_table_HEAD
+    MYFLT slope;
+} AtanTable;
 
 static void
-TableRec_compute_next_data_frame(TableRec *self)
-{
-    int i, num, upBound;
-    MYFLT val;
-    int size = PyInt_AsLong(NewTable_getSize((NewTable *)self->table));
-
-    for (i=0; i<self->bufsize; i++) {
-        self->trigsBuffer[i] = 0.0;
-    }
-
-    if (!self->active) {
-        for (i=0; i<self->bufsize; i++) {
-            self->time_buffer_streams[i] = self->pointer;
-        }
-    }
-
-    if ((size - self->pointer) >= self->bufsize)
-        num = self->bufsize;
-    else {
-        num = size - self->pointer;
-        if (self->active == 1) {
-            if (num <= 0)
-                self->trigsBuffer[0] = 1.0;
-            else
-                self->trigsBuffer[num-1] = 1.0;
-            self->active = 0;
-        }    
+AtanTable_generate(AtanTable *self) {
+    int i, hsize;
+    MYFLT drv, invhsize, val, t, fac = 0;
+
+    hsize = self->size / 2;
+    invhsize = 1.0 / hsize;
+
+    drv = 1 - self->slope;
+    drv = drv * drv * drv * PI;
+    for(i=0; i<=hsize; i++) {
+        t = i * invhsize - 1;
+        val = MYATAN2(t, drv);
+        if (i == 0)
+            fac = 1.0 / -val;
+        val = val * fac;
+        self->data[i] = val;
+        self->data[self->size - i] = -val;
     }
-
-    if (self->pointer < size) {   
-        upBound = (int)(size - self->fadeInSample);
-        
-        //MYFLT buffer[num];
-        //memset(&buffer, 0, sizeof(buffer));
-        for (i=0; i<self->bufsize; i++) {
-            self->buffer[i] = 0.0;
-        }
-        MYFLT *in = Stream_getData((Stream *)self->input_stream);
-        
-        for (i=0; i<num; i++) {
-            if (self->pointer < self->fadeInSample)
-                val = self->pointer / self->fadeInSample;
-            else if (self->pointer >= upBound)
-                val = (size - (self->pointer+1)) / self->fadeInSample;
-            else
-                val = 1.;
-            self->buffer[i] = in[i] * val;
-            self->time_buffer_streams[i] = self->pointer++;
-        }
-        NewTable_recordChunk((NewTable *)self->table, self->buffer, num);
-        
-        if (num < self->bufsize) {
-            for (i=num; i<self->bufsize; i++) {
-                self->time_buffer_streams[i] = self->pointer;
-            }
-        }
-    }    
-}
-
-static MYFLT *
-TableRec_getTimeBuffer(TableRec *self) {
-    return self->time_buffer_streams;
 }
 
 static int
-TableRec_traverse(TableRec *self, visitproc visit, void *arg)
+AtanTable_traverse(AtanTable *self, visitproc visit, void *arg)
 {
-    pyo_VISIT
-    Py_VISIT(self->input);
-    Py_VISIT(self->input_stream);
-    Py_VISIT(self->table);
-    Py_VISIT(self->trig_stream);    
+    pyo_table_VISIT
     return 0;
 }
 
-static int 
-TableRec_clear(TableRec *self)
+static int
+AtanTable_clear(AtanTable *self)
 {
-    pyo_CLEAR
-    Py_CLEAR(self->input);
-    Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->table);
-    Py_CLEAR(self->trig_stream);    
+    pyo_table_CLEAR
     return 0;
 }
 
 static void
-TableRec_dealloc(TableRec* self)
+AtanTable_dealloc(AtanTable* self)
 {
-    pyo_DEALLOC
-    free(self->buffer);
-    free(self->trigsBuffer);
-    free(self->time_buffer_streams);
-    TableRec_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    free(self->data);
+    AtanTable_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
-TableRec_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+AtanTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
-    int i;
-    PyObject *inputtmp, *input_streamtmp, *tabletmp;
-    TableRec *self;
-    self = (TableRec *)type->tp_alloc(type, 0);
-    
-    self->pointer = 0;
-    self->active = 1;
-    self->fadetime = 0.;
-    
-    INIT_OBJECT_COMMON
+    AtanTable *self;
+    self = (AtanTable *)type->tp_alloc(type, 0);
 
-    Stream_setFunctionPtr(self->stream, TableRec_compute_next_data_frame);
-    Stream_setStreamActive(self->stream, 0);
+    self->server = PyServer_get_server();
 
-    static char *kwlist[] = {"input", "table", "fadetime", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_OO_F, kwlist, &inputtmp, &tabletmp, &self->fadetime))
-        Py_RETURN_NONE; 
-    
-    INIT_INPUT_STREAM
-    
-    if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
-        PySys_WriteStderr("TypeError: \"table\" argument of TableRec must be a PyoTableObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
-    }
-    Py_XDECREF(self->table);
-    self->table = (NewTable *)tabletmp;
-    
-    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
+    self->size = 8192;
+    self->slope = 0.5;
 
-    self->buffer = (MYFLT *)realloc(self->buffer, self->bufsize * sizeof(MYFLT));
-    self->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT));
-    self->time_buffer_streams = (MYFLT *)realloc(self->time_buffer_streams, self->bufsize * sizeof(MYFLT));
+    MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL);
 
-    for (i=0; i<self->bufsize; i++) {
-        self->buffer[i] = self->trigsBuffer[i] = self->time_buffer_streams[i] = 0.0;
-    }    
+    static char *kwlist[] = {"slope", "size", NULL};
 
-    MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL);
-    TriggerStream_setData(self->trig_stream, self->trigsBuffer);
-    
-    int size = PyInt_AsLong(NewTable_getSize((NewTable *)self->table));
-    if ((self->fadetime * self->sr) >= (size * 0.5))
-        self->fadetime = size * 0.499 / self->sr;
-    if (self->fadetime == 0.0)
-        self->fadeInSample = 0.0;
-    else
-        self->fadeInSample = MYFLOOR(self->fadetime * self->sr);
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_F_I, kwlist, &self->slope, &self->size))
+        Py_RETURN_NONE;
+
+    self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
+    TableStream_setSize(self->tablestream, self->size);
+	TableStream_setData(self->tablestream, self->data);
+    AtanTable_generate(self);
+
+    double sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL));
+    TableStream_setSamplingRate(self->tablestream, sr);
 
     return (PyObject *)self;
 }
 
-static PyObject * TableRec_getServer(TableRec* self) { GET_SERVER };
-static PyObject * TableRec_getStream(TableRec* self) { GET_STREAM };
-static PyObject * TableRec_getTriggerStream(TableRec* self) { GET_TRIGGER_STREAM };
+static PyObject * AtanTable_getServer(AtanTable* self) { GET_SERVER };
+static PyObject * AtanTable_getTableStream(AtanTable* self) { GET_TABLE_STREAM };
+static PyObject * AtanTable_setData(AtanTable *self, PyObject *arg) { SET_TABLE_DATA };
+static PyObject * AtanTable_normalize(AtanTable *self) { NORMALIZE };
+static PyObject * AtanTable_reset(AtanTable *self) { TABLE_RESET };
+static PyObject * AtanTable_removeDC(AtanTable *self) { REMOVE_DC };
+static PyObject * AtanTable_reverse(AtanTable *self) { REVERSE };
+static PyObject * AtanTable_invert(AtanTable *self) { INVERT };
+static PyObject * AtanTable_rectify(AtanTable *self) { RECTIFY };
+static PyObject * AtanTable_bipolarGain(AtanTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN };
+static PyObject * AtanTable_lowpass(AtanTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS };
+static PyObject * AtanTable_fadein(AtanTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN };
+static PyObject * AtanTable_fadeout(AtanTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT };
+static PyObject * AtanTable_pow(AtanTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER };
+static PyObject * AtanTable_copy(AtanTable *self, PyObject *arg) { COPY };
+static PyObject * AtanTable_copyData(AtanTable *self, PyObject *args, PyObject *kwds) { TABLE_COPYDATA };
+static PyObject * AtanTable_rotate(AtanTable *self, PyObject *args, PyObject *kwds) { TABLE_ROTATE };
+static PyObject * AtanTable_setTable(AtanTable *self, PyObject *arg) { SET_TABLE };
+static PyObject * AtanTable_getTable(AtanTable *self) { GET_TABLE };
+static PyObject * AtanTable_getViewTable(AtanTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE };
+static PyObject * AtanTable_put(AtanTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT };
+static PyObject * AtanTable_get(AtanTable *self, PyObject *args, PyObject *kwds) { TABLE_GET };
+static PyObject * AtanTable_add(AtanTable *self, PyObject *arg) { TABLE_ADD };
+static PyObject * AtanTable_sub(AtanTable *self, PyObject *arg) { TABLE_SUB };
+static PyObject * AtanTable_mul(AtanTable *self, PyObject *arg) { TABLE_MUL };
 
-static PyObject * TableRec_play(TableRec *self, PyObject *args, PyObject *kwds) 
-{ 
-    self->pointer = 0;
-    self->active = 1;
-    PLAY 
-};
+static PyObject *
+AtanTable_setSlope(AtanTable *self, PyObject *value)
+{
+
+    if (! PyNumber_Check(value)) {
+        PyErr_SetString(PyExc_TypeError, "The slope attribute value must be a number.");
+        return PyInt_FromLong(-1);
+    }
+
+    self->slope = PyFloat_AsDouble(value);
+    if (self->slope < 0.0)
+        self->slope = 0.0;
+    else if (self->slope > 1.0)
+        self->slope = 1.0;
 
-static PyObject * TableRec_stop(TableRec *self) { STOP };
+    AtanTable_generate(self);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
 
 static PyObject *
-TableRec_setTable(TableRec *self, PyObject *arg)
+AtanTable_setSize(AtanTable *self, PyObject *value)
 {
-	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	tmp = arg;
-    Py_INCREF(tmp);
-	Py_DECREF(self->table);
-    self->table = (NewTable *)tmp;
-    
-	Py_INCREF(Py_None);
-	return Py_None;
-}
+    if (value == NULL) {
+        PyErr_SetString(PyExc_TypeError, "Cannot delete the size attribute.");
+        return PyInt_FromLong(-1);
+    }
 
-static PyMemberDef TableRec_members[] = {
-{"server", T_OBJECT_EX, offsetof(TableRec, server), 0, "Pyo server."},
-{"stream", T_OBJECT_EX, offsetof(TableRec, stream), 0, "Stream object."},
+    if (! PyInt_Check(value)) {
+        PyErr_SetString(PyExc_TypeError, "The size attribute value must be an integer.");
+        return PyInt_FromLong(-1);
+    }
+
+    self->size = PyInt_AsLong(value);
+
+    self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
+    TableStream_setSize(self->tablestream, self->size);
+
+    AtanTable_generate(self);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *
+AtanTable_getSize(AtanTable *self)
+{
+    return PyInt_FromLong(self->size);
+};
+
+static PyMemberDef AtanTable_members[] = {
+    {"server", T_OBJECT_EX, offsetof(AtanTable, server), 0, "Pyo server."},
+    {"tablestream", T_OBJECT_EX, offsetof(AtanTable, tablestream), 0, "Table stream object."},
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef AtanTable_methods[] = {
+    {"getServer", (PyCFunction)AtanTable_getServer, METH_NOARGS, "Returns server object."},
+    {"copy", (PyCFunction)AtanTable_copy, METH_O, "Copy data from table given in argument."},
+    {"copyData", (PyCFunction)AtanTable_copyData, METH_VARARGS|METH_KEYWORDS, "Copy data from table given in argument."},
+    {"rotate", (PyCFunction)AtanTable_rotate, METH_VARARGS|METH_KEYWORDS, "Rotate table around position as argument."},
+    {"setTable", (PyCFunction)AtanTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."},
+    {"getTable", (PyCFunction)AtanTable_getTable, METH_NOARGS, "Returns a list of table samples."},
+    {"getViewTable", (PyCFunction)AtanTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."},
+    {"getTableStream", (PyCFunction)AtanTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."},
+    {"setData", (PyCFunction)AtanTable_setData, METH_O, "Sets the table from samples in a text file."},
+    {"normalize", (PyCFunction)AtanTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"},
+    {"reset", (PyCFunction)AtanTable_reset, METH_NOARGS, "Resets table samples to 0.0"},
+    {"removeDC", (PyCFunction)AtanTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."},
+    {"reverse", (PyCFunction)AtanTable_reverse, METH_NOARGS, "Reverse the table's data."},
+    {"invert", (PyCFunction)AtanTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."},
+    {"rectify", (PyCFunction)AtanTable_rectify, METH_NOARGS, "Positive rectification of the table's data."},
+    {"bipolarGain", (PyCFunction)AtanTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."},
+    {"lowpass", (PyCFunction)AtanTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."},
+    {"fadein", (PyCFunction)AtanTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."},
+    {"fadeout", (PyCFunction)AtanTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."},
+    {"pow", (PyCFunction)AtanTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."},
+    {"setSize", (PyCFunction)AtanTable_setSize, METH_O, "Sets the size of the table in samples"},
+    {"getSize", (PyCFunction)AtanTable_getSize, METH_NOARGS, "Return the size of the table in samples"},
+    {"setSlope", (PyCFunction)AtanTable_setSlope, METH_O, "Sets the slope of the atan function."},
+    {"put", (PyCFunction)AtanTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."},
+    {"get", (PyCFunction)AtanTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."},
+    {"add", (PyCFunction)AtanTable_add, METH_O, "Performs table addition."},
+    {"sub", (PyCFunction)AtanTable_sub, METH_O, "Performs table substraction."},
+    {"mul", (PyCFunction)AtanTable_mul, METH_O, "Performs table multiplication."},
+    {NULL}  /* Sentinel */
+};
+
+PyTypeObject AtanTableType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.AtanTable_base",         /*tp_name*/
+    sizeof(AtanTable),         /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)AtanTable_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*/
+    "AtanTable objects. Generates a table filled with a sinc function.",  /* tp_doc */
+    (traverseproc)AtanTable_traverse,   /* tp_traverse */
+    (inquiry)AtanTable_clear,           /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    AtanTable_methods,             /* tp_methods */
+    AtanTable_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 */
+    AtanTable_new,                 /* tp_new */
+};
+
+static int
+isPowerOfTwo(int x) {
+    return (x != 0) && ((x & (x - 1)) == 0);
+}
+
+/***********************/
+/* PadSynthTable structure */
+/***********************/
+typedef struct {
+    pyo_table_HEAD
+    MYFLT **twiddle;
+    MYFLT basefreq;
+    MYFLT spread;
+    MYFLT bw;
+    MYFLT bwscl;
+    int nharms;
+    MYFLT damp;
+    double sr;
+} PadSynthTable;
+
+static void
+PadSynthTable_gen_twiddle(PadSynthTable *self) {
+    int i, n8;
+    n8 = self->size >> 3;
+    self->twiddle = (MYFLT **)realloc(self->twiddle, 4 * sizeof(MYFLT *));
+    for(i=0; i<4; i++)
+        self->twiddle[i] = (MYFLT *)malloc(n8 * sizeof(MYFLT));
+    fft_compute_split_twiddle(self->twiddle, self->size);
+}
+
+static void
+PadSynthTable_generate(PadSynthTable *self) {
+    int i, nh;
+    int hsize = self->size / 2;
+    MYFLT bfac, i2sr, bfonsr, nhspd, bwhz, bwi, fi, gain, absv, max, x;
+    MYFLT ifsize = 1.0 / (MYFLT)self->size;
+    MYFLT twopirndmax = TWOPI / (MYFLT)RAND_MAX;
+    MYFLT amp[hsize];
+    MYFLT phase[hsize];
+    MYFLT real[hsize];
+    MYFLT imag[hsize];
+    MYFLT inframe[self->size];
+
+    for (i=0; i<hsize; i++) {
+        amp[i] = 0.0;
+    }
+    
+    bfac = (MYPOW(2.0, self->bw / 1200.0) - 1.0) * self->basefreq;
+    i2sr = 1.0 / (2.0 * self->sr);
+    bfonsr = self->basefreq / self->sr;
+    gain = self->damp;
+    for (nh=1; nh<self->nharms; nh++) {
+        nhspd = MYPOW(nh, self->spread);
+        bwhz = bfac * MYPOW(nhspd, self->bwscl);
+        bwi = 1.0 / (bwhz * i2sr);
+        fi = bfonsr * nhspd;
+        for (i=0; i<hsize; i++) {
+            // harmonic profile.
+            x = (i * ifsize - fi) * bwi;
+            x *= x;
+            if (x < 14.71280603)
+                amp[i] += MYEXP(-x) * bwi * gain;
+        }
+        gain *= self->damp;
+    }
+
+    for (i=0; i<hsize; i++) {
+        phase[i] = rand() * twopirndmax;
+    }
+
+    for (i=0; i<hsize; i++) {
+        real[i] = amp[i] * MYCOS(phase[i]);
+        imag[i] = amp[i] * MYSIN(phase[i]);
+    }
+    
+    inframe[0] = real[0];
+    inframe[hsize] = 0.0;
+    for (i=1; i<hsize; i++) {
+        inframe[i] = real[i];
+        inframe[self->size - i] = imag[i];
+    }
+
+    irealfft_split(inframe, self->data, self->size, self->twiddle);
+
+    max = 0.0;
+    for (i=0; i<self->size; i++) {
+        absv = MYFABS(self->data[i]);
+        if (absv > max)
+            max = absv;
+    }
+    if (max < 1e-5)
+        max = 1e-5;
+    max = 1.0 / (max * 1.4142);
+    for (i=0; i<self->size; i++) {
+        self->data[i] *= max;
+    }
+
+    self->data[self->size] = self->data[0];
+}
+
+static int
+PadSynthTable_traverse(PadSynthTable *self, visitproc visit, void *arg)
+{
+    pyo_table_VISIT
+    return 0;
+}
+
+static int
+PadSynthTable_clear(PadSynthTable *self)
+{
+    pyo_table_CLEAR
+    return 0;
+}
+
+static void
+PadSynthTable_dealloc(PadSynthTable* self)
+{
+    int i;
+    for(i=0; i<4; i++) {
+        free(self->twiddle[i]);
+    }
+    free(self->twiddle);
+    free(self->data);
+    PadSynthTable_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+PadSynthTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    PadSynthTable *self;
+    self = (PadSynthTable *)type->tp_alloc(type, 0);
+
+    self->server = PyServer_get_server();
+
+    self->size = 262144;
+    self->basefreq = 440;
+    self->spread = 1.0;
+    self->bw = 50.0;
+    self->bwscl = 1.0;
+    self->nharms = 64;
+    self->damp = 0.7;
+
+    MAKE_NEW_TABLESTREAM(self->tablestream, &TableStreamType, NULL);
+
+    static char *kwlist[] = {"basefreq", "spread", "bw", "bwscl", "nharms", "damp", "size", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE__FFFFIFI, kwlist, &self->basefreq, &self->spread, &self->bw,
+                                      &self->bwscl, &self->nharms, &self->damp, &self->size))
+        Py_RETURN_NONE;
+
+    if (!isPowerOfTwo(self->size)) {
+        int k = 1;
+        while (k < self->size)
+            k *= 2;
+        self->size = k;
+        PySys_WriteStdout("PadSynthTable size must be a power-of-2, using the next power-of-2 greater than size : %d\n", self->size);
+    }
+
+    self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
+    TableStream_setSize(self->tablestream, self->size);
+	TableStream_setData(self->tablestream, self->data);
+
+    self->sr = PyFloat_AsDouble(PyObject_CallMethod(self->server, "getSamplingRate", NULL));
+    TableStream_setSamplingRate(self->tablestream, self->sr);
+
+    PadSynthTable_gen_twiddle(self);
+
+    srand(time(NULL));
+    PadSynthTable_generate(self);
+
+    return (PyObject *)self;
+}
+
+static PyObject * PadSynthTable_getServer(PadSynthTable* self) { GET_SERVER };
+static PyObject * PadSynthTable_getTableStream(PadSynthTable* self) { GET_TABLE_STREAM };
+static PyObject * PadSynthTable_setData(PadSynthTable *self, PyObject *arg) { SET_TABLE_DATA };
+static PyObject * PadSynthTable_normalize(PadSynthTable *self) { NORMALIZE };
+static PyObject * PadSynthTable_reset(PadSynthTable *self) { TABLE_RESET };
+static PyObject * PadSynthTable_removeDC(PadSynthTable *self) { REMOVE_DC };
+static PyObject * PadSynthTable_reverse(PadSynthTable *self) { REVERSE };
+static PyObject * PadSynthTable_invert(PadSynthTable *self) { INVERT };
+static PyObject * PadSynthTable_rectify(PadSynthTable *self) { RECTIFY };
+static PyObject * PadSynthTable_bipolarGain(PadSynthTable *self, PyObject *args, PyObject *kwds) { TABLE_BIPOLAR_GAIN };
+static PyObject * PadSynthTable_lowpass(PadSynthTable *self, PyObject *args, PyObject *kwds) { TABLE_LOWPASS };
+static PyObject * PadSynthTable_fadein(PadSynthTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEIN };
+static PyObject * PadSynthTable_fadeout(PadSynthTable *self, PyObject *args, PyObject *kwds) { TABLE_FADEOUT };
+static PyObject * PadSynthTable_pow(PadSynthTable *self, PyObject *args, PyObject *kwds) { TABLE_POWER };
+static PyObject * PadSynthTable_copy(PadSynthTable *self, PyObject *arg) { COPY };
+static PyObject * PadSynthTable_copyData(PadSynthTable *self, PyObject *args, PyObject *kwds) { TABLE_COPYDATA };
+static PyObject * PadSynthTable_rotate(PadSynthTable *self, PyObject *args, PyObject *kwds) { TABLE_ROTATE };
+static PyObject * PadSynthTable_setTable(PadSynthTable *self, PyObject *arg) { SET_TABLE };
+static PyObject * PadSynthTable_getTable(PadSynthTable *self) { GET_TABLE };
+static PyObject * PadSynthTable_getViewTable(PadSynthTable *self, PyObject *args, PyObject *kwds) { GET_VIEW_TABLE };
+static PyObject * PadSynthTable_put(PadSynthTable *self, PyObject *args, PyObject *kwds) { TABLE_PUT };
+static PyObject * PadSynthTable_get(PadSynthTable *self, PyObject *args, PyObject *kwds) { TABLE_GET };
+static PyObject * PadSynthTable_add(PadSynthTable *self, PyObject *arg) { TABLE_ADD };
+static PyObject * PadSynthTable_sub(PadSynthTable *self, PyObject *arg) { TABLE_SUB };
+static PyObject * PadSynthTable_mul(PadSynthTable *self, PyObject *arg) { TABLE_MUL };
+
+static PyObject *
+PadSynthTable_setBaseFreq(PadSynthTable *self, PyObject *args, PyObject *kwds)
+{
+    int generate = 1;
+
+    static char *kwlist[] = {"basefreq", "generate", NULL};
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_F_I, kwlist, &self->basefreq, &generate))
+        Py_RETURN_NONE;
+
+    if (generate)
+        PadSynthTable_generate(self);
+
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+PadSynthTable_setSpread(PadSynthTable *self, PyObject *args, PyObject *kwds)
+{
+    int generate = 1;
+
+    static char *kwlist[] = {"spread", "generate", NULL};
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_F_I, kwlist, &self->spread, &generate))
+        Py_RETURN_NONE;
+
+    if (generate)
+        PadSynthTable_generate(self);
+
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+PadSynthTable_setBw(PadSynthTable *self, PyObject *args, PyObject *kwds)
+{
+    int generate = 1;
+
+    static char *kwlist[] = {"bw", "generate", NULL};
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_F_I, kwlist, &self->bw, &generate))
+        Py_RETURN_NONE;
+
+    if (generate)
+        PadSynthTable_generate(self);
+
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+PadSynthTable_setBwScl(PadSynthTable *self, PyObject *args, PyObject *kwds)
+{
+    int generate = 1;
+
+    static char *kwlist[] = {"bwscl", "generate", NULL};
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_F_I, kwlist, &self->bwscl, &generate))
+        Py_RETURN_NONE;
+
+    if (generate)
+        PadSynthTable_generate(self);
+
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+PadSynthTable_setNharms(PadSynthTable *self, PyObject *args, PyObject *kwds)
+{
+    int generate = 1;
+
+    static char *kwlist[] = {"nharms", "generate", NULL};
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwlist, &self->nharms, &generate))
+        Py_RETURN_NONE;
+
+    if (generate)
+        PadSynthTable_generate(self);
+
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+PadSynthTable_setDamp(PadSynthTable *self, PyObject *args, PyObject *kwds)
+{
+    int generate = 1;
+
+    static char *kwlist[] = {"damp", "generate", NULL};
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_F_I, kwlist, &self->damp, &generate))
+        Py_RETURN_NONE;
+
+    if (generate)
+        PadSynthTable_generate(self);
+
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+PadSynthTable_setSize(PadSynthTable *self, PyObject *args, PyObject *kwds)
+{
+    int generate = 1;
+
+    static char *kwlist[] = {"size", "generate", NULL};
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "i|i", kwlist, &self->size, &generate))
+        Py_RETURN_NONE;
+
+    if (!isPowerOfTwo(self->size)) {
+        int k = 1;
+        while (k < self->size)
+            k *= 2;
+        self->size = k;
+        PySys_WriteStdout("PadSynthTable size must be a power-of-2, using the next power-of-2 greater than size : %d\n", self->size);
+    }
+
+    self->data = (MYFLT *)realloc(self->data, (self->size+1) * sizeof(MYFLT));
+    TableStream_setSize(self->tablestream, self->size);
+
+    if (generate)
+        PadSynthTable_generate(self);
+
+    Py_RETURN_NONE;
+}
+
+static PyObject *
+PadSynthTable_getSize(PadSynthTable *self)
+{
+    return PyInt_FromLong(self->size);
+};
+
+static PyMemberDef PadSynthTable_members[] = {
+    {"server", T_OBJECT_EX, offsetof(PadSynthTable, server), 0, "Pyo server."},
+    {"tablestream", T_OBJECT_EX, offsetof(PadSynthTable, tablestream), 0, "Table stream object."},
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef PadSynthTable_methods[] = {
+    {"getServer", (PyCFunction)PadSynthTable_getServer, METH_NOARGS, "Returns server object."},
+    {"copy", (PyCFunction)PadSynthTable_copy, METH_O, "Copy data from table given in argument."},
+    {"copyData", (PyCFunction)PadSynthTable_copyData, METH_VARARGS|METH_KEYWORDS, "Copy data from table given in argument."},
+    {"rotate", (PyCFunction)PadSynthTable_rotate, METH_VARARGS|METH_KEYWORDS, "Rotate table around position as argument."},
+    {"setTable", (PyCFunction)PadSynthTable_setTable, METH_O, "Sets the table content from a list of floats (must be the same size as the object size)."},
+    {"getTable", (PyCFunction)PadSynthTable_getTable, METH_NOARGS, "Returns a list of table samples."},
+    {"getViewTable", (PyCFunction)PadSynthTable_getViewTable, METH_VARARGS|METH_KEYWORDS, "Returns a list of pixel coordinates for drawing the table."},
+    {"getTableStream", (PyCFunction)PadSynthTable_getTableStream, METH_NOARGS, "Returns table stream object created by this table."},
+    {"setData", (PyCFunction)PadSynthTable_setData, METH_O, "Sets the table from samples in a text file."},
+    {"normalize", (PyCFunction)PadSynthTable_normalize, METH_NOARGS, "Normalize table samples between -1 and 1"},
+    {"reset", (PyCFunction)PadSynthTable_reset, METH_NOARGS, "Resets table samples to 0.0"},
+    {"removeDC", (PyCFunction)PadSynthTable_removeDC, METH_NOARGS, "Filter out DC offset from the table's data."},
+    {"reverse", (PyCFunction)PadSynthTable_reverse, METH_NOARGS, "Reverse the table's data."},
+    {"invert", (PyCFunction)PadSynthTable_invert, METH_NOARGS, "Reverse the table's data in amplitude."},
+    {"rectify", (PyCFunction)PadSynthTable_rectify, METH_NOARGS, "Positive rectification of the table's data."},
+    {"bipolarGain", (PyCFunction)PadSynthTable_bipolarGain, METH_VARARGS|METH_KEYWORDS, "Apply different amp values to positive and negative samples."},
+    {"lowpass", (PyCFunction)PadSynthTable_lowpass, METH_VARARGS|METH_KEYWORDS, "Apply a one-pole lowpass filter on table's samples."},
+    {"fadein", (PyCFunction)PadSynthTable_fadein, METH_VARARGS|METH_KEYWORDS, "Apply a gradual increase in the level of the table's samples."},
+    {"fadeout", (PyCFunction)PadSynthTable_fadeout, METH_VARARGS|METH_KEYWORDS, "Apply a gradual decrease in the level of the table's samples."},
+    {"pow", (PyCFunction)PadSynthTable_pow, METH_VARARGS|METH_KEYWORDS, "Apply a power function on each sample in the table."},
+    //{"setSize", (PyCFunction)PadSynthTable_setSize, METH_O, "Sets the size of the table in samples"},
+    {"getSize", (PyCFunction)PadSynthTable_getSize, METH_NOARGS, "Return the size of the table in samples"},
+    {"setBaseFreq", (PyCFunction)PadSynthTable_setBaseFreq, METH_VARARGS|METH_KEYWORDS, "Sets the base frequency in hertz."},
+    {"setSpread", (PyCFunction)PadSynthTable_setSpread, METH_VARARGS|METH_KEYWORDS, "Sets the frequency spreading factor."},
+    {"setBw", (PyCFunction)PadSynthTable_setBw, METH_VARARGS|METH_KEYWORDS, "Sets the bandwitdh of the first harmonic in cents."},
+    {"setBwScl", (PyCFunction)PadSynthTable_setBwScl, METH_VARARGS|METH_KEYWORDS, "Sets the bandwitdh scaling factor."},
+    {"setNharms", (PyCFunction)PadSynthTable_setNharms, METH_VARARGS|METH_KEYWORDS, "Sets the number of harmonics."},
+    {"setDamp", (PyCFunction)PadSynthTable_setDamp, METH_VARARGS|METH_KEYWORDS, "Sets the damping factor."},
+    {"setSize", (PyCFunction)PadSynthTable_setSize, METH_VARARGS|METH_KEYWORDS, "Sets the size of the table in samples"},
+    {"put", (PyCFunction)PadSynthTable_put, METH_VARARGS|METH_KEYWORDS, "Puts a value at specified position in the table."},
+    {"get", (PyCFunction)PadSynthTable_get, METH_VARARGS|METH_KEYWORDS, "Gets the value at specified position in the table."},
+    {"add", (PyCFunction)PadSynthTable_add, METH_O, "Performs table addition."},
+    {"sub", (PyCFunction)PadSynthTable_sub, METH_O, "Performs table substraction."},
+    {"mul", (PyCFunction)PadSynthTable_mul, METH_O, "Performs table multiplication."},
+    {NULL}  /* Sentinel */
+};
+
+PyTypeObject PadSynthTableType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.PadSynthTable_base",         /*tp_name*/
+    sizeof(PadSynthTable),         /*tp_basicsize*/
+    0,                         /*tp_itemsize*/
+    (destructor)PadSynthTable_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*/
+    "PadSynthTable objects. Generates a table filled with a sinc function.",  /* tp_doc */
+    (traverseproc)PadSynthTable_traverse,   /* tp_traverse */
+    (inquiry)PadSynthTable_clear,           /* tp_clear */
+    0,		               /* tp_richcompare */
+    0,		               /* tp_weaklistoffset */
+    0,		               /* tp_iter */
+    0,		               /* tp_iternext */
+    PadSynthTable_methods,             /* tp_methods */
+    PadSynthTable_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 */
+    PadSynthTable_new,                 /* tp_new */
+};
+
+/******************************/
+/* TableRec object definition */
+/******************************/
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *input;
+    Stream *input_stream;
+    NewTable *table;
+    int pointer;
+    int active;
+    MYFLT fadetime;
+    MYFLT fadeInSample;
+    MYFLT *trigsBuffer;
+    TriggerStream *trig_stream;
+    MYFLT *time_buffer_streams;
+    MYFLT *buffer;
+} TableRec;
+
+static void
+TableRec_compute_next_data_frame(TableRec *self)
+{
+    int i, num, upBound;
+    MYFLT val;
+    int size = PyInt_AsLong(NewTable_getSize((NewTable *)self->table));
+
+    for (i=0; i<self->bufsize; i++) {
+        self->trigsBuffer[i] = 0.0;
+    }
+
+    if (!self->active) {
+        for (i=0; i<self->bufsize; i++) {
+            self->time_buffer_streams[i] = self->pointer;
+        }
+    }
+
+    if ((size - self->pointer) >= self->bufsize)
+        num = self->bufsize;
+    else {
+        num = size - self->pointer;
+        if (self->active == 1) {
+            if (num <= 0)
+                self->trigsBuffer[0] = 1.0;
+            else
+                self->trigsBuffer[num-1] = 1.0;
+            self->active = 0;
+        }
+    }
+
+    if (self->pointer < size) {
+        upBound = (int)(size - self->fadeInSample);
+
+        for (i=0; i<self->bufsize; i++) {
+            self->buffer[i] = 0.0;
+        }
+        MYFLT *in = Stream_getData((Stream *)self->input_stream);
+
+        for (i=0; i<num; i++) {
+            if (self->pointer < self->fadeInSample)
+                val = self->pointer / self->fadeInSample;
+            else if (self->pointer >= upBound)
+                val = (size - (self->pointer+1)) / self->fadeInSample;
+            else
+                val = 1.;
+            self->buffer[i] = in[i] * val;
+            self->time_buffer_streams[i] = self->pointer++;
+        }
+        NewTable_recordChunk((NewTable *)self->table, self->buffer, num);
+
+        if (num < self->bufsize) {
+            for (i=num; i<self->bufsize; i++) {
+                self->time_buffer_streams[i] = self->pointer;
+            }
+        }
+    }
+}
+
+static MYFLT *
+TableRec_getTimeBuffer(TableRec *self) {
+    return self->time_buffer_streams;
+}
+
+static int
+TableRec_traverse(TableRec *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->input);
+    Py_VISIT(self->input_stream);
+    Py_VISIT(self->table);
+    Py_VISIT(self->trig_stream);
+    return 0;
+}
+
+static int
+TableRec_clear(TableRec *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->input);
+    Py_CLEAR(self->input_stream);
+    Py_CLEAR(self->table);
+    Py_CLEAR(self->trig_stream);
+    return 0;
+}
+
+static void
+TableRec_dealloc(TableRec* self)
+{
+    pyo_DEALLOC
+    free(self->buffer);
+    free(self->trigsBuffer);
+    free(self->time_buffer_streams);
+    TableRec_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+TableRec_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *inputtmp, *input_streamtmp, *tabletmp;
+    TableRec *self;
+    self = (TableRec *)type->tp_alloc(type, 0);
+
+    self->pointer = 0;
+    self->active = 1;
+    self->fadetime = 0.;
+
+    INIT_OBJECT_COMMON
+
+    Stream_setFunctionPtr(self->stream, TableRec_compute_next_data_frame);
+
+    static char *kwlist[] = {"input", "table", "fadetime", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_OO_F, kwlist, &inputtmp, &tabletmp, &self->fadetime))
+        Py_RETURN_NONE;
+
+    INIT_INPUT_STREAM
+
+    if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
+        PyErr_SetString(PyExc_TypeError, "\"table\" argument of TableRec must be a PyoTableObject.\n");
+        Py_RETURN_NONE;
+    }
+    Py_XDECREF(self->table);
+    Py_INCREF(tabletmp);
+    self->table = (NewTable *)tabletmp;
+
+    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
+
+    self->buffer = (MYFLT *)realloc(self->buffer, self->bufsize * sizeof(MYFLT));
+    self->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT));
+    self->time_buffer_streams = (MYFLT *)realloc(self->time_buffer_streams, self->bufsize * sizeof(MYFLT));
+
+    for (i=0; i<self->bufsize; i++) {
+        self->buffer[i] = self->trigsBuffer[i] = self->time_buffer_streams[i] = 0.0;
+    }
+
+    MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL);
+    TriggerStream_setData(self->trig_stream, self->trigsBuffer);
+
+    int size = PyInt_AsLong(NewTable_getSize((NewTable *)self->table));
+    if ((self->fadetime * self->sr) >= (size * 0.5))
+        self->fadetime = size * 0.499 / self->sr;
+    if (self->fadetime == 0.0)
+        self->fadeInSample = 0.0;
+    else
+        self->fadeInSample = MYFLOOR(self->fadetime * self->sr);
+
+    return (PyObject *)self;
+}
+
+static PyObject * TableRec_getServer(TableRec* self) { GET_SERVER };
+static PyObject * TableRec_getStream(TableRec* self) { GET_STREAM };
+static PyObject * TableRec_getTriggerStream(TableRec* self) { GET_TRIGGER_STREAM };
+
+static PyObject * TableRec_play(TableRec *self, PyObject *args, PyObject *kwds)
+{
+    int j;
+    for (j=0; j<self->bufsize; j++) {
+        self->time_buffer_streams[j] = 0;
+    }
+    self->pointer = 0;
+    self->active = 1;
+    NewTable_resetRecordingPointer((NewTable *)self->table);
+    PLAY
+};
+
+static PyObject * TableRec_stop(TableRec *self) { 
+    int j;
+    for (j=0; j<self->bufsize; j++) {
+        self->time_buffer_streams[j] = self->pointer;
+    }
+    STOP 
+};
+
+static PyObject *
+TableRec_setTable(TableRec *self, PyObject *arg)
+{
+	PyObject *tmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	tmp = arg;
+    Py_INCREF(tmp);
+	Py_DECREF(self->table);
+    self->table = (NewTable *)tmp;
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyMemberDef TableRec_members[] = {
+{"server", T_OBJECT_EX, offsetof(TableRec, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(TableRec, stream), 0, "Stream object."},
 {"trig_stream", T_OBJECT_EX, offsetof(TableRec, trig_stream), 0, "Trigger Stream object."},
 {"input", T_OBJECT_EX, offsetof(TableRec, input), 0, "Input sound object."},
 {"table", T_OBJECT_EX, offsetof(TableRec, table), 0, "Table to record in."},
@@ -4805,8 +5931,7 @@ static PyMethodDef TableRec_methods[] = {
 };
 
 PyTypeObject TableRecType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.TableRec_base",         /*tp_name*/
 sizeof(TableRec),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -4814,7 +5939,7 @@ sizeof(TableRec),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 0,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -4866,36 +5991,36 @@ static void
 TableRecTimeStream_setProcMode(TableRecTimeStream *self) {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = TableRecTimeStream_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = TableRecTimeStream_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = TableRecTimeStream_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = TableRecTimeStream_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = TableRecTimeStream_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = TableRecTimeStream_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = TableRecTimeStream_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = TableRecTimeStream_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = TableRecTimeStream_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
@@ -4906,7 +6031,7 @@ TableRecTimeStream_compute_next_data_frame(TableRecTimeStream *self)
     tmp = TableRec_getTimeBuffer((TableRec *)self->mainPlayer);
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = tmp[i];
-    }    
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -4918,11 +6043,11 @@ TableRecTimeStream_traverse(TableRecTimeStream *self, visitproc visit, void *arg
     return 0;
 }
 
-static int 
+static int
 TableRecTimeStream_clear(TableRecTimeStream *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->mainPlayer);    
+    Py_CLEAR(self->mainPlayer);
     return 0;
 }
 
@@ -4931,7 +6056,7 @@ TableRecTimeStream_dealloc(TableRecTimeStream* self)
 {
     pyo_DEALLOC
     TableRecTimeStream_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -4941,36 +6066,36 @@ TableRecTimeStream_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *maintmp=NULL;
     TableRecTimeStream *self;
     self = (TableRecTimeStream *)type->tp_alloc(type, 0);
-    
+
     self->modebuffer[0] = 0;
     self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, TableRecTimeStream_compute_next_data_frame);
     self->mode_func_ptr = TableRecTimeStream_setProcMode;
 
     static char *kwlist[] = {"mainPlayer", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &maintmp))
         Py_RETURN_NONE;
-    
+
     Py_XDECREF(self->mainPlayer);
     Py_INCREF(maintmp);
     self->mainPlayer = (TableRec *)maintmp;
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * TableRecTimeStream_getServer(TableRecTimeStream* self) { GET_SERVER };
 static PyObject * TableRecTimeStream_getStream(TableRecTimeStream* self) { GET_STREAM };
-static PyObject * TableRecTimeStream_setMul(TableRecTimeStream *self, PyObject *arg) { SET_MUL };	
-static PyObject * TableRecTimeStream_setAdd(TableRecTimeStream *self, PyObject *arg) { SET_ADD };	
-static PyObject * TableRecTimeStream_setSub(TableRecTimeStream *self, PyObject *arg) { SET_SUB };	
-static PyObject * TableRecTimeStream_setDiv(TableRecTimeStream *self, PyObject *arg) { SET_DIV };	
+static PyObject * TableRecTimeStream_setMul(TableRecTimeStream *self, PyObject *arg) { SET_MUL };
+static PyObject * TableRecTimeStream_setAdd(TableRecTimeStream *self, PyObject *arg) { SET_ADD };
+static PyObject * TableRecTimeStream_setSub(TableRecTimeStream *self, PyObject *arg) { SET_SUB };
+static PyObject * TableRecTimeStream_setDiv(TableRecTimeStream *self, PyObject *arg) { SET_DIV };
 
 static PyObject * TableRecTimeStream_play(TableRecTimeStream *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * TableRecTimeStream_out(TableRecTimeStream *self, PyObject *args, PyObject *kwds) { OUT };
@@ -5002,7 +6127,7 @@ static PyMethodDef TableRecTimeStream_methods[] = {
     {"setMul", (PyCFunction)TableRecTimeStream_setMul, METH_O, "Sets oscillator mul factor."},
     {"setAdd", (PyCFunction)TableRecTimeStream_setAdd, METH_O, "Sets oscillator add factor."},
     {"setSub", (PyCFunction)TableRecTimeStream_setSub, METH_O, "Sets inverse add factor."},
-    {"setDiv", (PyCFunction)TableRecTimeStream_setDiv, METH_O, "Sets inverse mul factor."},    
+    {"setDiv", (PyCFunction)TableRecTimeStream_setDiv, METH_O, "Sets inverse mul factor."},
     {NULL}  /* Sentinel */
 };
 
@@ -5010,7 +6135,7 @@ static PyNumberMethods TableRecTimeStream_as_number = {
     (binaryfunc)TableRecTimeStream_add,                         /*nb_add*/
     (binaryfunc)TableRecTimeStream_sub,                         /*nb_subtract*/
     (binaryfunc)TableRecTimeStream_multiply,                    /*nb_multiply*/
-    (binaryfunc)TableRecTimeStream_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -5024,16 +6149,16 @@ static PyNumberMethods TableRecTimeStream_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)TableRecTimeStream_inplace_add,                 /*inplace_add*/
     (binaryfunc)TableRecTimeStream_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)TableRecTimeStream_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)TableRecTimeStream_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -5042,15 +6167,14 @@ static PyNumberMethods TableRecTimeStream_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)TableRecTimeStream_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)TableRecTimeStream_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject TableRecTimeStreamType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.TableRecTimeStream_base",         /*tp_name*/
     sizeof(TableRecTimeStream),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -5058,7 +6182,7 @@ PyTypeObject TableRecTimeStreamType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &TableRecTimeStream_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -5130,32 +6254,32 @@ TableMorph_compute_next_data_frame(TableMorph *self)
 {
     int i, x, y;
     MYFLT input, interp, interp1, interp2;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     int size = PyInt_AsLong(NewTable_getSize((NewTable *)self->table));
     int len = PyList_Size(self->sources);
-    
+
     if (size != self->last_size)
         TableMorph_alloc_memories(self);
 
     input = TableMorph_clip(in[0]);
 
     interp = input * (len - 1);
-    x = (int)(interp);   
+    x = (int)(interp);
     y = x + 1;
-            
+
     MYFLT *tab1 = TableStream_getData((TableStream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->sources, x), "getTableStream", ""));
     MYFLT *tab2 = TableStream_getData((TableStream *)PyObject_CallMethod((PyObject *)PyList_GET_ITEM(self->sources, y), "getTableStream", ""));
-        
+
     interp = MYFMOD(interp, 1.0);
     interp1 = 1. - interp;
     interp2 = interp;
-    
+
     //MYFLT buffer[size];
     for (i=0; i<size; i++) {
         self->buffer[i] = tab1[i] * interp1 + tab2[i] * interp2;
-    }    
-    
+    }
+
     NewTable_recordChunk((NewTable *)self->table, self->buffer, size);
 }
 
@@ -5170,7 +6294,7 @@ TableMorph_traverse(TableMorph *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 TableMorph_clear(TableMorph *self)
 {
     pyo_CLEAR
@@ -5187,7 +6311,7 @@ TableMorph_dealloc(TableMorph* self)
     pyo_DEALLOC
     free(self->buffer);
     TableMorph_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -5197,35 +6321,34 @@ TableMorph_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *tabletmp, *sourcestmp;
     TableMorph *self;
     self = (TableMorph *)type->tp_alloc(type, 0);
-    
+
     INIT_OBJECT_COMMON
-    
+
     Stream_setFunctionPtr(self->stream, TableMorph_compute_next_data_frame);
 
     static char *kwlist[] = {"input", "table", "sources", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OOO", kwlist, &inputtmp, &tabletmp, &sourcestmp))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     INIT_INPUT_STREAM
-    
+
     if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
-        PySys_WriteStderr("TypeError: \"table\" argument of TableMorph must be a PyoTableObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"table\" argument of TableMorph must be a PyoTableObject.\n");
+        Py_RETURN_NONE;
     }
     Py_XDECREF(self->table);
+    Py_INCREF(tabletmp);
     self->table = (PyObject *)tabletmp;
-    
+
     Py_XDECREF(self->sources);
+    Py_INCREF(sourcestmp);
     self->sources = (PyObject *)sourcestmp;
-    
+
     TableMorph_alloc_memories(self);
 
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     return (PyObject *)self;
 }
 
@@ -5239,38 +6362,32 @@ static PyObject *
 TableMorph_setTable(TableMorph *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	tmp = arg;
     Py_INCREF(tmp);
 	Py_DECREF(self->table);
     self->table = (PyObject *)tmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
 
 static PyObject *
 TableMorph_setSources(TableMorph *self, PyObject *arg)
-{	
-    if (arg == NULL) {
-        PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute.");
-        return PyInt_FromLong(-1);
-    }
-    
+{
+    ASSERT_ARG_NOT_NULL
+
     if (! PyList_Check(arg)) {
         PyErr_SetString(PyExc_TypeError, "The amplitude list attribute value must be a list.");
         return PyInt_FromLong(-1);
     }
-    
+
     Py_INCREF(arg);
     Py_DECREF(self->sources);
     self->sources = arg;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -5295,8 +6412,7 @@ static PyMethodDef TableMorph_methods[] = {
 };
 
 PyTypeObject TableMorphType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.TableMorph_base",         /*tp_name*/
 sizeof(TableMorph),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -5304,7 +6420,7 @@ sizeof(TableMorph),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 0,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -5380,15 +6496,15 @@ TrigTableRec_compute_next_data_frame(TrigTableRec *self)
                 else
                     self->trigsBuffer[num-1] = 1.0;
                 self->active = 0;
-            }    
+            }
         }
-    
-        if (self->pointer < size) {   
+
+        if (self->pointer < size) {
             upBound = size - self->fadeInSample;
-        
+
             MYFLT buffer[num];
             memset(&buffer, 0, sizeof(buffer));
-        
+
             for (i=0; i<num; i++) {
                 if (self->pointer < self->fadeInSample)
                     val = self->pointer / self->fadeInSample;
@@ -5400,7 +6516,7 @@ TrigTableRec_compute_next_data_frame(TrigTableRec *self)
                 self->time_buffer_streams[i] = self->pointer++;
             }
             NewTable_recordChunk((NewTable *)self->table, buffer, num);
-        
+
             if (num < self->bufsize) {
                 for (i=num; i<self->bufsize; i++) {
                     self->time_buffer_streams[i] = self->pointer;
@@ -5414,6 +6530,7 @@ TrigTableRec_compute_next_data_frame(TrigTableRec *self)
             if (trig[j] == 1.0) {
                 self->active = 1;
                 self->pointer = 0;
+                NewTable_resetRecordingPointer((NewTable *)self->table);
                 if (size >= self->bufsize)
                     num = self->bufsize - j;
                 else {
@@ -5424,14 +6541,14 @@ TrigTableRec_compute_next_data_frame(TrigTableRec *self)
                         else
                             self->trigsBuffer[num-1] = 1.0;
                         self->active = 0;
-                    }    
+                    }
                 }
-                
+
                 upBound = size - self->fadeInSample;
-                    
+
                 MYFLT buffer[num];
                 memset(&buffer, 0, sizeof(buffer));
-                
+
                 for (i=0; i<num; i++) {
                     if (self->pointer < self->fadeInSample) {
                         val = self->pointer / self->fadeInSample;
@@ -5470,11 +6587,11 @@ TrigTableRec_traverse(TrigTableRec *self, visitproc visit, void *arg)
     Py_VISIT(self->trigger);
     Py_VISIT(self->trigger_stream);
     Py_VISIT(self->table);
-    Py_VISIT(self->trig_stream);    
+    Py_VISIT(self->trig_stream);
     return 0;
 }
 
-static int 
+static int
 TrigTableRec_clear(TrigTableRec *self)
 {
     pyo_CLEAR
@@ -5483,7 +6600,7 @@ TrigTableRec_clear(TrigTableRec *self)
     Py_CLEAR(self->trigger);
     Py_CLEAR(self->trigger_stream);
     Py_CLEAR(self->table);
-    Py_CLEAR(self->trig_stream);    
+    Py_CLEAR(self->trig_stream);
     return 0;
 }
 
@@ -5494,7 +6611,7 @@ TrigTableRec_dealloc(TrigTableRec* self)
     free(self->trigsBuffer);
     TrigTableRec_clear(self);
     free(self->time_buffer_streams);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -5504,51 +6621,50 @@ TrigTableRec_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *trigtmp, *trig_streamtmp, *tabletmp;
     TrigTableRec *self;
     self = (TrigTableRec *)type->tp_alloc(type, 0);
-    
+
     self->pointer = 0;
     self->active = 0;
     self->fadetime = 0.;
-    
+
     INIT_OBJECT_COMMON
-    
+
     Stream_setFunctionPtr(self->stream, TrigTableRec_compute_next_data_frame);
 
     static char *kwlist[] = {"input", "trig", "table", "fadetime", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_OOO_F, kwlist, &inputtmp, &trigtmp, &tabletmp, &self->fadetime))
-        Py_RETURN_NONE; 
-    
+        Py_RETURN_NONE;
+
     INIT_INPUT_STREAM
 
     Py_XDECREF(self->trigger);
+    Py_INCREF(trigtmp);
     self->trigger = trigtmp;
     trig_streamtmp = PyObject_CallMethod((PyObject *)self->trigger, "_getStream", NULL);
     Py_INCREF(trig_streamtmp);
     Py_XDECREF(self->trigger_stream);
     self->trigger_stream = (Stream *)trig_streamtmp;
-    
+
     if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
-        PySys_WriteStderr("TypeError: \"table\" argument of TrigTableRec must be a PyoTableObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"table\" argument of TrigTableRec must be a PyoTableObject.\n");
+        Py_RETURN_NONE;
     }
     Py_XDECREF(self->table);
+    Py_INCREF(tabletmp);
     self->table = (NewTable *)tabletmp;
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     self->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT));
     self->time_buffer_streams = (MYFLT *)realloc(self->time_buffer_streams, self->bufsize * sizeof(MYFLT));
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->trigsBuffer[i] = self->time_buffer_streams[i] = 0.0;
-    }    
+    }
 
     MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL);
     TriggerStream_setData(self->trig_stream, self->trigsBuffer);
-    
+
     int size = PyInt_AsLong(NewTable_getSize((NewTable *)self->table));
     if ((self->fadetime * self->sr) >= (size * 0.5))
         self->fadetime = size * 0.499 / self->sr;
@@ -5556,7 +6672,7 @@ TrigTableRec_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         self->fadeInSample = 0.0;
     else
         self->fadeInSample = MYROUND(self->fadetime * self->sr + 0.5);
-     
+
     return (PyObject *)self;
 }
 
@@ -5571,20 +6687,17 @@ static PyObject *
 TrigTableRec_setTable(TrigTableRec *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	tmp = arg;
     Py_INCREF(tmp);
 	Py_DECREF(self->table);
     self->table = (NewTable *)tmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef TrigTableRec_members[] = {
     {"server", T_OBJECT_EX, offsetof(TrigTableRec, server), 0, "Pyo server."},
@@ -5607,8 +6720,7 @@ static PyMethodDef TrigTableRec_methods[] = {
 };
 
 PyTypeObject TrigTableRecType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.TrigTableRec_base",         /*tp_name*/
     sizeof(TrigTableRec),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -5616,7 +6728,7 @@ PyTypeObject TrigTableRecType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     0,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -5668,36 +6780,36 @@ static void
 TrigTableRecTimeStream_setProcMode(TrigTableRecTimeStream *self) {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = TrigTableRecTimeStream_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = TrigTableRecTimeStream_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = TrigTableRecTimeStream_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = TrigTableRecTimeStream_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = TrigTableRecTimeStream_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = TrigTableRecTimeStream_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = TrigTableRecTimeStream_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = TrigTableRecTimeStream_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = TrigTableRecTimeStream_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
@@ -5708,7 +6820,7 @@ TrigTableRecTimeStream_compute_next_data_frame(TrigTableRecTimeStream *self)
     tmp = TrigTableRec_getTimeBuffer((TrigTableRec *)self->mainPlayer);
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = tmp[i];
-    }    
+    }
     (*self->muladd_func_ptr)(self);
 }
 
@@ -5720,11 +6832,11 @@ TrigTableRecTimeStream_traverse(TrigTableRecTimeStream *self, visitproc visit, v
     return 0;
 }
 
-static int 
+static int
 TrigTableRecTimeStream_clear(TrigTableRecTimeStream *self)
 {
     pyo_CLEAR
-    Py_CLEAR(self->mainPlayer);    
+    Py_CLEAR(self->mainPlayer);
     return 0;
 }
 
@@ -5733,7 +6845,7 @@ TrigTableRecTimeStream_dealloc(TrigTableRecTimeStream* self)
 {
     pyo_DEALLOC
     TrigTableRecTimeStream_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -5743,36 +6855,36 @@ TrigTableRecTimeStream_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *maintmp=NULL;
     TrigTableRecTimeStream *self;
     self = (TrigTableRecTimeStream *)type->tp_alloc(type, 0);
-    
+
     self->modebuffer[0] = 0;
     self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, TrigTableRecTimeStream_compute_next_data_frame);
     self->mode_func_ptr = TrigTableRecTimeStream_setProcMode;
 
     static char *kwlist[] = {"mainPlayer", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &maintmp))
         Py_RETURN_NONE;
-    
+
     Py_XDECREF(self->mainPlayer);
     Py_INCREF(maintmp);
     self->mainPlayer = (TrigTableRec *)maintmp;
-    
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * TrigTableRecTimeStream_getServer(TrigTableRecTimeStream* self) { GET_SERVER };
 static PyObject * TrigTableRecTimeStream_getStream(TrigTableRecTimeStream* self) { GET_STREAM };
-static PyObject * TrigTableRecTimeStream_setMul(TrigTableRecTimeStream *self, PyObject *arg) { SET_MUL };	
-static PyObject * TrigTableRecTimeStream_setAdd(TrigTableRecTimeStream *self, PyObject *arg) { SET_ADD };	
-static PyObject * TrigTableRecTimeStream_setSub(TrigTableRecTimeStream *self, PyObject *arg) { SET_SUB };	
-static PyObject * TrigTableRecTimeStream_setDiv(TrigTableRecTimeStream *self, PyObject *arg) { SET_DIV };	
+static PyObject * TrigTableRecTimeStream_setMul(TrigTableRecTimeStream *self, PyObject *arg) { SET_MUL };
+static PyObject * TrigTableRecTimeStream_setAdd(TrigTableRecTimeStream *self, PyObject *arg) { SET_ADD };
+static PyObject * TrigTableRecTimeStream_setSub(TrigTableRecTimeStream *self, PyObject *arg) { SET_SUB };
+static PyObject * TrigTableRecTimeStream_setDiv(TrigTableRecTimeStream *self, PyObject *arg) { SET_DIV };
 
 static PyObject * TrigTableRecTimeStream_play(TrigTableRecTimeStream *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * TrigTableRecTimeStream_out(TrigTableRecTimeStream *self, PyObject *args, PyObject *kwds) { OUT };
@@ -5804,7 +6916,7 @@ static PyMethodDef TrigTableRecTimeStream_methods[] = {
     {"setMul", (PyCFunction)TrigTableRecTimeStream_setMul, METH_O, "Sets oscillator mul factor."},
     {"setAdd", (PyCFunction)TrigTableRecTimeStream_setAdd, METH_O, "Sets oscillator add factor."},
     {"setSub", (PyCFunction)TrigTableRecTimeStream_setSub, METH_O, "Sets inverse add factor."},
-    {"setDiv", (PyCFunction)TrigTableRecTimeStream_setDiv, METH_O, "Sets inverse mul factor."},    
+    {"setDiv", (PyCFunction)TrigTableRecTimeStream_setDiv, METH_O, "Sets inverse mul factor."},
     {NULL}  /* Sentinel */
 };
 
@@ -5812,7 +6924,7 @@ static PyNumberMethods TrigTableRecTimeStream_as_number = {
     (binaryfunc)TrigTableRecTimeStream_add,                         /*nb_add*/
     (binaryfunc)TrigTableRecTimeStream_sub,                         /*nb_subtract*/
     (binaryfunc)TrigTableRecTimeStream_multiply,                    /*nb_multiply*/
-    (binaryfunc)TrigTableRecTimeStream_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -5826,16 +6938,16 @@ static PyNumberMethods TrigTableRecTimeStream_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)TrigTableRecTimeStream_inplace_add,                 /*inplace_add*/
     (binaryfunc)TrigTableRecTimeStream_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)TrigTableRecTimeStream_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)TrigTableRecTimeStream_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -5844,15 +6956,14 @@ static PyNumberMethods TrigTableRecTimeStream_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)TrigTableRecTimeStream_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)TrigTableRecTimeStream_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject TrigTableRecTimeStreamType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.TrigTableRecTimeStream_base",         /*tp_name*/
     sizeof(TrigTableRecTimeStream),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -5860,7 +6971,7 @@ PyTypeObject TrigTableRecTimeStreamType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &TrigTableRecTimeStream_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -5893,187 +7004,448 @@ PyTypeObject TrigTableRecTimeStreamType = {
 };
 
 /******************************/
-/* TablePut object definition */
+/* TablePut object definition */
+/******************************/
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *input;
+    Stream *input_stream;
+    DataTable *table;
+    int pointer;
+    int active;
+    MYFLT last_value;
+    MYFLT *trigsBuffer;
+    TriggerStream *trig_stream;
+} TablePut;
+
+static void
+TablePut_compute_next_data_frame(TablePut *self)
+{
+    int i;
+    int size = PyInt_AsLong(DataTable_getSize((DataTable *)self->table));
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+
+    for (i=0; i<self->bufsize; i++) {
+        self->trigsBuffer[i] = 0.0;
+    }
+
+    if (self->active == 1) {
+        for (i=0; i<self->bufsize; i++) {
+            if (in[i] != self->last_value) {
+                self->last_value = in[i];
+                DataTable_record((DataTable *)self->table, self->pointer++, self->last_value);
+                if (self->pointer >= size) {
+                    self->active = 0;
+                    self->trigsBuffer[i] = 1.0;
+                    break;
+                }
+            }
+        }
+    }
+}
+
+static int
+TablePut_traverse(TablePut *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->input);
+    Py_VISIT(self->input_stream);
+    Py_VISIT(self->table);
+    Py_VISIT(self->trig_stream);
+    return 0;
+}
+
+static int
+TablePut_clear(TablePut *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->input);
+    Py_CLEAR(self->input_stream);
+    Py_CLEAR(self->table);
+    Py_CLEAR(self->trig_stream);
+    return 0;
+}
+
+static void
+TablePut_dealloc(TablePut* self)
+{
+    pyo_DEALLOC
+    free(self->trigsBuffer);
+    TablePut_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+TablePut_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *inputtmp, *input_streamtmp, *tabletmp;
+    TablePut *self;
+    self = (TablePut *)type->tp_alloc(type, 0);
+
+    self->pointer = 0;
+    self->active = 1;
+    self->last_value = 0.0;
+
+    INIT_OBJECT_COMMON
+
+    Stream_setFunctionPtr(self->stream, TablePut_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 TablePut must be a PyoTableObject.\n");
+        Py_RETURN_NONE;
+    }
+    Py_XDECREF(self->table);
+    Py_INCREF(tabletmp);
+    self->table = (DataTable *)tabletmp;
+
+    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
+
+    self->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT));
+
+    for (i=0; i<self->bufsize; i++) {
+        self->trigsBuffer[i] = 0.0;
+    }
+
+    MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL);
+    TriggerStream_setData(self->trig_stream, self->trigsBuffer);
+
+    return (PyObject *)self;
+}
+
+static PyObject * TablePut_getServer(TablePut* self) { GET_SERVER };
+static PyObject * TablePut_getStream(TablePut* self) { GET_STREAM };
+static PyObject * TablePut_getTriggerStream(TablePut* self) { GET_TRIGGER_STREAM };
+
+static PyObject * TablePut_play(TablePut *self, PyObject *args, PyObject *kwds)
+{
+    self->pointer = 0;
+    self->active = 1;
+    PLAY
+};
+
+static PyObject * TablePut_stop(TablePut *self) { STOP };
+
+static PyObject *
+TablePut_setTable(TablePut *self, PyObject *arg)
+{
+	PyObject *tmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	tmp = arg;
+    Py_INCREF(tmp);
+	Py_DECREF(self->table);
+    self->table = (DataTable *)tmp;
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyMemberDef TablePut_members[] = {
+{"server", T_OBJECT_EX, offsetof(TablePut, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(TablePut, stream), 0, "Stream object."},
+{"trig_stream", T_OBJECT_EX, offsetof(TablePut, trig_stream), 0, "Trigger Stream object."},
+{"input", T_OBJECT_EX, offsetof(TablePut, input), 0, "Input sound object."},
+{"table", T_OBJECT_EX, offsetof(TablePut, table), 0, "Table to record in."},
+{NULL}  /* Sentinel */
+};
+
+static PyMethodDef TablePut_methods[] = {
+{"getServer", (PyCFunction)TablePut_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)TablePut_getStream, METH_NOARGS, "Returns stream object."},
+{"_getTriggerStream", (PyCFunction)TablePut_getTriggerStream, METH_NOARGS, "Returns trigger stream object."},
+{"setTable", (PyCFunction)TablePut_setTable, METH_O, "Sets a new data table."},
+{"play", (PyCFunction)TablePut_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"stop", (PyCFunction)TablePut_stop, METH_NOARGS, "Stops computing."},
+{NULL}  /* Sentinel */
+};
+
+PyTypeObject TablePutType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.TablePut_base",         /*tp_name*/
+sizeof(TablePut),         /*tp_basicsize*/
+0,                         /*tp_itemsize*/
+(destructor)TablePut_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*/
+"TablePut objects. Record new value in input in a data table object.",           /* tp_doc */
+(traverseproc)TablePut_traverse,   /* tp_traverse */
+(inquiry)TablePut_clear,           /* tp_clear */
+0,		               /* tp_richcompare */
+0,		               /* tp_weaklistoffset */
+0,		               /* tp_iter */
+0,		               /* tp_iternext */
+TablePut_methods,             /* tp_methods */
+TablePut_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 */
+TablePut_new,                 /* tp_new */
+};
+
+/******************************/
+/* TableWrite object definition */
 /******************************/
 typedef struct {
     pyo_audio_HEAD
     PyObject *input;
     Stream *input_stream;
-    DataTable *table;
-    int pointer;
-    int active;
-    MYFLT last_value;
-    MYFLT *trigsBuffer;
-    TriggerStream *trig_stream;
-} TablePut;
+    PyObject *pos;
+    Stream *pos_stream;
+    NewTable *table;
+    int mode;
+    int maxwindow;
+    int lastPos;
+    MYFLT lastValue;
+    int count;
+    MYFLT accum;
+    MYFLT valInTable;
+} TableWrite;
 
 static void
-TablePut_compute_next_data_frame(TablePut *self)
+TableWrite_compute_next_data_frame(TableWrite *self)
 {
-    int i;
-    int size = PyInt_AsLong(DataTable_getSize((DataTable *)self->table));
+    int i, j, ipos;
+    PyObject *table;
+
+    table = PyObject_CallMethod((PyObject *)self->table, "getTableStream", "");
+    MYFLT feed = NewTable_getFeedback((NewTable *)self->table);
+    MYFLT *tablelist = TableStream_getData((TableStream *)table);
+    int size = TableStream_getSize((TableStream *)table);
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
+    MYFLT *pos = Stream_getData((Stream *)self->pos_stream);
 
     for (i=0; i<self->bufsize; i++) {
-        self->trigsBuffer[i] = 0.0;
-    }
-
-    if (self->active == 1) {
-        for (i=0; i<self->bufsize; i++) {
-            if (in[i] != self->last_value) {
-                self->last_value = in[i];
-                DataTable_record((DataTable *)self->table, self->pointer++, self->last_value);
-                if (self->pointer >= size) {
-                    self->active = 0;
-                    self->trigsBuffer[i] = 1.0;
-                    break;
+        if (self->mode == 0)
+            ipos = (int)(pos[i] * size + 0.5);
+        else
+            ipos = (int)(pos[i] + 0.5);
+        if (ipos >= 0 && ipos < size) {
+            if (self->lastPos < 0) { /* Init case. */
+                self->valInTable = tablelist[ipos];
+                self->count = 1;
+                self->accum = in[i];
+                tablelist[ipos] = in[i] + tablelist[ipos] * feed;
+            }
+            else if (ipos == self->lastPos) { /* Same position, average inputs. */
+                self->count += 1;
+                self->accum += in[i];
+                tablelist[ipos] = self->accum / self->count + self->valInTable * feed;
+            }
+            else { /* Position changed. */
+                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];
+                self->count = 1;
+                self->accum = in[i];
+                if (steps < 2) { /* Moved one sample, no need to interpolate. */
+                    tablelist[ipos] = in[i] + tablelist[ipos] * feed;
+                }
+                else { /* Interpolate between last pos and current pos. */
+                    MYFLT inc = (in[i] - self->lastValue) / steps;
+                    for (j=1; j<=steps; j++) {
+                        MYFLT val = self->lastValue + inc * j;
+                        tablelist[self->lastPos+j*dir] = val + tablelist[self->lastPos+j*dir] * feed;
+                    }
                 }
             }
+            self->lastPos = ipos;
+            self->lastValue = in[i];
         }
     }
 }
 
 static int
-TablePut_traverse(TablePut *self, visitproc visit, void *arg)
+TableWrite_traverse(TableWrite *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
     Py_VISIT(self->table);
-    Py_VISIT(self->trig_stream);    
+    Py_VISIT(self->pos);
+    Py_VISIT(self->pos_stream);
     return 0;
 }
 
-static int 
-TablePut_clear(TablePut *self)
+static int
+TableWrite_clear(TableWrite *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
     Py_CLEAR(self->table);
-    Py_CLEAR(self->trig_stream);    
+    Py_CLEAR(self->pos);
+    Py_CLEAR(self->pos_stream);
     return 0;
 }
 
 static void
-TablePut_dealloc(TablePut* self)
+TableWrite_dealloc(TableWrite* self)
 {
     pyo_DEALLOC
-    free(self->trigsBuffer);
-    TablePut_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    TableWrite_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
-TablePut_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+TableWrite_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     int i;
-    PyObject *inputtmp, *input_streamtmp, *tabletmp;
-    TablePut *self;
-    self = (TablePut *)type->tp_alloc(type, 0);
-    
-    self->pointer = 0;
-    self->active = 1;
-    self->last_value = 0.0;
-    
+    PyObject *inputtmp, *input_streamtmp, *postmp, *tabletmp;
+    TableWrite *self;
+    self = (TableWrite *)type->tp_alloc(type, 0);
+
+    self->mode = 0;
+    self->maxwindow = 1024;
+    self->lastPos = -1;
+    self->lastValue = 0.0;
+    self->count = 0;
+    self->accum = 0.0;
+    self->valInTable = 0.0;
+
     INIT_OBJECT_COMMON
 
-    Stream_setFunctionPtr(self->stream, TablePut_compute_next_data_frame);
-    Stream_setStreamActive(self->stream, 0);
+    Stream_setFunctionPtr(self->stream, TableWrite_compute_next_data_frame);
+
+    static char *kwlist[] = {"input", "pos", "table", "mode", "maxwindow", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "OOOii", kwlist, &inputtmp, &postmp, &tabletmp, &self->mode, &self->maxwindow))
+        Py_RETURN_NONE;
 
-    static char *kwlist[] = {"input", "table", NULL};
-    
-    if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO", kwlist, &inputtmp, &tabletmp))
-        Py_RETURN_NONE; 
-    
     INIT_INPUT_STREAM
-    
+
+    if (postmp) {
+        PyObject_CallMethod((PyObject *)self, "setPos", "O", postmp);
+    }
+
     if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
-        PySys_WriteStderr("TypeError: \"table\" argument of TablePut must be a PyoTableObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"table\" argument of TableWrite must be a PyoTableObject.\n");
+        Py_RETURN_NONE;
     }
     Py_XDECREF(self->table);
-    self->table = (DataTable *)tabletmp;
-    
+    Py_INCREF(tabletmp);
+    self->table = (NewTable *)tabletmp;
+
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
 
-    self->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT));
+    return (PyObject *)self;
+}
 
-    for (i=0; i<self->bufsize; i++) {
-        self->trigsBuffer[i] = 0.0;
-    }    
+static PyObject * TableWrite_getServer(TableWrite* self) { GET_SERVER };
+static PyObject * TableWrite_getStream(TableWrite* self) { GET_STREAM };
 
-    MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL);
-    TriggerStream_setData(self->trig_stream, self->trigsBuffer);
+static PyObject * TableWrite_play(TableWrite *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * TableWrite_stop(TableWrite *self) { STOP };
 
-    return (PyObject *)self;
-}
+static PyObject *
+TableWrite_setPos(TableWrite *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
 
-static PyObject * TablePut_getServer(TablePut* self) { GET_SERVER };
-static PyObject * TablePut_getStream(TablePut* self) { GET_STREAM };
-static PyObject * TablePut_getTriggerStream(TablePut* self) { GET_TRIGGER_STREAM };
+    ASSERT_ARG_NOT_NULL
 
-static PyObject * TablePut_play(TablePut *self, PyObject *args, PyObject *kwds) 
-{ 
-    self->pointer = 0;
-    self->active = 1;
-    PLAY 
-};
+	tmp = arg;
+	if (PyObject_HasAttrString((PyObject *)tmp, "server") == 0) {
+        PyErr_SetString(PyExc_TypeError, "\"pos\" argument of TableWrite must be a PyoObject.\n");
+        Py_RETURN_NONE;
+	}
 
-static PyObject * TablePut_stop(TablePut *self) { STOP };
+	Py_INCREF(tmp);
+	Py_XDECREF(self->pos);
+
+    self->pos = tmp;
+    streamtmp = PyObject_CallMethod((PyObject *)self->pos, "_getStream", NULL);
+    Py_INCREF(streamtmp);
+    Py_XDECREF(self->pos_stream);
+    self->pos_stream = (Stream *)streamtmp;
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
 
 static PyObject *
-TablePut_setTable(TablePut *self, PyObject *arg)
+TableWrite_setTable(TableWrite *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	tmp = arg;
     Py_INCREF(tmp);
 	Py_DECREF(self->table);
-    self->table = (DataTable *)tmp;
-    
+    self->table = (NewTable *)tmp;
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
 
-static PyMemberDef TablePut_members[] = {
-{"server", T_OBJECT_EX, offsetof(TablePut, server), 0, "Pyo server."},
-{"stream", T_OBJECT_EX, offsetof(TablePut, stream), 0, "Stream object."},
-{"trig_stream", T_OBJECT_EX, offsetof(TablePut, trig_stream), 0, "Trigger Stream object."},
-{"input", T_OBJECT_EX, offsetof(TablePut, input), 0, "Input sound object."},
-{"table", T_OBJECT_EX, offsetof(TablePut, table), 0, "Table to record in."},
+static PyMemberDef TableWrite_members[] = {
+{"server", T_OBJECT_EX, offsetof(TableWrite, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(TableWrite, stream), 0, "Stream object."},
+{"input", T_OBJECT_EX, offsetof(TableWrite, input), 0, "Input sound object."},
+{"table", T_OBJECT_EX, offsetof(TableWrite, table), 0, "Table to record in."},
+{"pos", T_OBJECT_EX, offsetof(TableWrite, pos), 0, "Position in the Table to record in."},
 {NULL}  /* Sentinel */
 };
 
-static PyMethodDef TablePut_methods[] = {
-{"getServer", (PyCFunction)TablePut_getServer, METH_NOARGS, "Returns server object."},
-{"_getStream", (PyCFunction)TablePut_getStream, METH_NOARGS, "Returns stream object."},
-{"_getTriggerStream", (PyCFunction)TablePut_getTriggerStream, METH_NOARGS, "Returns trigger stream object."},
-{"setTable", (PyCFunction)TablePut_setTable, METH_O, "Sets a new data table."},
-{"play", (PyCFunction)TablePut_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
-{"stop", (PyCFunction)TablePut_stop, METH_NOARGS, "Stops computing."},
+static PyMethodDef TableWrite_methods[] = {
+{"getServer", (PyCFunction)TableWrite_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)TableWrite_getStream, METH_NOARGS, "Returns stream object."},
+{"setTable", (PyCFunction)TableWrite_setTable, METH_O, "Sets a new table."},
+{"setPos", (PyCFunction)TableWrite_setPos, METH_O, "Sets position in the sound table."},
+{"play", (PyCFunction)TableWrite_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"stop", (PyCFunction)TableWrite_stop, METH_NOARGS, "Stops computing."},
 {NULL}  /* Sentinel */
 };
 
-PyTypeObject TablePutType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
-"_pyo.TablePut_base",         /*tp_name*/
-sizeof(TablePut),         /*tp_basicsize*/
+PyTypeObject TableWriteType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.TableWrite_base",         /*tp_name*/
+sizeof(TableWrite),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
-(destructor)TablePut_dealloc, /*tp_dealloc*/
+(destructor)TableWrite_dealloc, /*tp_dealloc*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 0,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -6085,15 +7457,15 @@ sizeof(TablePut),         /*tp_basicsize*/
 0,                         /*tp_setattro*/
 0,                         /*tp_as_buffer*/
 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
-"TablePut objects. Record new value in input in a data table object.",           /* tp_doc */
-(traverseproc)TablePut_traverse,   /* tp_traverse */
-(inquiry)TablePut_clear,           /* tp_clear */
+"TableWrite objects. Record audio input in a table object.",           /* tp_doc */
+(traverseproc)TableWrite_traverse,   /* tp_traverse */
+(inquiry)TableWrite_clear,           /* tp_clear */
 0,		               /* tp_richcompare */
 0,		               /* tp_weaklistoffset */
 0,		               /* tp_iter */
 0,		               /* tp_iternext */
-TablePut_methods,             /* tp_methods */
-TablePut_members,             /* tp_members */
+TableWrite_methods,             /* tp_methods */
+TableWrite_members,             /* tp_members */
 0,                      /* tp_getset */
 0,                         /* tp_base */
 0,                         /* tp_dict */
@@ -6102,5 +7474,226 @@ TablePut_members,             /* tp_members */
 0,                         /* tp_dictoffset */
 0,      /* tp_init */
 0,                         /* tp_alloc */
-TablePut_new,                 /* tp_new */
+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 cdbcf85..d17d070 100644
--- a/src/objects/trigmodule.c
+++ b/src/objects/trigmodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include "pyomodule.h"
 #include "streammodule.h"
@@ -34,7 +35,7 @@ typedef struct {
     PyObject *max;
     Stream *max_stream;
     MYFLT value;
-    int modebuffer[3]; // need at least 2 slots for mul & add 
+    int modebuffer[3]; // need at least 2 slots for mul & add
 } TrigRandInt;
 
 static void
@@ -42,11 +43,11 @@ TrigRandInt_generate_i(TrigRandInt *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT ma = PyFloat_AS_DOUBLE(self->max);
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (in[i] == 1)
-            self->value = (MYFLT)((int)(rand()/((MYFLT)(RAND_MAX)+1)*ma));
-        
+            self->value = (MYFLT)((int)(RANDOM_UNIFORM * ma));
+
         self->data[i] = self->value;
     }
 }
@@ -56,11 +57,11 @@ TrigRandInt_generate_a(TrigRandInt *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *ma = Stream_getData((Stream *)self->max_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (in[i] == 1)
-            self->value = (MYFLT)((int)(rand()/((MYFLT)(RAND_MAX)+1)*ma[i]));
-        
+            self->value = (MYFLT)((int)(RANDOM_UNIFORM * ma[i]));
+
         self->data[i] = self->value;
     }
 }
@@ -81,50 +82,50 @@ TrigRandInt_setProcMode(TrigRandInt *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2];
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = TrigRandInt_generate_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = TrigRandInt_generate_a;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = TrigRandInt_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = TrigRandInt_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = TrigRandInt_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = TrigRandInt_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = TrigRandInt_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = TrigRandInt_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = TrigRandInt_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = TrigRandInt_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = TrigRandInt_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 TrigRandInt_compute_next_data_frame(TrigRandInt *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -134,19 +135,19 @@ TrigRandInt_traverse(TrigRandInt *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->max);    
-    Py_VISIT(self->max_stream);    
+    Py_VISIT(self->max);
+    Py_VISIT(self->max_stream);
     return 0;
 }
 
-static int 
+static int
 TrigRandInt_clear(TrigRandInt *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->max);    
-    Py_CLEAR(self->max_stream);    
+    Py_CLEAR(self->max);
+    Py_CLEAR(self->max_stream);
     return 0;
 }
 
@@ -155,7 +156,7 @@ TrigRandInt_dealloc(TrigRandInt* self)
 {
     pyo_DEALLOC
     TrigRandInt_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -166,45 +167,45 @@ TrigRandInt_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *maxtmp=NULL, *multmp=NULL, *addtmp=NULL;
     TrigRandInt *self;
     self = (TrigRandInt *)type->tp_alloc(type, 0);
-    
+
     self->max = PyFloat_FromDouble(100.);
     self->value = 0.;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, TrigRandInt_compute_next_data_frame);
     self->mode_func_ptr = TrigRandInt_setProcMode;
 
     static char *kwlist[] = {"input", "max", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &maxtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
 
     if (maxtmp) {
         PyObject_CallMethod((PyObject *)self, "setMax", "O", maxtmp);
     }
-    
+
     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);
-    
+
     Server_generateSeed((Server *)self->server, TRIGRANDINT_ID);
 
     if (self->modebuffer[2] == 0)
-        ma = PyFloat_AS_DOUBLE(PyNumber_Float(self->max));
+        ma = PyFloat_AsDouble(self->max);
     else
         ma = Stream_getData((Stream *)self->max_stream)[0];
-    self->value = (MYFLT)((int)(rand()/((MYFLT)(RAND_MAX)+1)*ma));
+    self->value = (MYFLT)((int)(RANDOM_UNIFORM * ma));
 
     (*self->mode_func_ptr)(self);
 
@@ -213,10 +214,10 @@ TrigRandInt_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * TrigRandInt_getServer(TrigRandInt* self) { GET_SERVER };
 static PyObject * TrigRandInt_getStream(TrigRandInt* self) { GET_STREAM };
-static PyObject * TrigRandInt_setMul(TrigRandInt *self, PyObject *arg) { SET_MUL };	
-static PyObject * TrigRandInt_setAdd(TrigRandInt *self, PyObject *arg) { SET_ADD };	
-static PyObject * TrigRandInt_setSub(TrigRandInt *self, PyObject *arg) { SET_SUB };	
-static PyObject * TrigRandInt_setDiv(TrigRandInt *self, PyObject *arg) { SET_DIV };	
+static PyObject * TrigRandInt_setMul(TrigRandInt *self, PyObject *arg) { SET_MUL };
+static PyObject * TrigRandInt_setAdd(TrigRandInt *self, PyObject *arg) { SET_ADD };
+static PyObject * TrigRandInt_setSub(TrigRandInt *self, PyObject *arg) { SET_SUB };
+static PyObject * TrigRandInt_setDiv(TrigRandInt *self, PyObject *arg) { SET_DIV };
 
 static PyObject * TrigRandInt_play(TrigRandInt *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * TrigRandInt_out(TrigRandInt *self, PyObject *args, PyObject *kwds) { OUT };
@@ -235,14 +236,11 @@ static PyObject *
 TrigRandInt_setMax(TrigRandInt *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->max);
@@ -258,12 +256,12 @@ TrigRandInt_setMax(TrigRandInt *self, PyObject *arg)
         self->max_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef TrigRandInt_members[] = {
     {"server", T_OBJECT_EX, offsetof(TrigRandInt, server), 0, "Pyo server."},
@@ -293,7 +291,7 @@ static PyNumberMethods TrigRandInt_as_number = {
     (binaryfunc)TrigRandInt_add,                         /*nb_add*/
     (binaryfunc)TrigRandInt_sub,                         /*nb_subtract*/
     (binaryfunc)TrigRandInt_multiply,                    /*nb_multiply*/
-    (binaryfunc)TrigRandInt_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -307,16 +305,16 @@ static PyNumberMethods TrigRandInt_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)TrigRandInt_inplace_add,                 /*inplace_add*/
     (binaryfunc)TrigRandInt_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)TrigRandInt_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)TrigRandInt_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -325,15 +323,14 @@ static PyNumberMethods TrigRandInt_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)TrigRandInt_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)TrigRandInt_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject TrigRandIntType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.TrigRandInt_base",                                   /*tp_name*/
     sizeof(TrigRandInt),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -341,7 +338,7 @@ PyTypeObject TrigRandIntType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &TrigRandInt_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -387,7 +384,7 @@ typedef struct {
     int timeStep;
     MYFLT stepVal;
     int timeCount;
-    int modebuffer[4]; // need at least 2 slots for mul & add 
+    int modebuffer[4]; // need at least 2 slots for mul & add
 } TrigRand;
 
 static void
@@ -397,17 +394,17 @@ TrigRand_generate_ii(TrigRand *self) {
     MYFLT mi = PyFloat_AS_DOUBLE(self->min);
     MYFLT ma = PyFloat_AS_DOUBLE(self->max);
     MYFLT range = ma - mi;
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (in[i] == 1) {
             self->timeCount = 0;
-            self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi;
+            self->value = range * RANDOM_UNIFORM + mi;
             if (self->time <= 0.0)
                 self->currentValue = self->value;
             else
                 self->stepVal = (self->value - self->currentValue) / self->timeStep;
         }
-        
+
         if (self->timeCount == (self->timeStep - 1)) {
             self->currentValue = self->value;
             self->timeCount++;
@@ -416,7 +413,7 @@ TrigRand_generate_ii(TrigRand *self) {
             self->currentValue += self->stepVal;
             self->timeCount++;
         }
-        
+
         self->data[i] = self->currentValue;
     }
 }
@@ -427,12 +424,12 @@ TrigRand_generate_ai(TrigRand *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *mi = Stream_getData((Stream *)self->min_stream);
     MYFLT ma = PyFloat_AS_DOUBLE(self->max);
-    
+
     for (i=0; i<self->bufsize; i++) {
         MYFLT range = ma - mi[i];
         if (in[i] == 1) {
             self->timeCount = 0;
-            self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi[i];
+            self->value = range * RANDOM_UNIFORM + mi[i];
             if (self->time <= 0.0)
                 self->currentValue = self->value;
             else
@@ -447,8 +444,8 @@ TrigRand_generate_ai(TrigRand *self) {
             self->currentValue += self->stepVal;
             self->timeCount++;
         }
-        
-        self->data[i] = self->currentValue;        
+
+        self->data[i] = self->currentValue;
     }
 }
 
@@ -458,18 +455,18 @@ TrigRand_generate_ia(TrigRand *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT mi = PyFloat_AS_DOUBLE(self->min);
     MYFLT *ma = Stream_getData((Stream *)self->max_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         MYFLT range = ma[i] - mi;
         if (in[i] == 1) {
             self->timeCount = 0;
-            self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi;
+            self->value = range * RANDOM_UNIFORM + mi;
             if (self->time <= 0.0)
                 self->currentValue = self->value;
             else
                 self->stepVal = (self->value - self->currentValue) / self->timeStep;
         }
-        
+
         if (self->timeCount == (self->timeStep - 1)) {
             self->currentValue = self->value;
             self->timeCount++;
@@ -478,7 +475,7 @@ TrigRand_generate_ia(TrigRand *self) {
             self->currentValue += self->stepVal;
             self->timeCount++;
         }
-        
+
         self->data[i] = self->currentValue;
     }
 }
@@ -489,18 +486,18 @@ TrigRand_generate_aa(TrigRand *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *mi = Stream_getData((Stream *)self->min_stream);
     MYFLT *ma = Stream_getData((Stream *)self->max_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         MYFLT range = ma[i] - mi[i];
         if (in[i] == 1) {
             self->timeCount = 0;
-            self->value = range * (rand()/((MYFLT)(RAND_MAX)+1)) + mi[i];
+            self->value = range * RANDOM_UNIFORM + mi[i];
             if (self->time <= 0.0)
                 self->currentValue = self->value;
             else
                 self->stepVal = (self->value - self->currentValue) / self->timeStep;
         }
-        
+
         if (self->timeCount == (self->timeStep - 1)) {
             self->currentValue = self->value;
             self->timeCount++;
@@ -509,7 +506,7 @@ TrigRand_generate_aa(TrigRand *self) {
             self->currentValue += self->stepVal;
             self->timeCount++;
         }
-        
+
         self->data[i] = self->currentValue;
     }
 }
@@ -530,56 +527,56 @@ TrigRand_setProcMode(TrigRand *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = TrigRand_generate_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = TrigRand_generate_ai;
             break;
-        case 10:    
+        case 10:
             self->proc_func_ptr = TrigRand_generate_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = TrigRand_generate_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = TrigRand_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = TrigRand_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = TrigRand_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = TrigRand_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = TrigRand_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = TrigRand_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = TrigRand_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = TrigRand_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = TrigRand_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 TrigRand_compute_next_data_frame(TrigRand *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -589,23 +586,23 @@ TrigRand_traverse(TrigRand *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->min);    
-    Py_VISIT(self->min_stream);    
-    Py_VISIT(self->max);    
-    Py_VISIT(self->max_stream);    
+    Py_VISIT(self->min);
+    Py_VISIT(self->min_stream);
+    Py_VISIT(self->max);
+    Py_VISIT(self->max_stream);
     return 0;
 }
 
-static int 
+static int
 TrigRand_clear(TrigRand *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->min);    
-    Py_CLEAR(self->min_stream);    
-    Py_CLEAR(self->max);    
-    Py_CLEAR(self->max_stream);    
+    Py_CLEAR(self->min);
+    Py_CLEAR(self->min_stream);
+    Py_CLEAR(self->max);
+    Py_CLEAR(self->max_stream);
     return 0;
 }
 
@@ -614,7 +611,7 @@ TrigRand_dealloc(TrigRand* self)
 {
     pyo_DEALLOC
     TrigRand_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -625,7 +622,7 @@ TrigRand_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *mintmp=NULL, *maxtmp=NULL, *multmp=NULL, *addtmp=NULL;
     TrigRand *self;
     self = (TrigRand *)type->tp_alloc(type, 0);
-    
+
     self->min = PyFloat_FromDouble(0.);
     self->max = PyFloat_FromDouble(1.);
     self->value = self->currentValue = 0.;
@@ -636,34 +633,34 @@ TrigRand_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, TrigRand_compute_next_data_frame);
     self->mode_func_ptr = TrigRand_setProcMode;
 
     static char *kwlist[] = {"input", "min", "max", "port", "init", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_OOFFOO, kwlist, &inputtmp, &mintmp, &maxtmp, &self->time, &inittmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (mintmp) {
         PyObject_CallMethod((PyObject *)self, "setMin", "O", mintmp);
     }
-    
+
     if (maxtmp) {
         PyObject_CallMethod((PyObject *)self, "setMax", "O", maxtmp);
     }
-    
+
     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);
 
     Server_generateSeed((Server *)self->server, TRIGRAND_ID);
@@ -678,10 +675,10 @@ TrigRand_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * TrigRand_getServer(TrigRand* self) { GET_SERVER };
 static PyObject * TrigRand_getStream(TrigRand* self) { GET_STREAM };
-static PyObject * TrigRand_setMul(TrigRand *self, PyObject *arg) { SET_MUL };	
-static PyObject * TrigRand_setAdd(TrigRand *self, PyObject *arg) { SET_ADD };	
-static PyObject * TrigRand_setSub(TrigRand *self, PyObject *arg) { SET_SUB };	
-static PyObject * TrigRand_setDiv(TrigRand *self, PyObject *arg) { SET_DIV };	
+static PyObject * TrigRand_setMul(TrigRand *self, PyObject *arg) { SET_MUL };
+static PyObject * TrigRand_setAdd(TrigRand *self, PyObject *arg) { SET_ADD };
+static PyObject * TrigRand_setSub(TrigRand *self, PyObject *arg) { SET_SUB };
+static PyObject * TrigRand_setDiv(TrigRand *self, PyObject *arg) { SET_DIV };
 
 static PyObject * TrigRand_play(TrigRand *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * TrigRand_out(TrigRand *self, PyObject *args, PyObject *kwds) { OUT };
@@ -700,14 +697,11 @@ static PyObject *
 TrigRand_setMin(TrigRand *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->min);
@@ -723,25 +717,22 @@ TrigRand_setMin(TrigRand *self, PyObject *arg)
         self->min_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 TrigRand_setMax(TrigRand *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->max);
@@ -757,35 +748,32 @@ TrigRand_setMax(TrigRand *self, PyObject *arg)
         self->max_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 TrigRand_setPort(TrigRand *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	if (isNumber == 1) {
-		self->time = PyFloat_AS_DOUBLE(PyNumber_Float(tmp));
+		self->time = PyFloat_AsDouble(tmp);
         self->timeStep = (int)(self->time * self->sr);
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef TrigRand_members[] = {
 {"server", T_OBJECT_EX, offsetof(TrigRand, server), 0, "Pyo server."},
@@ -818,7 +806,7 @@ static PyNumberMethods TrigRand_as_number = {
 (binaryfunc)TrigRand_add,                         /*nb_add*/
 (binaryfunc)TrigRand_sub,                         /*nb_subtract*/
 (binaryfunc)TrigRand_multiply,                    /*nb_multiply*/
-(binaryfunc)TrigRand_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -832,16 +820,16 @@ static PyNumberMethods TrigRand_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)TrigRand_inplace_add,                 /*inplace_add*/
 (binaryfunc)TrigRand_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)TrigRand_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)TrigRand_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -850,15 +838,14 @@ static PyNumberMethods TrigRand_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)TrigRand_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)TrigRand_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject TrigRandType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.TrigRand_base",                                   /*tp_name*/
 sizeof(TrigRand),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -866,7 +853,7 @@ sizeof(TrigRand),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &TrigRand_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -913,24 +900,24 @@ typedef struct {
     int timeStep;
     MYFLT stepVal;
     int timeCount;
-    int modebuffer[2]; // need at least 2 slots for mul & add 
+    int modebuffer[2]; // need at least 2 slots for mul & add
 } TrigChoice;
 
 static void
 TrigChoice_generate(TrigChoice *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (in[i] == 1) {
             self->timeCount = 0;
-            self->value = self->choice[(int)((rand()/((MYFLT)(RAND_MAX))) * self->chSize)];
+            self->value = self->choice[(int)(RANDOM_UNIFORM * self->chSize)];
             if (self->time <= 0.0)
                 self->currentValue = self->value;
             else
                 self->stepVal = (self->value - self->currentValue) / self->timeStep;
         }
-        
+
         if (self->timeCount == (self->timeStep - 1)) {
             self->currentValue = self->value;
             self->timeCount++;
@@ -939,7 +926,7 @@ TrigChoice_generate(TrigChoice *self) {
             self->currentValue += self->stepVal;
             self->timeCount++;
         }
-        
+
         self->data[i] = self->currentValue;
     }
 }
@@ -959,44 +946,44 @@ TrigChoice_setProcMode(TrigChoice *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = TrigChoice_generate;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = TrigChoice_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = TrigChoice_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = TrigChoice_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = TrigChoice_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = TrigChoice_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = TrigChoice_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = TrigChoice_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = TrigChoice_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = TrigChoice_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 TrigChoice_compute_next_data_frame(TrigChoice *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1009,7 +996,7 @@ TrigChoice_traverse(TrigChoice *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 TrigChoice_clear(TrigChoice *self)
 {
     pyo_CLEAR
@@ -1024,7 +1011,7 @@ TrigChoice_dealloc(TrigChoice* self)
     pyo_DEALLOC
     free(self->choice);
     TrigChoice_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1035,25 +1022,25 @@ TrigChoice_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *choicetmp=NULL, *multmp=NULL, *addtmp=NULL;
     TrigChoice *self;
     self = (TrigChoice *)type->tp_alloc(type, 0);
-    
+
     self->value = self->currentValue = 0.;
     self->time = 0.0;
     self->timeCount = 0;
     self->stepVal = 0.0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, TrigChoice_compute_next_data_frame);
     self->mode_func_ptr = TrigChoice_setProcMode;
 
     static char *kwlist[] = {"input", "choice", "port", "init", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_OO_FFOO, kwlist, &inputtmp, &choicetmp, &self->time, &inittmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (choicetmp) {
         PyObject_CallMethod((PyObject *)self, "setChoice", "O", choicetmp);
     }
@@ -1061,18 +1048,18 @@ TrigChoice_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     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);
-    
+
     Server_generateSeed((Server *)self->server, TRIGCHOICE_ID);
 
     self->value = self->currentValue = inittmp;
     self->timeStep = (int)(self->time * self->sr);
-    
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
@@ -1080,10 +1067,10 @@ TrigChoice_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * TrigChoice_getServer(TrigChoice* self) { GET_SERVER };
 static PyObject * TrigChoice_getStream(TrigChoice* self) { GET_STREAM };
-static PyObject * TrigChoice_setMul(TrigChoice *self, PyObject *arg) { SET_MUL };	
-static PyObject * TrigChoice_setAdd(TrigChoice *self, PyObject *arg) { SET_ADD };	
-static PyObject * TrigChoice_setSub(TrigChoice *self, PyObject *arg) { SET_SUB };	
-static PyObject * TrigChoice_setDiv(TrigChoice *self, PyObject *arg) { SET_DIV };	
+static PyObject * TrigChoice_setMul(TrigChoice *self, PyObject *arg) { SET_MUL };
+static PyObject * TrigChoice_setAdd(TrigChoice *self, PyObject *arg) { SET_ADD };
+static PyObject * TrigChoice_setSub(TrigChoice *self, PyObject *arg) { SET_SUB };
+static PyObject * TrigChoice_setDiv(TrigChoice *self, PyObject *arg) { SET_DIV };
 
 static PyObject * TrigChoice_play(TrigChoice *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * TrigChoice_out(TrigChoice *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1103,7 +1090,7 @@ TrigChoice_setChoice(TrigChoice *self, PyObject *arg)
 {
     int i;
 	PyObject *tmp;
-	
+
 	if (! PyList_Check(arg)) {
         PyErr_SetString(PyExc_TypeError, "The choice attribute must be a list.");
 		Py_INCREF(Py_None);
@@ -1114,37 +1101,34 @@ TrigChoice_setChoice(TrigChoice *self, PyObject *arg)
     self->chSize = PyList_Size(tmp);
     self->choice = (MYFLT *)realloc(self->choice, self->chSize * sizeof(MYFLT));
     for (i=0; i<self->chSize; i++) {
-        self->choice[i] = PyFloat_AS_DOUBLE(PyNumber_Float(PyList_GET_ITEM(tmp, i)));
+        self->choice[i] = PyFloat_AsDouble(PyList_GET_ITEM(tmp, i));
     }
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 TrigChoice_setPort(TrigChoice *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	if (isNumber == 1) {
-		self->time = PyFloat_AS_DOUBLE(PyNumber_Float(tmp));
+		self->time = PyFloat_AsDouble(tmp);
         self->timeStep = (int)(self->time * self->sr);
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef TrigChoice_members[] = {
 {"server", T_OBJECT_EX, offsetof(TrigChoice, server), 0, "Pyo server."},
@@ -1174,7 +1158,7 @@ static PyNumberMethods TrigChoice_as_number = {
 (binaryfunc)TrigChoice_add,                         /*nb_add*/
 (binaryfunc)TrigChoice_sub,                         /*nb_subtract*/
 (binaryfunc)TrigChoice_multiply,                    /*nb_multiply*/
-(binaryfunc)TrigChoice_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -1188,16 +1172,16 @@ static PyNumberMethods TrigChoice_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)TrigChoice_inplace_add,                 /*inplace_add*/
 (binaryfunc)TrigChoice_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)TrigChoice_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)TrigChoice_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -1206,15 +1190,14 @@ static PyNumberMethods TrigChoice_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)TrigChoice_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)TrigChoice_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject TrigChoiceType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.TrigChoice_base",                                   /*tp_name*/
 sizeof(TrigChoice),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -1222,7 +1205,7 @@ sizeof(TrigChoice),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &TrigChoice_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -1270,7 +1253,7 @@ TrigFunc_generate(TrigFunc *self) {
     int i;
     PyObject *tuple, *result;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (in[i] == 1) {
             if (self->arg == Py_None) {
@@ -1283,20 +1266,20 @@ TrigFunc_generate(TrigFunc *self) {
             else {
                 tuple = PyTuple_New(1);
                 PyTuple_SET_ITEM(tuple, 0, self->arg);
-                result = PyObject_Call(self->func, tuple, NULL);                
+                result = PyObject_Call(self->func, tuple, NULL);
                 if (result == NULL) {
                     PyErr_Print();
                     return;
                 }
             }
-        }    
+        }
     }
 }
 
 static void
 TrigFunc_compute_next_data_frame(TrigFunc *self)
 {
-    TrigFunc_generate(self); 
+    TrigFunc_generate(self);
 }
 
 static int
@@ -1310,7 +1293,7 @@ TrigFunc_traverse(TrigFunc *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 TrigFunc_clear(TrigFunc *self)
 {
     pyo_CLEAR
@@ -1326,7 +1309,7 @@ TrigFunc_dealloc(TrigFunc* self)
 {
     pyo_DEALLOC
     TrigFunc_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1343,20 +1326,27 @@ TrigFunc_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     Stream_setFunctionPtr(self->stream, TrigFunc_compute_next_data_frame);
 
     static char *kwlist[] = {"input", "function", "arg", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|O", kwlist, &inputtmp, &functmp, &argtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (functmp) {
         PyObject_CallMethod((PyObject *)self, "setFunction", "O", functmp);
     }
 
     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);
 
     return (PyObject *)self;
@@ -1372,21 +1362,21 @@ static PyObject *
 TrigFunc_setFunction(TrigFunc *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
+
 	if (! PyCallable_Check(arg)) {
         PyErr_SetString(PyExc_TypeError, "The function attribute must be callable.");
 		Py_INCREF(Py_None);
 		return Py_None;
 	}
-    
+
     tmp = arg;
     Py_XDECREF(self->func);
     Py_INCREF(tmp);
     self->func = tmp;
-  
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 TrigFunc_setArg(TrigFunc *self, PyObject *arg)
@@ -1394,13 +1384,13 @@ TrigFunc_setArg(TrigFunc *self, PyObject *arg)
 	PyObject *tmp;
 
     tmp = arg;
-    Py_DECREF(self->arg);
+    Py_XDECREF(self->arg);
     Py_INCREF(tmp);
     self->arg = tmp;
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef TrigFunc_members[] = {
 {"server", T_OBJECT_EX, offsetof(TrigFunc, server), 0, "Pyo server."},
@@ -1420,8 +1410,7 @@ static PyMethodDef TrigFunc_methods[] = {
 };
 
 PyTypeObject TrigFuncType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.TrigFunc_base",                                   /*tp_name*/
 sizeof(TrigFunc),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -1429,7 +1418,7 @@ sizeof(TrigFunc),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 0,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -1489,7 +1478,7 @@ TrigEnv_readframes_i(TrigEnv *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *tablelist = TableStream_getData(self->table);
     int size = TableStream_getSize(self->table);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->trigsBuffer[i] = 0.0;
         if (in[i] == 1) {
@@ -1514,11 +1503,11 @@ TrigEnv_readframes_i(TrigEnv *self) {
         }
         else
             self->data[i] = 0.;
-        
+
         if (self->pointerPos > size && self->active == 1) {
             self->trigsBuffer[i] = 1.0;
             self->active = 0;
-        }    
+        }
     }
 }
 
@@ -1530,7 +1519,7 @@ TrigEnv_readframes_a(TrigEnv *self) {
     MYFLT *dur_st = Stream_getData((Stream *)self->dur_stream);
     MYFLT *tablelist = TableStream_getData(self->table);
     int size = TableStream_getSize(self->table);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->trigsBuffer[i] = 0.0;
         if (in[i] == 1) {
@@ -1555,7 +1544,7 @@ TrigEnv_readframes_a(TrigEnv *self) {
         }
         else
             self->data[i] = 0.;
-        
+
         if (self->pointerPos > size && self->active == 1) {
             self->trigsBuffer[i] = 1.0;
             self->active = 0;
@@ -1579,50 +1568,50 @@ TrigEnv_setProcMode(TrigEnv *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2];
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:        
+        case 0:
             self->proc_func_ptr = TrigEnv_readframes_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = TrigEnv_readframes_a;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = TrigEnv_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = TrigEnv_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = TrigEnv_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = TrigEnv_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = TrigEnv_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = TrigEnv_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = TrigEnv_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = TrigEnv_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = TrigEnv_postprocessing_revareva;
             break;
-    } 
+    }
 }
 
 static void
 TrigEnv_compute_next_data_frame(TrigEnv *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1633,22 +1622,22 @@ TrigEnv_traverse(TrigEnv *self, visitproc visit, void *arg)
     Py_VISIT(self->table);
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->dur);    
-    Py_VISIT(self->dur_stream);    
-    Py_VISIT(self->trig_stream);    
+    Py_VISIT(self->dur);
+    Py_VISIT(self->dur_stream);
+    Py_VISIT(self->trig_stream);
     return 0;
 }
 
-static int 
+static int
 TrigEnv_clear(TrigEnv *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->table);
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->dur);    
-    Py_CLEAR(self->dur_stream);    
-    Py_CLEAR(self->trig_stream);    
+    Py_CLEAR(self->dur);
+    Py_CLEAR(self->dur_stream);
+    Py_CLEAR(self->trig_stream);
     return 0;
 }
 
@@ -1658,7 +1647,7 @@ TrigEnv_dealloc(TrigEnv* self)
     pyo_DEALLOC
     free(self->trigsBuffer);
     TrigEnv_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1668,15 +1657,15 @@ TrigEnv_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *tabletmp, *durtmp=NULL, *multmp=NULL, *addtmp=NULL;
     TrigEnv *self;
     self = (TrigEnv *)type->tp_alloc(type, 0);
-    
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
-    
+
     self->pointerPos = 0.;
     self->active = 0;
     self->interp = 2;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, TrigEnv_compute_next_data_frame);
     self->mode_func_ptr = TrigEnv_setProcMode;
@@ -1685,47 +1674,44 @@ TrigEnv_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->current_dur = self->sr;
 
     static char *kwlist[] = {"input", "table", "dur", "interp", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OiOO", kwlist, &inputtmp, &tabletmp, &durtmp, &self->interp, &multmp, &addtmp))
         Py_RETURN_NONE;
 
     INIT_INPUT_STREAM
-    
+
     if ( PyObject_HasAttrString((PyObject *)tabletmp, "getTableStream") == 0 ) {
-        PySys_WriteStderr("TypeError: \"table\" argument of TrigEnv must be a PyoTableObject.\n");
-        if (PyInt_AsLong(PyObject_CallMethod(self->server, "getIsBooted", NULL))) {
-            PyObject_CallMethod(self->server, "shutdown", NULL);
-        }
-        Py_Exit(1);
+        PyErr_SetString(PyExc_TypeError, "\"table\" argument of TrigEnv must be a PyoTableObject.\n");
+        Py_RETURN_NONE;
     }
     Py_XDECREF(self->table);
     self->table = PyObject_CallMethod((PyObject *)tabletmp, "getTableStream", "");
-    
+
     if (durtmp) {
         PyObject_CallMethod((PyObject *)self, "setDur", "O", durtmp);
     }
-    
+
     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->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT));
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->trigsBuffer[i] = 0.0;
-    }    
-    
+    }
+
     MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL);
     TriggerStream_setData(self->trig_stream, self->trigsBuffer);
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     SET_INTERP_POINTER
 
     return (PyObject *)self;
@@ -1734,10 +1720,10 @@ TrigEnv_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 static PyObject * TrigEnv_getServer(TrigEnv* self) { GET_SERVER };
 static PyObject * TrigEnv_getStream(TrigEnv* self) { GET_STREAM };
 static PyObject * TrigEnv_getTriggerStream(TrigEnv* self) { GET_TRIGGER_STREAM };
-static PyObject * TrigEnv_setMul(TrigEnv *self, PyObject *arg) { SET_MUL };	
-static PyObject * TrigEnv_setAdd(TrigEnv *self, PyObject *arg) { SET_ADD };	
-static PyObject * TrigEnv_setSub(TrigEnv *self, PyObject *arg) { SET_SUB };	
-static PyObject * TrigEnv_setDiv(TrigEnv *self, PyObject *arg) { SET_DIV };	
+static PyObject * TrigEnv_setMul(TrigEnv *self, PyObject *arg) { SET_MUL };
+static PyObject * TrigEnv_setAdd(TrigEnv *self, PyObject *arg) { SET_ADD };
+static PyObject * TrigEnv_setSub(TrigEnv *self, PyObject *arg) { SET_SUB };
+static PyObject * TrigEnv_setDiv(TrigEnv *self, PyObject *arg) { SET_DIV };
 
 static PyObject * TrigEnv_play(TrigEnv *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * TrigEnv_out(TrigEnv *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1763,32 +1749,26 @@ static PyObject *
 TrigEnv_setTable(TrigEnv *self, PyObject *arg)
 {
 	PyObject *tmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    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 *
 TrigEnv_setDur(TrigEnv *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->dur);
@@ -1804,29 +1784,26 @@ TrigEnv_setDur(TrigEnv *self, PyObject *arg)
         self->dur_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 TrigEnv_setInterp(TrigEnv *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
     int isNumber = PyNumber_Check(arg);
-    
+
 	if (isNumber == 1) {
 		self->interp = PyInt_AsLong(PyNumber_Int(arg));
-    }  
-    
+    }
+
     SET_INTERP_POINTER
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -1864,7 +1841,7 @@ static PyNumberMethods TrigEnv_as_number = {
 (binaryfunc)TrigEnv_add,                      /*nb_add*/
 (binaryfunc)TrigEnv_sub,                 /*nb_subtract*/
 (binaryfunc)TrigEnv_multiply,                 /*nb_multiply*/
-(binaryfunc)TrigEnv_div,                   /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -1878,16 +1855,16 @@ static PyNumberMethods TrigEnv_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
 (binaryfunc)TrigEnv_inplace_add,              /*inplace_add*/
 (binaryfunc)TrigEnv_inplace_sub,         /*inplace_subtract*/
 (binaryfunc)TrigEnv_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)TrigEnv_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -1896,15 +1873,14 @@ static PyNumberMethods TrigEnv_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)TrigEnv_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)TrigEnv_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
 PyTypeObject TrigEnvType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.TrigEnv_base",         /*tp_name*/
 sizeof(TrigEnv),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -1912,7 +1888,7 @@ sizeof(TrigEnv),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &TrigEnv_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -1971,23 +1947,23 @@ static void
 TrigLinseg_convert_pointslist(TrigLinseg *self) {
     int i;
     PyObject *tup;
-    
+
     self->listsize = PyList_Size(self->pointslist);
     self->targets = (MYFLT *)realloc(self->targets, self->listsize * sizeof(MYFLT));
     self->times = (MYFLT *)realloc(self->times, self->listsize * sizeof(MYFLT));
     for (i=0; i<self->listsize; i++) {
         tup = PyList_GET_ITEM(self->pointslist, i);
-        self->times[i] = PyFloat_AsDouble(PyNumber_Float(PyTuple_GET_ITEM(tup, 0)));
-        self->targets[i] = PyFloat_AsDouble(PyNumber_Float(PyTuple_GET_ITEM(tup, 1)));
+        self->times[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 0));
+        self->targets[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 1));
     }
 }
 
-static void 
+static void
 TrigLinseg_reinit(TrigLinseg *self) {
     if (self->newlist == 1) {
         TrigLinseg_convert_pointslist((TrigLinseg *)self);
         self->newlist = 0;
-    }    
+    }
     self->currentTime = 0.0;
     self->currentValue = self->targets[0];
     self->which = 0;
@@ -1998,7 +1974,7 @@ static void
 TrigLinseg_generate(TrigLinseg *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->trigsBuffer[i] = 0.0;
         if (in[i] == 1)
@@ -2011,7 +1987,7 @@ TrigLinseg_generate(TrigLinseg *self) {
                     self->trigsBuffer[i] = 1.0;
                     self->flag = 0;
                     self->currentValue = self->targets[self->which-1];
-                }    
+                }
                 else
                     if ((self->times[self->which] - self->times[self->which-1]) <= 0)
                         self->increment = self->targets[self->which] - self->currentValue;
@@ -2019,9 +1995,9 @@ TrigLinseg_generate(TrigLinseg *self) {
                         self->increment = (self->targets[self->which] - self->targets[self->which-1]) / ((self->times[self->which] - self->times[self->which-1]) / self->sampleToSec);
             }
             if (self->currentTime <= self->times[self->listsize-1])
-                self->currentValue += self->increment;            
+                self->currentValue += self->increment;
             self->data[i] = (MYFLT)self->currentValue;
-            self->currentTime += self->sampleToSec;    
+            self->currentTime += self->sampleToSec;
         }
         else
             self->data[i] = (MYFLT)self->currentValue;
@@ -2043,44 +2019,44 @@ TrigLinseg_setProcMode(TrigLinseg *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = TrigLinseg_generate;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = TrigLinseg_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = TrigLinseg_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = TrigLinseg_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = TrigLinseg_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = TrigLinseg_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = TrigLinseg_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = TrigLinseg_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = TrigLinseg_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = TrigLinseg_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 TrigLinseg_compute_next_data_frame(TrigLinseg *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -2089,20 +2065,20 @@ TrigLinseg_traverse(TrigLinseg *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->pointslist);
-    Py_VISIT(self->trig_stream);    
-    Py_VISIT(self->input);    
-    Py_VISIT(self->input_stream);    
+    Py_VISIT(self->trig_stream);
+    Py_VISIT(self->input);
+    Py_VISIT(self->input_stream);
     return 0;
 }
 
-static int 
+static int
 TrigLinseg_clear(TrigLinseg *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->pointslist);
-    Py_CLEAR(self->trig_stream);    
-    Py_CLEAR(self->input);    
-    Py_CLEAR(self->input_stream);    
+    Py_CLEAR(self->trig_stream);
+    Py_CLEAR(self->input);
+    Py_CLEAR(self->input_stream);
     return 0;
 }
 
@@ -2114,7 +2090,7 @@ TrigLinseg_dealloc(TrigLinseg* self)
     free(self->times);
     free(self->trigsBuffer);
     TrigLinseg_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2124,11 +2100,11 @@ TrigLinseg_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *pointslist=NULL, *multmp=NULL, *addtmp=NULL;
     TrigLinseg *self;
     self = (TrigLinseg *)type->tp_alloc(type, 0);
-    
+
     self->newlist = 1;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, TrigLinseg_compute_next_data_frame);
     self->mode_func_ptr = TrigLinseg_setProcMode;
@@ -2136,7 +2112,7 @@ TrigLinseg_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->sampleToSec = 1. / self->sr;
 
     static char *kwlist[] = {"input", "list", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist, &inputtmp, &pointslist, &multmp, &addtmp))
         Py_RETURN_NONE;
 
@@ -2146,38 +2122,38 @@ TrigLinseg_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     Py_XDECREF(self->pointslist);
     self->pointslist = pointslist;
     TrigLinseg_convert_pointslist((TrigLinseg *)self);
-    
+
     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->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT));
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->trigsBuffer[i] = 0.0;
-    }    
-    
+    }
+
     MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL);
     TriggerStream_setData(self->trig_stream, self->trigsBuffer);
 
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * TrigLinseg_getServer(TrigLinseg* self) { GET_SERVER };
 static PyObject * TrigLinseg_getStream(TrigLinseg* self) { GET_STREAM };
 static PyObject * TrigLinseg_getTriggerStream(TrigLinseg* self) { GET_TRIGGER_STREAM };
-static PyObject * TrigLinseg_setMul(TrigLinseg *self, PyObject *arg) { SET_MUL };	
-static PyObject * TrigLinseg_setAdd(TrigLinseg *self, PyObject *arg) { SET_ADD };	
-static PyObject * TrigLinseg_setSub(TrigLinseg *self, PyObject *arg) { SET_SUB };	
-static PyObject * TrigLinseg_setDiv(TrigLinseg *self, PyObject *arg) { SET_DIV };	
+static PyObject * TrigLinseg_setMul(TrigLinseg *self, PyObject *arg) { SET_MUL };
+static PyObject * TrigLinseg_setAdd(TrigLinseg *self, PyObject *arg) { SET_ADD };
+static PyObject * TrigLinseg_setSub(TrigLinseg *self, PyObject *arg) { SET_SUB };
+static PyObject * TrigLinseg_setDiv(TrigLinseg *self, PyObject *arg) { SET_DIV };
 
 static PyObject * TrigLinseg_play(TrigLinseg *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * TrigLinseg_stop(TrigLinseg *self) { STOP };
@@ -2198,18 +2174,18 @@ TrigLinseg_setList(TrigLinseg *self, PyObject *value)
         PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyList_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The points list attribute value must be a list of tuples.");
         return PyInt_FromLong(-1);
     }
-    
+
     Py_INCREF(value);
     Py_DECREF(self->pointslist);
-    self->pointslist = value; 
-    
+    self->pointslist = value;
+
     self->newlist = 1;
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -2242,7 +2218,7 @@ static PyNumberMethods TrigLinseg_as_number = {
 (binaryfunc)TrigLinseg_add,                      /*nb_add*/
 (binaryfunc)TrigLinseg_sub,                 /*nb_subtract*/
 (binaryfunc)TrigLinseg_multiply,                 /*nb_multiply*/
-(binaryfunc)TrigLinseg_div,                   /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -2256,16 +2232,16 @@ static PyNumberMethods TrigLinseg_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
 (binaryfunc)TrigLinseg_inplace_add,              /*inplace_add*/
 (binaryfunc)TrigLinseg_inplace_sub,         /*inplace_subtract*/
 (binaryfunc)TrigLinseg_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)TrigLinseg_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -2274,15 +2250,14 @@ static PyNumberMethods TrigLinseg_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)TrigLinseg_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)TrigLinseg_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
 PyTypeObject TrigLinsegType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.TrigLinseg_base",         /*tp_name*/
 sizeof(TrigLinseg),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -2290,7 +2265,7 @@ sizeof(TrigLinseg),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &TrigLinseg_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -2347,7 +2322,7 @@ typedef struct {
     double exp;
     double exp_tmp;
     int inverse;
-    int inverse_tmp;    
+    int inverse_tmp;
     MYFLT *trigsBuffer;
     TriggerStream *trig_stream;
 } TrigExpseg;
@@ -2356,23 +2331,23 @@ static void
 TrigExpseg_convert_pointslist(TrigExpseg *self) {
     int i;
     PyObject *tup;
-    
+
     self->listsize = PyList_Size(self->pointslist);
     self->targets = (MYFLT *)realloc(self->targets, self->listsize * sizeof(MYFLT));
     self->times = (MYFLT *)realloc(self->times, self->listsize * sizeof(MYFLT));
     for (i=0; i<self->listsize; i++) {
         tup = PyList_GET_ITEM(self->pointslist, i);
-        self->times[i] = PyFloat_AsDouble(PyNumber_Float(PyTuple_GET_ITEM(tup, 0)));
-        self->targets[i] = PyFloat_AsDouble(PyNumber_Float(PyTuple_GET_ITEM(tup, 1)));
+        self->times[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 0));
+        self->targets[i] = PyFloat_AsDouble(PyTuple_GET_ITEM(tup, 1));
     }
 }
 
-static void 
+static void
 TrigExpseg_reinit(TrigExpseg *self) {
     if (self->newlist == 1) {
         TrigExpseg_convert_pointslist((TrigExpseg *)self);
         self->newlist = 0;
-    }    
+    }
     self->currentTime = 0.0;
     self->currentValue = self->targets[0];
     self->which = 0;
@@ -2386,12 +2361,12 @@ TrigExpseg_generate(TrigExpseg *self) {
     int i;
     MYFLT scl;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->trigsBuffer[i] = 0.0;
         if (in[i] == 1)
             TrigExpseg_reinit((TrigExpseg *)self);
-        
+
         if (self->flag == 1) {
             if (self->currentTime >= self->times[self->which]) {
                 self->which++;
@@ -2399,7 +2374,7 @@ TrigExpseg_generate(TrigExpseg *self) {
                     self->trigsBuffer[i] = 1.0;
                     self->flag = 0;
                     self->currentValue = self->targets[self->which-1];
-                }    
+                }
                 else {
                     self->range = self->targets[self->which] - self->targets[self->which-1];
                     self->steps = (self->times[self->which] - self->times[self->which-1]) * self->sr;
@@ -2407,9 +2382,9 @@ TrigExpseg_generate(TrigExpseg *self) {
                         self->inc = 1.0;
                     else
                         self->inc = 1.0 / self->steps;
-                    self->pointer = 0.0;                    
+                    self->pointer = 0.0;
                 }
-            }    
+            }
             if (self->currentTime <= self->times[self->listsize-1]) {
                 if (self->pointer >= 1.0)
                     self->pointer = 1.0;
@@ -2417,12 +2392,12 @@ TrigExpseg_generate(TrigExpseg *self) {
                     scl = 1.0 - MYPOW(1.0 - self->pointer, self->exp);
                 else
                     scl = MYPOW(self->pointer, self->exp);
-                
+
                 self->currentValue = scl * self->range + self->targets[self->which-1];
                 self->pointer += self->inc;
-            } 
+            }
             self->data[i] = (MYFLT)self->currentValue;
-            self->currentTime += self->sampleToSec;    
+            self->currentTime += self->sampleToSec;
         }
         else
             self->data[i] = (MYFLT)self->currentValue;
@@ -2444,44 +2419,44 @@ TrigExpseg_setProcMode(TrigExpseg *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = TrigExpseg_generate;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = TrigExpseg_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = TrigExpseg_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = TrigExpseg_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = TrigExpseg_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = TrigExpseg_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = TrigExpseg_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = TrigExpseg_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = TrigExpseg_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = TrigExpseg_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 TrigExpseg_compute_next_data_frame(TrigExpseg *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -2490,20 +2465,20 @@ TrigExpseg_traverse(TrigExpseg *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->pointslist);
-    Py_VISIT(self->trig_stream);    
-    Py_VISIT(self->input);    
-    Py_VISIT(self->input_stream);    
+    Py_VISIT(self->trig_stream);
+    Py_VISIT(self->input);
+    Py_VISIT(self->input_stream);
     return 0;
 }
 
-static int 
+static int
 TrigExpseg_clear(TrigExpseg *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->pointslist);
-    Py_CLEAR(self->trig_stream);    
-    Py_CLEAR(self->input);    
-    Py_CLEAR(self->input_stream);    
+    Py_CLEAR(self->trig_stream);
+    Py_CLEAR(self->input);
+    Py_CLEAR(self->input_stream);
     return 0;
 }
 
@@ -2515,7 +2490,7 @@ TrigExpseg_dealloc(TrigExpseg* self)
     free(self->times);
     free(self->trigsBuffer);
     TrigExpseg_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2525,62 +2500,62 @@ TrigExpseg_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *pointslist=NULL, *multmp=NULL, *addtmp=NULL;
     TrigExpseg *self;
     self = (TrigExpseg *)type->tp_alloc(type, 0);
-    
+
     self->newlist = 1;
     self->exp = self->exp_tmp = 10;
     self->inverse = self->inverse_tmp = 1;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, TrigExpseg_compute_next_data_frame);
     self->mode_func_ptr = TrigExpseg_setProcMode;
-    
+
     self->sampleToSec = 1. / self->sr;
 
     static char *kwlist[] = {"input", "list", "exp", "inverse", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|diOO", kwlist, &inputtmp, &pointslist, &self->exp_tmp, &self->inverse_tmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     Py_INCREF(pointslist);
     Py_XDECREF(self->pointslist);
     self->pointslist = pointslist;
     TrigExpseg_convert_pointslist((TrigExpseg *)self);
-    
+
     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->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT));
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->trigsBuffer[i] = 0.0;
-    }    
+    }
 
     MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL);
     TriggerStream_setData(self->trig_stream, self->trigsBuffer);
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
 static PyObject * TrigExpseg_getServer(TrigExpseg* self) { GET_SERVER };
 static PyObject * TrigExpseg_getStream(TrigExpseg* self) { GET_STREAM };
 static PyObject * TrigExpseg_getTriggerStream(TrigExpseg* self) { GET_TRIGGER_STREAM };
-static PyObject * TrigExpseg_setMul(TrigExpseg *self, PyObject *arg) { SET_MUL };	
-static PyObject * TrigExpseg_setAdd(TrigExpseg *self, PyObject *arg) { SET_ADD };	
-static PyObject * TrigExpseg_setSub(TrigExpseg *self, PyObject *arg) { SET_SUB };	
-static PyObject * TrigExpseg_setDiv(TrigExpseg *self, PyObject *arg) { SET_DIV };	
+static PyObject * TrigExpseg_setMul(TrigExpseg *self, PyObject *arg) { SET_MUL };
+static PyObject * TrigExpseg_setAdd(TrigExpseg *self, PyObject *arg) { SET_ADD };
+static PyObject * TrigExpseg_setSub(TrigExpseg *self, PyObject *arg) { SET_SUB };
+static PyObject * TrigExpseg_setDiv(TrigExpseg *self, PyObject *arg) { SET_DIV };
 
 static PyObject * TrigExpseg_play(TrigExpseg *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * TrigExpseg_stop(TrigExpseg *self) { STOP };
@@ -2601,18 +2576,18 @@ TrigExpseg_setList(TrigExpseg *self, PyObject *value)
         PyErr_SetString(PyExc_TypeError, "Cannot delete the list attribute.");
         return PyInt_FromLong(-1);
     }
-    
+
     if (! PyList_Check(value)) {
         PyErr_SetString(PyExc_TypeError, "The points list attribute value must be a list of tuples.");
         return PyInt_FromLong(-1);
     }
-    
+
     Py_INCREF(value);
     Py_DECREF(self->pointslist);
-    self->pointslist = value; 
-    
+    self->pointslist = value;
+
     self->newlist = 1;
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -2620,13 +2595,11 @@ TrigExpseg_setList(TrigExpseg *self, PyObject *value)
 static PyObject *
 TrigExpseg_setExp(TrigExpseg *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-    self->exp_tmp = PyFloat_AsDouble(PyNumber_Float(arg));
-    
+    ASSERT_ARG_NOT_NULL
+
+    // TODO: PyNumber_Check()
+    self->exp_tmp = PyFloat_AsDouble(arg);
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -2634,13 +2607,10 @@ TrigExpseg_setExp(TrigExpseg *self, PyObject *arg)
 static PyObject *
 TrigExpseg_setInverse(TrigExpseg *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
     self->inverse_tmp = PyInt_AsLong(PyNumber_Int(arg));
-    
+
     Py_INCREF(Py_None);
     return Py_None;
 }
@@ -2675,7 +2645,7 @@ static PyNumberMethods TrigExpseg_as_number = {
 (binaryfunc)TrigExpseg_add,                      /*nb_add*/
 (binaryfunc)TrigExpseg_sub,                 /*nb_subtract*/
 (binaryfunc)TrigExpseg_multiply,                 /*nb_multiply*/
-(binaryfunc)TrigExpseg_div,                   /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -2689,16 +2659,16 @@ static PyNumberMethods TrigExpseg_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
 (binaryfunc)TrigExpseg_inplace_add,              /*inplace_add*/
 (binaryfunc)TrigExpseg_inplace_sub,         /*inplace_subtract*/
 (binaryfunc)TrigExpseg_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)TrigExpseg_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -2707,15 +2677,14 @@ static PyNumberMethods TrigExpseg_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)TrigExpseg_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)TrigExpseg_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
 PyTypeObject TrigExpsegType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.TrigExpseg_base",         /*tp_name*/
 sizeof(TrigExpseg),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -2723,7 +2692,7 @@ sizeof(TrigExpseg),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &TrigExpseg_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -2782,18 +2751,18 @@ typedef struct {
     int loopCountRec;
     int loopLen;
     int loopStop;
-    int modebuffer[4]; // need at least 2 slots for mul & add 
+    int modebuffer[4]; // need at least 2 slots for mul & add
 } TrigXnoise;
 
 // no parameter
 static MYFLT
 TrigXnoise_uniform(TrigXnoise *self) {
-    return RANDOM_UNIFORM;    
+    return RANDOM_UNIFORM;
 }
 
 static MYFLT
 TrigXnoise_linear_min(TrigXnoise *self) {
-    MYFLT a = RANDOM_UNIFORM;    
+    MYFLT a = RANDOM_UNIFORM;
     MYFLT b = RANDOM_UNIFORM;
     if (a < b) return a;
     else return b;
@@ -2801,7 +2770,7 @@ TrigXnoise_linear_min(TrigXnoise *self) {
 
 static MYFLT
 TrigXnoise_linear_max(TrigXnoise *self) {
-    MYFLT a = RANDOM_UNIFORM;    
+    MYFLT a = RANDOM_UNIFORM;
     MYFLT b = RANDOM_UNIFORM;
     if (a > b) return a;
     else return b;
@@ -2809,7 +2778,7 @@ TrigXnoise_linear_max(TrigXnoise *self) {
 
 static MYFLT
 TrigXnoise_triangle(TrigXnoise *self) {
-    MYFLT a = RANDOM_UNIFORM;    
+    MYFLT a = RANDOM_UNIFORM;
     MYFLT b = RANDOM_UNIFORM;
     return ((a + b) * 0.5);
 }
@@ -2818,7 +2787,7 @@ TrigXnoise_triangle(TrigXnoise *self) {
 static MYFLT
 TrigXnoise_expon_min(TrigXnoise *self) {
     if (self->xx1 <= 0.0) self->xx1 = 0.00001;
-    MYFLT val = -MYLOG(RANDOM_UNIFORM) / self->xx1;    
+    MYFLT val = -MYLOG(RANDOM_UNIFORM) / self->xx1;
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -2827,7 +2796,7 @@ TrigXnoise_expon_min(TrigXnoise *self) {
 static MYFLT
 TrigXnoise_expon_max(TrigXnoise *self) {
     if (self->xx1 <= 0.0) self->xx1 = 0.00001;
-    MYFLT val = 1.0 - (-MYLOG(RANDOM_UNIFORM) / self->xx1);    
+    MYFLT val = 1.0 - (-MYLOG(RANDOM_UNIFORM) / self->xx1);
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -2839,16 +2808,16 @@ TrigXnoise_biexpon(TrigXnoise *self) {
     MYFLT polar, val;
     if (self->xx1 <= 0.0) self->xx1 = 0.00001;
     MYFLT sum = RANDOM_UNIFORM * 2.0;
-    
+
     if (sum > 1.0) {
         polar = -1;
         sum = 2.0 - sum;
     }
     else
         polar = 1;
-    
+
     val = 0.5 * (polar * MYLOG(sum) / self->xx1) + 0.5;
-    
+
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -2861,14 +2830,14 @@ TrigXnoise_cauchy(TrigXnoise *self) {
         rnd = RANDOM_UNIFORM;
     }
     while (rnd == 0.5);
-    
-    if (rand() < (RAND_MAX / 2))
+
+    if (pyorand() < (PYO_RAND_MAX / 2))
         dir = -1;
     else
         dir = 1;
-    
+
     val = 0.5 * (MYTAN(rnd) * self->xx1 * dir) + 0.5;
-    
+
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -2879,10 +2848,10 @@ static MYFLT
 TrigXnoise_weibull(TrigXnoise *self) {
     MYFLT rnd, val;
     if (self->xx2 <= 0.0) self->xx2 = 0.00001;
-    
+
     rnd = 1.0 / (1.0 - RANDOM_UNIFORM);
     val = self->xx1 * MYPOW(MYLOG(rnd), (1.0 / self->xx2));
-    
+
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -2892,10 +2861,10 @@ TrigXnoise_weibull(TrigXnoise *self) {
 static MYFLT
 TrigXnoise_gaussian(TrigXnoise *self) {
     MYFLT rnd, val;
-    
+
     rnd = (RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM);
     val = (self->xx2 * (rnd - 3.0) * 0.33 + self->xx1);
-    
+
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -2909,7 +2878,7 @@ TrigXnoise_poisson(TrigXnoise *self) {
     MYFLT val;
     if (self->xx1 < 0.1) self->xx1 = 0.1;
     if (self->xx2 < 0.1) self->xx2 = 0.1;
-    
+
     if (self->xx1 != self->lastPoissonX1) {
         self->lastPoissonX1 = self->xx1;
         self->poisson_tab = 0;
@@ -2923,8 +2892,8 @@ TrigXnoise_poisson(TrigXnoise *self) {
             }
         }
     }
-    val = self->poisson_buffer[rand() % self->poisson_tab] / 12.0 * self->xx2;
-    
+    val = self->poisson_buffer[pyorand() % self->poisson_tab] / 12.0 * self->xx2;
+
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -2933,77 +2902,77 @@ TrigXnoise_poisson(TrigXnoise *self) {
 // x1 = max value, x2 = max step
 static MYFLT
 TrigXnoise_walker(TrigXnoise *self) {
-    int modulo, dir;
-    
+    unsigned int modulo, dir;
+
     if (self->xx2 < 0.002) self->xx2 = 0.002;
-    
-    modulo = (int)(self->xx2 * 1000.0);
-    dir = rand() % 2;
-    
-    if (dir == 0)
-        self->walkerValue = self->walkerValue + (((rand() % modulo) - (modulo / 2)) * 0.001);
+
+    modulo = (unsigned int)(self->xx2 * 1000.0);
+    dir = pyorand() % 100;
+
+    if (dir < 50)
+        self->walkerValue += ((MYFLT)(pyorand() % modulo) * 0.001);
     else
-        self->walkerValue = self->walkerValue - (((rand() % modulo) - (modulo / 2)) * 0.001);
-    
+        self->walkerValue -= ((MYFLT)(pyorand() % modulo) * 0.001);
+
     if (self->walkerValue > self->xx1)
         self->walkerValue = self->xx1;
-    if (self->walkerValue < 0.0)
+    else if (self->walkerValue < 0.0)
         self->walkerValue = 0.0;
-    
+
     return self->walkerValue;
 }
 
 // x1 = max value, x2 = max step
 static MYFLT
 TrigXnoise_loopseg(TrigXnoise *self) {
-    int modulo, dir;
-    
+    unsigned int modulo, dir;
+
     if (self->loopChoice == 0) {
-        
+
         self->loopCountPlay = self->loopTime = 0;
-        
+
         if (self->xx2 < 0.002) self->xx2 = 0.002;
-        
-        modulo = (int)(self->xx2 * 1000.0);
-        dir = rand() % 2;
-        
-        if (dir == 0)
-            self->walkerValue = self->walkerValue + (((rand() % modulo) - (modulo / 2)) * 0.001);
+
+        modulo = (unsigned int)(self->xx2 * 1000.0);
+        dir = pyorand() % 100;
+
+        if (dir < 50)
+            self->walkerValue += ((MYFLT)(pyorand() % modulo) * 0.001);
         else
-            self->walkerValue = self->walkerValue - (((rand() % modulo) - (modulo / 2)) * 0.001);
-        
+            self->walkerValue -= ((MYFLT)(pyorand() % modulo) * 0.001);
+
         if (self->walkerValue > self->xx1)
             self->walkerValue = self->xx1;
-        if (self->walkerValue < 0.0)
+        else if (self->walkerValue < 0.0)
             self->walkerValue = 0.0;
-        
+
         self->loop_buffer[self->loopCountRec++] = self->walkerValue;
-        
+
         if (self->loopCountRec < self->loopLen)
             self->loopChoice = 0;
         else {
             self->loopChoice = 1;
-            self->loopStop = (rand() % 4) + 1;
+            self->loopStop = (pyorand() % 4) + 1;
         }
     }
     else {
         self->loopCountRec = 0;
-        
+
         self->walkerValue = self->loop_buffer[self->loopCountPlay++];
-        
+
         if (self->loopCountPlay < self->loopLen)
             self->loopChoice = 1;
         else {
             self->loopCountPlay = 0;
             self->loopTime++;
         }
-        
+
         if (self->loopTime == self->loopStop) {
             self->loopChoice = 0;
-            self->loopLen = (rand() % 10) + 3;
+            self->loopLen = (pyorand() % 10) + 3;
         }
     }
-    
+
     return self->walkerValue;
 }
 
@@ -3013,7 +2982,7 @@ TrigXnoise_generate_ii(TrigXnoise *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     self->xx1 = PyFloat_AS_DOUBLE(self->x1);
     self->xx2 = PyFloat_AS_DOUBLE(self->x2);
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (in[i] == 1)
             self->value = (*self->type_func_ptr)(self);
@@ -3027,7 +2996,7 @@ TrigXnoise_generate_ai(TrigXnoise *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *x1 = Stream_getData((Stream *)self->x1_stream);
     self->xx2 = PyFloat_AS_DOUBLE(self->x2);
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (in[i] == 1) {
             self->xx1 = x1[i];
@@ -3043,7 +3012,7 @@ TrigXnoise_generate_ia(TrigXnoise *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     self->xx1 = PyFloat_AS_DOUBLE(self->x1);
     MYFLT *x2 = Stream_getData((Stream *)self->x2_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (in[i] == 1) {
             self->xx2 = x2[i];
@@ -3059,7 +3028,7 @@ TrigXnoise_generate_aa(TrigXnoise *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *x1 = Stream_getData((Stream *)self->x1_stream);
     MYFLT *x2 = Stream_getData((Stream *)self->x2_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (in[i] == 1) {
             self->xx1 = x1[i];
@@ -3083,8 +3052,8 @@ static void TrigXnoise_postprocessing_revareva(TrigXnoise *self) { POST_PROCESSI
 static void
 TrigXnoise_setRandomType(TrigXnoise *self)
 {
-    
-    switch (self->type) {            
+
+    switch (self->type) {
         case 0:
             self->type_func_ptr = TrigXnoise_uniform;
             break;
@@ -3124,7 +3093,7 @@ TrigXnoise_setRandomType(TrigXnoise *self)
         case 12:
             self->type_func_ptr = TrigXnoise_loopseg;
             break;
-    }        
+    }
 }
 
 static void
@@ -3133,56 +3102,56 @@ TrigXnoise_setProcMode(TrigXnoise *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = TrigXnoise_generate_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = TrigXnoise_generate_ai;
             break;
-        case 10:    
+        case 10:
             self->proc_func_ptr = TrigXnoise_generate_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = TrigXnoise_generate_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = TrigXnoise_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = TrigXnoise_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = TrigXnoise_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = TrigXnoise_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = TrigXnoise_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = TrigXnoise_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = TrigXnoise_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = TrigXnoise_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = TrigXnoise_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 TrigXnoise_compute_next_data_frame(TrigXnoise *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -3192,23 +3161,23 @@ TrigXnoise_traverse(TrigXnoise *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->x1);    
-    Py_VISIT(self->x1_stream);    
-    Py_VISIT(self->x2);    
-    Py_VISIT(self->x2_stream);    
+    Py_VISIT(self->x1);
+    Py_VISIT(self->x1_stream);
+    Py_VISIT(self->x2);
+    Py_VISIT(self->x2_stream);
     return 0;
 }
 
-static int 
+static int
 TrigXnoise_clear(TrigXnoise *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->x1);    
-    Py_CLEAR(self->x1_stream);    
-    Py_CLEAR(self->x2);    
-    Py_CLEAR(self->x2_stream);    
+    Py_CLEAR(self->x1);
+    Py_CLEAR(self->x1_stream);
+    Py_CLEAR(self->x2);
+    Py_CLEAR(self->x2_stream);
     return 0;
 }
 
@@ -3217,7 +3186,7 @@ TrigXnoise_dealloc(TrigXnoise* self)
 {
     pyo_DEALLOC
     TrigXnoise_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -3227,7 +3196,7 @@ TrigXnoise_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *x1tmp=NULL, *x2tmp=NULL, *multmp=NULL, *addtmp=NULL;
     TrigXnoise *self;
     self = (TrigXnoise *)type->tp_alloc(type, 0);
-        
+
     self->x1 = PyFloat_FromDouble(0.5);
     self->x2 = PyFloat_FromDouble(0.5);
     self->xx1 = self->xx2 = self->walkerValue = 0.5;
@@ -3238,7 +3207,7 @@ TrigXnoise_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[3] = 0;
 
     INIT_OBJECT_COMMON
-    
+
     Server_generateSeed((Server *)self->server, TRIGXNOISE_ID);
 
     self->poisson_tab = 0;
@@ -3249,23 +3218,23 @@ TrigXnoise_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     for (i=0; i<15; i++) {
         self->loop_buffer[i] = 0.0;
     }
-    self->loopChoice = self->loopCountPlay = self->loopTime = self->loopCountRec = self->loopStop = 0;    
-    self->loopLen = (rand() % 10) + 3;
-    
+    self->loopChoice = self->loopCountPlay = self->loopTime = self->loopCountRec = self->loopStop = 0;
+    self->loopLen = (pyorand() % 10) + 3;
+
     Stream_setFunctionPtr(self->stream, TrigXnoise_compute_next_data_frame);
     self->mode_func_ptr = TrigXnoise_setProcMode;
 
     static char *kwlist[] = {"input", "type", "x1", "x2", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOOOO", kwlist, &inputtmp, &self->type, &x1tmp, &x2tmp, &multmp, &addtmp))
         Py_RETURN_NONE;
 
     INIT_INPUT_STREAM
-    
+
     if (x1tmp) {
         PyObject_CallMethod((PyObject *)self, "setX1", "O", x1tmp);
     }
-    
+
     if (x2tmp) {
         PyObject_CallMethod((PyObject *)self, "setX2", "O", x2tmp);
     }
@@ -3273,15 +3242,15 @@ TrigXnoise_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     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);
-    
+
     TrigXnoise_setRandomType(self);
-    
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
@@ -3289,10 +3258,10 @@ TrigXnoise_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * TrigXnoise_getServer(TrigXnoise* self) { GET_SERVER };
 static PyObject * TrigXnoise_getStream(TrigXnoise* self) { GET_STREAM };
-static PyObject * TrigXnoise_setMul(TrigXnoise *self, PyObject *arg) { SET_MUL };	
-static PyObject * TrigXnoise_setAdd(TrigXnoise *self, PyObject *arg) { SET_ADD };	
-static PyObject * TrigXnoise_setSub(TrigXnoise *self, PyObject *arg) { SET_SUB };	
-static PyObject * TrigXnoise_setDiv(TrigXnoise *self, PyObject *arg) { SET_DIV };	
+static PyObject * TrigXnoise_setMul(TrigXnoise *self, PyObject *arg) { SET_MUL };
+static PyObject * TrigXnoise_setAdd(TrigXnoise *self, PyObject *arg) { SET_ADD };
+static PyObject * TrigXnoise_setSub(TrigXnoise *self, PyObject *arg) { SET_SUB };
+static PyObject * TrigXnoise_setDiv(TrigXnoise *self, PyObject *arg) { SET_DIV };
 
 static PyObject * TrigXnoise_play(TrigXnoise *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * TrigXnoise_out(TrigXnoise *self, PyObject *args, PyObject *kwds) { OUT };
@@ -3309,35 +3278,29 @@ static PyObject * TrigXnoise_inplace_div(TrigXnoise *self, PyObject *arg) { INPL
 
 static PyObject *
 TrigXnoise_setType(TrigXnoise *self, PyObject *arg)
-{	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+{
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyInt_Check(arg);
-	
+
 	if (isNumber == 1) {
 		self->type = PyInt_AsLong(arg);
         TrigXnoise_setRandomType(self);
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 TrigXnoise_setX1(TrigXnoise *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->x1);
@@ -3353,25 +3316,22 @@ TrigXnoise_setX1(TrigXnoise *self, PyObject *arg)
         self->x1_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 TrigXnoise_setX2(TrigXnoise *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->x2);
@@ -3387,12 +3347,12 @@ TrigXnoise_setX2(TrigXnoise *self, PyObject *arg)
         self->x2_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef TrigXnoise_members[] = {
     {"server", T_OBJECT_EX, offsetof(TrigXnoise, server), 0, "Pyo server."},
@@ -3425,7 +3385,7 @@ static PyNumberMethods TrigXnoise_as_number = {
     (binaryfunc)TrigXnoise_add,                         /*nb_add*/
     (binaryfunc)TrigXnoise_sub,                         /*nb_subtract*/
     (binaryfunc)TrigXnoise_multiply,                    /*nb_multiply*/
-    (binaryfunc)TrigXnoise_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -3439,16 +3399,16 @@ static PyNumberMethods TrigXnoise_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)TrigXnoise_inplace_add,                 /*inplace_add*/
     (binaryfunc)TrigXnoise_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)TrigXnoise_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)TrigXnoise_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -3457,15 +3417,14 @@ static PyNumberMethods TrigXnoise_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)TrigXnoise_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)TrigXnoise_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject TrigXnoiseType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.TrigXnoise_base",                                   /*tp_name*/
     sizeof(TrigXnoise),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -3473,7 +3432,7 @@ PyTypeObject TrigXnoiseType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &TrigXnoise_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -3536,21 +3495,21 @@ typedef struct {
     int loopCountRec;
     int loopLen;
     int loopStop;
-    int modebuffer[4]; // need at least 2 slots for mul & add 
+    int modebuffer[4]; // need at least 2 slots for mul & add
 } TrigXnoiseMidi;
 
 static MYFLT
 TrigXnoiseMidi_convert(TrigXnoiseMidi *self) {
     int midival;
     MYFLT val;
-    
+
     midival = (int)((self->value * (self->range_max-self->range_min)) + self->range_min);
-    
+
     if (midival < 0)
         midival = 0;
     else if (midival > 127)
         midival = 127;
-    
+
     if (self->scale == 0)
         val = (MYFLT)midival;
     else if (self->scale == 1)
@@ -3567,12 +3526,12 @@ TrigXnoiseMidi_convert(TrigXnoiseMidi *self) {
 // no parameter
 static MYFLT
 TrigXnoiseMidi_uniform(TrigXnoiseMidi *self) {
-    return RANDOM_UNIFORM;    
+    return RANDOM_UNIFORM;
 }
 
 static MYFLT
 TrigXnoiseMidi_linear_min(TrigXnoiseMidi *self) {
-    MYFLT a = RANDOM_UNIFORM;    
+    MYFLT a = RANDOM_UNIFORM;
     MYFLT b = RANDOM_UNIFORM;
     if (a < b) return a;
     else return b;
@@ -3580,7 +3539,7 @@ TrigXnoiseMidi_linear_min(TrigXnoiseMidi *self) {
 
 static MYFLT
 TrigXnoiseMidi_linear_max(TrigXnoiseMidi *self) {
-    MYFLT a = RANDOM_UNIFORM;    
+    MYFLT a = RANDOM_UNIFORM;
     MYFLT b = RANDOM_UNIFORM;
     if (a > b) return a;
     else return b;
@@ -3588,7 +3547,7 @@ TrigXnoiseMidi_linear_max(TrigXnoiseMidi *self) {
 
 static MYFLT
 TrigXnoiseMidi_triangle(TrigXnoiseMidi *self) {
-    MYFLT a = RANDOM_UNIFORM;    
+    MYFLT a = RANDOM_UNIFORM;
     MYFLT b = RANDOM_UNIFORM;
     return ((a + b) * 0.5);
 }
@@ -3597,7 +3556,7 @@ TrigXnoiseMidi_triangle(TrigXnoiseMidi *self) {
 static MYFLT
 TrigXnoiseMidi_expon_min(TrigXnoiseMidi *self) {
     if (self->xx1 <= 0.0) self->xx1 = 0.00001;
-    MYFLT val = -MYLOG10(RANDOM_UNIFORM) / self->xx1;    
+    MYFLT val = -MYLOG10(RANDOM_UNIFORM) / self->xx1;
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -3606,7 +3565,7 @@ TrigXnoiseMidi_expon_min(TrigXnoiseMidi *self) {
 static MYFLT
 TrigXnoiseMidi_expon_max(TrigXnoiseMidi *self) {
     if (self->xx1 <= 0.0) self->xx1 = 0.00001;
-    MYFLT val = 1.0 - (-MYLOG10(RANDOM_UNIFORM) / self->xx1);    
+    MYFLT val = 1.0 - (-MYLOG10(RANDOM_UNIFORM) / self->xx1);
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -3618,16 +3577,16 @@ TrigXnoiseMidi_biexpon(TrigXnoiseMidi *self) {
     MYFLT polar, val;
     if (self->xx1 <= 0.0) self->xx1 = 0.00001;
     MYFLT sum = RANDOM_UNIFORM * 2.0;
-    
+
     if (sum > 1.0) {
         polar = -1;
         sum = 2.0 - sum;
     }
     else
         polar = 1;
-    
+
     val = 0.5 * (polar * MYLOG10(sum) / self->xx1) + 0.5;
-    
+
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -3640,14 +3599,14 @@ TrigXnoiseMidi_cauchy(TrigXnoiseMidi *self) {
         rnd = RANDOM_UNIFORM;
     }
     while (rnd == 0.5);
-    
-    if (rand() < (RAND_MAX / 2))
+
+    if (pyorand() < (PYO_RAND_MAX / 2))
         dir = -1;
     else
         dir = 1;
-    
+
     val = 0.5 * (MYTAN(rnd) * self->xx1 * dir) + 0.5;
-    
+
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -3658,10 +3617,10 @@ static MYFLT
 TrigXnoiseMidi_weibull(TrigXnoiseMidi *self) {
     MYFLT rnd, val;
     if (self->xx2 <= 0.0) self->xx2 = 0.00001;
-    
+
     rnd = 1.0 / (1.0 - RANDOM_UNIFORM);
     val = self->xx1 * MYPOW(MYLOG(rnd), (1.0 / self->xx2));
-    
+
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -3671,10 +3630,10 @@ TrigXnoiseMidi_weibull(TrigXnoiseMidi *self) {
 static MYFLT
 TrigXnoiseMidi_gaussian(TrigXnoiseMidi *self) {
     MYFLT rnd, val;
-    
+
     rnd = (RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM + RANDOM_UNIFORM);
     val = (self->xx2 * (rnd - 3.0) * 0.33 + self->xx1);
-    
+
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -3688,7 +3647,7 @@ TrigXnoiseMidi_poisson(TrigXnoiseMidi *self) {
     MYFLT val;
     if (self->xx1 < 0.1) self->xx1 = 0.1;
     if (self->xx2 < 0.1) self->xx2 = 0.1;
-    
+
     if (self->xx1 != self->lastPoissonX1) {
         self->lastPoissonX1 = self->xx1;
         self->poisson_tab = 0;
@@ -3702,8 +3661,8 @@ TrigXnoiseMidi_poisson(TrigXnoiseMidi *self) {
             }
         }
     }
-    val = self->poisson_buffer[rand() % self->poisson_tab] / 12.0 * self->xx2;
-    
+    val = self->poisson_buffer[pyorand() % self->poisson_tab] / 12.0 * self->xx2;
+
     if (val < 0.0) return 0.0;
     else if (val > 1.0) return 1.0;
     else return val;
@@ -3712,77 +3671,77 @@ TrigXnoiseMidi_poisson(TrigXnoiseMidi *self) {
 // x1 = max value, x2 = max step
 static MYFLT
 TrigXnoiseMidi_walker(TrigXnoiseMidi *self) {
-    int modulo, dir;
-    
+    unsigned int modulo, dir;
+
     if (self->xx2 < 0.002) self->xx2 = 0.002;
-    
-    modulo = (int)(self->xx2 * 1000.0);
-    dir = rand() % 2;
-    
-    if (dir == 0)
-        self->walkerValue = self->walkerValue + (((rand() % modulo) - (modulo / 2)) * 0.001);
+
+    modulo = (unsigned int)(self->xx2 * 1000.0);
+    dir = pyorand() % 100;
+
+    if (dir < 50)
+        self->walkerValue += ((MYFLT)(pyorand() % modulo) * 0.001);
     else
-        self->walkerValue = self->walkerValue - (((rand() % modulo) - (modulo / 2)) * 0.001);
-    
+        self->walkerValue -= ((MYFLT)(pyorand() % modulo) * 0.001);
+
     if (self->walkerValue > self->xx1)
         self->walkerValue = self->xx1;
-    if (self->walkerValue < 0.0)
+    else if (self->walkerValue < 0.0)
         self->walkerValue = 0.0;
-    
+
     return self->walkerValue;
 }
 
 // x1 = max value, x2 = max step
 static MYFLT
 TrigXnoiseMidi_loopseg(TrigXnoiseMidi *self) {
-    int modulo, dir;
-    
+    unsigned int modulo, dir;
+
     if (self->loopChoice == 0) {
-        
+
         self->loopCountPlay = self->loopTime = 0;
-        
+
         if (self->xx2 < 0.002) self->xx2 = 0.002;
-        
-        modulo = (int)(self->xx2 * 1000.0);
-        dir = rand() % 2;
-        
-        if (dir == 0)
-            self->walkerValue = self->walkerValue + (((rand() % modulo) - (modulo / 2)) * 0.001);
+
+        modulo = (unsigned int)(self->xx2 * 1000.0);
+        dir = pyorand() % 100;
+
+        if (dir < 50)
+            self->walkerValue += ((MYFLT)(pyorand() % modulo) * 0.001);
         else
-            self->walkerValue = self->walkerValue - (((rand() % modulo) - (modulo / 2)) * 0.001);
-        
+            self->walkerValue -= ((MYFLT)(pyorand() % modulo) * 0.001);
+
         if (self->walkerValue > self->xx1)
             self->walkerValue = self->xx1;
-        if (self->walkerValue < 0.0)
+        else if (self->walkerValue < 0.0)
             self->walkerValue = 0.0;
-        
+
         self->loop_buffer[self->loopCountRec++] = self->walkerValue;
-        
+
         if (self->loopCountRec < self->loopLen)
             self->loopChoice = 0;
         else {
             self->loopChoice = 1;
-            self->loopStop = (rand() % 4) + 1;
+            self->loopStop = (pyorand() % 4) + 1;
         }
     }
     else {
         self->loopCountRec = 0;
-        
+
         self->walkerValue = self->loop_buffer[self->loopCountPlay++];
-        
+
         if (self->loopCountPlay < self->loopLen)
             self->loopChoice = 1;
         else {
             self->loopCountPlay = 0;
             self->loopTime++;
         }
-        
+
         if (self->loopTime == self->loopStop) {
             self->loopChoice = 0;
-            self->loopLen = (rand() % 10) + 3;
+            self->loopLen = (pyorand() % 10) + 3;
         }
     }
-    
+
     return self->walkerValue;
 }
 
@@ -3792,12 +3751,12 @@ TrigXnoiseMidi_generate_ii(TrigXnoiseMidi *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     self->xx1 = PyFloat_AS_DOUBLE(self->x1);
     self->xx2 = PyFloat_AS_DOUBLE(self->x2);
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (in[i] == 1) {
             self->value = (*self->type_func_ptr)(self);
             self->value = TrigXnoiseMidi_convert(self);
-        }    
+        }
         self->data[i] = self->value;
     }
 }
@@ -3808,7 +3767,7 @@ TrigXnoiseMidi_generate_ai(TrigXnoiseMidi *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *x1 = Stream_getData((Stream *)self->x1_stream);
     self->xx2 = PyFloat_AS_DOUBLE(self->x2);
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (in[i] == 1) {
             self->xx1 = x1[i];
@@ -3825,7 +3784,7 @@ TrigXnoiseMidi_generate_ia(TrigXnoiseMidi *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     self->xx1 = PyFloat_AS_DOUBLE(self->x1);
     MYFLT *x2 = Stream_getData((Stream *)self->x2_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (in[i] == 1) {
             self->xx2 = x2[i];
@@ -3842,7 +3801,7 @@ TrigXnoiseMidi_generate_aa(TrigXnoiseMidi *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *x1 = Stream_getData((Stream *)self->x1_stream);
     MYFLT *x2 = Stream_getData((Stream *)self->x2_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (in[i] == 1) {
             self->xx1 = x1[i];
@@ -3867,8 +3826,8 @@ static void TrigXnoiseMidi_postprocessing_revareva(TrigXnoiseMidi *self) { POST_
 static void
 TrigXnoiseMidi_setRandomType(TrigXnoiseMidi *self)
 {
-    
-    switch (self->type) {            
+
+    switch (self->type) {
         case 0:
             self->type_func_ptr = TrigXnoiseMidi_uniform;
             break;
@@ -3908,7 +3867,7 @@ TrigXnoiseMidi_setRandomType(TrigXnoiseMidi *self)
         case 12:
             self->type_func_ptr = TrigXnoiseMidi_loopseg;
             break;
-    }        
+    }
 }
 
 static void
@@ -3917,56 +3876,56 @@ TrigXnoiseMidi_setProcMode(TrigXnoiseMidi *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = TrigXnoiseMidi_generate_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = TrigXnoiseMidi_generate_ai;
             break;
-        case 10:    
+        case 10:
             self->proc_func_ptr = TrigXnoiseMidi_generate_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = TrigXnoiseMidi_generate_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = TrigXnoiseMidi_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = TrigXnoiseMidi_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = TrigXnoiseMidi_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = TrigXnoiseMidi_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = TrigXnoiseMidi_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = TrigXnoiseMidi_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = TrigXnoiseMidi_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = TrigXnoiseMidi_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = TrigXnoiseMidi_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 TrigXnoiseMidi_compute_next_data_frame(TrigXnoiseMidi *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -3976,23 +3935,23 @@ TrigXnoiseMidi_traverse(TrigXnoiseMidi *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->x1);    
-    Py_VISIT(self->x1_stream);    
-    Py_VISIT(self->x2);    
-    Py_VISIT(self->x2_stream);    
+    Py_VISIT(self->x1);
+    Py_VISIT(self->x1_stream);
+    Py_VISIT(self->x2);
+    Py_VISIT(self->x2_stream);
     return 0;
 }
 
-static int 
+static int
 TrigXnoiseMidi_clear(TrigXnoiseMidi *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->x1);    
-    Py_CLEAR(self->x1_stream);    
-    Py_CLEAR(self->x2);    
-    Py_CLEAR(self->x2_stream);    
+    Py_CLEAR(self->x1);
+    Py_CLEAR(self->x1_stream);
+    Py_CLEAR(self->x2);
+    Py_CLEAR(self->x2_stream);
     return 0;
 }
 
@@ -4001,7 +3960,7 @@ TrigXnoiseMidi_dealloc(TrigXnoiseMidi* self)
 {
     pyo_DEALLOC
     TrigXnoiseMidi_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -4011,7 +3970,7 @@ TrigXnoiseMidi_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *x1tmp=NULL, *x2tmp=NULL, *rangetmp=NULL, *multmp=NULL, *addtmp=NULL;
     TrigXnoiseMidi *self;
     self = (TrigXnoiseMidi *)type->tp_alloc(type, 0);
-        
+
     self->x1 = PyFloat_FromDouble(0.5);
     self->x2 = PyFloat_FromDouble(0.5);
     self->xx1 = self->xx2 = self->walkerValue = 0.5;
@@ -4024,9 +3983,9 @@ TrigXnoiseMidi_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
-        
+
     INIT_OBJECT_COMMON
-    
+
     Server_generateSeed((Server *)self->server, TRIGXNOISEMIDI_ID);
 
     self->poisson_tab = 0;
@@ -4037,23 +3996,23 @@ TrigXnoiseMidi_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     for (i=0; i<15; i++) {
         self->loop_buffer[i] = 0.0;
     }
-    self->loopChoice = self->loopCountPlay = self->loopTime = self->loopCountRec = self->loopStop = 0;    
-    self->loopLen = (rand() % 10) + 3;
-    
+    self->loopChoice = self->loopCountPlay = self->loopTime = self->loopCountRec = self->loopStop = 0;
+    self->loopLen = (pyorand() % 10) + 3;
+
     Stream_setFunctionPtr(self->stream, TrigXnoiseMidi_compute_next_data_frame);
     self->mode_func_ptr = TrigXnoiseMidi_setProcMode;
 
     static char *kwlist[] = {"input", "type", "x1", "x2", "scale", "range", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOOiOOO", kwlist, &inputtmp, &self->type, &x1tmp, &x2tmp, &self->scale, &rangetmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (x1tmp) {
         PyObject_CallMethod((PyObject *)self, "setX1", "O", x1tmp);
     }
-    
+
     if (x2tmp) {
         PyObject_CallMethod((PyObject *)self, "setX2", "O", x2tmp);
     }
@@ -4061,19 +4020,19 @@ TrigXnoiseMidi_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (rangetmp) {
         PyObject_CallMethod((PyObject *)self, "setRange", "O", rangetmp);
     }
-    
+
     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);
-    
+
     TrigXnoiseMidi_setRandomType(self);
-    
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
@@ -4081,10 +4040,10 @@ TrigXnoiseMidi_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * TrigXnoiseMidi_getServer(TrigXnoiseMidi* self) { GET_SERVER };
 static PyObject * TrigXnoiseMidi_getStream(TrigXnoiseMidi* self) { GET_STREAM };
-static PyObject * TrigXnoiseMidi_setMul(TrigXnoiseMidi *self, PyObject *arg) { SET_MUL };	
-static PyObject * TrigXnoiseMidi_setAdd(TrigXnoiseMidi *self, PyObject *arg) { SET_ADD };	
-static PyObject * TrigXnoiseMidi_setSub(TrigXnoiseMidi *self, PyObject *arg) { SET_SUB };	
-static PyObject * TrigXnoiseMidi_setDiv(TrigXnoiseMidi *self, PyObject *arg) { SET_DIV };	
+static PyObject * TrigXnoiseMidi_setMul(TrigXnoiseMidi *self, PyObject *arg) { SET_MUL };
+static PyObject * TrigXnoiseMidi_setAdd(TrigXnoiseMidi *self, PyObject *arg) { SET_ADD };
+static PyObject * TrigXnoiseMidi_setSub(TrigXnoiseMidi *self, PyObject *arg) { SET_SUB };
+static PyObject * TrigXnoiseMidi_setDiv(TrigXnoiseMidi *self, PyObject *arg) { SET_DIV };
 
 static PyObject * TrigXnoiseMidi_play(TrigXnoiseMidi *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * TrigXnoiseMidi_out(TrigXnoiseMidi *self, PyObject *args, PyObject *kwds) { OUT };
@@ -4101,78 +4060,70 @@ static PyObject * TrigXnoiseMidi_inplace_div(TrigXnoiseMidi *self, PyObject *arg
 
 static PyObject *
 TrigXnoiseMidi_setType(TrigXnoiseMidi *self, PyObject *arg)
-{	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+{
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyInt_Check(arg);
-	
+
 	if (isNumber == 1) {
 		self->type = PyInt_AsLong(arg);
         TrigXnoiseMidi_setRandomType(self);
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 TrigXnoiseMidi_setScale(TrigXnoiseMidi *self, PyObject *arg)
-{	
+{
     int tmp;
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyInt_Check(arg);
-	
+
 	if (isNumber == 1) {
 		tmp = PyInt_AsLong(arg);
         if (tmp >= 0 && tmp <= 2)
             self->scale = tmp;
         else
-            printf("scale attribute must be an integer {0, 1, 2}\n");
+            PySys_WriteStdout("TrigXnoiseMidi: scale attribute must be an integer {0, 1, 2}\n");
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 TrigXnoiseMidi_setRange(TrigXnoiseMidi *self, PyObject *args)
-{	
+{
 	if (args == NULL) {
 		Py_INCREF(Py_None);
 		return Py_None;
 	}
-    
+
 	int isTuple = PyTuple_Check(args);
-    
+
 	if (isTuple == 1) {
         self->range_min = PyInt_AsLong(PyTuple_GET_ITEM(args, 0));
         self->range_max = PyInt_AsLong(PyTuple_GET_ITEM(args, 1));
         self->centralkey = (int)((self->range_max + self->range_min) / 2);
 	}
-    
+
     Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 TrigXnoiseMidi_setX1(TrigXnoiseMidi *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->x1);
@@ -4188,25 +4139,22 @@ TrigXnoiseMidi_setX1(TrigXnoiseMidi *self, PyObject *arg)
         self->x1_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 TrigXnoiseMidi_setX2(TrigXnoiseMidi *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->x2);
@@ -4222,12 +4170,12 @@ TrigXnoiseMidi_setX2(TrigXnoiseMidi *self, PyObject *arg)
         self->x2_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef TrigXnoiseMidi_members[] = {
     {"server", T_OBJECT_EX, offsetof(TrigXnoiseMidi, server), 0, "Pyo server."},
@@ -4262,7 +4210,7 @@ static PyNumberMethods TrigXnoiseMidi_as_number = {
     (binaryfunc)TrigXnoiseMidi_add,                         /*nb_add*/
     (binaryfunc)TrigXnoiseMidi_sub,                         /*nb_subtract*/
     (binaryfunc)TrigXnoiseMidi_multiply,                    /*nb_multiply*/
-    (binaryfunc)TrigXnoiseMidi_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -4276,16 +4224,16 @@ static PyNumberMethods TrigXnoiseMidi_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)TrigXnoiseMidi_inplace_add,                 /*inplace_add*/
     (binaryfunc)TrigXnoiseMidi_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)TrigXnoiseMidi_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)TrigXnoiseMidi_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -4294,15 +4242,14 @@ static PyNumberMethods TrigXnoiseMidi_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)TrigXnoiseMidi_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)TrigXnoiseMidi_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject TrigXnoiseMidiType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.TrigXnoiseMidi_base",                                   /*tp_name*/
     sizeof(TrigXnoiseMidi),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -4310,7 +4257,7 @@ PyTypeObject TrigXnoiseMidiType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &TrigXnoiseMidi_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -4355,14 +4302,14 @@ typedef struct {
     int dir;
     int direction;
     MYFLT value;
-    int modebuffer[2]; // need at least 2 slots for mul & add 
+    int modebuffer[2]; // need at least 2 slots for mul & add
 } Counter;
 
 static void
 Counter_generates(Counter *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (in[i] == 1) {
             self->value = (MYFLT)self->tmp;
@@ -4370,22 +4317,22 @@ Counter_generates(Counter *self) {
                 self->tmp++;
                 if (self->tmp >= self->max)
                     self->tmp = self->min;
-            }    
+            }
             else if (self->dir == 1) {
                 self->tmp--;
                 if (self->tmp < self->min)
                     self->tmp = self->max - 1;
-            }    
+            }
             else if (self->dir == 2) {
                 self->tmp = self->tmp + self->direction;
                 if (self->tmp >= self->max) {
                     self->direction = -1;
                     self->tmp = self->max - 2;
-                }    
+                }
                 if (self->tmp <= self->min) {
                     self->direction = 1;
                     self->tmp = self->min;
-                }    
+                }
             }
         }
         self->data[i] = self->value;
@@ -4407,44 +4354,44 @@ Counter_setProcMode(Counter *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = Counter_generates;
 
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Counter_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Counter_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Counter_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Counter_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Counter_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Counter_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Counter_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Counter_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Counter_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 Counter_compute_next_data_frame(Counter *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -4457,7 +4404,7 @@ Counter_traverse(Counter *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Counter_clear(Counter *self)
 {
     pyo_CLEAR
@@ -4471,7 +4418,7 @@ Counter_dealloc(Counter* self)
 {
     pyo_DEALLOC
     Counter_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -4481,40 +4428,40 @@ Counter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     Counter *self;
     self = (Counter *)type->tp_alloc(type, 0);
-    
+
     self->min = 0;
     self->max = 100;
     self->dir = 0;
     self->direction = 1;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Counter_compute_next_data_frame);
     self->mode_func_ptr = Counter_setProcMode;
 
     static char *kwlist[] = {"input", "min", "max", "dir", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|lliOO", kwlist, &inputtmp, &self->min, &self->max, &self->dir, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
 
     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);
 
     if (self->dir == 0 || self->dir == 2)
         self->tmp = self->min;
     else
         self->tmp = self->max - 1;
-    
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
@@ -4522,10 +4469,10 @@ Counter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Counter_getServer(Counter* self) { GET_SERVER };
 static PyObject * Counter_getStream(Counter* self) { GET_STREAM };
-static PyObject * Counter_setMul(Counter *self, PyObject *arg) { SET_MUL };	
-static PyObject * Counter_setAdd(Counter *self, PyObject *arg) { SET_ADD };	
-static PyObject * Counter_setSub(Counter *self, PyObject *arg) { SET_SUB };	
-static PyObject * Counter_setDiv(Counter *self, PyObject *arg) { SET_DIV };	
+static PyObject * Counter_setMul(Counter *self, PyObject *arg) { SET_MUL };
+static PyObject * Counter_setAdd(Counter *self, PyObject *arg) { SET_ADD };
+static PyObject * Counter_setSub(Counter *self, PyObject *arg) { SET_SUB };
+static PyObject * Counter_setDiv(Counter *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Counter_play(Counter *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Counter_stop(Counter *self) { STOP };
@@ -4541,57 +4488,48 @@ static PyObject * Counter_inplace_div(Counter *self, PyObject *arg) { INPLACE_DI
 
 static PyObject *
 Counter_setMin(Counter *self, PyObject *arg)
-{	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	if (PyLong_Check(arg) || PyInt_Check(arg)) {	
+{
+    ASSERT_ARG_NOT_NULL
+
+	if (PyLong_Check(arg) || PyInt_Check(arg)) {
 		self->min = PyLong_AsLong(arg);
 	}
 
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Counter_setMax(Counter *self, PyObject *arg)
-{	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	if (PyLong_Check(arg) || PyInt_Check(arg)) {	
+{
+    ASSERT_ARG_NOT_NULL
+
+	if (PyLong_Check(arg) || PyInt_Check(arg)) {
 		self->max = PyLong_AsLong(arg);
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Counter_setDir(Counter *self, PyObject *arg)
-{	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	if (PyInt_Check(arg)) {	
+{
+    ASSERT_ARG_NOT_NULL
+
+	if (PyInt_Check(arg)) {
 		self->dir = PyInt_AsLong(arg);
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Counter_reset(Counter *self, PyObject *arg)
 {
     int val;
-    
+
     if (arg == Py_None) {
         if (self->dir == 0 || self->dir == 2)
             val = self->min;
@@ -4599,12 +4537,12 @@ Counter_reset(Counter *self, PyObject *arg)
             val = self->max - 1;
         self->tmp = val;
     }
-    
+
     else if (PyInt_Check(arg)) {
         val = PyInt_AsLong(arg);
         self->tmp = val;
     }
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -4638,7 +4576,7 @@ static PyNumberMethods Counter_as_number = {
 (binaryfunc)Counter_add,                         /*nb_add*/
 (binaryfunc)Counter_sub,                         /*nb_subtract*/
 (binaryfunc)Counter_multiply,                    /*nb_multiply*/
-(binaryfunc)Counter_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -4652,16 +4590,16 @@ static PyNumberMethods Counter_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)Counter_inplace_add,                 /*inplace_add*/
 (binaryfunc)Counter_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)Counter_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)Counter_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -4670,15 +4608,14 @@ static PyNumberMethods Counter_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)Counter_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)Counter_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject CounterType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Counter_base",                                   /*tp_name*/
 sizeof(Counter),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -4686,7 +4623,7 @@ sizeof(Counter),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &Counter_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -4748,7 +4685,7 @@ Thresh_generates_i(Thresh *self) {
                 }
                 else if (in[i] <= thresh && self->ready == 0)
                     self->ready = 1;
-            } 
+            }
             break;
         case 1:
             for (i=0; i<self->bufsize; i++) {
@@ -4759,7 +4696,7 @@ Thresh_generates_i(Thresh *self) {
                 }
                 else if (in[i] >= thresh && self->ready == 0)
                     self->ready = 1;
-            } 
+            }
             break;
         case 2:
             for (i=0; i<self->bufsize; i++) {
@@ -4771,8 +4708,8 @@ Thresh_generates_i(Thresh *self) {
                 else if (in[i] <= thresh && self->ready == 0) {
                     self->data[i] = 1.0;
                     self->ready = 1;
-                }    
-            } 
+                }
+            }
             break;
     }
 }
@@ -4782,7 +4719,7 @@ Thresh_generates_a(Thresh *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *thresh = Stream_getData((Stream *)self->threshold_stream);
-    
+
     switch (self->dir) {
         case 0:
             for (i=0; i<self->bufsize; i++) {
@@ -4793,7 +4730,7 @@ Thresh_generates_a(Thresh *self) {
                 }
                 else if (in[i] <= thresh[i] && self->ready == 0)
                     self->ready = 1;
-            } 
+            }
             break;
         case 1:
             for (i=0; i<self->bufsize; i++) {
@@ -4804,7 +4741,7 @@ Thresh_generates_a(Thresh *self) {
                 }
                 else if (in[i] >= thresh[i] && self->ready == 0)
                     self->ready = 1;
-            } 
+            }
             break;
         case 2:
             for (i=0; i<self->bufsize; i++) {
@@ -4816,7 +4753,7 @@ Thresh_generates_a(Thresh *self) {
                 else if (in[i] <= thresh[i] && self->ready == 0)
                     self->data[i] = 1.0;
                 self->ready = 1;
-            } 
+            }
             break;
     }
 }
@@ -4833,53 +4770,53 @@ static void Thresh_postprocessing_revareva(Thresh *self) { POST_PROCESSING_REVAR
 
 static void
 Thresh_setProcMode(Thresh *self)
-{    
+{
     int procmode = self->modebuffer[2];
     int muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
 
     switch (procmode) {
-        case 0:        
+        case 0:
             self->proc_func_ptr = Thresh_generates_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Thresh_generates_a;
             break;
     }
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Thresh_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Thresh_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Thresh_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Thresh_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Thresh_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Thresh_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Thresh_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Thresh_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Thresh_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 Thresh_compute_next_data_frame(Thresh *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -4894,7 +4831,7 @@ Thresh_traverse(Thresh *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Thresh_clear(Thresh *self)
 {
     pyo_CLEAR
@@ -4910,7 +4847,7 @@ Thresh_dealloc(Thresh* self)
 {
     pyo_DEALLOC
     Thresh_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -4920,36 +4857,36 @@ Thresh_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *thresholdtmp, *multmp=NULL, *addtmp=NULL;
     Thresh *self;
     self = (Thresh *)type->tp_alloc(type, 0);
-    
+
     self->threshold = PyFloat_FromDouble(0.);
     self->dir = 0;
     self->ready = 0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
     self->modebuffer[2] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Thresh_compute_next_data_frame);
     self->mode_func_ptr = Thresh_setProcMode;
 
     static char *kwlist[] = {"input", "threshold", "dir", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OiOO", kwlist, &inputtmp, &thresholdtmp, &self->dir, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (thresholdtmp) {
         PyObject_CallMethod((PyObject *)self, "setThreshold", "O", thresholdtmp);
     }
     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);
@@ -4959,10 +4896,10 @@ Thresh_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Thresh_getServer(Thresh* self) { GET_SERVER };
 static PyObject * Thresh_getStream(Thresh* self) { GET_STREAM };
-static PyObject * Thresh_setMul(Thresh *self, PyObject *arg) { SET_MUL };	
-static PyObject * Thresh_setAdd(Thresh *self, PyObject *arg) { SET_ADD };	
-static PyObject * Thresh_setSub(Thresh *self, PyObject *arg) { SET_SUB };	
-static PyObject * Thresh_setDiv(Thresh *self, PyObject *arg) { SET_DIV };	
+static PyObject * Thresh_setMul(Thresh *self, PyObject *arg) { SET_MUL };
+static PyObject * Thresh_setAdd(Thresh *self, PyObject *arg) { SET_ADD };
+static PyObject * Thresh_setSub(Thresh *self, PyObject *arg) { SET_SUB };
+static PyObject * Thresh_setDiv(Thresh *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Thresh_play(Thresh *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Thresh_stop(Thresh *self) { STOP };
@@ -4980,14 +4917,11 @@ static PyObject *
 Thresh_setThreshold(Thresh *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->threshold);
@@ -5003,28 +4937,25 @@ Thresh_setThreshold(Thresh *self, PyObject *arg)
         self->threshold_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Thresh_setDir(Thresh *self, PyObject *arg)
-{	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	if (PyInt_Check(arg)) {	
+{
+    ASSERT_ARG_NOT_NULL
+
+	if (PyInt_Check(arg)) {
 		self->dir = PyInt_AsLong(arg);
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Thresh_members[] = {
 {"server", T_OBJECT_EX, offsetof(Thresh, server), 0, "Pyo server."},
@@ -5054,7 +4985,7 @@ static PyNumberMethods Thresh_as_number = {
     (binaryfunc)Thresh_add,                         /*nb_add*/
     (binaryfunc)Thresh_sub,                         /*nb_subtract*/
     (binaryfunc)Thresh_multiply,                    /*nb_multiply*/
-    (binaryfunc)Thresh_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -5068,16 +4999,16 @@ static PyNumberMethods Thresh_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Thresh_inplace_add,                 /*inplace_add*/
     (binaryfunc)Thresh_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Thresh_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Thresh_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -5086,15 +5017,14 @@ static PyNumberMethods Thresh_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Thresh_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Thresh_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject ThreshType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Thresh_base",                                   /*tp_name*/
 sizeof(Thresh),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -5102,7 +5032,7 @@ sizeof(Thresh),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &Thresh_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -5155,10 +5085,10 @@ Percent_generates_i(Percent *self) {
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = 0.0;
         if (in[i] == 1.0) {
-            guess = (rand()/((MYFLT)(RAND_MAX)+1)) * 100.0;
+            guess = RANDOM_UNIFORM * 100.0;
             if (guess <= perc)
                 self->data[i] = 1.0;
-        }    
+        }
     }
 }
 
@@ -5168,14 +5098,14 @@ Percent_generates_a(Percent *self) {
     MYFLT guess;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *perc = Stream_getData((Stream *)self->percent_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = 0.0;
         if (in[i] == 1.0) {
-            guess = (rand()/((MYFLT)(RAND_MAX)+1)) * 100.0;
+            guess = RANDOM_UNIFORM * 100.0;
             if (guess <= perc[i])
                 self->data[i] = 1.0;
-        }    
+        }
     }
 }
 
@@ -5191,54 +5121,54 @@ static void Percent_postprocessing_revareva(Percent *self) { POST_PROCESSING_REV
 
 static void
 Percent_setProcMode(Percent *self)
-{    
+{
     int muladdmode, procmode
     ;
     procmode = self->modebuffer[2];
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
     switch (procmode) {
-        case 0:        
+        case 0:
             self->proc_func_ptr = Percent_generates_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Percent_generates_a;
             break;
     }
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Percent_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Percent_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Percent_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Percent_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Percent_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Percent_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Percent_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Percent_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Percent_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 Percent_compute_next_data_frame(Percent *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -5253,7 +5183,7 @@ Percent_traverse(Percent *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Percent_clear(Percent *self)
 {
     pyo_CLEAR
@@ -5269,7 +5199,7 @@ Percent_dealloc(Percent* self)
 {
     pyo_DEALLOC
     Percent_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -5279,36 +5209,36 @@ Percent_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *percenttmp, *multmp=NULL, *addtmp=NULL;
     Percent *self;
     self = (Percent *)type->tp_alloc(type, 0);
-    
+
     self->percent = PyFloat_FromDouble(50.);
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
     self->modebuffer[2] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Percent_compute_next_data_frame);
     self->mode_func_ptr = Percent_setProcMode;
 
     static char *kwlist[] = {"input", "percent", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist, &inputtmp, &percenttmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (percenttmp) {
         PyObject_CallMethod((PyObject *)self, "setPercent", "O", percenttmp);
     }
     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);
-    
+
     Server_generateSeed((Server *)self->server, PERCENT_ID);
 
     (*self->mode_func_ptr)(self);
@@ -5318,10 +5248,10 @@ Percent_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Percent_getServer(Percent* self) { GET_SERVER };
 static PyObject * Percent_getStream(Percent* self) { GET_STREAM };
-static PyObject * Percent_setMul(Percent *self, PyObject *arg) { SET_MUL };	
-static PyObject * Percent_setAdd(Percent *self, PyObject *arg) { SET_ADD };	
-static PyObject * Percent_setSub(Percent *self, PyObject *arg) { SET_SUB };	
-static PyObject * Percent_setDiv(Percent *self, PyObject *arg) { SET_DIV };	
+static PyObject * Percent_setMul(Percent *self, PyObject *arg) { SET_MUL };
+static PyObject * Percent_setAdd(Percent *self, PyObject *arg) { SET_ADD };
+static PyObject * Percent_setSub(Percent *self, PyObject *arg) { SET_SUB };
+static PyObject * Percent_setDiv(Percent *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Percent_play(Percent *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Percent_stop(Percent *self) { STOP };
@@ -5339,14 +5269,11 @@ static PyObject *
 Percent_setPercent(Percent *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->percent);
@@ -5362,12 +5289,12 @@ Percent_setPercent(Percent *self, PyObject *arg)
         self->percent_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Percent_members[] = {
     {"server", T_OBJECT_EX, offsetof(Percent, server), 0, "Pyo server."},
@@ -5396,7 +5323,7 @@ static PyNumberMethods Percent_as_number = {
     (binaryfunc)Percent_add,                         /*nb_add*/
     (binaryfunc)Percent_sub,                         /*nb_subtract*/
     (binaryfunc)Percent_multiply,                    /*nb_multiply*/
-    (binaryfunc)Percent_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -5410,16 +5337,16 @@ static PyNumberMethods Percent_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Percent_inplace_add,                 /*inplace_add*/
     (binaryfunc)Percent_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Percent_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Percent_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -5428,15 +5355,14 @@ static PyNumberMethods Percent_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Percent_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Percent_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject PercentType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Percent_base",                                   /*tp_name*/
     sizeof(Percent),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -5444,7 +5370,7 @@ PyTypeObject PercentType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &Percent_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -5496,7 +5422,7 @@ Timer_generates(Timer *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *in2 = Stream_getData((Stream *)self->input2_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (self->started == 1) {
             self->count++;
@@ -5505,14 +5431,14 @@ Timer_generates(Timer *self) {
                 self->started = 0;
             }
         }
-        
+
         if (in2[i] == 1 && self->started == 0) {
             self->count = 0;
             self->started = 1;
         }
-        
+
         self->data[i] = self->lasttime;
-    } 
+    }
 }
 
 static void Timer_postprocessing_ii(Timer *self) { POST_PROCESSING_II };
@@ -5527,46 +5453,46 @@ static void Timer_postprocessing_revareva(Timer *self) { POST_PROCESSING_REVAREV
 
 static void
 Timer_setProcMode(Timer *self)
-{    
+{
     int muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = Timer_generates;
-    
+
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Timer_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Timer_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Timer_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Timer_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Timer_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Timer_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Timer_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Timer_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Timer_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 Timer_compute_next_data_frame(Timer *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -5581,7 +5507,7 @@ Timer_traverse(Timer *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Timer_clear(Timer *self)
 {
     pyo_CLEAR
@@ -5597,7 +5523,7 @@ Timer_dealloc(Timer* self)
 {
     pyo_DEALLOC
     Timer_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -5607,41 +5533,41 @@ Timer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *input2tmp, *input2_streamtmp, *multmp=NULL, *addtmp=NULL;
     Timer *self;
     self = (Timer *)type->tp_alloc(type, 0);
-    
+
     self->count = 0;
     self->started = 0;
     self->lasttime = 0.0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Timer_compute_next_data_frame);
     self->mode_func_ptr = Timer_setProcMode;
 
     static char *kwlist[] = {"input", "input2", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist, &inputtmp, &input2tmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     Py_XDECREF(self->input2);
     self->input2 = input2tmp;
     input2_streamtmp = PyObject_CallMethod((PyObject *)self->input2, "_getStream", NULL);
     Py_INCREF(input2_streamtmp);
     Py_XDECREF(self->input2_stream);
     self->input2_stream = (Stream *)input2_streamtmp;
-    
+
     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;
@@ -5649,10 +5575,10 @@ Timer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Timer_getServer(Timer* self) { GET_SERVER };
 static PyObject * Timer_getStream(Timer* self) { GET_STREAM };
-static PyObject * Timer_setMul(Timer *self, PyObject *arg) { SET_MUL };	
-static PyObject * Timer_setAdd(Timer *self, PyObject *arg) { SET_ADD };	
-static PyObject * Timer_setSub(Timer *self, PyObject *arg) { SET_SUB };	
-static PyObject * Timer_setDiv(Timer *self, PyObject *arg) { SET_DIV };	
+static PyObject * Timer_setMul(Timer *self, PyObject *arg) { SET_MUL };
+static PyObject * Timer_setAdd(Timer *self, PyObject *arg) { SET_ADD };
+static PyObject * Timer_setSub(Timer *self, PyObject *arg) { SET_SUB };
+static PyObject * Timer_setDiv(Timer *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Timer_play(Timer *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Timer_stop(Timer *self) { STOP };
@@ -5692,7 +5618,7 @@ static PyNumberMethods Timer_as_number = {
     (binaryfunc)Timer_add,                         /*nb_add*/
     (binaryfunc)Timer_sub,                         /*nb_subtract*/
     (binaryfunc)Timer_multiply,                    /*nb_multiply*/
-    (binaryfunc)Timer_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -5706,16 +5632,16 @@ static PyNumberMethods Timer_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Timer_inplace_add,                 /*inplace_add*/
     (binaryfunc)Timer_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Timer_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Timer_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -5724,15 +5650,14 @@ static PyNumberMethods Timer_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Timer_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Timer_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject TimerType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Timer_base",                                   /*tp_name*/
     sizeof(Timer),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -5740,7 +5665,7 @@ PyTypeObject TimerType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &Timer_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -5779,26 +5704,57 @@ typedef struct {
     pyo_audio_HEAD
     PyObject *input;
     Stream *input_stream;
+    PyObject *choice;
+    Stream *audioval;
     int chSize;
     int chCount;
-    MYFLT *choice;
+    int curIsAudio;
     MYFLT value;
-    int modebuffer[2]; // need at least 2 slots for mul & add 
+    MYFLT *trigsBuffer;
+    TriggerStream *trig_stream;
+    int modebuffer[2]; // need at least 2 slots for mul & add
 } Iter;
 
 static void
+Iter_get_stream(Iter *self, PyObject *obj) {
+	PyObject *streamtmp;
+    streamtmp = PyObject_CallMethod((PyObject *)obj, "_getStream", NULL);
+    Py_INCREF(streamtmp);
+    Py_XDECREF(self->audioval);
+    self->audioval = (Stream *)streamtmp;
+}
+
+static void
 Iter_generate(Iter *self) {
     int i;
+    PyObject *obj;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
+        self->trigsBuffer[i] = 0.0;
         if (in[i] == 1) {
             if (self->chCount >= self->chSize)
                 self->chCount = 0;
-            self->value = self->choice[self->chCount];
+            obj = PyList_GetItem(self->choice, self->chCount);
+            if (PyNumber_Check(obj)) {
+                self->value = PyFloat_AsDouble(obj);
+                self->curIsAudio = 0;
+            }
+            else {
+                self->curIsAudio = 1;
+                Iter_get_stream(self, obj);
+            }
             self->chCount++;
+            if (self->chCount == self->chSize)
+                self->trigsBuffer[i] = 1.0;
+        }
+        if (self->curIsAudio) {
+            MYFLT *val = Stream_getData((Stream *)self->audioval);
+            self->data[i] = val[i];
+        }
+        else {
+            self->data[i] = self->value;
         }
-        self->data[i] = self->value;
     }
 }
 
@@ -5817,44 +5773,44 @@ Iter_setProcMode(Iter *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = Iter_generate;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Iter_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Iter_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Iter_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Iter_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Iter_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Iter_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Iter_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Iter_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Iter_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 Iter_compute_next_data_frame(Iter *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -5864,15 +5820,21 @@ Iter_traverse(Iter *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
+    Py_VISIT(self->choice);
+    Py_VISIT(self->audioval);
+    Py_VISIT(self->trig_stream);
     return 0;
 }
 
-static int 
+static int
 Iter_clear(Iter *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
+    Py_CLEAR(self->choice);
+    Py_CLEAR(self->audioval);
+    Py_CLEAR(self->trig_stream);
     return 0;
 }
 
@@ -5880,9 +5842,9 @@ static void
 Iter_dealloc(Iter* self)
 {
     pyo_DEALLOC
-    free(self->choice);
+    free(self->trigsBuffer);
     Iter_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -5893,39 +5855,49 @@ Iter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *choicetmp=NULL, *multmp=NULL, *addtmp=NULL;
     Iter *self;
     self = (Iter *)type->tp_alloc(type, 0);
-    
+
     self->value = 0.;
     self->chCount = 0;
+    self->curIsAudio = 0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Iter_compute_next_data_frame);
     self->mode_func_ptr = Iter_setProcMode;
 
     static char *kwlist[] = {"input", "choice", "init", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_OO_FOO, kwlist, &inputtmp, &choicetmp, &inittmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (choicetmp) {
         PyObject_CallMethod((PyObject *)self, "setChoice", "O", choicetmp);
     }
-    
+
     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->value = inittmp;
-    
+
+    self->trigsBuffer = (MYFLT *)realloc(self->trigsBuffer, self->bufsize * sizeof(MYFLT));
+
+    for (i=0; i<self->bufsize; i++) {
+        self->trigsBuffer[i] = 0.0;
+    }
+
+    MAKE_NEW_TRIGGER_STREAM(self->trig_stream, &TriggerStreamType, NULL);
+    TriggerStream_setData(self->trig_stream, self->trigsBuffer);
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
@@ -5933,10 +5905,11 @@ Iter_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Iter_getServer(Iter* self) { GET_SERVER };
 static PyObject * Iter_getStream(Iter* self) { GET_STREAM };
-static PyObject * Iter_setMul(Iter *self, PyObject *arg) { SET_MUL };	
-static PyObject * Iter_setAdd(Iter *self, PyObject *arg) { SET_ADD };	
-static PyObject * Iter_setSub(Iter *self, PyObject *arg) { SET_SUB };	
-static PyObject * Iter_setDiv(Iter *self, PyObject *arg) { SET_DIV };	
+static PyObject * Iter_getTriggerStream(Iter* self) { GET_TRIGGER_STREAM };
+static PyObject * Iter_setMul(Iter *self, PyObject *arg) { SET_MUL };
+static PyObject * Iter_setAdd(Iter *self, PyObject *arg) { SET_ADD };
+static PyObject * Iter_setSub(Iter *self, PyObject *arg) { SET_SUB };
+static PyObject * Iter_setDiv(Iter *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Iter_play(Iter *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Iter_out(Iter *self, PyObject *args, PyObject *kwds) { OUT };
@@ -5954,29 +5927,23 @@ static PyObject * Iter_inplace_div(Iter *self, PyObject *arg) { INPLACE_DIV };
 static PyObject *
 Iter_setChoice(Iter *self, PyObject *arg)
 {
-    int i;
 	PyObject *tmp;
-	
+
 	if (! PyList_Check(arg)) {
         PyErr_SetString(PyExc_TypeError, "The choice attribute must be a list.");
-		Py_INCREF(Py_None);
-		return Py_None;
+        Py_RETURN_NONE;
 	}
-    
+
     tmp = arg;
     self->chSize = PyList_Size(tmp);
-    self->choice = (MYFLT *)realloc(self->choice, self->chSize * sizeof(MYFLT));
-    for (i=0; i<self->chSize; i++) {
-        self->choice[i] = PyFloat_AS_DOUBLE(PyNumber_Float(PyList_GET_ITEM(tmp, i)));
-    }
-    
-    (*self->mode_func_ptr)(self);
-    
-	Py_INCREF(Py_None);
-	return Py_None;
-}	
+    Py_INCREF(tmp);
+	Py_XDECREF(self->choice);
+    self->choice = tmp;
+
+    Py_RETURN_NONE;
+}
 
-static PyObject * 
+static PyObject *
 Iter_reset(Iter *self, PyObject *arg)
 {
     int tmp;
@@ -5987,13 +5954,13 @@ Iter_reset(Iter *self, PyObject *arg)
         else
             self->chCount = 0;
     }
-	Py_INCREF(Py_None);
-	return Py_None;
+    Py_RETURN_NONE;
 }
 
 static PyMemberDef Iter_members[] = {
     {"server", T_OBJECT_EX, offsetof(Iter, server), 0, "Pyo server."},
     {"stream", T_OBJECT_EX, offsetof(Iter, stream), 0, "Stream object."},
+    {"trig_stream", T_OBJECT_EX, offsetof(Iter, trig_stream), 0, "Trigger Stream object."},
     {"input", T_OBJECT_EX, offsetof(Iter, input), 0, "Input sound object."},
     {"mul", T_OBJECT_EX, offsetof(Iter, mul), 0, "Mul factor."},
     {"add", T_OBJECT_EX, offsetof(Iter, add), 0, "Add factor."},
@@ -6003,6 +5970,7 @@ static PyMemberDef Iter_members[] = {
 static PyMethodDef Iter_methods[] = {
     {"getServer", (PyCFunction)Iter_getServer, METH_NOARGS, "Returns server object."},
     {"_getStream", (PyCFunction)Iter_getStream, METH_NOARGS, "Returns stream object."},
+    {"_getTriggerStream", (PyCFunction)Iter_getTriggerStream, METH_NOARGS, "Returns trigger stream object."},
     {"play", (PyCFunction)Iter_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
     {"out", (PyCFunction)Iter_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
     {"stop", (PyCFunction)Iter_stop, METH_NOARGS, "Stops computing."},
@@ -6019,7 +5987,7 @@ static PyNumberMethods Iter_as_number = {
     (binaryfunc)Iter_add,                         /*nb_add*/
     (binaryfunc)Iter_sub,                         /*nb_subtract*/
     (binaryfunc)Iter_multiply,                    /*nb_multiply*/
-    (binaryfunc)Iter_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -6033,16 +6001,16 @@ static PyNumberMethods Iter_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Iter_inplace_add,                 /*inplace_add*/
     (binaryfunc)Iter_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Iter_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Iter_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -6051,15 +6019,14 @@ static PyNumberMethods Iter_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Iter_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Iter_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject IterType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Iter_base",                                   /*tp_name*/
     sizeof(Iter),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -6067,7 +6034,7 @@ PyTypeObject IterType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &Iter_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -6117,8 +6084,8 @@ static void
 Count_generates(Count *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
-    for (i=0; i<self->bufsize; i++) {        
+
+    for (i=0; i<self->bufsize; i++) {
         if (in[i] == 1) {
             self->count = self->min;
             self->started = 1;
@@ -6131,7 +6098,7 @@ Count_generates(Count *self) {
         else {
             self->data[i] = self->min;
         }
-    } 
+    }
 }
 
 static void Count_postprocessing_ii(Count *self) { POST_PROCESSING_II };
@@ -6146,46 +6113,46 @@ static void Count_postprocessing_revareva(Count *self) { POST_PROCESSING_REVAREV
 
 static void
 Count_setProcMode(Count *self)
-{    
+{
     int muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = Count_generates;
-    
+
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Count_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Count_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Count_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Count_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Count_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Count_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Count_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Count_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Count_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 Count_compute_next_data_frame(Count *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -6198,7 +6165,7 @@ Count_traverse(Count *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Count_clear(Count *self)
 {
     pyo_CLEAR
@@ -6212,7 +6179,7 @@ Count_dealloc(Count* self)
 {
     pyo_DEALLOC
     Count_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -6222,35 +6189,35 @@ Count_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     Count *self;
     self = (Count *)type->tp_alloc(type, 0);
-    
+
     self->started = 0;
     self->count = 0;
     self->min = 0;
     self->max = 0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Count_compute_next_data_frame);
     self->mode_func_ptr = Count_setProcMode;
 
     static char *kwlist[] = {"input", "min", "max", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|kkOO", kwlist, &inputtmp, &self->min, &self->max, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
 
     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;
@@ -6258,10 +6225,10 @@ Count_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Count_getServer(Count* self) { GET_SERVER };
 static PyObject * Count_getStream(Count* self) { GET_STREAM };
-static PyObject * Count_setMul(Count *self, PyObject *arg) { SET_MUL };	
-static PyObject * Count_setAdd(Count *self, PyObject *arg) { SET_ADD };	
-static PyObject * Count_setSub(Count *self, PyObject *arg) { SET_SUB };	
-static PyObject * Count_setDiv(Count *self, PyObject *arg) { SET_DIV };	
+static PyObject * Count_setMul(Count *self, PyObject *arg) { SET_MUL };
+static PyObject * Count_setAdd(Count *self, PyObject *arg) { SET_ADD };
+static PyObject * Count_setSub(Count *self, PyObject *arg) { SET_SUB };
+static PyObject * Count_setDiv(Count *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Count_play(Count *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Count_stop(Count *self) { STOP };
@@ -6277,25 +6244,25 @@ static PyObject * Count_inplace_div(Count *self, PyObject *arg) { INPLACE_DIV };
 
 static PyObject *
 Count_setMin(Count *self, PyObject *arg)
-{	    
-	if (PyLong_Check(arg) || PyInt_Check(arg))	
+{
+	if (PyLong_Check(arg) || PyInt_Check(arg))
 		self->min = PyLong_AsLong(arg);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Count_setMax(Count *self, PyObject *arg)
-{	  
+{
     if (arg == Py_None)
         self->max = 0;
-	else if (PyLong_Check(arg) || PyInt_Check(arg))	
+	else if (PyLong_Check(arg) || PyInt_Check(arg))
 		self->max = PyLong_AsLong(arg);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Count_members[] = {
     {"server", T_OBJECT_EX, offsetof(Count, server), 0, "Pyo server."},
@@ -6324,7 +6291,7 @@ static PyNumberMethods Count_as_number = {
     (binaryfunc)Count_add,                         /*nb_add*/
     (binaryfunc)Count_sub,                         /*nb_subtract*/
     (binaryfunc)Count_multiply,                    /*nb_multiply*/
-    (binaryfunc)Count_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -6338,16 +6305,16 @@ static PyNumberMethods Count_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Count_inplace_add,                 /*inplace_add*/
     (binaryfunc)Count_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Count_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Count_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -6356,15 +6323,14 @@ static PyNumberMethods Count_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Count_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Count_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject CountType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Count_base",                                   /*tp_name*/
     sizeof(Count),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -6372,7 +6338,7 @@ PyTypeObject CountType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &Count_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -6422,17 +6388,17 @@ NextTrig_generates(NextTrig *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *in2 = Stream_getData((Stream *)self->input2_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = 0.0;
         if (self->gate == 1 && in[i] == 1.0) {
                 self->data[i] = 1.0;
                 self->gate = 0;
         }
-        
+
         if (in2[i] == 1 && self->gate == 0)
             self->gate = 1;
-    } 
+    }
 }
 
 static void NextTrig_postprocessing_ii(NextTrig *self) { POST_PROCESSING_II };
@@ -6447,46 +6413,46 @@ static void NextTrig_postprocessing_revareva(NextTrig *self) { POST_PROCESSING_R
 
 static void
 NextTrig_setProcMode(NextTrig *self)
-{    
+{
     int muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = NextTrig_generates;
-    
+
     switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = NextTrig_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = NextTrig_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = NextTrig_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = NextTrig_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = NextTrig_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = NextTrig_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = NextTrig_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = NextTrig_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = NextTrig_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 NextTrig_compute_next_data_frame(NextTrig *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -6501,7 +6467,7 @@ NextTrig_traverse(NextTrig *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 NextTrig_clear(NextTrig *self)
 {
     pyo_CLEAR
@@ -6517,7 +6483,7 @@ NextTrig_dealloc(NextTrig* self)
 {
     pyo_DEALLOC
     NextTrig_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -6527,39 +6493,39 @@ NextTrig_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *input2tmp, *input2_streamtmp, *multmp=NULL, *addtmp=NULL;
     NextTrig *self;
     self = (NextTrig *)type->tp_alloc(type, 0);
-    
+
     self->gate = 0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, NextTrig_compute_next_data_frame);
     self->mode_func_ptr = NextTrig_setProcMode;
 
     static char *kwlist[] = {"input", "input2", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO", kwlist, &inputtmp, &input2tmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     Py_XDECREF(self->input2);
     self->input2 = input2tmp;
     input2_streamtmp = PyObject_CallMethod((PyObject *)self->input2, "_getStream", NULL);
     Py_INCREF(input2_streamtmp);
     Py_XDECREF(self->input2_stream);
     self->input2_stream = (Stream *)input2_streamtmp;
-    
+
     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;
@@ -6567,10 +6533,10 @@ NextTrig_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * NextTrig_getServer(NextTrig* self) { GET_SERVER };
 static PyObject * NextTrig_getStream(NextTrig* self) { GET_STREAM };
-static PyObject * NextTrig_setMul(NextTrig *self, PyObject *arg) { SET_MUL };	
-static PyObject * NextTrig_setAdd(NextTrig *self, PyObject *arg) { SET_ADD };	
-static PyObject * NextTrig_setSub(NextTrig *self, PyObject *arg) { SET_SUB };	
-static PyObject * NextTrig_setDiv(NextTrig *self, PyObject *arg) { SET_DIV };	
+static PyObject * NextTrig_setMul(NextTrig *self, PyObject *arg) { SET_MUL };
+static PyObject * NextTrig_setAdd(NextTrig *self, PyObject *arg) { SET_ADD };
+static PyObject * NextTrig_setSub(NextTrig *self, PyObject *arg) { SET_SUB };
+static PyObject * NextTrig_setDiv(NextTrig *self, PyObject *arg) { SET_DIV };
 
 static PyObject * NextTrig_play(NextTrig *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * NextTrig_stop(NextTrig *self) { STOP };
@@ -6610,7 +6576,7 @@ static PyNumberMethods NextTrig_as_number = {
     (binaryfunc)NextTrig_add,                         /*nb_add*/
     (binaryfunc)NextTrig_sub,                         /*nb_subtract*/
     (binaryfunc)NextTrig_multiply,                    /*nb_multiply*/
-    (binaryfunc)NextTrig_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -6624,16 +6590,16 @@ static PyNumberMethods NextTrig_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)NextTrig_inplace_add,                 /*inplace_add*/
     (binaryfunc)NextTrig_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)NextTrig_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)NextTrig_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -6642,15 +6608,14 @@ static PyNumberMethods NextTrig_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)NextTrig_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)NextTrig_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject NextTrigType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.NextTrig_base",                                   /*tp_name*/
     sizeof(NextTrig),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -6658,7 +6623,7 @@ PyTypeObject NextTrigType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &NextTrig_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -6697,7 +6662,7 @@ typedef struct {
     PyObject *value;
     Stream *value_stream;
     MYFLT current_value;
-    int modebuffer[3]; // need at least 2 slots for mul & add 
+    int modebuffer[3]; // need at least 2 slots for mul & add
 } TrigVal;
 
 static void
@@ -6705,11 +6670,11 @@ TrigVal_generate_i(TrigVal *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT val = PyFloat_AS_DOUBLE(self->value);
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (in[i] == 1)
             self->current_value = val;
-        
+
         self->data[i] = self->current_value;
     }
 }
@@ -6719,11 +6684,11 @@ TrigVal_generate_a(TrigVal *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *val = Stream_getData((Stream *)self->value_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (in[i] == 1)
             self->current_value = val[i];
-        
+
         self->data[i] = self->current_value;
     }
 }
@@ -6744,50 +6709,50 @@ TrigVal_setProcMode(TrigVal *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2];
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = TrigVal_generate_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = TrigVal_generate_a;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = TrigVal_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = TrigVal_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = TrigVal_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = TrigVal_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = TrigVal_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = TrigVal_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = TrigVal_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = TrigVal_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = TrigVal_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 TrigVal_compute_next_data_frame(TrigVal *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -6797,19 +6762,19 @@ TrigVal_traverse(TrigVal *self, visitproc visit, void *arg)
     pyo_VISIT
     Py_VISIT(self->input);
     Py_VISIT(self->input_stream);
-    Py_VISIT(self->value);    
-    Py_VISIT(self->value_stream);    
+    Py_VISIT(self->value);
+    Py_VISIT(self->value_stream);
     return 0;
 }
 
-static int 
+static int
 TrigVal_clear(TrigVal *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->value);    
-    Py_CLEAR(self->value_stream);    
+    Py_CLEAR(self->value);
+    Py_CLEAR(self->value_stream);
     return 0;
 }
 
@@ -6818,7 +6783,7 @@ TrigVal_dealloc(TrigVal* self)
 {
     pyo_DEALLOC
     TrigVal_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -6828,49 +6793,49 @@ TrigVal_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *valuetmp=NULL, *multmp=NULL, *addtmp=NULL;
     TrigVal *self;
     self = (TrigVal *)type->tp_alloc(type, 0);
-    
+
     self->value = PyFloat_FromDouble(0.);
     self->current_value = 0.;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, TrigVal_compute_next_data_frame);
     self->mode_func_ptr = TrigVal_setProcMode;
-    
+
     static char *kwlist[] = {"input", "value", "init", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_OFOO, kwlist, &inputtmp, &valuetmp, &self->current_value, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (valuetmp) {
         PyObject_CallMethod((PyObject *)self, "setValue", "O", valuetmp);
     }
-    
+
     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 * TrigVal_getServer(TrigVal* self) { GET_SERVER };
 static PyObject * TrigVal_getStream(TrigVal* self) { GET_STREAM };
-static PyObject * TrigVal_setMul(TrigVal *self, PyObject *arg) { SET_MUL };	
-static PyObject * TrigVal_setAdd(TrigVal *self, PyObject *arg) { SET_ADD };	
-static PyObject * TrigVal_setSub(TrigVal *self, PyObject *arg) { SET_SUB };	
-static PyObject * TrigVal_setDiv(TrigVal *self, PyObject *arg) { SET_DIV };	
+static PyObject * TrigVal_setMul(TrigVal *self, PyObject *arg) { SET_MUL };
+static PyObject * TrigVal_setAdd(TrigVal *self, PyObject *arg) { SET_ADD };
+static PyObject * TrigVal_setSub(TrigVal *self, PyObject *arg) { SET_SUB };
+static PyObject * TrigVal_setDiv(TrigVal *self, PyObject *arg) { SET_DIV };
 
 static PyObject * TrigVal_play(TrigVal *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * TrigVal_out(TrigVal *self, PyObject *args, PyObject *kwds) { OUT };
@@ -6889,14 +6854,11 @@ static PyObject *
 TrigVal_setValue(TrigVal *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->value);
@@ -6912,12 +6874,12 @@ TrigVal_setValue(TrigVal *self, PyObject *arg)
         self->value_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef TrigVal_members[] = {
     {"server", T_OBJECT_EX, offsetof(TrigVal, server), 0, "Pyo server."},
@@ -6947,7 +6909,7 @@ static PyNumberMethods TrigVal_as_number = {
     (binaryfunc)TrigVal_add,                         /*nb_add*/
     (binaryfunc)TrigVal_sub,                         /*nb_subtract*/
     (binaryfunc)TrigVal_multiply,                    /*nb_multiply*/
-    (binaryfunc)TrigVal_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -6961,16 +6923,16 @@ static PyNumberMethods TrigVal_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)TrigVal_inplace_add,                 /*inplace_add*/
     (binaryfunc)TrigVal_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)TrigVal_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)TrigVal_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -6979,15 +6941,14 @@ static PyNumberMethods TrigVal_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)TrigVal_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)TrigVal_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject TrigValType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.TrigVal_base",                                   /*tp_name*/
     sizeof(TrigVal),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -6995,7 +6956,7 @@ PyTypeObject TrigValType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &TrigVal_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -7025,4 +6986,4 @@ PyTypeObject TrigValType = {
     0,                          /* tp_init */
     0,                                              /* tp_alloc */
     TrigVal_new,                                     /* tp_new */
-};
+};
\ No newline at end of file
diff --git a/src/objects/utilsmodule.c b/src/objects/utilsmodule.c
index a82cec9..cab8d87 100644
--- a/src/objects/utilsmodule.c
+++ b/src/objects/utilsmodule.c
@@ -1,30 +1,32 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
 #include "streammodule.h"
 #include "servermodule.h"
 #include "dummymodule.h"
+#include "interpolation.h"
 
 /************/
 /* Print */
@@ -45,14 +47,14 @@ static void
 Print_process_time(Print *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (self->currentTime >= self->time) {
             self->currentTime = 0.0;
             if (self->message == NULL || self->message[0] == '\0')
-                printf("%f\n", in[i]);
+                PySys_WriteStdout("%f\n", in[i]);
             else
-                printf("%s : %f\n", self->message, in[i]);
+                PySys_WriteStdout("%s : %f\n", self->message, in[i]);
         }
         self->currentTime += self->sampleToSec;
     }
@@ -68,20 +70,20 @@ Print_process_change(Print *self) {
         inval = in[i];
         if (inval < (self->lastValue-0.00001) || inval > (self->lastValue+0.00001)) {
             if (self->message == NULL || self->message[0] == '\0')
-                printf("%f\n", inval);
+                PySys_WriteStdout("%f\n", inval);
             else
-                printf("%s : %f\n", self->message, inval);
+                PySys_WriteStdout("%s : %f\n", self->message, inval);
             self->lastValue = inval;
         }
-    }    
+    }
 }
 
 static void
 Print_setProcMode(Print *self)
-{    
+{
     if (self->method < 0 || self->method > 1)
         self->method = 0;
-        
+
     switch (self->method) {
         case 0:
             self->proc_func_ptr = Print_process_time;
@@ -89,13 +91,13 @@ Print_setProcMode(Print *self)
         case 1:
             self->proc_func_ptr = Print_process_change;
             break;
-    }        
+    }
 }
 
 static void
 Print_compute_next_data_frame(Print *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
 }
 
 static int
@@ -107,7 +109,7 @@ Print_traverse(Print *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Print_clear(Print *self)
 {
     pyo_CLEAR
@@ -121,7 +123,7 @@ Print_dealloc(Print* self)
 {
     pyo_DEALLOC
     Print_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -135,7 +137,7 @@ Print_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->method = 0;
     self->time = 0.25;
     self->lastValue = -99999.0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Print_compute_next_data_frame);
     self->mode_func_ptr = Print_setProcMode;
@@ -144,16 +146,16 @@ Print_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->currentTime = 0.;
 
     static char *kwlist[] = {"input", "method", "interval", "message", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_IFS, kwlist, &inputtmp, &self->method, &self->time, &self->message))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
 
     PyObject_CallMethod(self->server, "addStream", "O", self->stream);
-    
+
     (*self->mode_func_ptr)(self);
-    
+
     return (PyObject *)self;
 }
 
@@ -166,56 +168,36 @@ static PyObject * Print_stop(Print *self) { STOP };
 static PyObject *
 Print_setMethod(Print *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	int isNumber = PyNumber_Check(arg);
-	
-	if (isNumber == 1) {
+    ASSERT_ARG_NOT_NULL
+
+	if (PyNumber_Check(arg) == 1) {
 		self->method = PyInt_AsLong(arg);
         (*self->mode_func_ptr)(self);
 	}
-    
-	Py_INCREF(Py_None);
-	return Py_None;
+
+	Py_RETURN_NONE;
 }
 
 static PyObject *
 Print_setInterval(Print *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	int isNumber = PyNumber_Check(arg);
-	
-	if (isNumber == 1) {
-		self->time = PyFloat_AS_DOUBLE(PyNumber_Float(arg));
-	}
-    
-	Py_INCREF(Py_None);
-	return Py_None;
+    ASSERT_ARG_NOT_NULL
+
+	if (PyNumber_Check(arg) == 1)
+		self->time = PyFloat_AsDouble(arg);
+
+	Py_RETURN_NONE;
 }
 
 static PyObject *
 Print_setMessage(Print *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
-	int isString = PyString_Check(arg);
-	
-	if (isString == 1) {
-		self->message = PyString_AsString(arg);
-	}
-    
-	Py_INCREF(Py_None);
-	return Py_None;
+    ASSERT_ARG_NOT_NULL
+
+    if (PY_STRING_CHECK(arg))
+        self->message = PY_STRING_AS_STRING(arg);
+
+	Py_RETURN_NONE;
 }
 
 static PyMemberDef Print_members[] = {
@@ -237,8 +219,7 @@ static PyMethodDef Print_methods[] = {
 };
 
 PyTypeObject PrintType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Print_base",                                   /*tp_name*/
 sizeof(Print),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -246,7 +227,7 @@ sizeof(Print),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 0,                                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -291,14 +272,14 @@ typedef struct {
     MYFLT *choice;
     MYFLT value;
     MYFLT last_input;
-    int modebuffer[2]; // need at least 2 slots for mul & add 
+    int modebuffer[2]; // need at least 2 slots for mul & add
 } Snap;
 
 static MYFLT
 Snap_convert(Snap *self) {
     int midival;
     MYFLT val;
-    
+
     midival = self->value;
 
     if (self->scale == 1)
@@ -307,7 +288,7 @@ Snap_convert(Snap *self) {
         val = MYPOW(1.0594630943593, midival - 60);
     else
         val = midival;
-    
+
     return val;
 }
 
@@ -316,7 +297,7 @@ Snap_generate(Snap *self) {
     int i, j, pos;
     MYFLT intmp, diff, difftmp;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         if (in[i] < (self->last_input-0.001) || in[i] > (self->last_input + 0.001)) {
             int oct = 0;
@@ -332,12 +313,12 @@ Snap_generate(Snap *self) {
                 if (difftmp < diff) {
                     diff = difftmp;
                     pos = j;
-                }    
+                }
             }
             self->value = self->choice[pos] + (self->highbound * oct);
-            self->value = Snap_convert(self);  
+            self->value = Snap_convert(self);
         }
-     
+
         self->data[i] = self->value;
     }
 }
@@ -357,44 +338,44 @@ Snap_setProcMode(Snap *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = Snap_generate;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Snap_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Snap_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Snap_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Snap_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Snap_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Snap_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Snap_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Snap_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Snap_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 Snap_compute_next_data_frame(Snap *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -407,7 +388,7 @@ Snap_traverse(Snap *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Snap_clear(Snap *self)
 {
     pyo_CLEAR
@@ -422,7 +403,7 @@ Snap_dealloc(Snap* self)
     pyo_DEALLOC
     free(self->choice);
     Snap_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -432,36 +413,36 @@ Snap_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *choicetmp=NULL, *multmp=NULL, *addtmp=NULL;
     Snap *self;
     self = (Snap *)type->tp_alloc(type, 0);
-    
+
     self->value = self->last_input = 0.;
     self->scale = 0;
     self->highbound = 12;
     self->modebuffer[0] = 0;
     self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Snap_compute_next_data_frame);
     self->mode_func_ptr = Snap_setProcMode;
 
     static char *kwlist[] = {"input", "choice", "scale", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|iOO", kwlist, &inputtmp, &choicetmp, &self->scale, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (choicetmp) {
         PyObject_CallMethod((PyObject *)self, "setChoice", "O", choicetmp);
     }
-    
+
     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);
@@ -471,10 +452,10 @@ Snap_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Snap_getServer(Snap* self) { GET_SERVER };
 static PyObject * Snap_getStream(Snap* self) { GET_STREAM };
-static PyObject * Snap_setMul(Snap *self, PyObject *arg) { SET_MUL };	
-static PyObject * Snap_setAdd(Snap *self, PyObject *arg) { SET_ADD };	
-static PyObject * Snap_setSub(Snap *self, PyObject *arg) { SET_SUB };	
-static PyObject * Snap_setDiv(Snap *self, PyObject *arg) { SET_DIV };	
+static PyObject * Snap_setMul(Snap *self, PyObject *arg) { SET_MUL };
+static PyObject * Snap_setAdd(Snap *self, PyObject *arg) { SET_ADD };
+static PyObject * Snap_setSub(Snap *self, PyObject *arg) { SET_SUB };
+static PyObject * Snap_setDiv(Snap *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Snap_play(Snap *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Snap_out(Snap *self, PyObject *args, PyObject *kwds) { OUT };
@@ -495,58 +476,56 @@ Snap_setChoice(Snap *self, PyObject *arg)
     int i, oct;
     MYFLT max;
 	PyObject *tmp;
-	
+
 	if (! PyList_Check(arg)) {
         PyErr_SetString(PyExc_TypeError, "The choice attribute must be a list.");
 		Py_INCREF(Py_None);
 		return Py_None;
 	}
-    
+
     tmp = arg;
     self->chSize = PyList_Size(tmp);
     self->choice = (MYFLT *)realloc(self->choice, self->chSize * sizeof(MYFLT));
-    
+
     for (i=0; i<self->chSize; i++) {
-        self->choice[i] = PyFloat_AS_DOUBLE(PyNumber_Float(PyList_GET_ITEM(tmp, i)));
+        self->choice[i] = PyFloat_AsDouble(PyList_GET_ITEM(tmp, i));
     }
-    
+
     max = self->choice[self->chSize-1];
-    
+
     oct = 12;
     while (max >= oct) {
         oct += 12;
     }
-    
+
     self->highbound = oct;
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Snap_setScale(Snap *self, PyObject *arg)
-{	
+{
     int tmp;
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyInt_Check(arg);
-	
+
 	if (isNumber == 1) {
 		tmp = PyInt_AsLong(arg);
         if (tmp >= 0 && tmp <= 2)
             self->scale = tmp;
         else
-            printf("scale attribute must be an integer {0, 1, 2}\n");
+            PySys_WriteStdout("Snap: scale attribute must be an integer {0, 1, 2}\n");
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Snap_members[] = {
     {"server", T_OBJECT_EX, offsetof(Snap, server), 0, "Pyo server."},
@@ -576,7 +555,7 @@ static PyNumberMethods Snap_as_number = {
     (binaryfunc)Snap_add,                         /*nb_add*/
     (binaryfunc)Snap_sub,                         /*nb_subtract*/
     (binaryfunc)Snap_multiply,                    /*nb_multiply*/
-    (binaryfunc)Snap_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -590,16 +569,16 @@ static PyNumberMethods Snap_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Snap_inplace_add,                 /*inplace_add*/
     (binaryfunc)Snap_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Snap_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Snap_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -608,15 +587,14 @@ static PyNumberMethods Snap_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Snap_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Snap_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject SnapType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Snap_base",                                   /*tp_name*/
     sizeof(Snap),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -624,7 +602,7 @@ PyTypeObject SnapType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &Snap_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -667,7 +645,7 @@ typedef struct {
     Stream *input2_stream;
     PyObject *interp;
     Stream *interp_stream;
-    int modebuffer[3]; // need at least 2 slots for mul & add 
+    int modebuffer[3]; // need at least 2 slots for mul & add
 } Interp;
 
 static void
@@ -682,8 +660,8 @@ Interp_filters_i(Interp *self) {
         inter = 0.0;
     else if (inter > 1.0)
         inter = 1.0;
-    
-    amp2 = 1.0 - inter; 
+
+    amp2 = 1.0 - inter;
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = in[i] * amp2 + in2[i] * inter;
     }
@@ -696,15 +674,15 @@ Interp_filters_a(Interp *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *in2 = Stream_getData((Stream *)self->input2_stream);
     MYFLT *inter = Stream_getData((Stream *)self->interp_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         amp1 = inter[i];
         if (amp1 < 0.0)
             amp1 = 0.0;
         else if (amp1 > 1.0)
             amp1 = 1.0;
-        
-        amp2 = 1.0 - amp1; 
+
+        amp2 = 1.0 - amp1;
         self->data[i] = in[i] * amp2 + in2[i] * amp1;
     }
 }
@@ -725,50 +703,50 @@ Interp_setProcMode(Interp *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2];
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Interp_filters_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Interp_filters_a;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Interp_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Interp_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Interp_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Interp_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Interp_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Interp_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Interp_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Interp_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Interp_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Interp_compute_next_data_frame(Interp *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -780,12 +758,12 @@ Interp_traverse(Interp *self, visitproc visit, void *arg)
     Py_VISIT(self->input_stream);
     Py_VISIT(self->input2);
     Py_VISIT(self->input2_stream);
-    Py_VISIT(self->interp);    
-    Py_VISIT(self->interp_stream);    
+    Py_VISIT(self->interp);
+    Py_VISIT(self->interp_stream);
     return 0;
 }
 
-static int 
+static int
 Interp_clear(Interp *self)
 {
     pyo_CLEAR
@@ -793,8 +771,8 @@ Interp_clear(Interp *self)
     Py_CLEAR(self->input_stream);
     Py_CLEAR(self->input2);
     Py_CLEAR(self->input2_stream);
-    Py_CLEAR(self->interp);    
-    Py_CLEAR(self->interp_stream);    
+    Py_CLEAR(self->interp);
+    Py_CLEAR(self->interp_stream);
     return 0;
 }
 
@@ -803,7 +781,7 @@ Interp_dealloc(Interp* self)
 {
     pyo_DEALLOC
     Interp_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -813,21 +791,21 @@ Interp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *input2tmp, *input2_streamtmp, *interptmp=NULL, *multmp=NULL, *addtmp=NULL;
     Interp *self;
     self = (Interp *)type->tp_alloc(type, 0);
-    
+
     self->interp = PyFloat_FromDouble(.5);
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Interp_compute_next_data_frame);
     self->mode_func_ptr = Interp_setProcMode;
 
     static char *kwlist[] = {"input", "input2", "interp", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOO", kwlist, &inputtmp, &input2tmp, &interptmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
 
     Py_XDECREF(self->input2);
@@ -836,21 +814,21 @@ Interp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     Py_INCREF(input2_streamtmp);
     Py_XDECREF(self->input2_stream);
     self->input2_stream = (Stream *)input2_streamtmp;
-    
+
     if (interptmp) {
         PyObject_CallMethod((PyObject *)self, "setInterp", "O", interptmp);
     }
-    
+
     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;
@@ -858,10 +836,10 @@ Interp_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Interp_getServer(Interp* self) { GET_SERVER };
 static PyObject * Interp_getStream(Interp* self) { GET_STREAM };
-static PyObject * Interp_setMul(Interp *self, PyObject *arg) { SET_MUL };	
-static PyObject * Interp_setAdd(Interp *self, PyObject *arg) { SET_ADD };	
-static PyObject * Interp_setSub(Interp *self, PyObject *arg) { SET_SUB };	
-static PyObject * Interp_setDiv(Interp *self, PyObject *arg) { SET_DIV };	
+static PyObject * Interp_setMul(Interp *self, PyObject *arg) { SET_MUL };
+static PyObject * Interp_setAdd(Interp *self, PyObject *arg) { SET_ADD };
+static PyObject * Interp_setSub(Interp *self, PyObject *arg) { SET_SUB };
+static PyObject * Interp_setDiv(Interp *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Interp_play(Interp *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Interp_out(Interp *self, PyObject *args, PyObject *kwds) { OUT };
@@ -880,14 +858,11 @@ static PyObject *
 Interp_setInterp(Interp *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->interp);
@@ -903,9 +878,9 @@ Interp_setInterp(Interp *self, PyObject *arg)
         self->interp_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -939,7 +914,7 @@ static PyNumberMethods Interp_as_number = {
 (binaryfunc)Interp_add,                         /*nb_add*/
 (binaryfunc)Interp_sub,                         /*nb_subtract*/
 (binaryfunc)Interp_multiply,                    /*nb_multiply*/
-(binaryfunc)Interp_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -953,16 +928,16 @@ static PyNumberMethods Interp_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)Interp_inplace_add,                 /*inplace_add*/
 (binaryfunc)Interp_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)Interp_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)Interp_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -971,15 +946,14 @@ static PyNumberMethods Interp_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)Interp_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)Interp_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject InterpType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Interp_base",                                   /*tp_name*/
 sizeof(Interp),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -987,7 +961,7 @@ sizeof(Interp),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &Interp_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -1032,7 +1006,7 @@ typedef struct {
     Stream *value_stream;
     MYFLT currentValue;
     int flag;
-    int modebuffer[3]; // need at least 2 slots for mul & add 
+    int modebuffer[3]; // need at least 2 slots for mul & add
 } SampHold;
 
 static void
@@ -1049,7 +1023,7 @@ SampHold_filters_i(SampHold *self) {
             if (self->flag == 1) {
                 self->currentValue = in[i];
                 self->flag = 0;
-            }    
+            }
         }
         else
             self->flag = 1;
@@ -1064,7 +1038,7 @@ SampHold_filters_a(SampHold *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *ctrlsig = Stream_getData((Stream *)self->controlsig_stream);
     MYFLT *valsig = Stream_getData((Stream *)self->value_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         ctrl = ctrlsig[i];
         val = valsig[i];
@@ -1072,7 +1046,7 @@ SampHold_filters_a(SampHold *self) {
             if (self->flag == 1) {
                 self->currentValue = in[i];
                 self->flag = 0;
-            }    
+            }
         }
         else
             self->flag = 1;
@@ -1096,50 +1070,50 @@ SampHold_setProcMode(SampHold *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2];
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = SampHold_filters_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = SampHold_filters_a;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = SampHold_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = SampHold_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = SampHold_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = SampHold_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = SampHold_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = SampHold_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = SampHold_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = SampHold_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = SampHold_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 SampHold_compute_next_data_frame(SampHold *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1151,12 +1125,12 @@ SampHold_traverse(SampHold *self, visitproc visit, void *arg)
     Py_VISIT(self->input_stream);
     Py_VISIT(self->controlsig);
     Py_VISIT(self->controlsig_stream);
-    Py_VISIT(self->value);    
-    Py_VISIT(self->value_stream);    
+    Py_VISIT(self->value);
+    Py_VISIT(self->value_stream);
     return 0;
 }
 
-static int 
+static int
 SampHold_clear(SampHold *self)
 {
     pyo_CLEAR
@@ -1164,8 +1138,8 @@ SampHold_clear(SampHold *self)
     Py_CLEAR(self->input_stream);
     Py_CLEAR(self->controlsig);
     Py_CLEAR(self->controlsig_stream);
-    Py_CLEAR(self->value);    
-    Py_CLEAR(self->value_stream);    
+    Py_CLEAR(self->value);
+    Py_CLEAR(self->value_stream);
     return 0;
 }
 
@@ -1174,7 +1148,7 @@ SampHold_dealloc(SampHold* self)
 {
     pyo_DEALLOC
     SampHold_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1184,46 +1158,46 @@ SampHold_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *controlsigtmp, *controlsig_streamtmp, *valuetmp=NULL, *multmp=NULL, *addtmp=NULL;
     SampHold *self;
     self = (SampHold *)type->tp_alloc(type, 0);
-    
+
     self->value = PyFloat_FromDouble(0.0);
     self->currentValue = 0.0;
     self->flag = 1;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, SampHold_compute_next_data_frame);
     self->mode_func_ptr = SampHold_setProcMode;
 
     static char *kwlist[] = {"input", "controlsig", "value", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOO", kwlist, &inputtmp, &controlsigtmp, &valuetmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
-    Py_XDECREF(self->controlsig); \
-    self->controlsig = controlsigtmp; \
-    controlsig_streamtmp = PyObject_CallMethod((PyObject *)self->controlsig, "_getStream", NULL); \
-    Py_INCREF(controlsig_streamtmp); \
-    Py_XDECREF(self->controlsig_stream); \
+
+    Py_XDECREF(self->controlsig);
+    self->controlsig = controlsigtmp;
+    controlsig_streamtmp = PyObject_CallMethod((PyObject *)self->controlsig, "_getStream", NULL);
+    Py_INCREF(controlsig_streamtmp);
+    Py_XDECREF(self->controlsig_stream);
     self->controlsig_stream = (Stream *)controlsig_streamtmp;
-    
+
     if (valuetmp) {
         PyObject_CallMethod((PyObject *)self, "setValue", "O", valuetmp);
     }
-    
+
     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;
@@ -1231,10 +1205,10 @@ SampHold_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * SampHold_getServer(SampHold* self) { GET_SERVER };
 static PyObject * SampHold_getStream(SampHold* self) { GET_STREAM };
-static PyObject * SampHold_setMul(SampHold *self, PyObject *arg) { SET_MUL };	
-static PyObject * SampHold_setAdd(SampHold *self, PyObject *arg) { SET_ADD };	
-static PyObject * SampHold_setSub(SampHold *self, PyObject *arg) { SET_SUB };	
-static PyObject * SampHold_setDiv(SampHold *self, PyObject *arg) { SET_DIV };	
+static PyObject * SampHold_setMul(SampHold *self, PyObject *arg) { SET_MUL };
+static PyObject * SampHold_setAdd(SampHold *self, PyObject *arg) { SET_ADD };
+static PyObject * SampHold_setSub(SampHold *self, PyObject *arg) { SET_SUB };
+static PyObject * SampHold_setDiv(SampHold *self, PyObject *arg) { SET_DIV };
 
 static PyObject * SampHold_play(SampHold *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * SampHold_out(SampHold *self, PyObject *args, PyObject *kwds) { OUT };
@@ -1253,14 +1227,11 @@ static PyObject *
 SampHold_setValue(SampHold *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->value);
@@ -1276,9 +1247,9 @@ SampHold_setValue(SampHold *self, PyObject *arg)
         self->value_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
@@ -1312,7 +1283,7 @@ static PyNumberMethods SampHold_as_number = {
 (binaryfunc)SampHold_add,                         /*nb_add*/
 (binaryfunc)SampHold_sub,                         /*nb_subtract*/
 (binaryfunc)SampHold_multiply,                    /*nb_multiply*/
-(binaryfunc)SampHold_div,                                              /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -1326,16 +1297,16 @@ static PyNumberMethods SampHold_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)SampHold_inplace_add,                 /*inplace_add*/
 (binaryfunc)SampHold_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)SampHold_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)SampHold_inplace_div,                                              /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -1344,15 +1315,14 @@ static PyNumberMethods SampHold_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)SampHold_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)SampHold_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject SampHoldType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.SampHold_base",                                   /*tp_name*/
 sizeof(SampHold),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -1360,7 +1330,7 @@ sizeof(SampHold),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &SampHold_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -1393,71 +1363,444 @@ SampHold_new,                                     /* tp_new */
 };
 
 /************/
-/* Compare */
+/* TrackHold */
 /************/
 typedef struct {
     pyo_audio_HEAD
     PyObject *input;
     Stream *input_stream;
-    PyObject *comp;
-    Stream *comp_stream;
-    MYFLT (*compare_func_ptr)(MYFLT, MYFLT); // true = 1.0, false = 0.0
-    int modebuffer[3]; // need at least 2 slots for mul & add 
-} Compare;
-
-static MYFLT
-Compare_lt(MYFLT in, MYFLT comp) {
-    if (in < comp) { return 1.0; }
-    else { return 0.0; }
-}
-
-static MYFLT
-Compare_elt(MYFLT in, MYFLT comp) {
-    if (in <= comp) { return 1.0; }
-    else { return 0.0; }
-}
-
-static MYFLT
-Compare_gt(MYFLT in, MYFLT comp) {
-    if (in > comp) { return 1.0; }
-    else { return 0.0; }
-}
-
-static MYFLT
-Compare_egt(MYFLT in, MYFLT comp) {
-    if (in >= comp) { return 1.0; }
-    else { return 0.0; }
-}
-
-static MYFLT
-Compare_eq(MYFLT in, MYFLT comp) {
-    if (in >= (comp - 0.0001) && in <= (comp + 0.0001)) { return 1.0; }
-    else { return 0.0; }
-}
-
-static MYFLT
-Compare_neq(MYFLT in, MYFLT comp) {
-    if (in <= (comp - 0.0001) || in >= (comp + 0.0001)) { return 1.0; }
-    else { return 0.0; }
-}
+    PyObject *controlsig;
+    Stream *controlsig_stream;
+    PyObject *value;
+    Stream *value_stream;
+    MYFLT currentValue;
+    int flag;
+    int modebuffer[3]; // need at least 2 slots for mul & add
+} TrackHold;
 
 static void
-Compare_process_i(Compare *self) {
+TrackHold_filters_i(TrackHold *self) {
+    MYFLT ctrl;
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    MYFLT comp = PyFloat_AS_DOUBLE(self->comp);
-    
-    for (i=0; i<self->bufsize; i++) {
-        self->data[i] = (*self->compare_func_ptr)(in[i], comp);
-    }
-}
+    MYFLT *ctrlsig = Stream_getData((Stream *)self->controlsig_stream);
+    MYFLT val = PyFloat_AS_DOUBLE(self->value);
 
-static void
+    for (i=0; i<self->bufsize; i++) {
+        ctrl = ctrlsig[i];
+        if (ctrl > (val - 0.0001) && ctrl < (val + 0.0001)) {
+            if (self->flag == 1) {
+                self->currentValue = in[i];
+                self->flag = 0;
+            }
+        }
+        else {
+            self->currentValue = in[i];
+            self->flag = 1;
+        }
+        self->data[i] = self->currentValue;
+    }
+}
+
+static void
+TrackHold_filters_a(TrackHold *self) {
+    MYFLT ctrl, val;
+    int i;
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+    MYFLT *ctrlsig = Stream_getData((Stream *)self->controlsig_stream);
+    MYFLT *valsig = Stream_getData((Stream *)self->value_stream);
+
+    for (i=0; i<self->bufsize; i++) {
+        ctrl = ctrlsig[i];
+        val = valsig[i];
+        if (ctrl > (val - 0.0001) && ctrl < (val + 0.0001)) {
+            if (self->flag == 1) {
+                self->currentValue = in[i];
+                self->flag = 0;
+            }
+        }
+        else {
+            self->currentValue = in[i];
+            self->flag = 1;
+        }
+        self->data[i] = self->currentValue;
+    }
+}
+
+static void TrackHold_postprocessing_ii(TrackHold *self) { POST_PROCESSING_II };
+static void TrackHold_postprocessing_ai(TrackHold *self) { POST_PROCESSING_AI };
+static void TrackHold_postprocessing_ia(TrackHold *self) { POST_PROCESSING_IA };
+static void TrackHold_postprocessing_aa(TrackHold *self) { POST_PROCESSING_AA };
+static void TrackHold_postprocessing_ireva(TrackHold *self) { POST_PROCESSING_IREVA };
+static void TrackHold_postprocessing_areva(TrackHold *self) { POST_PROCESSING_AREVA };
+static void TrackHold_postprocessing_revai(TrackHold *self) { POST_PROCESSING_REVAI };
+static void TrackHold_postprocessing_revaa(TrackHold *self) { POST_PROCESSING_REVAA };
+static void TrackHold_postprocessing_revareva(TrackHold *self) { POST_PROCESSING_REVAREVA };
+
+static void
+TrackHold_setProcMode(TrackHold *self)
+{
+    int procmode, muladdmode;
+    procmode = self->modebuffer[2];
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+	switch (procmode) {
+        case 0:
+            self->proc_func_ptr = TrackHold_filters_i;
+            break;
+        case 1:
+            self->proc_func_ptr = TrackHold_filters_a;
+            break;
+    }
+	switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = TrackHold_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = TrackHold_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = TrackHold_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = TrackHold_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = TrackHold_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = TrackHold_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = TrackHold_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = TrackHold_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = TrackHold_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+TrackHold_compute_next_data_frame(TrackHold *self)
+{
+    (*self->proc_func_ptr)(self);
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+TrackHold_traverse(TrackHold *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->input);
+    Py_VISIT(self->input_stream);
+    Py_VISIT(self->controlsig);
+    Py_VISIT(self->controlsig_stream);
+    Py_VISIT(self->value);
+    Py_VISIT(self->value_stream);
+    return 0;
+}
+
+static int
+TrackHold_clear(TrackHold *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->input);
+    Py_CLEAR(self->input_stream);
+    Py_CLEAR(self->controlsig);
+    Py_CLEAR(self->controlsig_stream);
+    Py_CLEAR(self->value);
+    Py_CLEAR(self->value_stream);
+    return 0;
+}
+
+static void
+TrackHold_dealloc(TrackHold* self)
+{
+    pyo_DEALLOC
+    TrackHold_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+TrackHold_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *inputtmp, *input_streamtmp, *controlsigtmp, *controlsig_streamtmp, *valuetmp=NULL, *multmp=NULL, *addtmp=NULL;
+    TrackHold *self;
+    self = (TrackHold *)type->tp_alloc(type, 0);
+
+    self->value = PyFloat_FromDouble(0.0);
+    self->currentValue = 0.0;
+    self->flag = 1;
+	self->modebuffer[0] = 0;
+	self->modebuffer[1] = 0;
+	self->modebuffer[2] = 0;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, TrackHold_compute_next_data_frame);
+    self->mode_func_ptr = TrackHold_setProcMode;
+
+    static char *kwlist[] = {"input", "controlsig", "value", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOO", kwlist, &inputtmp, &controlsigtmp, &valuetmp, &multmp, &addtmp))
+        Py_RETURN_NONE;
+
+    INIT_INPUT_STREAM
+
+    Py_XDECREF(self->controlsig);
+    self->controlsig = controlsigtmp;
+    controlsig_streamtmp = PyObject_CallMethod((PyObject *)self->controlsig, "_getStream", NULL);
+    Py_INCREF(controlsig_streamtmp);
+    Py_XDECREF(self->controlsig_stream);
+    self->controlsig_stream = (Stream *)controlsig_streamtmp;
+
+    if (valuetmp) {
+        PyObject_CallMethod((PyObject *)self, "setValue", "O", valuetmp);
+    }
+
+    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 * TrackHold_getServer(TrackHold* self) { GET_SERVER };
+static PyObject * TrackHold_getStream(TrackHold* self) { GET_STREAM };
+static PyObject * TrackHold_setMul(TrackHold *self, PyObject *arg) { SET_MUL };
+static PyObject * TrackHold_setAdd(TrackHold *self, PyObject *arg) { SET_ADD };
+static PyObject * TrackHold_setSub(TrackHold *self, PyObject *arg) { SET_SUB };
+static PyObject * TrackHold_setDiv(TrackHold *self, PyObject *arg) { SET_DIV };
+
+static PyObject * TrackHold_play(TrackHold *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * TrackHold_out(TrackHold *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * TrackHold_stop(TrackHold *self) { STOP };
+
+static PyObject * TrackHold_multiply(TrackHold *self, PyObject *arg) { MULTIPLY };
+static PyObject * TrackHold_inplace_multiply(TrackHold *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * TrackHold_add(TrackHold *self, PyObject *arg) { ADD };
+static PyObject * TrackHold_inplace_add(TrackHold *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * TrackHold_sub(TrackHold *self, PyObject *arg) { SUB };
+static PyObject * TrackHold_inplace_sub(TrackHold *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * TrackHold_div(TrackHold *self, PyObject *arg) { DIV };
+static PyObject * TrackHold_inplace_div(TrackHold *self, PyObject *arg) { INPLACE_DIV };
+
+static PyObject *
+TrackHold_setValue(TrackHold *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->value);
+	if (isNumber == 1) {
+		self->value = PyNumber_Float(tmp);
+        self->modebuffer[2] = 0;
+	}
+	else {
+		self->value = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->value, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->value_stream);
+        self->value_stream = (Stream *)streamtmp;
+		self->modebuffer[2] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyMemberDef TrackHold_members[] = {
+{"server", T_OBJECT_EX, offsetof(TrackHold, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(TrackHold, stream), 0, "Stream object."},
+{"input", T_OBJECT_EX, offsetof(TrackHold, input), 0, "Input sound object."},
+{"controlsig", T_OBJECT_EX, offsetof(TrackHold, controlsig), 0, "Control input object."},
+{"value", T_OBJECT_EX, offsetof(TrackHold, value), 0, "Trigger value."},
+{"mul", T_OBJECT_EX, offsetof(TrackHold, mul), 0, "Mul factor."},
+{"add", T_OBJECT_EX, offsetof(TrackHold, add), 0, "Add factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyMethodDef TrackHold_methods[] = {
+{"getServer", (PyCFunction)TrackHold_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)TrackHold_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)TrackHold_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"out", (PyCFunction)TrackHold_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+{"stop", (PyCFunction)TrackHold_stop, METH_NOARGS, "Stops computing."},
+{"setValue", (PyCFunction)TrackHold_setValue, METH_O, "Sets trigger value."},
+{"setMul", (PyCFunction)TrackHold_setMul, METH_O, "Sets oscillator mul factor."},
+{"setAdd", (PyCFunction)TrackHold_setAdd, METH_O, "Sets oscillator add factor."},
+{"setSub", (PyCFunction)TrackHold_setSub, METH_O, "Sets inverse add factor."},
+{"setDiv", (PyCFunction)TrackHold_setDiv, METH_O, "Sets inverse mul factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyNumberMethods TrackHold_as_number = {
+(binaryfunc)TrackHold_add,                         /*nb_add*/
+(binaryfunc)TrackHold_sub,                         /*nb_subtract*/
+(binaryfunc)TrackHold_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)TrackHold_inplace_add,                 /*inplace_add*/
+(binaryfunc)TrackHold_inplace_sub,                 /*inplace_subtract*/
+(binaryfunc)TrackHold_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)TrackHold_div,                       /*nb_true_divide*/
+0,                                              /*nb_inplace_floor_divide*/
+(binaryfunc)TrackHold_inplace_div,                       /*nb_inplace_true_divide*/
+0,                                              /* nb_index */
+};
+
+PyTypeObject TrackHoldType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.TrackHold_base",                                   /*tp_name*/
+sizeof(TrackHold),                                 /*tp_basicsize*/
+0,                                              /*tp_itemsize*/
+(destructor)TrackHold_dealloc,                     /*tp_dealloc*/
+0,                                              /*tp_print*/
+0,                                              /*tp_getattr*/
+0,                                              /*tp_setattr*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
+0,                                              /*tp_repr*/
+&TrackHold_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*/
+"TrackHold objects. Let pass and freeze an audio stream.",           /* tp_doc */
+(traverseproc)TrackHold_traverse,                  /* tp_traverse */
+(inquiry)TrackHold_clear,                          /* tp_clear */
+0,                                              /* tp_richcompare */
+0,                                              /* tp_weaklistoffset */
+0,                                              /* tp_iter */
+0,                                              /* tp_iternext */
+TrackHold_methods,                                 /* tp_methods */
+TrackHold_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 */
+TrackHold_new,                                     /* tp_new */
+};
+
+/************/
+/* Compare */
+/************/
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *input;
+    Stream *input_stream;
+    PyObject *comp;
+    Stream *comp_stream;
+    MYFLT (*compare_func_ptr)(MYFLT, MYFLT); // true = 1.0, false = 0.0
+    int modebuffer[3]; // need at least 2 slots for mul & add
+} Compare;
+
+static MYFLT
+Compare_lt(MYFLT in, MYFLT comp) {
+    if (in < comp) { return 1.0; }
+    else { return 0.0; }
+}
+
+static MYFLT
+Compare_elt(MYFLT in, MYFLT comp) {
+    if (in <= comp) { return 1.0; }
+    else { return 0.0; }
+}
+
+static MYFLT
+Compare_gt(MYFLT in, MYFLT comp) {
+    if (in > comp) { return 1.0; }
+    else { return 0.0; }
+}
+
+static MYFLT
+Compare_egt(MYFLT in, MYFLT comp) {
+    if (in >= comp) { return 1.0; }
+    else { return 0.0; }
+}
+
+static MYFLT
+Compare_eq(MYFLT in, MYFLT comp) {
+    if (in >= (comp - 0.0001) && in <= (comp + 0.0001)) { return 1.0; }
+    else { return 0.0; }
+}
+
+static MYFLT
+Compare_neq(MYFLT in, MYFLT comp) {
+    if (in <= (comp - 0.0001) || in >= (comp + 0.0001)) { return 1.0; }
+    else { return 0.0; }
+}
+
+static void
+Compare_process_i(Compare *self) {
+    int i;
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+    MYFLT comp = PyFloat_AS_DOUBLE(self->comp);
+
+    for (i=0; i<self->bufsize; i++) {
+        self->data[i] = (*self->compare_func_ptr)(in[i], comp);
+    }
+}
+
+static void
 Compare_process_a(Compare *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *comp = Stream_getData((Stream *)self->comp_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = (*self->compare_func_ptr)(in[i], comp[i]);
     }
@@ -1479,50 +1822,50 @@ Compare_setProcMode(Compare *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2];
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Compare_process_i;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Compare_process_a;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Compare_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Compare_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Compare_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Compare_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Compare_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Compare_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Compare_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Compare_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Compare_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Compare_compute_next_data_frame(Compare *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1537,7 +1880,7 @@ Compare_traverse(Compare *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Compare_clear(Compare *self)
 {
     pyo_CLEAR
@@ -1553,7 +1896,7 @@ Compare_dealloc(Compare* self)
 {
     pyo_DEALLOC
     Compare_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1563,42 +1906,42 @@ Compare_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *comptmp, *modetmp=NULL, *multmp=NULL, *addtmp=NULL;
     Compare *self;
     self = (Compare *)type->tp_alloc(type, 0);
-    
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
-    
+
     self->compare_func_ptr = Compare_lt;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Compare_compute_next_data_frame);
     self->mode_func_ptr = Compare_setProcMode;
 
     static char *kwlist[] = {"input", "comp", "mode", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "OO|OOO", kwlist, &inputtmp, &comptmp, &modetmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (comptmp) {
         PyObject_CallMethod((PyObject *)self, "setComp", "O", comptmp);
     }
-    
+
     if (modetmp) {
         PyObject_CallMethod((PyObject *)self, "setMode", "O", modetmp);
     }
-    
+
     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;
@@ -1606,10 +1949,10 @@ Compare_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Compare_getServer(Compare* self) { GET_SERVER };
 static PyObject * Compare_getStream(Compare* self) { GET_STREAM };
-static PyObject * Compare_setMul(Compare *self, PyObject *arg) { SET_MUL };	
-static PyObject * Compare_setAdd(Compare *self, PyObject *arg) { SET_ADD };	
-static PyObject * Compare_setSub(Compare *self, PyObject *arg) { SET_SUB };	
-static PyObject * Compare_setDiv(Compare *self, PyObject *arg) { SET_DIV };	
+static PyObject * Compare_setMul(Compare *self, PyObject *arg) { SET_MUL };
+static PyObject * Compare_setAdd(Compare *self, PyObject *arg) { SET_ADD };
+static PyObject * Compare_setSub(Compare *self, PyObject *arg) { SET_SUB };
+static PyObject * Compare_setDiv(Compare *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Compare_play(Compare *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Compare_stop(Compare *self) { STOP };
@@ -1627,13 +1970,11 @@ static PyObject *
 Compare_setComp(Compare *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-    
-	if (arg == NULL) {
-		Py_RETURN_NONE;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_XDECREF(self->comp);
@@ -1649,27 +1990,25 @@ Compare_setComp(Compare *self, PyObject *arg)
         self->comp_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
 
 static PyObject *
 Compare_setMode(Compare *self, PyObject *arg)
-{	
-	if (arg == NULL) {
-		Py_RETURN_NONE;
-	}
-    
+{
+    ASSERT_ARG_NOT_NULL
+
 	if (! PyInt_Check(arg)) {
-        printf("mode should be a comparison operator as a string\n");
+        PySys_WriteStdout("Compare: mode attribute should be a comparison operator as a string\n");
 		Py_RETURN_NONE;
     }
 
     int tmp = PyInt_AsLong(arg);
-    
+
     if (tmp == 0)
         self->compare_func_ptr = Compare_lt;
     else if (tmp == 1)
@@ -1682,7 +2021,7 @@ Compare_setMode(Compare *self, PyObject *arg)
         self->compare_func_ptr = Compare_eq;
     else if (tmp == 5)
         self->compare_func_ptr = Compare_neq;
-    
+
     Py_RETURN_NONE;
 }
 
@@ -1714,7 +2053,7 @@ static PyNumberMethods Compare_as_number = {
 (binaryfunc)Compare_add,                         /*nb_add*/
 (binaryfunc)Compare_sub,                         /*nb_subtract*/
 (binaryfunc)Compare_multiply,                    /*nb_multiply*/
-(binaryfunc)Compare_div,                         /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO  /*nb_divide*/
 0,                                              /*nb_remainder*/
 0,                                              /*nb_divmod*/
 0,                                              /*nb_power*/
@@ -1728,16 +2067,16 @@ static PyNumberMethods Compare_as_number = {
 0,                                              /*nb_and*/
 0,                                              /*nb_xor*/
 0,                                              /*nb_or*/
-0,                                              /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
 0,                                              /*nb_int*/
 0,                                              /*nb_long*/
 0,                                              /*nb_float*/
-0,                                              /*nb_oct*/
-0,                                              /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
 (binaryfunc)Compare_inplace_add,                 /*inplace_add*/
 (binaryfunc)Compare_inplace_sub,                 /*inplace_subtract*/
 (binaryfunc)Compare_inplace_multiply,            /*inplace_multiply*/
-(binaryfunc)Compare_inplace_div,                 /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO              /*inplace_divide*/
 0,                                              /*inplace_remainder*/
 0,                                              /*inplace_power*/
 0,                                              /*inplace_lshift*/
@@ -1746,15 +2085,14 @@ static PyNumberMethods Compare_as_number = {
 0,                                              /*inplace_xor*/
 0,                                              /*inplace_or*/
 0,                                              /*nb_floor_divide*/
-0,                                              /*nb_true_divide*/
+(binaryfunc)Compare_div,                       /*nb_true_divide*/
 0,                                              /*nb_inplace_floor_divide*/
-0,                                              /*nb_inplace_true_divide*/
+(binaryfunc)Compare_inplace_div,                       /*nb_inplace_true_divide*/
 0,                                              /* nb_index */
 };
 
 PyTypeObject CompareType = {
-PyObject_HEAD_INIT(NULL)
-0,                                              /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.Compare_base",                                   /*tp_name*/
 sizeof(Compare),                                 /*tp_basicsize*/
 0,                                              /*tp_itemsize*/
@@ -1762,7 +2100,7 @@ sizeof(Compare),                                 /*tp_basicsize*/
 0,                                              /*tp_print*/
 0,                                              /*tp_getattr*/
 0,                                              /*tp_setattr*/
-0,                                              /*tp_compare*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
 0,                                              /*tp_repr*/
 &Compare_as_number,                              /*tp_as_number*/
 0,                                              /*tp_as_sequence*/
@@ -1816,7 +2154,7 @@ Between_transform_ii(Between *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT mi = PyFloat_AS_DOUBLE(self->min);
     MYFLT ma = PyFloat_AS_DOUBLE(self->max);
-    
+
     for (i=0; i<self->bufsize; i++) {
         val = in[i];
         if(val >= mi && val < ma)
@@ -1833,7 +2171,7 @@ Between_transform_ai(Between *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *mi = Stream_getData((Stream *)self->min_stream);
     MYFLT ma = PyFloat_AS_DOUBLE(self->max);
-    
+
     for (i=0; i<self->bufsize; i++) {
         val = in[i];
         if(val >= mi[i] && val < ma)
@@ -1850,7 +2188,7 @@ Between_transform_ia(Between *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT mi = PyFloat_AS_DOUBLE(self->min);
     MYFLT *ma = Stream_getData((Stream *)self->max_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         val = in[i];
         if(val >= mi && val < ma[i])
@@ -1867,7 +2205,7 @@ Between_transform_aa(Between *self) {
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *mi = Stream_getData((Stream *)self->min_stream);
     MYFLT *ma = Stream_getData((Stream *)self->max_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         val = in[i];
         if(val >= mi[i] && val < ma[i])
@@ -1893,56 +2231,56 @@ Between_setProcMode(Between *self)
     int procmode, muladdmode;
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = Between_transform_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = Between_transform_ai;
             break;
-        case 10:        
+        case 10:
             self->proc_func_ptr = Between_transform_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = Between_transform_aa;
             break;
-    } 
+    }
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Between_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Between_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Between_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Between_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Between_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Between_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Between_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Between_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Between_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Between_compute_next_data_frame(Between *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -1951,24 +2289,24 @@ Between_traverse(Between *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->input);
-    Py_VISIT(self->input_stream);    
-    Py_VISIT(self->min);    
-    Py_VISIT(self->min_stream);    
-    Py_VISIT(self->max);    
-    Py_VISIT(self->max_stream);    
+    Py_VISIT(self->input_stream);
+    Py_VISIT(self->min);
+    Py_VISIT(self->min_stream);
+    Py_VISIT(self->max);
+    Py_VISIT(self->max_stream);
     return 0;
 }
 
-static int 
+static int
 Between_clear(Between *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
     Py_CLEAR(self->input_stream);
-    Py_CLEAR(self->min);    
-    Py_CLEAR(self->min_stream);    
-    Py_CLEAR(self->max);    
-    Py_CLEAR(self->max_stream);    
+    Py_CLEAR(self->min);
+    Py_CLEAR(self->min_stream);
+    Py_CLEAR(self->max);
+    Py_CLEAR(self->max_stream);
     return 0;
 }
 
@@ -1977,7 +2315,7 @@ Between_dealloc(Between* self)
 {
     pyo_DEALLOC
     Between_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -1987,54 +2325,54 @@ Between_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *mintmp=NULL, *maxtmp=NULL, *multmp=NULL, *addtmp=NULL;
     Between *self;
     self = (Between *)type->tp_alloc(type, 0);
-    
+
     self->min = PyFloat_FromDouble(0.0);
     self->max = PyFloat_FromDouble(1.0);
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Between_compute_next_data_frame);
     self->mode_func_ptr = Between_setProcMode;
 
     static char *kwlist[] = {"input", "min", "max", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOO", kwlist, &inputtmp, &mintmp, &maxtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (mintmp) {
         PyObject_CallMethod((PyObject *)self, "setMin", "O", mintmp);
     }
-    
+
     if (maxtmp) {
         PyObject_CallMethod((PyObject *)self, "setMax", "O", maxtmp);
     }
-    
+
     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 * Between_getServer(Between* self) { GET_SERVER };
 static PyObject * Between_getStream(Between* self) { GET_STREAM };
-static PyObject * Between_setMul(Between *self, PyObject *arg) { SET_MUL };	
-static PyObject * Between_setAdd(Between *self, PyObject *arg) { SET_ADD };	
-static PyObject * Between_setSub(Between *self, PyObject *arg) { SET_SUB };	
-static PyObject * Between_setDiv(Between *self, PyObject *arg) { SET_DIV };	
+static PyObject * Between_setMul(Between *self, PyObject *arg) { SET_MUL };
+static PyObject * Between_setAdd(Between *self, PyObject *arg) { SET_ADD };
+static PyObject * Between_setSub(Between *self, PyObject *arg) { SET_SUB };
+static PyObject * Between_setDiv(Between *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Between_play(Between *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Between_out(Between *self, PyObject *args, PyObject *kwds) { OUT };
@@ -2053,14 +2391,11 @@ static PyObject *
 Between_setMin(Between *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->min);
@@ -2076,25 +2411,22 @@ Between_setMin(Between *self, PyObject *arg)
         self->min_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Between_setMax(Between *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->max);
@@ -2110,12 +2442,12 @@ Between_setMax(Between *self, PyObject *arg)
         self->max_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Between_members[] = {
     {"server", T_OBJECT_EX, offsetof(Between, server), 0, "Pyo server."},
@@ -2147,7 +2479,7 @@ static PyNumberMethods Between_as_number = {
     (binaryfunc)Between_add,                      /*nb_add*/
     (binaryfunc)Between_sub,                 /*nb_subtract*/
     (binaryfunc)Between_multiply,                 /*nb_multiply*/
-    (binaryfunc)Between_div,                   /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
     0,                /*nb_remainder*/
     0,                   /*nb_divmod*/
     0,                   /*nb_power*/
@@ -2161,16 +2493,16 @@ static PyNumberMethods Between_as_number = {
     0,              /*nb_and*/
     0,              /*nb_xor*/
     0,               /*nb_or*/
-    0,                                          /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
     0,                       /*nb_int*/
     0,                      /*nb_long*/
     0,                     /*nb_float*/
-    0,                       /*nb_oct*/
-    0,                       /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
     (binaryfunc)Between_inplace_add,              /*inplace_add*/
     (binaryfunc)Between_inplace_sub,         /*inplace_subtract*/
     (binaryfunc)Between_inplace_multiply,         /*inplace_multiply*/
-    (binaryfunc)Between_inplace_div,           /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
     0,        /*inplace_remainder*/
     0,           /*inplace_power*/
     0,       /*inplace_lshift*/
@@ -2179,15 +2511,14 @@ static PyNumberMethods Between_as_number = {
     0,      /*inplace_xor*/
     0,       /*inplace_or*/
     0,             /*nb_floor_divide*/
-    0,              /*nb_true_divide*/
+    (binaryfunc)Between_div,                       /*nb_true_divide*/
     0,     /*nb_inplace_floor_divide*/
-    0,      /*nb_inplace_true_divide*/
+    (binaryfunc)Between_inplace_div,                       /*nb_inplace_true_divide*/
     0,                     /* nb_index */
 };
 
 PyTypeObject BetweenType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                         /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Between_base",         /*tp_name*/
     sizeof(Between),         /*tp_basicsize*/
     0,                         /*tp_itemsize*/
@@ -2195,7 +2526,7 @@ PyTypeObject BetweenType = {
     0,                         /*tp_print*/
     0,                         /*tp_getattr*/
     0,                         /*tp_setattr*/
-    0,                         /*tp_compare*/
+    0,                         /*tp_as_async (tp_compare in Python 2)*/
     0,                         /*tp_repr*/
     &Between_as_number,             /*tp_as_number*/
     0,                         /*tp_as_sequence*/
@@ -2232,23 +2563,23 @@ PyTypeObject BetweenType = {
 /* Denorm */
 /************/
 #ifndef USE_DOUBLE
-#define DENORM_RAND  ((MYFLT) ((rand()/((MYFLT)(RAND_MAX)*0.5+1) - 1.0) * (MYFLT)(1.0e-24)))
+#define DENORM_RAND  ((MYFLT) ((pyorand()/((MYFLT)(PYO_RAND_MAX)*0.5+1) - 1.0) * (MYFLT)(1.0e-24)))
 #else
-#define DENORM_RAND  ((MYFLT) ((rand()/((MYFLT)(RAND_MAX)*0.5+1) - 1.0) * (MYFLT)(1.0e-60)))
+#define DENORM_RAND  ((MYFLT) ((pyorand()/((MYFLT)(PYO_RAND_MAX)*0.5+1) - 1.0) * (MYFLT)(1.0e-60)))
 #endif
 
 typedef struct {
     pyo_audio_HEAD
     PyObject *input;
     Stream *input_stream;
-    int modebuffer[2]; // need at least 2 slots for mul & add 
+    int modebuffer[2]; // need at least 2 slots for mul & add
 } Denorm;
 
 static void
 Denorm_filters(Denorm *self) {
     int i;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         self->data[i] = in[i] + DENORM_RAND;
     }
@@ -2269,44 +2600,44 @@ Denorm_setProcMode(Denorm *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = Denorm_filters;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Denorm_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Denorm_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Denorm_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Denorm_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Denorm_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Denorm_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Denorm_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Denorm_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Denorm_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 Denorm_compute_next_data_frame(Denorm *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -2319,7 +2650,7 @@ Denorm_traverse(Denorm *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Denorm_clear(Denorm *self)
 {
     pyo_CLEAR
@@ -2333,7 +2664,7 @@ Denorm_dealloc(Denorm* self)
 {
     pyo_DEALLOC
     Denorm_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2343,31 +2674,31 @@ Denorm_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     Denorm *self;
     self = (Denorm *)type->tp_alloc(type, 0);
-    
+
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Denorm_compute_next_data_frame);
     self->mode_func_ptr = Denorm_setProcMode;
 
     static char *kwlist[] = {"input", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     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);
-    
+
     Server_generateSeed((Server *)self->server, DENORM_ID);
 
     (*self->mode_func_ptr)(self);
@@ -2377,10 +2708,10 @@ Denorm_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Denorm_getServer(Denorm* self) { GET_SERVER };
 static PyObject * Denorm_getStream(Denorm* self) { GET_STREAM };
-static PyObject * Denorm_setMul(Denorm *self, PyObject *arg) { SET_MUL };	
-static PyObject * Denorm_setAdd(Denorm *self, PyObject *arg) { SET_ADD };	
-static PyObject * Denorm_setSub(Denorm *self, PyObject *arg) { SET_SUB };	
-static PyObject * Denorm_setDiv(Denorm *self, PyObject *arg) { SET_DIV };	
+static PyObject * Denorm_setMul(Denorm *self, PyObject *arg) { SET_MUL };
+static PyObject * Denorm_setAdd(Denorm *self, PyObject *arg) { SET_ADD };
+static PyObject * Denorm_setSub(Denorm *self, PyObject *arg) { SET_SUB };
+static PyObject * Denorm_setDiv(Denorm *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Denorm_play(Denorm *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Denorm_out(Denorm *self, PyObject *args, PyObject *kwds) { OUT };
@@ -2421,7 +2752,7 @@ static PyNumberMethods Denorm_as_number = {
     (binaryfunc)Denorm_add,                         /*nb_add*/
     (binaryfunc)Denorm_sub,                         /*nb_subtract*/
     (binaryfunc)Denorm_multiply,                    /*nb_multiply*/
-    (binaryfunc)Denorm_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -2435,16 +2766,16 @@ static PyNumberMethods Denorm_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Denorm_inplace_add,                 /*inplace_add*/
     (binaryfunc)Denorm_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Denorm_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Denorm_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -2453,15 +2784,14 @@ static PyNumberMethods Denorm_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Denorm_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Denorm_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject DenormType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Denorm_base",                                   /*tp_name*/
     sizeof(Denorm),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -2469,7 +2799,7 @@ PyTypeObject DenormType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &Denorm_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -2518,7 +2848,7 @@ DBToA_process(DBToA *self) {
     int i;
     MYFLT db;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         db = in[i];
         if (db <= -120.0) {
@@ -2549,44 +2879,44 @@ DBToA_setProcMode(DBToA *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = DBToA_process;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = DBToA_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = DBToA_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = DBToA_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = DBToA_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = DBToA_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = DBToA_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = DBToA_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = DBToA_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = DBToA_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 DBToA_compute_next_data_frame(DBToA *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -2599,7 +2929,7 @@ DBToA_traverse(DBToA *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 DBToA_clear(DBToA *self)
 {
     pyo_CLEAR
@@ -2613,7 +2943,7 @@ DBToA_dealloc(DBToA* self)
 {
     pyo_DEALLOC
     DBToA_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2623,33 +2953,33 @@ DBToA_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     DBToA *self;
     self = (DBToA *)type->tp_alloc(type, 0);
-    
+
     self->lastdb = -120.0;
     self->currentamp = MYPOW(10.0, self->lastdb * 0.05);
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, DBToA_compute_next_data_frame);
     self->mode_func_ptr = DBToA_setProcMode;
 
     static char *kwlist[] = {"input", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     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;
@@ -2657,10 +2987,10 @@ DBToA_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * DBToA_getServer(DBToA* self) { GET_SERVER };
 static PyObject * DBToA_getStream(DBToA* self) { GET_STREAM };
-static PyObject * DBToA_setMul(DBToA *self, PyObject *arg) { SET_MUL };	
-static PyObject * DBToA_setAdd(DBToA *self, PyObject *arg) { SET_ADD };	
-static PyObject * DBToA_setSub(DBToA *self, PyObject *arg) { SET_SUB };	
-static PyObject * DBToA_setDiv(DBToA *self, PyObject *arg) { SET_DIV };	
+static PyObject * DBToA_setMul(DBToA *self, PyObject *arg) { SET_MUL };
+static PyObject * DBToA_setAdd(DBToA *self, PyObject *arg) { SET_ADD };
+static PyObject * DBToA_setSub(DBToA *self, PyObject *arg) { SET_SUB };
+static PyObject * DBToA_setDiv(DBToA *self, PyObject *arg) { SET_DIV };
 
 static PyObject * DBToA_play(DBToA *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * DBToA_out(DBToA *self, PyObject *args, PyObject *kwds) { OUT };
@@ -2701,7 +3031,7 @@ static PyNumberMethods DBToA_as_number = {
     (binaryfunc)DBToA_add,                         /*nb_add*/
     (binaryfunc)DBToA_sub,                         /*nb_subtract*/
     (binaryfunc)DBToA_multiply,                    /*nb_multiply*/
-    (binaryfunc)DBToA_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -2715,16 +3045,16 @@ static PyNumberMethods DBToA_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)DBToA_inplace_add,                 /*inplace_add*/
     (binaryfunc)DBToA_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)DBToA_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)DBToA_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -2733,15 +3063,14 @@ static PyNumberMethods DBToA_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)DBToA_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)DBToA_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject DBToAType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.DBToA_base",                                   /*tp_name*/
     sizeof(DBToA),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -2749,7 +3078,7 @@ PyTypeObject DBToAType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &DBToA_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -2798,7 +3127,7 @@ AToDB_process(AToDB *self) {
     int i;
     MYFLT amp;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         amp = in[i];
         if (amp <= 0.000001) {
@@ -2829,44 +3158,44 @@ AToDB_setProcMode(AToDB *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = AToDB_process;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = AToDB_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = AToDB_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = AToDB_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = AToDB_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = AToDB_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = AToDB_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = AToDB_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = AToDB_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = AToDB_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 AToDB_compute_next_data_frame(AToDB *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -2879,7 +3208,7 @@ AToDB_traverse(AToDB *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 AToDB_clear(AToDB *self)
 {
     pyo_CLEAR
@@ -2893,7 +3222,7 @@ AToDB_dealloc(AToDB* self)
 {
     pyo_DEALLOC
     AToDB_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -2903,33 +3232,33 @@ AToDB_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     AToDB *self;
     self = (AToDB *)type->tp_alloc(type, 0);
-    
+
     self->lastamp = 0.000001;
     self->currentdb = 20.0 * MYLOG10(self->lastamp);
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, AToDB_compute_next_data_frame);
     self->mode_func_ptr = AToDB_setProcMode;
 
     static char *kwlist[] = {"input", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     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;
@@ -2937,10 +3266,10 @@ AToDB_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * AToDB_getServer(AToDB* self) { GET_SERVER };
 static PyObject * AToDB_getStream(AToDB* self) { GET_STREAM };
-static PyObject * AToDB_setMul(AToDB *self, PyObject *arg) { SET_MUL };	
-static PyObject * AToDB_setAdd(AToDB *self, PyObject *arg) { SET_ADD };	
-static PyObject * AToDB_setSub(AToDB *self, PyObject *arg) { SET_SUB };	
-static PyObject * AToDB_setDiv(AToDB *self, PyObject *arg) { SET_DIV };	
+static PyObject * AToDB_setMul(AToDB *self, PyObject *arg) { SET_MUL };
+static PyObject * AToDB_setAdd(AToDB *self, PyObject *arg) { SET_ADD };
+static PyObject * AToDB_setSub(AToDB *self, PyObject *arg) { SET_SUB };
+static PyObject * AToDB_setDiv(AToDB *self, PyObject *arg) { SET_DIV };
 
 static PyObject * AToDB_play(AToDB *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * AToDB_out(AToDB *self, PyObject *args, PyObject *kwds) { OUT };
@@ -2981,7 +3310,7 @@ static PyNumberMethods AToDB_as_number = {
     (binaryfunc)AToDB_add,                         /*nb_add*/
     (binaryfunc)AToDB_sub,                         /*nb_subtract*/
     (binaryfunc)AToDB_multiply,                    /*nb_multiply*/
-    (binaryfunc)AToDB_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -2995,16 +3324,16 @@ static PyNumberMethods AToDB_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)AToDB_inplace_add,                 /*inplace_add*/
     (binaryfunc)AToDB_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)AToDB_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)AToDB_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -3013,15 +3342,14 @@ static PyNumberMethods AToDB_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)AToDB_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)AToDB_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject AToDBType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.AToDB_base",                                   /*tp_name*/
     sizeof(AToDB),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -3029,7 +3357,7 @@ PyTypeObject AToDBType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &AToDB_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -3078,7 +3406,7 @@ typedef struct {
     Stream *outmax_stream;
     PyObject *exp;
     Stream *exp_stream;
-    int modebuffer[7]; // need at least 2 slots for mul & add 
+    int modebuffer[7]; // need at least 2 slots for mul & add
 } Scale;
 
 static MYFLT
@@ -3097,7 +3425,7 @@ Scale_generate(Scale *self) {
     MYFLT tmp, inrange, outrange, normin;
     MYFLT inmin, inmax, outmin, outmax, exp;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (self->modebuffer[2] == 0)
         inmin = PyFloat_AS_DOUBLE(self->inmin);
     else
@@ -3106,7 +3434,7 @@ Scale_generate(Scale *self) {
         inmax = PyFloat_AS_DOUBLE(self->inmax);
     else
         inmax = Stream_getData((Stream *)self->inmax_stream)[0];
-    
+
     if (inmin < inmax) {
         inrev = 0;
     }
@@ -3126,7 +3454,7 @@ Scale_generate(Scale *self) {
         outmax = PyFloat_AS_DOUBLE(self->outmax);
     else
         outmax = Stream_getData((Stream *)self->outmax_stream)[0];
-    
+
     if (outmin < outmax) {
         outrev = 0;
     }
@@ -3137,7 +3465,7 @@ Scale_generate(Scale *self) {
         outrev = 1;
     }
     outrange = outmax - outmin;
-    
+
     if (self->modebuffer[6] == 0)
         exp = PyFloat_AS_DOUBLE(self->exp);
     else
@@ -3157,7 +3485,7 @@ Scale_generate(Scale *self) {
             for (i=0; i<self->bufsize; i++) {
                 normin = (_scale_clip(in[i], inmin, inmax) - inmin) / inrange;
                 self->data[i] = normin * outrange + outmin;
-            }            
+            }
         }
         else if (inrev == 1 && outrev == 0) {
             for (i=0; i<self->bufsize; i++) {
@@ -3184,7 +3512,7 @@ Scale_generate(Scale *self) {
             for (i=0; i<self->bufsize; i++) {
                 normin = MYPOW((_scale_clip(in[i], inmin, inmax) - inmin) / inrange, exp);
                 self->data[i] = normin * outrange + outmin;
-            }            
+            }
         }
         else if (inrev == 1 && outrev == 0) {
             for (i=0; i<self->bufsize; i++) {
@@ -3222,44 +3550,44 @@ Scale_setProcMode(Scale *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = Scale_generate;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = Scale_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = Scale_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = Scale_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = Scale_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = Scale_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = Scale_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = Scale_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = Scale_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = Scale_postprocessing_revareva;
             break;
-    }  
+    }
 }
 
 static void
 Scale_compute_next_data_frame(Scale *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -3282,7 +3610,7 @@ Scale_traverse(Scale *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 Scale_clear(Scale *self)
 {
     pyo_CLEAR
@@ -3306,7 +3634,7 @@ Scale_dealloc(Scale* self)
 {
     pyo_DEALLOC
     Scale_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -3316,7 +3644,7 @@ Scale_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *inmintmp=NULL, *inmaxtmp=NULL, *outmintmp=NULL, *outmaxtmp=NULL, *exptmp=NULL, *multmp=NULL, *addtmp=NULL;
     Scale *self;
     self = (Scale *)type->tp_alloc(type, 0);
-    
+
     self->inmin = PyFloat_FromDouble(0.0);
     self->inmax = PyFloat_FromDouble(1.0);
     self->outmin = PyFloat_FromDouble(0.0);
@@ -3329,18 +3657,18 @@ Scale_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     self->modebuffer[4] = 0;
     self->modebuffer[5] = 0;
     self->modebuffer[6] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, Scale_compute_next_data_frame);
     self->mode_func_ptr = Scale_setProcMode;
 
     static char *kwlist[] = {"input", "inmin", "inmax", "outmin", "outmax", "exp", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOOOOO", kwlist, &inputtmp, &inmintmp, &inmaxtmp, &outmintmp, &outmaxtmp, &exptmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     if (inmintmp) {
         PyObject_CallMethod((PyObject *)self, "setInMin", "O", inmintmp);
     }
@@ -3360,17 +3688,17 @@ Scale_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (exptmp) {
         PyObject_CallMethod((PyObject *)self, "setExp", "O", exptmp);
     }
-    
+
     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;
@@ -3378,10 +3706,10 @@ Scale_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * Scale_getServer(Scale* self) { GET_SERVER };
 static PyObject * Scale_getStream(Scale* self) { GET_STREAM };
-static PyObject * Scale_setMul(Scale *self, PyObject *arg) { SET_MUL };	
-static PyObject * Scale_setAdd(Scale *self, PyObject *arg) { SET_ADD };	
-static PyObject * Scale_setSub(Scale *self, PyObject *arg) { SET_SUB };	
-static PyObject * Scale_setDiv(Scale *self, PyObject *arg) { SET_DIV };	
+static PyObject * Scale_setMul(Scale *self, PyObject *arg) { SET_MUL };
+static PyObject * Scale_setAdd(Scale *self, PyObject *arg) { SET_ADD };
+static PyObject * Scale_setSub(Scale *self, PyObject *arg) { SET_SUB };
+static PyObject * Scale_setDiv(Scale *self, PyObject *arg) { SET_DIV };
 
 static PyObject * Scale_play(Scale *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * Scale_out(Scale *self, PyObject *args, PyObject *kwds) { OUT };
@@ -3400,14 +3728,11 @@ static PyObject *
 Scale_setInMin(Scale *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->inmin);
@@ -3423,25 +3748,22 @@ Scale_setInMin(Scale *self, PyObject *arg)
         self->inmin_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Scale_setInMax(Scale *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->inmax);
@@ -3457,25 +3779,22 @@ Scale_setInMax(Scale *self, PyObject *arg)
         self->inmax_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Scale_setOutMin(Scale *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->outmin);
@@ -3491,25 +3810,22 @@ Scale_setOutMin(Scale *self, PyObject *arg)
         self->outmin_stream = (Stream *)streamtmp;
 		self->modebuffer[4] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Scale_setOutMax(Scale *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->outmax);
@@ -3525,25 +3841,22 @@ Scale_setOutMax(Scale *self, PyObject *arg)
         self->outmax_stream = (Stream *)streamtmp;
 		self->modebuffer[5] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 Scale_setExp(Scale *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->exp);
@@ -3559,12 +3872,12 @@ Scale_setExp(Scale *self, PyObject *arg)
         self->exp_stream = (Stream *)streamtmp;
 		self->modebuffer[6] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef Scale_members[] = {
     {"server", T_OBJECT_EX, offsetof(Scale, server), 0, "Pyo server."},
@@ -3597,7 +3910,7 @@ static PyNumberMethods Scale_as_number = {
     (binaryfunc)Scale_add,                         /*nb_add*/
     (binaryfunc)Scale_sub,                         /*nb_subtract*/
     (binaryfunc)Scale_multiply,                    /*nb_multiply*/
-    (binaryfunc)Scale_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -3611,16 +3924,16 @@ static PyNumberMethods Scale_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)Scale_inplace_add,                 /*inplace_add*/
     (binaryfunc)Scale_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)Scale_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)Scale_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -3629,15 +3942,14 @@ static PyNumberMethods Scale_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)Scale_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)Scale_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject ScaleType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.Scale_base",                                   /*tp_name*/
     sizeof(Scale),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -3645,7 +3957,7 @@ PyTypeObject ScaleType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &Scale_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -3694,7 +4006,7 @@ CentsToTranspo_process(CentsToTranspo *self) {
     int i;
     MYFLT cents;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         cents = in[i];
         if (cents != self->lastcents) {
@@ -3721,44 +4033,44 @@ CentsToTranspo_setProcMode(CentsToTranspo *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = CentsToTranspo_process;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = CentsToTranspo_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = CentsToTranspo_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = CentsToTranspo_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = CentsToTranspo_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = CentsToTranspo_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = CentsToTranspo_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = CentsToTranspo_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = CentsToTranspo_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = CentsToTranspo_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 CentsToTranspo_compute_next_data_frame(CentsToTranspo *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -3771,7 +4083,7 @@ CentsToTranspo_traverse(CentsToTranspo *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 CentsToTranspo_clear(CentsToTranspo *self)
 {
     pyo_CLEAR
@@ -3785,7 +4097,7 @@ CentsToTranspo_dealloc(CentsToTranspo* self)
 {
     pyo_DEALLOC
     CentsToTranspo_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -3795,33 +4107,33 @@ CentsToTranspo_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     CentsToTranspo *self;
     self = (CentsToTranspo *)type->tp_alloc(type, 0);
-    
+
     self->lastcents = 0.0;
     self->curtranspo = 1.0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, CentsToTranspo_compute_next_data_frame);
     self->mode_func_ptr = CentsToTranspo_setProcMode;
 
     static char *kwlist[] = {"input", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     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;
@@ -3829,10 +4141,10 @@ CentsToTranspo_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * CentsToTranspo_getServer(CentsToTranspo* self) { GET_SERVER };
 static PyObject * CentsToTranspo_getStream(CentsToTranspo* self) { GET_STREAM };
-static PyObject * CentsToTranspo_setMul(CentsToTranspo *self, PyObject *arg) { SET_MUL };	
-static PyObject * CentsToTranspo_setAdd(CentsToTranspo *self, PyObject *arg) { SET_ADD };	
-static PyObject * CentsToTranspo_setSub(CentsToTranspo *self, PyObject *arg) { SET_SUB };	
-static PyObject * CentsToTranspo_setDiv(CentsToTranspo *self, PyObject *arg) { SET_DIV };	
+static PyObject * CentsToTranspo_setMul(CentsToTranspo *self, PyObject *arg) { SET_MUL };
+static PyObject * CentsToTranspo_setAdd(CentsToTranspo *self, PyObject *arg) { SET_ADD };
+static PyObject * CentsToTranspo_setSub(CentsToTranspo *self, PyObject *arg) { SET_SUB };
+static PyObject * CentsToTranspo_setDiv(CentsToTranspo *self, PyObject *arg) { SET_DIV };
 
 static PyObject * CentsToTranspo_play(CentsToTranspo *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * CentsToTranspo_out(CentsToTranspo *self, PyObject *args, PyObject *kwds) { OUT };
@@ -3873,7 +4185,7 @@ static PyNumberMethods CentsToTranspo_as_number = {
     (binaryfunc)CentsToTranspo_add,                         /*nb_add*/
     (binaryfunc)CentsToTranspo_sub,                         /*nb_subtract*/
     (binaryfunc)CentsToTranspo_multiply,                    /*nb_multiply*/
-    (binaryfunc)CentsToTranspo_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -3887,16 +4199,16 @@ static PyNumberMethods CentsToTranspo_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)CentsToTranspo_inplace_add,                 /*inplace_add*/
     (binaryfunc)CentsToTranspo_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)CentsToTranspo_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)CentsToTranspo_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -3905,15 +4217,14 @@ static PyNumberMethods CentsToTranspo_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)CentsToTranspo_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)CentsToTranspo_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject CentsToTranspoType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.CentsToTranspo_base",                                   /*tp_name*/
     sizeof(CentsToTranspo),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -3921,7 +4232,7 @@ PyTypeObject CentsToTranspoType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &CentsToTranspo_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -3970,7 +4281,7 @@ TranspoToCents_process(TranspoToCents *self) {
     int i;
     MYFLT transpo;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         transpo = in[i];
         if (transpo != self->lasttranspo) {
@@ -3997,44 +4308,44 @@ TranspoToCents_setProcMode(TranspoToCents *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = TranspoToCents_process;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = TranspoToCents_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = TranspoToCents_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = TranspoToCents_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = TranspoToCents_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = TranspoToCents_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = TranspoToCents_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = TranspoToCents_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = TranspoToCents_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = TranspoToCents_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 TranspoToCents_compute_next_data_frame(TranspoToCents *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -4047,7 +4358,7 @@ TranspoToCents_traverse(TranspoToCents *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 TranspoToCents_clear(TranspoToCents *self)
 {
     pyo_CLEAR
@@ -4061,7 +4372,7 @@ TranspoToCents_dealloc(TranspoToCents* self)
 {
     pyo_DEALLOC
     TranspoToCents_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -4071,33 +4382,33 @@ TranspoToCents_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     TranspoToCents *self;
     self = (TranspoToCents *)type->tp_alloc(type, 0);
-    
+
     self->lasttranspo = 1.0;
     self->curcents = 0.0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, TranspoToCents_compute_next_data_frame);
     self->mode_func_ptr = TranspoToCents_setProcMode;
 
     static char *kwlist[] = {"input", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     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;
@@ -4105,10 +4416,10 @@ TranspoToCents_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * TranspoToCents_getServer(TranspoToCents* self) { GET_SERVER };
 static PyObject * TranspoToCents_getStream(TranspoToCents* self) { GET_STREAM };
-static PyObject * TranspoToCents_setMul(TranspoToCents *self, PyObject *arg) { SET_MUL };	
-static PyObject * TranspoToCents_setAdd(TranspoToCents *self, PyObject *arg) { SET_ADD };	
-static PyObject * TranspoToCents_setSub(TranspoToCents *self, PyObject *arg) { SET_SUB };	
-static PyObject * TranspoToCents_setDiv(TranspoToCents *self, PyObject *arg) { SET_DIV };	
+static PyObject * TranspoToCents_setMul(TranspoToCents *self, PyObject *arg) { SET_MUL };
+static PyObject * TranspoToCents_setAdd(TranspoToCents *self, PyObject *arg) { SET_ADD };
+static PyObject * TranspoToCents_setSub(TranspoToCents *self, PyObject *arg) { SET_SUB };
+static PyObject * TranspoToCents_setDiv(TranspoToCents *self, PyObject *arg) { SET_DIV };
 
 static PyObject * TranspoToCents_play(TranspoToCents *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * TranspoToCents_out(TranspoToCents *self, PyObject *args, PyObject *kwds) { OUT };
@@ -4149,7 +4460,7 @@ static PyNumberMethods TranspoToCents_as_number = {
     (binaryfunc)TranspoToCents_add,                         /*nb_add*/
     (binaryfunc)TranspoToCents_sub,                         /*nb_subtract*/
     (binaryfunc)TranspoToCents_multiply,                    /*nb_multiply*/
-    (binaryfunc)TranspoToCents_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -4163,16 +4474,16 @@ static PyNumberMethods TranspoToCents_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)TranspoToCents_inplace_add,                 /*inplace_add*/
     (binaryfunc)TranspoToCents_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)TranspoToCents_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)TranspoToCents_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -4181,15 +4492,14 @@ static PyNumberMethods TranspoToCents_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)TranspoToCents_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)TranspoToCents_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject TranspoToCentsType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.TranspoToCents_base",                                   /*tp_name*/
     sizeof(TranspoToCents),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -4197,7 +4507,7 @@ PyTypeObject TranspoToCentsType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &TranspoToCents_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -4246,11 +4556,11 @@ MToF_process(MToF *self) {
     int i;
     MYFLT midi;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         midi = in[i];
         if (midi != self->lastmidi) {
-            self->data[i] = self->curfreq = 8.1757989156437 * MYPOW(1.0594630943593, midi);
+            self->data[i] = self->curfreq = 440.0 * MYPOW(2.0, (midi - 69) / 12.0);
             self->lastmidi = midi;
         }
         else
@@ -4273,44 +4583,44 @@ MToF_setProcMode(MToF *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = MToF_process;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = MToF_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = MToF_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = MToF_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = MToF_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = MToF_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = MToF_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = MToF_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = MToF_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = MToF_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 MToF_compute_next_data_frame(MToF *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -4323,7 +4633,7 @@ MToF_traverse(MToF *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 MToF_clear(MToF *self)
 {
     pyo_CLEAR
@@ -4337,7 +4647,7 @@ MToF_dealloc(MToF* self)
 {
     pyo_DEALLOC
     MToF_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -4347,33 +4657,33 @@ MToF_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     MToF *self;
     self = (MToF *)type->tp_alloc(type, 0);
-    
+
     self->lastmidi = 0;
     self->curfreq = 8.1757989156437;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, MToF_compute_next_data_frame);
     self->mode_func_ptr = MToF_setProcMode;
 
     static char *kwlist[] = {"input", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     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;
@@ -4381,10 +4691,10 @@ MToF_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * MToF_getServer(MToF* self) { GET_SERVER };
 static PyObject * MToF_getStream(MToF* self) { GET_STREAM };
-static PyObject * MToF_setMul(MToF *self, PyObject *arg) { SET_MUL };	
-static PyObject * MToF_setAdd(MToF *self, PyObject *arg) { SET_ADD };	
-static PyObject * MToF_setSub(MToF *self, PyObject *arg) { SET_SUB };	
-static PyObject * MToF_setDiv(MToF *self, PyObject *arg) { SET_DIV };	
+static PyObject * MToF_setMul(MToF *self, PyObject *arg) { SET_MUL };
+static PyObject * MToF_setAdd(MToF *self, PyObject *arg) { SET_ADD };
+static PyObject * MToF_setSub(MToF *self, PyObject *arg) { SET_SUB };
+static PyObject * MToF_setDiv(MToF *self, PyObject *arg) { SET_DIV };
 
 static PyObject * MToF_play(MToF *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * MToF_out(MToF *self, PyObject *args, PyObject *kwds) { OUT };
@@ -4425,7 +4735,284 @@ static PyNumberMethods MToF_as_number = {
     (binaryfunc)MToF_add,                         /*nb_add*/
     (binaryfunc)MToF_sub,                         /*nb_subtract*/
     (binaryfunc)MToF_multiply,                    /*nb_multiply*/
-    (binaryfunc)MToF_div,                                              /*nb_divide*/
+    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)MToF_inplace_add,                 /*inplace_add*/
+    (binaryfunc)MToF_inplace_sub,                 /*inplace_subtract*/
+    (binaryfunc)MToF_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)MToF_div,                       /*nb_true_divide*/
+    0,                                              /*nb_inplace_floor_divide*/
+    (binaryfunc)MToF_inplace_div,                       /*nb_inplace_true_divide*/
+    0,                                              /* nb_index */
+};
+
+PyTypeObject MToFType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.MToF_base",                                   /*tp_name*/
+    sizeof(MToF),                                 /*tp_basicsize*/
+    0,                                              /*tp_itemsize*/
+    (destructor)MToF_dealloc,                     /*tp_dealloc*/
+    0,                                              /*tp_print*/
+    0,                                              /*tp_getattr*/
+    0,                                              /*tp_setattr*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
+    0,                                              /*tp_repr*/
+    &MToF_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*/
+    "MToF objects. Converts midi notes to frequency.",           /* tp_doc */
+    (traverseproc)MToF_traverse,                  /* tp_traverse */
+    (inquiry)MToF_clear,                          /* tp_clear */
+    0,                                              /* tp_richcompare */
+    0,                                              /* tp_weaklistoffset */
+    0,                                              /* tp_iter */
+    0,                                              /* tp_iternext */
+    MToF_methods,                                 /* tp_methods */
+    MToF_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 */
+    MToF_new,                                     /* tp_new */
+};
+
+/************/
+/* FToM */
+/************/
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *input;
+    Stream *input_stream;
+    MYFLT lastfreq;
+    MYFLT curmidi;
+    int modebuffer[2]; // need at least 2 slots for mul & add
+} FToM;
+
+static void
+FToM_process(FToM *self) {
+    int i;
+    MYFLT freq;
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+
+    for (i=0; i<self->bufsize; i++) {
+        freq = in[i];
+        if (freq != self->lastfreq) {
+            if (freq < 8.1758)
+                freq = 8.1578;
+            self->curmidi = 12.0 * MYLOG2(freq / 440.0) + 69;
+            self->lastfreq = freq;
+        }
+        else
+            self->data[i] = self->curmidi;
+    }
+}
+
+static void FToM_postprocessing_ii(FToM *self) { POST_PROCESSING_II };
+static void FToM_postprocessing_ai(FToM *self) { POST_PROCESSING_AI };
+static void FToM_postprocessing_ia(FToM *self) { POST_PROCESSING_IA };
+static void FToM_postprocessing_aa(FToM *self) { POST_PROCESSING_AA };
+static void FToM_postprocessing_ireva(FToM *self) { POST_PROCESSING_IREVA };
+static void FToM_postprocessing_areva(FToM *self) { POST_PROCESSING_AREVA };
+static void FToM_postprocessing_revai(FToM *self) { POST_PROCESSING_REVAI };
+static void FToM_postprocessing_revaa(FToM *self) { POST_PROCESSING_REVAA };
+static void FToM_postprocessing_revareva(FToM *self) { POST_PROCESSING_REVAREVA };
+
+static void
+FToM_setProcMode(FToM *self)
+{
+    int muladdmode;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+    self->proc_func_ptr = FToM_process;
+
+	switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = FToM_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = FToM_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = FToM_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = FToM_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = FToM_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = FToM_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = FToM_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = FToM_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = FToM_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+FToM_compute_next_data_frame(FToM *self)
+{
+    (*self->proc_func_ptr)(self);
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+FToM_traverse(FToM *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->input);
+    Py_VISIT(self->input_stream);
+    return 0;
+}
+
+static int
+FToM_clear(FToM *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->input);
+    Py_CLEAR(self->input_stream);
+    return 0;
+}
+
+static void
+FToM_dealloc(FToM* self)
+{
+    pyo_DEALLOC
+    FToM_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+FToM_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
+    FToM *self;
+    self = (FToM *)type->tp_alloc(type, 0);
+
+    self->lastfreq = 8.1758;
+    self->curmidi = 0.0;
+	self->modebuffer[0] = 0;
+	self->modebuffer[1] = 0;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, FToM_compute_next_data_frame);
+    self->mode_func_ptr = FToM_setProcMode;
+
+    static char *kwlist[] = {"input", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OO", kwlist, &inputtmp, &multmp, &addtmp))
+        Py_RETURN_NONE;
+
+    INIT_INPUT_STREAM
+
+    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 * FToM_getServer(FToM* self) { GET_SERVER };
+static PyObject * FToM_getStream(FToM* self) { GET_STREAM };
+static PyObject * FToM_setMul(FToM *self, PyObject *arg) { SET_MUL };
+static PyObject * FToM_setAdd(FToM *self, PyObject *arg) { SET_ADD };
+static PyObject * FToM_setSub(FToM *self, PyObject *arg) { SET_SUB };
+static PyObject * FToM_setDiv(FToM *self, PyObject *arg) { SET_DIV };
+
+static PyObject * FToM_play(FToM *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * FToM_out(FToM *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * FToM_stop(FToM *self) { STOP };
+
+static PyObject * FToM_multiply(FToM *self, PyObject *arg) { MULTIPLY };
+static PyObject * FToM_inplace_multiply(FToM *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * FToM_add(FToM *self, PyObject *arg) { ADD };
+static PyObject * FToM_inplace_add(FToM *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * FToM_sub(FToM *self, PyObject *arg) { SUB };
+static PyObject * FToM_inplace_sub(FToM *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * FToM_div(FToM *self, PyObject *arg) { DIV };
+static PyObject * FToM_inplace_div(FToM *self, PyObject *arg) { INPLACE_DIV };
+
+static PyMemberDef FToM_members[] = {
+    {"server", T_OBJECT_EX, offsetof(FToM, server), 0, "Pyo server."},
+    {"stream", T_OBJECT_EX, offsetof(FToM, stream), 0, "Stream object."},
+    {"input", T_OBJECT_EX, offsetof(FToM, input), 0, "Input sound object."},
+    {"mul", T_OBJECT_EX, offsetof(FToM, mul), 0, "Mul factor."},
+    {"add", T_OBJECT_EX, offsetof(FToM, add), 0, "Add factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyMethodDef FToM_methods[] = {
+    {"getServer", (PyCFunction)FToM_getServer, METH_NOARGS, "Returns server object."},
+    {"_getStream", (PyCFunction)FToM_getStream, METH_NOARGS, "Returns stream object."},
+    {"play", (PyCFunction)FToM_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+    {"stop", (PyCFunction)FToM_stop, METH_NOARGS, "Stops computing."},
+    {"out", (PyCFunction)FToM_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+    {"setMul", (PyCFunction)FToM_setMul, METH_O, "Sets oscillator mul factor."},
+    {"setAdd", (PyCFunction)FToM_setAdd, METH_O, "Sets oscillator add factor."},
+    {"setSub", (PyCFunction)FToM_setSub, METH_O, "Sets inverse add factor."},
+    {"setDiv", (PyCFunction)FToM_setDiv, METH_O, "Sets inverse mul factor."},
+    {NULL}  /* Sentinel */
+};
+
+static PyNumberMethods FToM_as_number = {
+    (binaryfunc)FToM_add,                         /*nb_add*/
+    (binaryfunc)FToM_sub,                         /*nb_subtract*/
+    (binaryfunc)FToM_multiply,                    /*nb_multiply*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -4439,16 +5026,16 @@ static PyNumberMethods MToF_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
-    (binaryfunc)MToF_inplace_add,                 /*inplace_add*/
-    (binaryfunc)MToF_inplace_sub,                 /*inplace_subtract*/
-    (binaryfunc)MToF_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)MToF_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
+    (binaryfunc)FToM_inplace_add,                 /*inplace_add*/
+    (binaryfunc)FToM_inplace_sub,                 /*inplace_subtract*/
+    (binaryfunc)FToM_inplace_multiply,            /*inplace_multiply*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -4457,25 +5044,24 @@ static PyNumberMethods MToF_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)FToM_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)FToM_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
-PyTypeObject MToFType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
-    "_pyo.MToF_base",                                   /*tp_name*/
-    sizeof(MToF),                                 /*tp_basicsize*/
+PyTypeObject FToMType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "_pyo.FToM_base",                                   /*tp_name*/
+    sizeof(FToM),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
-    (destructor)MToF_dealloc,                     /*tp_dealloc*/
+    (destructor)FToM_dealloc,                     /*tp_dealloc*/
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
-    &MToF_as_number,                              /*tp_as_number*/
+    &FToM_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
     0,                                              /*tp_as_mapping*/
     0,                                              /*tp_hash */
@@ -4485,15 +5071,15 @@ PyTypeObject MToFType = {
     0,                                              /*tp_setattro*/
     0,                                              /*tp_as_buffer*/
     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
-    "MToF objects. Converts midi notes to frequency.",           /* tp_doc */
-    (traverseproc)MToF_traverse,                  /* tp_traverse */
-    (inquiry)MToF_clear,                          /* tp_clear */
+    "FToM objects. Converts frequency to midi note.",           /* tp_doc */
+    (traverseproc)FToM_traverse,                  /* tp_traverse */
+    (inquiry)FToM_clear,                          /* tp_clear */
     0,                                              /* tp_richcompare */
     0,                                              /* tp_weaklistoffset */
     0,                                              /* tp_iter */
     0,                                              /* tp_iternext */
-    MToF_methods,                                 /* tp_methods */
-    MToF_members,                                 /* tp_members */
+    FToM_methods,                                 /* tp_methods */
+    FToM_members,                                 /* tp_members */
     0,                                              /* tp_getset */
     0,                                              /* tp_base */
     0,                                              /* tp_dict */
@@ -4502,7 +5088,7 @@ PyTypeObject MToFType = {
     0,                                              /* tp_dictoffset */
     0,                          /* tp_init */
     0,                                              /* tp_alloc */
-    MToF_new,                                     /* tp_new */
+    FToM_new,                                     /* tp_new */
 };
 
 /************/
@@ -4523,7 +5109,7 @@ MToT_process(MToT *self) {
     int i;
     MYFLT midi;
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         midi = in[i];
         if (midi != self->lastmidi) {
@@ -4550,44 +5136,44 @@ MToT_setProcMode(MToT *self)
 {
     int muladdmode;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
-    
+
     self->proc_func_ptr = MToT_process;
-    
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = MToT_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = MToT_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = MToT_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = MToT_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = MToT_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = MToT_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = MToT_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = MToT_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = MToT_postprocessing_revareva;
             break;
-    }   
+    }
 }
 
 static void
 MToT_compute_next_data_frame(MToT *self)
 {
-    (*self->proc_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -4600,7 +5186,7 @@ MToT_traverse(MToT *self, visitproc visit, void *arg)
     return 0;
 }
 
-static int 
+static int
 MToT_clear(MToT *self)
 {
     pyo_CLEAR
@@ -4614,7 +5200,7 @@ MToT_dealloc(MToT* self)
 {
     pyo_DEALLOC
     MToT_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -4624,34 +5210,34 @@ MToT_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
     MToT *self;
     self = (MToT *)type->tp_alloc(type, 0);
-    
+
     self->centralkey = 60.0;
     self->lastmidi = 0;
     self->curfreq = 8.1757989156437;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, MToT_compute_next_data_frame);
     self->mode_func_ptr = MToT_setProcMode;
 
     static char *kwlist[] = {"input", "centralkey", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_FOO, kwlist, &inputtmp, &self->centralkey, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-    
+
     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;
@@ -4660,27 +5246,24 @@ MToT_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 static PyObject *
 MToT_setCentralKey(MToT *self, PyObject *arg)
 {
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-	
+
 	if (isNumber == 1) {
-		self->centralkey = PyFloat_AS_DOUBLE(PyNumber_Float(arg));
+		self->centralkey = PyFloat_AsDouble(arg);
 	}
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
 }
 
 static PyObject * MToT_getServer(MToT* self) { GET_SERVER };
 static PyObject * MToT_getStream(MToT* self) { GET_STREAM };
-static PyObject * MToT_setMul(MToT *self, PyObject *arg) { SET_MUL };	
-static PyObject * MToT_setAdd(MToT *self, PyObject *arg) { SET_ADD };	
-static PyObject * MToT_setSub(MToT *self, PyObject *arg) { SET_SUB };	
-static PyObject * MToT_setDiv(MToT *self, PyObject *arg) { SET_DIV };	
+static PyObject * MToT_setMul(MToT *self, PyObject *arg) { SET_MUL };
+static PyObject * MToT_setAdd(MToT *self, PyObject *arg) { SET_ADD };
+static PyObject * MToT_setSub(MToT *self, PyObject *arg) { SET_SUB };
+static PyObject * MToT_setDiv(MToT *self, PyObject *arg) { SET_DIV };
 
 static PyObject * MToT_play(MToT *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * MToT_out(MToT *self, PyObject *args, PyObject *kwds) { OUT };
@@ -4722,7 +5305,7 @@ static PyNumberMethods MToT_as_number = {
     (binaryfunc)MToT_add,                         /*nb_add*/
     (binaryfunc)MToT_sub,                         /*nb_subtract*/
     (binaryfunc)MToT_multiply,                    /*nb_multiply*/
-    (binaryfunc)MToT_div,                                              /*nb_divide*/
+    INITIALIZE_NB_DIVIDE_ZERO                       /*nb_divide*/
     0,                                              /*nb_remainder*/
     0,                                              /*nb_divmod*/
     0,                                              /*nb_power*/
@@ -4736,16 +5319,16 @@ static PyNumberMethods MToT_as_number = {
     0,                                              /*nb_and*/
     0,                                              /*nb_xor*/
     0,                                              /*nb_or*/
-    0,                                              /*nb_coerce*/
+    INITIALIZE_NB_COERCE_ZERO                       /*nb_coerce*/
     0,                                              /*nb_int*/
     0,                                              /*nb_long*/
     0,                                              /*nb_float*/
-    0,                                              /*nb_oct*/
-    0,                                              /*nb_hex*/
+    INITIALIZE_NB_OCT_ZERO                          /*nb_oct*/
+    INITIALIZE_NB_HEX_ZERO                          /*nb_hex*/
     (binaryfunc)MToT_inplace_add,                 /*inplace_add*/
     (binaryfunc)MToT_inplace_sub,                 /*inplace_subtract*/
     (binaryfunc)MToT_inplace_multiply,            /*inplace_multiply*/
-    (binaryfunc)MToT_inplace_div,                                              /*inplace_divide*/
+    INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO                                           /*inplace_divide*/
     0,                                              /*inplace_remainder*/
     0,                                              /*inplace_power*/
     0,                                              /*inplace_lshift*/
@@ -4754,15 +5337,14 @@ static PyNumberMethods MToT_as_number = {
     0,                                              /*inplace_xor*/
     0,                                              /*inplace_or*/
     0,                                              /*nb_floor_divide*/
-    0,                                              /*nb_true_divide*/
+    (binaryfunc)MToT_div,                       /*nb_true_divide*/
     0,                                              /*nb_inplace_floor_divide*/
-    0,                                              /*nb_inplace_true_divide*/
+    (binaryfunc)MToT_inplace_div,                       /*nb_inplace_true_divide*/
     0,                                              /* nb_index */
 };
 
 PyTypeObject MToTType = {
-    PyObject_HEAD_INIT(NULL)
-    0,                                              /*ob_size*/
+    PyVarObject_HEAD_INIT(NULL, 0)
     "_pyo.MToT_base",                                   /*tp_name*/
     sizeof(MToT),                                 /*tp_basicsize*/
     0,                                              /*tp_itemsize*/
@@ -4770,7 +5352,7 @@ PyTypeObject MToTType = {
     0,                                              /*tp_print*/
     0,                                              /*tp_getattr*/
     0,                                              /*tp_setattr*/
-    0,                                              /*tp_compare*/
+    0,                                              /*tp_as_async (tp_compare in Python 2)*/
     0,                                              /*tp_repr*/
     &MToT_as_number,                              /*tp_as_number*/
     0,                                              /*tp_as_sequence*/
@@ -4801,3 +5383,439 @@ PyTypeObject MToTType = {
     0,                                              /* tp_alloc */
     MToT_new,                                     /* tp_new */
 };
+
+/************/
+/* Resample */
+/************/
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *input;
+    Stream *input_stream;
+    MYFLT **pimpulse;
+    MYFLT **pinput;
+    int factor;
+    int count;
+    int dir;    // Up = 1, DOWN = 0
+    int size;   // UP: 0 = zero-padding, 1 = sample-and-hold, 2+ polyphase lowpass filtering
+                // DOWN: <2 = discard extra samples, 2+ polyphase lowpass filtering
+    int modebuffer[2]; // need at least 2 slots for mul & add
+} Resample;
+
+static void
+Resample_create_impulse(Resample *self) {
+    int i, half;
+    MYFLT val, scl, sum, invSum, env, w;
+    MYFLT impulse[self->size];
+
+    half = self->size / 2;
+    sum = 0.0;
+    w = TWOPI * 0.49 / self->factor;
+
+    for (i=0; i<half; i++) {
+        env = 0.5 * (1.0 - MYCOS(TWOPI * i / self->size));
+        scl = i - half;
+        val = (MYSIN(w * scl) / scl) * env;
+        sum += val;
+        impulse[i] = val;
+    }
+    sum *= 2.0;
+    sum += w;
+    invSum = 1.0 / sum;
+    impulse[half] = w * invSum;
+    for (i=0; i<half; i++) {
+        impulse[i] *= invSum;
+    }
+    for (i=half+1; i<self->size; i++) {
+        impulse[i] = impulse[self->size-i];
+    }
+    
+    /* Create sub-filters. */
+    for (i=0; i<self->size; i++) {
+        self->pimpulse[i%self->factor][(int)(i/self->factor)] = impulse[i];
+    }
+}
+
+static void
+Resample_downsample(Resample *self) {
+    int i, j, k, tmp_count, len;
+    MYFLT filtout;
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+
+    len = self->size / self->factor;
+
+    if (self->size <= self->factor) {
+        for (i=0; i<self->bufsize; i++) {
+            self->data[i] = in[i * self->factor];
+        }
+    }
+    else {
+        for (i=0; i<self->bufsize; i++) {
+            self->data[i] = 0.0;
+            for (j=0; j<self->factor; j++) { // for each polyphase sub-filter...
+                filtout = 0.0;
+                tmp_count = self->count;
+                for (k=0; k<len; k++) { // ... apply filter...
+                    if (tmp_count < 0)
+                        tmp_count += len;
+                    filtout += self->pinput[j][tmp_count--] * self->pimpulse[j][k];
+                }
+                self->data[i] += filtout; // ... and sum.
+            }
+
+            // Input decomposition (input delay line in reverse order).
+            self->count++;
+            if (self->count == len)
+                self->count = 0;
+            for (j=0; j<self->factor; j++) {
+                self->pinput[self->factor-1-j][self->count] = in[i*self->factor+j];
+            }
+        }
+    }
+}
+
+static void
+Resample_upsample(Resample *self) {
+    int i, j, k, tmp_count, len;
+    MYFLT filtout;
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+
+    len = self->size / self->factor;
+
+    if (self->size == 0) {
+        for (i=0; i<(self->bufsize/self->factor); i++) {
+            j = i*self->factor;
+            self->data[j] = in[i];
+            for (k=1; k<self->factor; k++) {
+                self->data[j+k] = 0.0;
+            }
+        }
+    } else if (self->size == self->factor) {
+        for (i=0; i<(self->bufsize/self->factor); i++) {
+            for (k=0; k<self->factor; k++) {
+                self->data[i*self->factor+k] = in[i];
+            }
+        }
+    } else {
+        for (i=0; i<self->bufsize/self->factor; i++) {
+            for(j=0; j<self->factor; j++) { // for each polyphase sub-filter...
+                filtout = 0.0;
+                tmp_count = self->count;
+                for (k=0; k<len; k++) { // ... apply filter...
+                    if (tmp_count < 0)
+                        tmp_count += len;
+                    filtout += self->pinput[j][tmp_count--] * self->pimpulse[j][k];
+                }
+                self->data[i*self->factor+j] = filtout;
+            }
+
+            self->count++;
+            if (self->count == len)
+                self->count = 0;
+            for (j=0; j<self->factor; j++) {
+                self->pinput[self->factor-1-j][self->count] = in[i];
+            }
+        }
+    }
+}
+
+static void
+Resample_process(Resample *self) {
+    if (self->dir == 0)
+        Resample_downsample(self);
+    else
+        Resample_upsample(self);
+}
+
+static void Resample_postprocessing_ii(Resample *self) { POST_PROCESSING_II };
+static void Resample_postprocessing_ai(Resample *self) { POST_PROCESSING_AI };
+static void Resample_postprocessing_ia(Resample *self) { POST_PROCESSING_IA };
+static void Resample_postprocessing_aa(Resample *self) { POST_PROCESSING_AA };
+static void Resample_postprocessing_ireva(Resample *self) { POST_PROCESSING_IREVA };
+static void Resample_postprocessing_areva(Resample *self) { POST_PROCESSING_AREVA };
+static void Resample_postprocessing_revai(Resample *self) { POST_PROCESSING_REVAI };
+static void Resample_postprocessing_revaa(Resample *self) { POST_PROCESSING_REVAA };
+static void Resample_postprocessing_revareva(Resample *self) { POST_PROCESSING_REVAREVA };
+
+static void
+Resample_setProcMode(Resample *self)
+{
+    int muladdmode;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+    self->proc_func_ptr = Resample_process;
+
+	switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = Resample_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = Resample_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = Resample_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = Resample_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = Resample_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = Resample_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = Resample_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = Resample_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = Resample_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+Resample_compute_next_data_frame(Resample *self)
+{
+    (*self->proc_func_ptr)(self);
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+Resample_traverse(Resample *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->input);
+    Py_VISIT(self->input_stream);
+    return 0;
+}
+
+static int
+Resample_clear(Resample *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->input);
+    Py_CLEAR(self->input_stream);
+    return 0;
+}
+
+static void
+Resample_dealloc(Resample* self)
+{
+    int i;
+    pyo_DEALLOC
+    if (self->size > self->factor) {
+        for (i=0; i<self->factor; i++) {
+            free(self->pimpulse[i]);
+            free(self->pinput[i]);
+        }
+        free(self->pimpulse);
+        free(self->pinput);
+    }
+    Resample_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+Resample_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i, j, lfac, cfac, mode;
+    PyObject *inputtmp, *input_streamtmp, *multmp=NULL, *addtmp=NULL;
+    Resample *self;
+    self = (Resample *)type->tp_alloc(type, 0);
+
+    self->factor = 1;
+    self->size = 0;
+    self->count = 0;
+    self->dir = 0;
+	self->modebuffer[0] = 0;
+	self->modebuffer[1] = 0;
+
+    static char *kwlist[] = {"input", "mode", "mul", "add", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|iOO", kwlist, &inputtmp, &mode, &multmp, &addtmp))
+        Py_RETURN_NONE;
+
+    INIT_INPUT_STREAM
+
+    lfac = Server_getLastResamplingFactor((Server *)PyServer_get_server());
+    cfac = Server_getCurrentResamplingFactor((Server *)PyServer_get_server());
+
+    if (lfac == 1) {
+        if (cfac < 0) {
+            self->dir = 0;
+            cfac = -cfac;
+        }
+        else
+            self->dir = 1;
+        self->factor = cfac;
+    }
+    else if (cfac == 1) {
+        if (lfac < 0) {
+            self->dir = 1;
+            lfac = -lfac;
+        }
+        else
+            self->dir = 0;
+        self->factor = lfac;
+    }
+    
+    self->size = self->factor * mode;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, Resample_compute_next_data_frame);
+    self->mode_func_ptr = Resample_setProcMode;
+
+    if (self->size > self->factor) {
+        self->pimpulse = (MYFLT **)realloc(self->pimpulse, self->factor * sizeof(MYFLT *));
+        self->pinput = (MYFLT **)realloc(self->pinput, self->factor * sizeof(MYFLT *));
+        for (j=0; j<self->factor; j++) {
+            self->pimpulse[j] = (MYFLT *)malloc(self->size / self->factor * sizeof(MYFLT));
+            self->pinput[j] = (MYFLT *)malloc(self->size / self->factor * sizeof(MYFLT));
+            for (i=0; i<self->size/self->factor; i++) {
+                self->pinput[j][i] = 0.0;
+            }
+        }
+        Resample_create_impulse(self);
+    }
+
+    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 * Resample_getServer(Resample* self) { GET_SERVER };
+static PyObject * Resample_getStream(Resample* self) { GET_STREAM };
+static PyObject * Resample_setMul(Resample *self, PyObject *arg) { SET_MUL };
+static PyObject * Resample_setAdd(Resample *self, PyObject *arg) { SET_ADD };
+static PyObject * Resample_setSub(Resample *self, PyObject *arg) { SET_SUB };
+static PyObject * Resample_setDiv(Resample *self, PyObject *arg) { SET_DIV };
+
+static PyObject * Resample_play(Resample *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * Resample_out(Resample *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * Resample_stop(Resample *self) { STOP };
+
+static PyObject * Resample_multiply(Resample *self, PyObject *arg) { MULTIPLY };
+static PyObject * Resample_inplace_multiply(Resample *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * Resample_add(Resample *self, PyObject *arg) { ADD };
+static PyObject * Resample_inplace_add(Resample *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * Resample_sub(Resample *self, PyObject *arg) { SUB };
+static PyObject * Resample_inplace_sub(Resample *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * Resample_div(Resample *self, PyObject *arg) { DIV };
+static PyObject * Resample_inplace_div(Resample *self, PyObject *arg) { INPLACE_DIV };
+
+static PyMemberDef Resample_members[] = {
+{"server", T_OBJECT_EX, offsetof(Resample, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(Resample, stream), 0, "Stream object."},
+{"input", T_OBJECT_EX, offsetof(Resample, input), 0, "Input sound object."},
+{"mul", T_OBJECT_EX, offsetof(Resample, mul), 0, "Mul factor."},
+{"add", T_OBJECT_EX, offsetof(Resample, add), 0, "Add factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyMethodDef Resample_methods[] = {
+{"getServer", (PyCFunction)Resample_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)Resample_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)Resample_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"stop", (PyCFunction)Resample_stop, METH_NOARGS, "Stops computing."},
+{"out", (PyCFunction)Resample_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+{"setMul", (PyCFunction)Resample_setMul, METH_O, "Sets oscillator mul factor."},
+{"setAdd", (PyCFunction)Resample_setAdd, METH_O, "Sets oscillator add factor."},
+{"setSub", (PyCFunction)Resample_setSub, METH_O, "Sets inverse add factor."},
+{"setDiv", (PyCFunction)Resample_setDiv, METH_O, "Sets inverse mul factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyNumberMethods Resample_as_number = {
+(binaryfunc)Resample_add,                         /*nb_add*/
+(binaryfunc)Resample_sub,                         /*nb_subtract*/
+(binaryfunc)Resample_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)Resample_inplace_add,                 /*inplace_add*/
+(binaryfunc)Resample_inplace_sub,                 /*inplace_subtract*/
+(binaryfunc)Resample_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)Resample_div,                       /*nb_true_divide*/
+0,                                              /*nb_inplace_floor_divide*/
+(binaryfunc)Resample_inplace_div,                       /*nb_inplace_true_divide*/
+0,                                              /* nb_index */
+};
+
+PyTypeObject ResampleType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.Resample_base",                                   /*tp_name*/
+sizeof(Resample),                                 /*tp_basicsize*/
+0,                                              /*tp_itemsize*/
+(destructor)Resample_dealloc,                     /*tp_dealloc*/
+0,                                              /*tp_print*/
+0,                                              /*tp_getattr*/
+0,                                              /*tp_setattr*/
+0,                                              /*tp_as_async (tp_compare in Python 2)*/
+0,                                              /*tp_repr*/
+&Resample_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*/
+"Resample objects. Performs resampling of an audio signal.",           /* tp_doc */
+(traverseproc)Resample_traverse,                  /* tp_traverse */
+(inquiry)Resample_clear,                          /* tp_clear */
+0,                                              /* tp_richcompare */
+0,                                              /* tp_weaklistoffset */
+0,                                              /* tp_iter */
+0,                                              /* tp_iternext */
+Resample_methods,                                 /* tp_methods */
+Resample_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 */
+Resample_new,                                     /* tp_new */
+};
diff --git a/src/objects/wgverbmodule.c b/src/objects/wgverbmodule.c
index 79970ce..5af9328 100644
--- a/src/objects/wgverbmodule.c
+++ b/src/objects/wgverbmodule.c
@@ -1,24 +1,25 @@
-/*************************************************************************
- * Copyright 2010 Olivier Belanger                                        *                  
- *                                                                        * 
+/**************************************************************************
+ * Copyright 2009-2015 Olivier Belanger                                   *
+ *                                                                        *
  * This file is part of pyo, a python module to help digital signal       *
- * processing script creation.                                            *  
- *                                                                        * 
+ * processing script creation.                                            *
+ *                                                                        *
  * pyo is free software: you can redistribute it and/or modify            *
- * it under the terms of the GNU General Public License as published by   *
- * the Free Software Foundation, either version 3 of the License, or      *
- * (at your option) any later version.                                    * 
+ * it under the terms of the GNU Lesser General Public License as         *
+ * published by the Free Software Foundation, either version 3 of the     *
+ * License, or (at your option) any later version.                        *
  *                                                                        *
  * pyo is distributed in the hope that it will be useful,                 *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of         *    
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of         *
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
- * GNU General Public License for more details.                           *
+ * GNU Lesser General Public License for more details.                    *
  *                                                                        *
- * You should have received a copy of the GNU General Public License      *
- * along with pyo.  If not, see <http://www.gnu.org/licenses/>.           *
+ * You should have received a copy of the GNU Lesser General Public       *
+ * License along with pyo.  If not, see <http://www.gnu.org/licenses/>.   *
  *************************************************************************/
 
 #include <Python.h>
+#include "py2to3.h"
 #include "structmember.h"
 #include <math.h>
 #include "pyomodule.h"
@@ -26,18 +27,20 @@
 #include "servermodule.h"
 #include "dummymodule.h"
 
+#define NUM_REFS  13
 
 static const MYFLT randomScaling = 0.5;
-static const MYFLT reverbParams[8][3] = {
-{ 2473.0, 0.0010, 3.100 },
-{ 2767.0, 0.0011, 3.500 },
-{ 3217.0, 0.0017, 1.110 },
-{ 3557.0, 0.0006, 3.973 },
-{ 3907.0, 0.0010, 2.341 },
-{ 4127.0, 0.0011, 1.897 },
-{ 2143.0, 0.0017, 0.891 },
-{ 1933.0, 0.0006, 3.221 }
-};
+static const MYFLT reverbParams[8][4] = {
+{ 2473.0, 0.0010, 3.100, 2503.0 },
+{ 2767.0, 0.0011, 3.500, 2749.0 },
+{ 3217.0, 0.0017, 1.110, 3187.0 },
+{ 3557.0, 0.0006, 3.973, 3583.0 },
+{ 3907.0, 0.0010, 2.341, 3929.0 },
+{ 4127.0, 0.0011, 1.897, 4093.0 },
+{ 2143.0, 0.0017, 0.891, 2131.0 },
+{ 1933.0, 0.0006, 3.221, 1951.0 }};
+
+static const MYFLT first_ref_delays[NUM_REFS] = {283, 467, 587, 677, 757, 911, 1117, 1223, 1307, 1429, 1553, 1613, 1783};
 
 typedef struct {
     pyo_audio_HEAD
@@ -76,11 +79,11 @@ static void
 WGVerb_process_ii(WGVerb *self) {
     MYFLT val, x, x1, xind, frac, junction, inval, filt;
     int i, j, ind;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT feed = PyFloat_AS_DOUBLE(self->feedback);
     MYFLT freq = PyFloat_AS_DOUBLE(self->cutoff);
-        
+
     if (feed < 0)
         feed = 0;
     else if (feed > 1)
@@ -91,7 +94,7 @@ WGVerb_process_ii(WGVerb *self) {
         self->damp = 2.0 - MYCOS(TWOPI * freq / self->sr);
         self->damp = (self->damp - MYSQRT(self->damp * self->damp - 1.0));
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         inval = in[i];
         junction = self->total_signal * .25;
@@ -103,11 +106,11 @@ WGVerb_process_ii(WGVerb *self) {
             else if (self->rnd_time[j] >= 1.0) {
                 self->rnd_time[j] -= 1.0;
                 self->rnd_oldValue[j] = self->rnd_value[j];
-                self->rnd_value[j] = self->rnd_range[j] * (rand()/((MYFLT)(RAND_MAX)+1)) - self->rnd_halfRange[j];
+                self->rnd_value[j] = self->rnd_range[j] * RANDOM_UNIFORM - self->rnd_halfRange[j];
                 self->rnd_diff[j] = self->rnd_value[j] - self->rnd_oldValue[j];
             }
             self->rnd[j] = self->rnd_oldValue[j] + self->rnd_diff[j] * self->rnd_time[j];
-            
+
             xind = self->in_count[j] - (self->delays[j] + self->rnd[j]);
             if (xind < 0)
                 xind += self->size[j];
@@ -119,7 +122,7 @@ WGVerb_process_ii(WGVerb *self) {
             val *= feed;
             filt = (self->lastSamples[j] - val) * self->damp + val;
             self->total_signal += filt;
-        
+
             self->buffer[j][self->in_count[j]] = inval + junction - self->lastSamples[j];
             self->lastSamples[j] = filt;
             if(self->in_count[j] == 0)
@@ -127,7 +130,7 @@ WGVerb_process_ii(WGVerb *self) {
             self->in_count[j]++;
             if (self->in_count[j] >= self->size[j])
                 self->in_count[j] = 0;
-        } 
+        }
         self->data[i] = self->total_signal * 0.25;
     }
 }
@@ -136,24 +139,24 @@ static void
 WGVerb_process_ai(WGVerb *self) {
     MYFLT val, x, x1, xind, frac, junction, inval, filt, feed;
     int i, j, ind;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *feedback = Stream_getData((Stream *)self->feedback_stream);
     MYFLT freq = PyFloat_AS_DOUBLE(self->cutoff);
-        
+
     if (freq != self->lastFreq) {
         self->lastFreq = freq;
         self->damp = 2.0 - MYCOS(TWOPI * freq / self->sr);
         self->damp = (self->damp - MYSQRT(self->damp * self->damp - 1.0));
     }
-    
+
     for (i=0; i<self->bufsize; i++) {
         inval = in[i];
         feed = feedback[i];
         if (feed < 0)
             feed = 0;
         else if (feed > 1)
-            feed = 1;        
+            feed = 1;
         junction = self->total_signal * .25;
         self->total_signal = 0.0;
         for (j=0; j<8; j++) {
@@ -163,11 +166,11 @@ WGVerb_process_ai(WGVerb *self) {
             else if (self->rnd_time[j] >= 1.0) {
                 self->rnd_time[j] -= 1.0;
                 self->rnd_oldValue[j] = self->rnd_value[j];
-                self->rnd_value[j] = self->rnd_range[j] * (rand()/((MYFLT)(RAND_MAX)+1)) - self->rnd_halfRange[j];
+                self->rnd_value[j] = self->rnd_range[j] * RANDOM_UNIFORM - self->rnd_halfRange[j];
                 self->rnd_diff[j] = self->rnd_value[j] - self->rnd_oldValue[j];
             }
             self->rnd[j] = self->rnd_oldValue[j] + self->rnd_diff[j] * self->rnd_time[j];
-            
+
             xind = self->in_count[j] - (self->delays[j] + self->rnd[j]);
             if (xind < 0)
                 xind += self->size[j];
@@ -179,7 +182,7 @@ WGVerb_process_ai(WGVerb *self) {
             val *= feed;
             filt = (self->lastSamples[j] - val) * self->damp + val;
             self->total_signal += filt;
-            
+
             self->buffer[j][self->in_count[j]] = inval + junction - self->lastSamples[j];
             self->lastSamples[j] = filt;
             if(self->in_count[j] == 0)
@@ -187,20 +190,20 @@ WGVerb_process_ai(WGVerb *self) {
             self->in_count[j]++;
             if (self->in_count[j] >= self->size[j])
                 self->in_count[j] = 0;
-        } 
+        }
         self->data[i] = self->total_signal * 0.25;
-    }    
+    }
 }
 
 static void
 WGVerb_process_ia(WGVerb *self) {
     MYFLT val, x, x1, xind, frac, junction, inval, filt, freq;
     int i, j, ind;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT feed = PyFloat_AS_DOUBLE(self->feedback);
     MYFLT *cutoff = Stream_getData((Stream *)self->cutoff_stream);
-    
+
     if (feed < 0)
         feed = 0;
     else if (feed > 1)
@@ -213,7 +216,7 @@ WGVerb_process_ia(WGVerb *self) {
             self->lastFreq = freq;
             self->damp = 2.0 - MYCOS(TWOPI * freq / self->sr);
             self->damp = (self->damp - MYSQRT(self->damp * self->damp - 1.0));
-        }        
+        }
         junction = self->total_signal * .25;
         self->total_signal = 0.0;
         for (j=0; j<8; j++) {
@@ -223,11 +226,11 @@ WGVerb_process_ia(WGVerb *self) {
             else if (self->rnd_time[j] >= 1.0) {
                 self->rnd_time[j] -= 1.0;
                 self->rnd_oldValue[j] = self->rnd_value[j];
-                self->rnd_value[j] = self->rnd_range[j] * (rand()/((MYFLT)(RAND_MAX)+1)) - self->rnd_halfRange[j];
+                self->rnd_value[j] = self->rnd_range[j] * RANDOM_UNIFORM - self->rnd_halfRange[j];
                 self->rnd_diff[j] = self->rnd_value[j] - self->rnd_oldValue[j];
             }
             self->rnd[j] = self->rnd_oldValue[j] + self->rnd_diff[j] * self->rnd_time[j];
-            
+
             xind = self->in_count[j] - (self->delays[j] + self->rnd[j]);
             if (xind < 0)
                 xind += self->size[j];
@@ -239,7 +242,7 @@ WGVerb_process_ia(WGVerb *self) {
             val *= feed;
             filt = (self->lastSamples[j] - val) * self->damp + val;
             self->total_signal += filt;
-            
+
             self->buffer[j][self->in_count[j]] = inval + junction - self->lastSamples[j];
             self->lastSamples[j] = filt;
             if(self->in_count[j] == 0)
@@ -247,16 +250,16 @@ WGVerb_process_ia(WGVerb *self) {
             self->in_count[j]++;
             if (self->in_count[j] >= self->size[j])
                 self->in_count[j] = 0;
-        } 
+        }
         self->data[i] = self->total_signal * 0.25;
-    }    
+    }
 }
 
 static void
 WGVerb_process_aa(WGVerb *self) {
     MYFLT val, x, x1, xind, frac, junction, inval, filt, feed, freq;
     int i, j, ind;
-    
+
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
     MYFLT *feedback = Stream_getData((Stream *)self->feedback_stream);
     MYFLT *cutoff = Stream_getData((Stream *)self->cutoff_stream);
@@ -268,12 +271,12 @@ WGVerb_process_aa(WGVerb *self) {
         if (feed < 0)
             feed = 0;
         else if (feed > 1)
-            feed = 1;        
+            feed = 1;
         if (freq != self->lastFreq) {
             self->lastFreq = freq;
             self->damp = 2.0 - MYCOS(TWOPI * freq / self->sr);
             self->damp = (self->damp - MYSQRT(self->damp * self->damp - 1.0));
-        }        
+        }
         junction = self->total_signal * .25;
         self->total_signal = 0.0;
         for (j=0; j<8; j++) {
@@ -283,11 +286,11 @@ WGVerb_process_aa(WGVerb *self) {
             else if (self->rnd_time[j] >= 1.0) {
                 self->rnd_time[j] -= 1.0;
                 self->rnd_oldValue[j] = self->rnd_value[j];
-                self->rnd_value[j] = self->rnd_range[j] * (rand()/((MYFLT)(RAND_MAX)+1)) - self->rnd_halfRange[j];
+                self->rnd_value[j] = self->rnd_range[j] * RANDOM_UNIFORM - self->rnd_halfRange[j];
                 self->rnd_diff[j] = self->rnd_value[j] - self->rnd_oldValue[j];
             }
             self->rnd[j] = self->rnd_oldValue[j] + self->rnd_diff[j] * self->rnd_time[j];
-            
+
             xind = self->in_count[j] - (self->delays[j] + self->rnd[j]);
             if (xind < 0)
                 xind += self->size[j];
@@ -299,7 +302,7 @@ WGVerb_process_aa(WGVerb *self) {
             val *= feed;
             filt = (self->lastSamples[j] - val) * self->damp + val;
             self->total_signal += filt;
-            
+
             self->buffer[j][self->in_count[j]] = inval + junction - self->lastSamples[j];
             self->lastSamples[j] = filt;
             if(self->in_count[j] == 0)
@@ -307,24 +310,24 @@ WGVerb_process_aa(WGVerb *self) {
             self->in_count[j]++;
             if (self->in_count[j] >= self->size[j])
                 self->in_count[j] = 0;
-        } 
+        }
         self->data[i] = self->total_signal * 0.25;
-    } 
+    }
 }
 
 static void
 WGVerb_mix_i(WGVerb *self) {
     int i;
     MYFLT val;
-    
+
     MYFLT mix = PyFloat_AS_DOUBLE(self->mix);
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     if (mix < 0.0)
         mix = 0.0;
     else if (mix > 1.0)
         mix = 1.0;
-    
+
     for (i=0; i<self->bufsize; i++) {
         val = in[i] * (1.0 - mix) + self->data[i] * mix;
         self->data[i] = val;
@@ -335,17 +338,17 @@ static void
 WGVerb_mix_a(WGVerb *self) {
     int i;
     MYFLT mix, val;
-    
+
     MYFLT *mi = Stream_getData((Stream *)self->mix_stream);
     MYFLT *in = Stream_getData((Stream *)self->input_stream);
-    
+
     for (i=0; i<self->bufsize; i++) {
         mix = mi[i];
         if (mix < 0.0)
             mix = 0.0;
         else if (mix > 1.0)
             mix = 1.0;
-        
+
         val = in[i] * (1.0 - mix) + self->data[i] * mix;
         self->data[i] = val;
     }
@@ -368,66 +371,66 @@ WGVerb_setProcMode(WGVerb *self)
     procmode = self->modebuffer[2] + self->modebuffer[3] * 10;
     muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
     mixmode = self->modebuffer[4];
-    
+
 	switch (procmode) {
-        case 0:    
+        case 0:
             self->proc_func_ptr = WGVerb_process_ii;
             break;
-        case 1:    
+        case 1:
             self->proc_func_ptr = WGVerb_process_ai;
             break;
-        case 10:    
+        case 10:
             self->proc_func_ptr = WGVerb_process_ia;
             break;
-        case 11:    
+        case 11:
             self->proc_func_ptr = WGVerb_process_aa;
             break;
-    } 
+    }
     switch (mixmode) {
-        case 0:    
+        case 0:
             self->mix_func_ptr = WGVerb_mix_i;
             break;
-        case 1:    
+        case 1:
             self->mix_func_ptr = WGVerb_mix_a;
             break;
-    }        
-            
+    }
+
 	switch (muladdmode) {
-        case 0:        
+        case 0:
             self->muladd_func_ptr = WGVerb_postprocessing_ii;
             break;
-        case 1:    
+        case 1:
             self->muladd_func_ptr = WGVerb_postprocessing_ai;
             break;
-        case 2:    
+        case 2:
             self->muladd_func_ptr = WGVerb_postprocessing_revai;
             break;
-        case 10:        
+        case 10:
             self->muladd_func_ptr = WGVerb_postprocessing_ia;
             break;
-        case 11:    
+        case 11:
             self->muladd_func_ptr = WGVerb_postprocessing_aa;
             break;
-        case 12:    
+        case 12:
             self->muladd_func_ptr = WGVerb_postprocessing_revaa;
             break;
-        case 20:        
+        case 20:
             self->muladd_func_ptr = WGVerb_postprocessing_ireva;
             break;
-        case 21:    
+        case 21:
             self->muladd_func_ptr = WGVerb_postprocessing_areva;
             break;
-        case 22:    
+        case 22:
             self->muladd_func_ptr = WGVerb_postprocessing_revareva;
             break;
-    } 
+    }
 }
 
 static void
 WGVerb_compute_next_data_frame(WGVerb *self)
 {
-    (*self->proc_func_ptr)(self); 
-    (*self->mix_func_ptr)(self); 
+    (*self->proc_func_ptr)(self);
+    (*self->mix_func_ptr)(self);
     (*self->muladd_func_ptr)(self);
 }
 
@@ -436,28 +439,28 @@ WGVerb_traverse(WGVerb *self, visitproc visit, void *arg)
 {
     pyo_VISIT
     Py_VISIT(self->input);
-    Py_VISIT(self->input_stream);    
-    Py_VISIT(self->feedback);    
-    Py_VISIT(self->feedback_stream);    
-    Py_VISIT(self->cutoff);    
-    Py_VISIT(self->cutoff_stream);    
-    Py_VISIT(self->mix);    
-    Py_VISIT(self->mix_stream);    
+    Py_VISIT(self->input_stream);
+    Py_VISIT(self->feedback);
+    Py_VISIT(self->feedback_stream);
+    Py_VISIT(self->cutoff);
+    Py_VISIT(self->cutoff_stream);
+    Py_VISIT(self->mix);
+    Py_VISIT(self->mix_stream);
     return 0;
 }
 
-static int 
+static int
 WGVerb_clear(WGVerb *self)
 {
     pyo_CLEAR
     Py_CLEAR(self->input);
-    Py_CLEAR(self->input_stream);    
-    Py_CLEAR(self->feedback);    
-    Py_CLEAR(self->feedback_stream);    
-    Py_CLEAR(self->cutoff);    
-    Py_CLEAR(self->cutoff_stream);    
-    Py_CLEAR(self->mix);    
-    Py_CLEAR(self->mix_stream);    
+    Py_CLEAR(self->input_stream);
+    Py_CLEAR(self->feedback);
+    Py_CLEAR(self->feedback_stream);
+    Py_CLEAR(self->cutoff);
+    Py_CLEAR(self->cutoff_stream);
+    Py_CLEAR(self->mix);
+    Py_CLEAR(self->mix_stream);
     return 0;
 }
 
@@ -468,9 +471,9 @@ WGVerb_dealloc(WGVerb* self)
     pyo_DEALLOC
     for (i=0; i<8; i++) {
         free(self->buffer[i]);
-    }    
+    }
     WGVerb_clear(self);
-    self->ob_type->tp_free((PyObject*)self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
 }
 
 static PyObject *
@@ -480,29 +483,23 @@ WGVerb_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyObject *inputtmp, *input_streamtmp, *feedbacktmp=NULL, *cutofftmp=NULL, *mixtmp=NULL, *multmp=NULL, *addtmp=NULL;
     WGVerb *self;
     self = (WGVerb *)type->tp_alloc(type, 0);
-    
+
     self->feedback = PyFloat_FromDouble(0.5);
     self->cutoff = PyFloat_FromDouble(5000.0);
     self->mix = PyFloat_FromDouble(0.5);
     self->lastFreq = self->damp = 0.0;
-    
-    for (i=0; i<8; i++) {
-        self->in_count[i] = 0;
-        self->lastSamples[i] = 0.0;
-        self->rnd_value[i] = self->rnd_oldValue[i] = self->rnd_diff[i] = 0.0;
-        self->rnd_time[i] = 1.0;
-    }    
+
     self->total_signal = 0.0;
 	self->modebuffer[0] = 0;
 	self->modebuffer[1] = 0;
 	self->modebuffer[2] = 0;
 	self->modebuffer[3] = 0;
 	self->modebuffer[4] = 0;
-    
+
     INIT_OBJECT_COMMON
     Stream_setFunctionPtr(self->stream, WGVerb_compute_next_data_frame);
     self->mode_func_ptr = WGVerb_setProcMode;
-    
+
     for (i=0; i<8; i++) {
         self->in_count[i] = 0;
         self->lastSamples[i] = 0.0;
@@ -515,12 +512,12 @@ WGVerb_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     }
 
     static char *kwlist[] = {"input", "feedback", "cutoff", "mix", "mul", "add", NULL};
-    
+
     if (! PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOOO", kwlist, &inputtmp, &feedbacktmp, &cutofftmp, &mixtmp, &multmp, &addtmp))
         Py_RETURN_NONE;
-    
+
     INIT_INPUT_STREAM
-       
+
     if (feedbacktmp) {
         PyObject_CallMethod((PyObject *)self, "setFeedback", "O", feedbacktmp);
     }
@@ -532,15 +529,15 @@ WGVerb_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     if (mixtmp) {
         PyObject_CallMethod((PyObject *)self, "setMix", "O", mixtmp);
     }
-    
+
     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);
 
     for (i=0; i<8; i++) {
@@ -548,9 +545,9 @@ WGVerb_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         self->buffer[i] = (MYFLT *)realloc(self->buffer[i], (self->size[i]+1) * sizeof(MYFLT));
         for (j=0; j<(self->size[i]+1); j++) {
             self->buffer[i][j] = 0.;
-        }    
-    }    
-    
+        }
+    }
+
     (*self->mode_func_ptr)(self);
 
     return (PyObject *)self;
@@ -558,10 +555,10 @@ WGVerb_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static PyObject * WGVerb_getServer(WGVerb* self) { GET_SERVER };
 static PyObject * WGVerb_getStream(WGVerb* self) { GET_STREAM };
-static PyObject * WGVerb_setMul(WGVerb *self, PyObject *arg) { SET_MUL };	
-static PyObject * WGVerb_setAdd(WGVerb *self, PyObject *arg) { SET_ADD };	
-static PyObject * WGVerb_setSub(WGVerb *self, PyObject *arg) { SET_SUB };	
-static PyObject * WGVerb_setDiv(WGVerb *self, PyObject *arg) { SET_DIV };	
+static PyObject * WGVerb_setMul(WGVerb *self, PyObject *arg) { SET_MUL };
+static PyObject * WGVerb_setAdd(WGVerb *self, PyObject *arg) { SET_ADD };
+static PyObject * WGVerb_setSub(WGVerb *self, PyObject *arg) { SET_SUB };
+static PyObject * WGVerb_setDiv(WGVerb *self, PyObject *arg) { SET_DIV };
 
 static PyObject * WGVerb_play(WGVerb *self, PyObject *args, PyObject *kwds) { PLAY };
 static PyObject * WGVerb_out(WGVerb *self, PyObject *args, PyObject *kwds) { OUT };
@@ -577,17 +574,30 @@ static PyObject * WGVerb_div(WGVerb *self, PyObject *arg) { DIV };
 static PyObject * WGVerb_inplace_div(WGVerb *self, PyObject *arg) { INPLACE_DIV };
 
 static PyObject *
+WGVerb_reset(WGVerb *self)
+{
+    int i, j;
+    for (i=0; i<8; i++) {
+        self->in_count[i] = 0;
+        self->lastSamples[i] = 0.0;
+        for (j=0; j<(self->size[i]+1); j++) {
+            self->buffer[i][j] = 0.;
+        }
+    }
+    self->total_signal = 0.0;
+
+	Py_RETURN_NONE;
+}
+
+static PyObject *
 WGVerb_setFeedback(WGVerb *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-    
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->feedback);
@@ -603,25 +613,22 @@ WGVerb_setFeedback(WGVerb *self, PyObject *arg)
         self->feedback_stream = (Stream *)streamtmp;
 		self->modebuffer[2] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 WGVerb_setCutoff(WGVerb *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-    
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->cutoff);
@@ -637,25 +644,22 @@ WGVerb_setCutoff(WGVerb *self, PyObject *arg)
         self->cutoff_stream = (Stream *)streamtmp;
 		self->modebuffer[3] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyObject *
 WGVerb_setMix(WGVerb *self, PyObject *arg)
 {
 	PyObject *tmp, *streamtmp;
-	
-	if (arg == NULL) {
-		Py_INCREF(Py_None);
-		return Py_None;
-	}
-    
+
+    ASSERT_ARG_NOT_NULL
+
 	int isNumber = PyNumber_Check(arg);
-    
+
 	tmp = arg;
 	Py_INCREF(tmp);
 	Py_DECREF(self->mix);
@@ -671,12 +675,12 @@ WGVerb_setMix(WGVerb *self, PyObject *arg)
         self->mix_stream = (Stream *)streamtmp;
 		self->modebuffer[4] = 1;
 	}
-    
+
     (*self->mode_func_ptr)(self);
-    
+
 	Py_INCREF(Py_None);
 	return Py_None;
-}	
+}
 
 static PyMemberDef WGVerb_members[] = {
 {"server", T_OBJECT_EX, offsetof(WGVerb, server), 0, "Pyo server."},
@@ -696,6 +700,7 @@ static PyMethodDef WGVerb_methods[] = {
 {"play", (PyCFunction)WGVerb_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
 {"out", (PyCFunction)WGVerb_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
 {"stop", (PyCFunction)WGVerb_stop, METH_NOARGS, "Stops computing."},
+{"reset", (PyCFunction)WGVerb_reset, METH_NOARGS, "Reset the delay line."},
 {"setFeedback", (PyCFunction)WGVerb_setFeedback, METH_O, "Sets feedback value between 0 -> 1."},
 {"setCutoff", (PyCFunction)WGVerb_setCutoff, METH_O, "Sets lowpass filter cutoff."},
 {"setMix", (PyCFunction)WGVerb_setMix, METH_O, "Sets balance between dry and wet signals."},
@@ -710,7 +715,7 @@ static PyNumberMethods WGVerb_as_number = {
 (binaryfunc)WGVerb_add,                      /*nb_add*/
 (binaryfunc)WGVerb_sub,                 /*nb_subtract*/
 (binaryfunc)WGVerb_multiply,                 /*nb_multiply*/
-(binaryfunc)WGVerb_div,                   /*nb_divide*/
+INITIALIZE_NB_DIVIDE_ZERO               /*nb_divide*/
 0,                /*nb_remainder*/
 0,                   /*nb_divmod*/
 0,                   /*nb_power*/
@@ -724,16 +729,16 @@ static PyNumberMethods WGVerb_as_number = {
 0,              /*nb_and*/
 0,              /*nb_xor*/
 0,               /*nb_or*/
-0,                                          /*nb_coerce*/
+INITIALIZE_NB_COERCE_ZERO                   /*nb_coerce*/
 0,                       /*nb_int*/
 0,                      /*nb_long*/
 0,                     /*nb_float*/
-0,                       /*nb_oct*/
-0,                       /*nb_hex*/
+INITIALIZE_NB_OCT_ZERO   /*nb_oct*/
+INITIALIZE_NB_HEX_ZERO   /*nb_hex*/
 (binaryfunc)WGVerb_inplace_add,              /*inplace_add*/
 (binaryfunc)WGVerb_inplace_sub,         /*inplace_subtract*/
 (binaryfunc)WGVerb_inplace_multiply,         /*inplace_multiply*/
-(binaryfunc)WGVerb_inplace_div,           /*inplace_divide*/
+INITIALIZE_NB_IN_PLACE_DIVIDE_ZERO        /*inplace_divide*/
 0,        /*inplace_remainder*/
 0,           /*inplace_power*/
 0,       /*inplace_lshift*/
@@ -742,15 +747,14 @@ static PyNumberMethods WGVerb_as_number = {
 0,      /*inplace_xor*/
 0,       /*inplace_or*/
 0,             /*nb_floor_divide*/
-0,              /*nb_true_divide*/
+(binaryfunc)WGVerb_div,                       /*nb_true_divide*/
 0,     /*nb_inplace_floor_divide*/
-0,      /*nb_inplace_true_divide*/
+(binaryfunc)WGVerb_inplace_div,                       /*nb_inplace_true_divide*/
 0,                     /* nb_index */
 };
 
 PyTypeObject WGVerbType = {
-PyObject_HEAD_INIT(NULL)
-0,                         /*ob_size*/
+PyVarObject_HEAD_INIT(NULL, 0)
 "_pyo.WGVerb_base",         /*tp_name*/
 sizeof(WGVerb),         /*tp_basicsize*/
 0,                         /*tp_itemsize*/
@@ -758,7 +762,7 @@ sizeof(WGVerb),         /*tp_basicsize*/
 0,                         /*tp_print*/
 0,                         /*tp_getattr*/
 0,                         /*tp_setattr*/
-0,                         /*tp_compare*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
 0,                         /*tp_repr*/
 &WGVerb_as_number,             /*tp_as_number*/
 0,                         /*tp_as_sequence*/
@@ -770,7 +774,7 @@ sizeof(WGVerb),         /*tp_basicsize*/
 0,                         /*tp_setattro*/
 0,                         /*tp_as_buffer*/
 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
-"WGVerb objects. WGVerb signal by x samples.",           /* tp_doc */
+"WGVerb objects. Waveguide-based reverberation network.",           /* tp_doc */
 (traverseproc)WGVerb_traverse,   /* tp_traverse */
 (inquiry)WGVerb_clear,           /* tp_clear */
 0,		               /* tp_richcompare */
@@ -789,3 +793,1344 @@ WGVerb_members,             /* tp_members */
 0,                         /* tp_alloc */
 WGVerb_new,                 /* tp_new */
 };
+
+/***************/
+/**** STRev ****/
+/***************/
+typedef struct {
+    pyo_audio_HEAD
+    PyObject *input;
+    Stream *input_stream;
+    PyObject *inpos;
+    Stream *inpos_stream;
+    PyObject *revtime;
+    Stream *revtime_stream;
+    PyObject *cutoff;
+    Stream *cutoff_stream;
+    PyObject *mix;
+    Stream *mix_stream;
+    void (*mix_func_ptr)();
+    int modebuffer[4];
+    MYFLT firstRefGain;
+    MYFLT total_signal[2];
+    MYFLT delays[2][8];
+    long size[2][8];
+    int in_count[2][8];
+    MYFLT *buffer[2][8];
+    MYFLT *ref_buffer[NUM_REFS];
+    int ref_size[NUM_REFS];
+    int ref_in_count[NUM_REFS];
+    MYFLT avg_time;
+    MYFLT srfac;
+    // lowpass
+    MYFLT damp[2];
+    MYFLT lastFreq;
+    MYFLT nyquist;
+    MYFLT lastInpos;
+    // sample memories
+    MYFLT lastSamples[2][8];
+    // jitters
+    MYFLT rnd[2][8];
+    MYFLT rnd_value[2][8];
+    MYFLT rnd_oldValue[2][8];
+    MYFLT rnd_diff[2][8];
+    MYFLT rnd_time[2][8];
+    MYFLT rnd_timeInc[2][8];
+    MYFLT rnd_range[2][8];
+    MYFLT rnd_halfRange[2][8];
+    MYFLT *buffer_streams;
+    MYFLT *input_buffer[2];
+} STReverb;
+
+static void
+STReverb_process_ii(STReverb *self) {
+    int i, j, k, k2, ind, half;
+    MYFLT val, x, x1, xind, frac, junction, inval, filt, amp1, amp2, b, f, sum_ref, feed, step, invp;
+    MYFLT ref_amp_l[NUM_REFS];
+    MYFLT ref_amp_r[NUM_REFS];
+    MYFLT ref_buf[2];
+
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+    MYFLT inpos = PyFloat_AS_DOUBLE(self->inpos);
+    if (self->modebuffer[1] == 0)
+        feed = PyFloat_AS_DOUBLE(self->revtime);
+    else
+        feed = Stream_getData((Stream *)self->revtime_stream)[0];
+    MYFLT freq = PyFloat_AS_DOUBLE(self->cutoff);
+
+    if (inpos < 0.0)
+        inpos = 0.0;
+    else if (inpos > 1.0)
+        inpos = 1.0;
+
+    if (feed < 0.01)
+        feed = 0.01;
+    feed = MYPOW(100.0, -self->avg_time/feed);
+
+    if (freq < 20.0)
+        freq = 20.0;
+    else if (freq > self->nyquist)
+        freq = self->nyquist;
+
+    if (freq != self->lastFreq || inpos != self->lastInpos) {
+        self->lastFreq = freq;
+        self->lastInpos = inpos;
+        f = ((1.0 - inpos) * 0.3 + 0.7) * freq;
+        b = 2.0 - MYCOS(TWOPI * f / self->sr);
+        self->damp[0] = (b - MYSQRT(b * b - 1.0));
+        f = (inpos * 0.3 + 0.7) * freq;
+        b = 2.0 - MYCOS(TWOPI * f / self->sr);
+        self->damp[1] = (b - MYSQRT(b * b - 1.0));
+    }
+
+    /* position of the source and first reflexions */
+    amp1 = 1.0 - inpos;
+    amp2 = inpos;
+    half = (NUM_REFS - 1) / 2;
+    if (inpos <= 0.5) {
+        step = (0.5 - inpos) / half;
+        ref_amp_l[half] = ref_amp_r[half] = 0.5;
+        for (k=0; k<half; k++) {
+            k2 = NUM_REFS - 1 - k;
+            ref_amp_r[k] = ref_amp_l[k2] = inpos + step * k;
+            ref_amp_l[k] = ref_amp_r[k2] = 1.0 - ref_amp_r[k];
+            ref_amp_r[k2] *= inpos + 0.5;
+        }
+    }
+    else {
+        invp = 1.0 - inpos;
+        step = (0.5 - invp) / half;
+        ref_amp_l[half] = ref_amp_r[half] = 0.5;
+        for (k=0; k<half; k++) {
+            k2 = NUM_REFS - 1 - k;
+            ref_amp_l[k] = ref_amp_r[k2] = invp + step * k;
+            ref_amp_r[k] = ref_amp_l[k2] = 1.0 - ref_amp_l[k];
+            ref_amp_l[k2] *= invp + 0.5;
+        }
+    }
+
+    for (i=0; i<self->bufsize; i++) {
+        self->input_buffer[0][i] = in[i] * amp1;
+        self->input_buffer[1][i] = in[i] * amp2;
+        ref_buf[0] = ref_buf[1] = 0.0;
+        for (k=0; k<NUM_REFS; k++) {
+            sum_ref = self->ref_buffer[k][self->ref_in_count[k]];
+            self->ref_buffer[k][self->ref_in_count[k]] = in[i];
+            self->ref_in_count[k]++;
+            if (self->ref_in_count[k] == self->ref_size[k])
+                self->ref_in_count[k] = 0;
+            ref_buf[0] += sum_ref * ref_amp_l[k];
+            ref_buf[1] += sum_ref * ref_amp_r[k];
+        }
+        for (k=0; k<2; k++) {
+            inval = self->input_buffer[k][i] * 0.8 + self->input_buffer[1-k][i] * 0.2 + ref_buf[k] * 0.1;
+            junction = self->total_signal[k] * .25;
+            self->total_signal[k] = ref_buf[k] * self->firstRefGain;
+            for (j=0; j<8; j++) {
+                self->rnd_time[k][j] += self->rnd_timeInc[k][j];
+                if (self->rnd_time[k][j] < 0.0)
+                    self->rnd_time[k][j] += 1.0;
+                else if (self->rnd_time[k][j] >= 1.0) {
+                    self->rnd_time[k][j] -= 1.0;
+                    self->rnd_oldValue[k][j] = self->rnd_value[k][j];
+                    self->rnd_value[k][j] = self->rnd_range[k][j] * RANDOM_UNIFORM - self->rnd_halfRange[k][j];
+                    self->rnd_diff[k][j] = self->rnd_value[k][j] - self->rnd_oldValue[k][j];
+                }
+                self->rnd[k][j] = self->rnd_oldValue[k][j] + self->rnd_diff[k][j] * self->rnd_time[k][j];
+
+                xind = self->in_count[k][j] - (self->delays[k][j] + self->rnd[k][j]);
+                if (xind < 0)
+                    xind += self->size[k][j];
+                ind = (int)xind;
+                frac = xind - ind;
+                x = self->buffer[k][j][ind];
+                x1 = self->buffer[k][j][ind+1];
+                val = x + (x1 - x) * frac;
+                val *= feed;
+                filt = val + (self->lastSamples[k][j] - val) * self->damp[k];
+                self->total_signal[k] += filt;
+
+                self->buffer[k][j][self->in_count[k][j]] = inval + junction - self->lastSamples[k][j];
+                self->lastSamples[k][j] = filt;
+                if(self->in_count[k][j] == 0)
+                    self->buffer[k][j][self->size[k][j]] = self->buffer[k][j][0];
+                self->in_count[k][j]++;
+                if (self->in_count[k][j] >= self->size[k][j])
+                    self->in_count[k][j] = 0;
+            }
+            self->buffer_streams[i+k*self->bufsize] = self->total_signal[k] * 0.25;
+        }
+    }
+}
+
+static void
+STReverb_process_ai(STReverb *self) {
+    MYFLT val, x, x1, xind, frac, junction, inval, filt, amp1, amp2, b, f, sum_ref, inpos, feed, step, invp;
+    MYFLT ref_amp_l[NUM_REFS];
+    MYFLT ref_amp_r[NUM_REFS];
+    MYFLT ref_buf[2];
+    int i, j, k, k2, ind, half;
+
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+    MYFLT *pos = Stream_getData((Stream *)self->inpos_stream);
+    if (self->modebuffer[1] == 0)
+        feed = PyFloat_AS_DOUBLE(self->revtime);
+    else
+        feed = Stream_getData((Stream *)self->revtime_stream)[0];
+    MYFLT freq = PyFloat_AS_DOUBLE(self->cutoff);
+
+    if (feed < 0.01)
+        feed = 0.01;
+    feed = MYPOW(100.0, -self->avg_time/feed);
+
+    if (freq < 20.0)
+        freq = 20.0;
+    else if (freq > self->nyquist)
+        freq = self->nyquist;
+
+    for (i=0; i<self->bufsize; i++) {
+        inpos = pos[i];
+        if (inpos < 0.0)
+            inpos = 0.0;
+        else if (inpos > 1.0)
+            inpos = 1.0;
+        if (freq != self->lastFreq || inpos != self->lastInpos) {
+            self->lastFreq = freq;
+            self->lastInpos = inpos;
+            f = ((1.0 - inpos) * 0.3 + 0.7) * freq;
+            b = 2.0 - MYCOS(TWOPI * f / self->sr);
+            self->damp[0] = (b - MYSQRT(b * b - 1.0));
+            f = (inpos * 0.3 + 0.7) * freq;
+            b = 2.0 - MYCOS(TWOPI * f / self->sr);
+            self->damp[1] = (b - MYSQRT(b * b - 1.0));
+        }
+
+        /* position of the source and first reflexions */
+        amp1 = 1.0 - inpos;
+        amp2 = inpos;
+        half = (NUM_REFS - 1) / 2;
+        if (inpos <= 0.5) {
+            step = (0.5 - inpos) / half;
+            ref_amp_l[half] = ref_amp_r[half] = 0.5;
+            for (k=0; k<half; k++) {
+                k2 = NUM_REFS - 1 - k;
+                ref_amp_r[k] = ref_amp_l[k2] = inpos + step * k;
+                ref_amp_l[k] = ref_amp_r[k2] = 1.0 - ref_amp_r[k];
+                ref_amp_r[k2] *= inpos + 0.5;
+            }
+        }
+        else {
+            invp = 1.0 - inpos;
+            step = (0.5 - invp) / half;
+            ref_amp_l[half] = ref_amp_r[half] = 0.5;
+            for (k=0; k<half; k++) {
+                k2 = NUM_REFS - 1 - k;
+                ref_amp_l[k] = ref_amp_r[k2] = invp + step * k;
+                ref_amp_r[k] = ref_amp_l[k2] = 1.0 - ref_amp_l[k];
+                ref_amp_l[k2] *= invp + 0.5;
+            }
+        }
+
+        self->input_buffer[0][i] = in[i] * amp1;
+        self->input_buffer[1][i] = in[i] * amp2;
+        ref_buf[0] = ref_buf[1] = 0.0;
+        for (k=0; k<NUM_REFS; k++) {
+            sum_ref = self->ref_buffer[k][self->ref_in_count[k]];
+            self->ref_buffer[k][self->ref_in_count[k]] = in[i];
+            self->ref_in_count[k]++;
+            if (self->ref_in_count[k] == self->ref_size[k])
+                self->ref_in_count[k] = 0;
+            ref_buf[0] += sum_ref * ref_amp_l[k];
+            ref_buf[1] += sum_ref * ref_amp_r[k];
+        }
+        for (k=0; k<2; k++) {
+            inval = self->input_buffer[k][i] * 0.8 + self->input_buffer[1-k][i] * 0.2 + ref_buf[k] * 0.1;
+            junction = self->total_signal[k] * .25;
+            self->total_signal[k] = ref_buf[k] * self->firstRefGain;
+            for (j=0; j<8; j++) {
+                self->rnd_time[k][j] += self->rnd_timeInc[k][j];
+                if (self->rnd_time[k][j] < 0.0)
+                    self->rnd_time[k][j] += 1.0;
+                else if (self->rnd_time[k][j] >= 1.0) {
+                    self->rnd_time[k][j] -= 1.0;
+                    self->rnd_oldValue[k][j] = self->rnd_value[k][j];
+                    self->rnd_value[k][j] = self->rnd_range[k][j] * RANDOM_UNIFORM - self->rnd_halfRange[k][j];
+                    self->rnd_diff[k][j] = self->rnd_value[k][j] - self->rnd_oldValue[k][j];
+                }
+                self->rnd[k][j] = self->rnd_oldValue[k][j] + self->rnd_diff[k][j] * self->rnd_time[k][j];
+
+                xind = self->in_count[k][j] - (self->delays[k][j] + self->rnd[k][j]);
+                if (xind < 0)
+                    xind += self->size[k][j];
+                ind = (int)xind;
+                frac = xind - ind;
+                x = self->buffer[k][j][ind];
+                x1 = self->buffer[k][j][ind+1];
+                val = x + (x1 - x) * frac;
+                val *= feed;
+                filt = val + (self->lastSamples[k][j] - val) * self->damp[k];
+                self->total_signal[k] += filt;
+
+                self->buffer[k][j][self->in_count[k][j]] = inval + junction - self->lastSamples[k][j];
+                self->lastSamples[k][j] = filt;
+                if(self->in_count[k][j] == 0)
+                    self->buffer[k][j][self->size[k][j]] = self->buffer[k][j][0];
+                self->in_count[k][j]++;
+                if (self->in_count[k][j] >= self->size[k][j])
+                    self->in_count[k][j] = 0;
+            }
+            self->buffer_streams[i+k*self->bufsize] = self->total_signal[k] * 0.25;
+        }
+    }
+}
+
+static void
+STReverb_process_ia(STReverb *self) {
+    MYFLT val, x, x1, xind, frac, junction, inval, filt, amp1, amp2, b, f, sum_ref, feed, freq, step, invp;
+    MYFLT ref_amp_l[NUM_REFS];
+    MYFLT ref_amp_r[NUM_REFS];
+    MYFLT ref_buf[2];
+    int i, j, k, k2, ind, half;
+
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+    MYFLT inpos = PyFloat_AS_DOUBLE(self->inpos);
+    if (self->modebuffer[1] == 0)
+        feed = PyFloat_AS_DOUBLE(self->revtime);
+    else
+        feed = Stream_getData((Stream *)self->revtime_stream)[0];
+    MYFLT *fr = Stream_getData((Stream *)self->cutoff_stream);
+
+    if (inpos < 0.0)
+        inpos = 0.0;
+    else if (inpos > 1.0)
+        inpos = 1.0;
+
+    if (feed < 0.01)
+        feed = 0.01;
+    feed = MYPOW(100.0, -self->avg_time/feed);
+
+    /* position of the source and first reflexions */
+    amp1 = 1.0 - inpos;
+    amp2 = inpos;
+    half = (NUM_REFS - 1) / 2;
+    if (inpos <= 0.5) {
+        step = (0.5 - inpos) / half;
+        ref_amp_l[half] = ref_amp_r[half] = 0.5;
+        for (k=0; k<half; k++) {
+            k2 = NUM_REFS - 1 - k;
+            ref_amp_r[k] = ref_amp_l[k2] = inpos + step * k;
+            ref_amp_l[k] = ref_amp_r[k2] = 1.0 - ref_amp_r[k];
+            ref_amp_r[k2] *= inpos + 0.5;
+        }
+    }
+    else {
+        invp = 1.0 - inpos;
+        step = (0.5 - invp) / half;
+        ref_amp_l[half] = ref_amp_r[half] = 0.5;
+        for (k=0; k<half; k++) {
+            k2 = NUM_REFS - 1 - k;
+            ref_amp_l[k] = ref_amp_r[k2] = invp + step * k;
+            ref_amp_r[k] = ref_amp_l[k2] = 1.0 - ref_amp_l[k];
+            ref_amp_l[k2] *= invp + 0.5;
+        }
+    }
+
+    for (i=0; i<self->bufsize; i++) {
+        freq = fr[i];
+        if (freq < 20.0)
+            freq = 20.0;
+        else if (freq > self->nyquist)
+            freq = self->nyquist;
+
+        if (freq != self->lastFreq || inpos != self->lastInpos) {
+            self->lastFreq = freq;
+            self->lastInpos = inpos;
+            f = ((1.0 - inpos) * 0.3 + 0.7) * freq;
+            b = 2.0 - MYCOS(TWOPI * f / self->sr);
+            self->damp[0] = (b - MYSQRT(b * b - 1.0));
+            f = (inpos * 0.3 + 0.7) * freq;
+            b = 2.0 - MYCOS(TWOPI * f / self->sr);
+            self->damp[1] = (b - MYSQRT(b * b - 1.0));
+        }
+
+        self->input_buffer[0][i] = in[i] * amp1;
+        self->input_buffer[1][i] = in[i] * amp2;
+        ref_buf[0] = ref_buf[1] = 0.0;
+        for (k=0; k<NUM_REFS; k++) {
+            sum_ref = self->ref_buffer[k][self->ref_in_count[k]];
+            self->ref_buffer[k][self->ref_in_count[k]] = in[i];
+            self->ref_in_count[k]++;
+            if (self->ref_in_count[k] == self->ref_size[k])
+                self->ref_in_count[k] = 0;
+            ref_buf[0] += sum_ref * ref_amp_l[k];
+            ref_buf[1] += sum_ref * ref_amp_r[k];
+        }
+        for (k=0; k<2; k++) {
+            inval = self->input_buffer[k][i] * 0.8 + self->input_buffer[1-k][i] * 0.2 + ref_buf[k] * 0.1;
+            junction = self->total_signal[k] * .25;
+            self->total_signal[k] = ref_buf[k] * self->firstRefGain;
+            for (j=0; j<8; j++) {
+                self->rnd_time[k][j] += self->rnd_timeInc[k][j];
+                if (self->rnd_time[k][j] < 0.0)
+                    self->rnd_time[k][j] += 1.0;
+                else if (self->rnd_time[k][j] >= 1.0) {
+                    self->rnd_time[k][j] -= 1.0;
+                    self->rnd_oldValue[k][j] = self->rnd_value[k][j];
+                    self->rnd_value[k][j] = self->rnd_range[k][j] * RANDOM_UNIFORM - self->rnd_halfRange[k][j];
+                    self->rnd_diff[k][j] = self->rnd_value[k][j] - self->rnd_oldValue[k][j];
+                }
+                self->rnd[k][j] = self->rnd_oldValue[k][j] + self->rnd_diff[k][j] * self->rnd_time[k][j];
+
+                xind = self->in_count[k][j] - (self->delays[k][j] + self->rnd[k][j]);
+                if (xind < 0)
+                    xind += self->size[k][j];
+                ind = (int)xind;
+                frac = xind - ind;
+                x = self->buffer[k][j][ind];
+                x1 = self->buffer[k][j][ind+1];
+                val = x + (x1 - x) * frac;
+                val *= feed;
+                filt = val + (self->lastSamples[k][j] - val) * self->damp[k];
+                self->total_signal[k] += filt;
+
+                self->buffer[k][j][self->in_count[k][j]] = inval + junction - self->lastSamples[k][j];
+                self->lastSamples[k][j] = filt;
+                if(self->in_count[k][j] == 0)
+                    self->buffer[k][j][self->size[k][j]] = self->buffer[k][j][0];
+                self->in_count[k][j]++;
+                if (self->in_count[k][j] >= self->size[k][j])
+                    self->in_count[k][j] = 0;
+            }
+            self->buffer_streams[i+k*self->bufsize] = self->total_signal[k] * 0.25;
+        }
+    }
+}
+
+static void
+STReverb_process_aa(STReverb *self) {
+    MYFLT val, x, x1, xind, frac, junction, inval, filt, amp1, amp2, b, f, sum_ref, inpos, feed, freq, step, invp;
+    MYFLT ref_amp_l[NUM_REFS];
+    MYFLT ref_amp_r[NUM_REFS];
+    MYFLT ref_buf[2];
+    int i, j, k, k2, ind, half;
+
+    MYFLT *in = Stream_getData((Stream *)self->input_stream);
+    MYFLT *pos = Stream_getData((Stream *)self->inpos_stream);
+    if (self->modebuffer[1] == 0)
+        feed = PyFloat_AS_DOUBLE(self->revtime);
+    else
+        feed = Stream_getData((Stream *)self->revtime_stream)[0];
+    MYFLT *fr = Stream_getData((Stream *)self->cutoff_stream);
+
+    if (feed < 0.01)
+        feed = 0.01;
+    feed = MYPOW(100.0, -self->avg_time/feed);
+
+    for (i=0; i<self->bufsize; i++) {
+        inpos = pos[i];
+        freq = fr[i];
+        if (inpos < 0.0)
+            inpos = 0.0;
+        else if (inpos > 1.0)
+            inpos = 1.0;
+        if (freq < 20.0)
+            freq = 20.0;
+        else if (freq > self->nyquist)
+            freq = self->nyquist;
+
+        if (freq != self->lastFreq || inpos != self->lastInpos) {
+            self->lastFreq = freq;
+            self->lastInpos = inpos;
+            f = ((1.0 - inpos) * 0.3 + 0.7) * freq;
+            b = 2.0 - MYCOS(TWOPI * f / self->sr);
+            self->damp[0] = (b - MYSQRT(b * b - 1.0));
+            f = (inpos * 0.3 + 0.7) * freq;
+            b = 2.0 - MYCOS(TWOPI * f / self->sr);
+            self->damp[1] = (b - MYSQRT(b * b - 1.0));
+        }
+
+        /* position of the source and first reflexions */
+        amp1 = 1.0 - inpos;
+        amp2 = inpos;
+        half = (NUM_REFS - 1) / 2;
+        if (inpos <= 0.5) {
+            step = (0.5 - inpos) / half;
+            ref_amp_l[half] = ref_amp_r[half] = 0.5;
+            for (k=0; k<half; k++) {
+                k2 = NUM_REFS - 1 - k;
+                ref_amp_r[k] = ref_amp_l[k2] = inpos + step * k;
+                ref_amp_l[k] = ref_amp_r[k2] = 1.0 - ref_amp_r[k];
+                ref_amp_r[k2] *= inpos + 0.5;
+            }
+        }
+        else {
+            invp = 1.0 - inpos;
+            step = (0.5 - invp) / half;
+            ref_amp_l[half] = ref_amp_r[half] = 0.5;
+            for (k=0; k<half; k++) {
+                k2 = NUM_REFS - 1 - k;
+                ref_amp_l[k] = ref_amp_r[k2] = invp + step * k;
+                ref_amp_r[k] = ref_amp_l[k2] = 1.0 - ref_amp_l[k];
+                ref_amp_l[k2] *= invp + 0.5;
+            }
+        }
+
+        self->input_buffer[0][i] = in[i] * amp1;
+        self->input_buffer[1][i] = in[i] * amp2;
+        ref_buf[0] = ref_buf[1] = 0.0;
+        for (k=0; k<NUM_REFS; k++) {
+            sum_ref = self->ref_buffer[k][self->ref_in_count[k]];
+            self->ref_buffer[k][self->ref_in_count[k]] = in[i];
+            self->ref_in_count[k]++;
+            if (self->ref_in_count[k] == self->ref_size[k])
+                self->ref_in_count[k] = 0;
+            ref_buf[0] += sum_ref * ref_amp_l[k];
+            ref_buf[1] += sum_ref * ref_amp_r[k];
+        }
+        for (k=0; k<2; k++) {
+            inval = self->input_buffer[k][i] * 0.8 + self->input_buffer[1-k][i] * 0.2 + ref_buf[k] * 0.1;
+            junction = self->total_signal[k] * .25;
+            self->total_signal[k] = ref_buf[k] * self->firstRefGain;
+            for (j=0; j<8; j++) {
+                self->rnd_time[k][j] += self->rnd_timeInc[k][j];
+                if (self->rnd_time[k][j] < 0.0)
+                    self->rnd_time[k][j] += 1.0;
+                else if (self->rnd_time[k][j] >= 1.0) {
+                    self->rnd_time[k][j] -= 1.0;
+                    self->rnd_oldValue[k][j] = self->rnd_value[k][j];
+                    self->rnd_value[k][j] = self->rnd_range[k][j] * RANDOM_UNIFORM - self->rnd_halfRange[k][j];
+                    self->rnd_diff[k][j] = self->rnd_value[k][j] - self->rnd_oldValue[k][j];
+                }
+                self->rnd[k][j] = self->rnd_oldValue[k][j] + self->rnd_diff[k][j] * self->rnd_time[k][j];
+
+                xind = self->in_count[k][j] - (self->delays[k][j] + self->rnd[k][j]);
+                if (xind < 0)
+                    xind += self->size[k][j];
+                ind = (int)xind;
+                frac = xind - ind;
+                x = self->buffer[k][j][ind];
+                x1 = self->buffer[k][j][ind+1];
+                val = x + (x1 - x) * frac;
+                val *= feed;
+                filt = val + (self->lastSamples[k][j] - val) * self->damp[k];
+                self->total_signal[k] += filt;
+
+                self->buffer[k][j][self->in_count[k][j]] = inval + junction - self->lastSamples[k][j];
+                self->lastSamples[k][j] = filt;
+                if(self->in_count[k][j] == 0)
+                    self->buffer[k][j][self->size[k][j]] = self->buffer[k][j][0];
+                self->in_count[k][j]++;
+                if (self->in_count[k][j] >= self->size[k][j])
+                    self->in_count[k][j] = 0;
+            }
+            self->buffer_streams[i+k*self->bufsize] = self->total_signal[k] * 0.25;
+        }
+    }
+}
+
+static void
+STReverb_mix_i(STReverb *self) {
+    int i, k;
+    MYFLT val;
+
+    MYFLT mix = PyFloat_AS_DOUBLE(self->mix);
+
+    if (mix < 0.0)
+        mix = 0.0;
+    else if (mix > 1.0)
+        mix = 1.0;
+
+    for (i=0; i<self->bufsize; i++) {
+        for (k=0; k<2; k++) {
+            val = self->input_buffer[k][i] + (self->buffer_streams[i+k*self->bufsize] - self->input_buffer[k][i]) * mix;
+            self->buffer_streams[i+k*self->bufsize] = val;
+        }
+    }
+}
+
+static void
+STReverb_mix_a(STReverb *self) {
+    int i, k;
+    MYFLT mix, val;
+
+    MYFLT *mi = Stream_getData((Stream *)self->mix_stream);
+
+    for (i=0; i<self->bufsize; i++) {
+        mix = mi[i];
+        if (mix < 0.0)
+            mix = 0.0;
+        else if (mix > 1.0)
+            mix = 1.0;
+
+        for (k=0; k<2; k++) {
+            val = self->input_buffer[k][i] + (self->buffer_streams[i+k*self->bufsize] - self->input_buffer[k][i]) * mix;
+            self->buffer_streams[i+k*self->bufsize] = val;
+        }
+    }
+}
+
+static void
+STReverb_setProcMode(STReverb *self)
+{
+    int procmode, mixmode;
+    procmode = self->modebuffer[0] + self->modebuffer[2] * 10;
+    mixmode = self->modebuffer[3];
+
+	switch (procmode) {
+        case 0:
+            self->proc_func_ptr = STReverb_process_ii;
+            break;
+        case 1:
+            self->proc_func_ptr = STReverb_process_ai;
+            break;
+        case 10:
+            self->proc_func_ptr = STReverb_process_ia;
+            break;
+        case 11:
+            self->proc_func_ptr = STReverb_process_aa;
+            break;
+    }
+    switch (mixmode) {
+        case 0:
+            self->mix_func_ptr = STReverb_mix_i;
+            break;
+        case 1:
+            self->mix_func_ptr = STReverb_mix_a;
+            break;
+    }
+}
+
+MYFLT *
+STReverb_getSamplesBuffer(STReverb *self)
+{
+    return (MYFLT *)self->buffer_streams;
+}
+
+static void
+STReverb_compute_next_data_frame(STReverb *self)
+{
+    (*self->proc_func_ptr)(self);
+    (*self->mix_func_ptr)(self);
+}
+
+static int
+STReverb_traverse(STReverb *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->input);
+    Py_VISIT(self->input_stream);
+    Py_VISIT(self->inpos);
+    Py_VISIT(self->inpos_stream);
+    Py_VISIT(self->revtime);
+    Py_VISIT(self->revtime_stream);
+    Py_VISIT(self->cutoff);
+    Py_VISIT(self->cutoff_stream);
+    Py_VISIT(self->mix);
+    Py_VISIT(self->mix_stream);
+    return 0;
+}
+
+static int
+STReverb_clear(STReverb *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->input);
+    Py_CLEAR(self->input_stream);
+    Py_CLEAR(self->inpos);
+    Py_CLEAR(self->inpos_stream);
+    Py_CLEAR(self->revtime);
+    Py_CLEAR(self->revtime_stream);
+    Py_CLEAR(self->cutoff);
+    Py_CLEAR(self->cutoff_stream);
+    Py_CLEAR(self->mix);
+    Py_CLEAR(self->mix_stream);
+    return 0;
+}
+
+static void
+STReverb_dealloc(STReverb* self)
+{
+    int i, k;
+    pyo_DEALLOC
+    for (k=0; k<2; k++) {
+            free(self->input_buffer[k]);
+        for (i=0; i<8; i++) {
+            free(self->buffer[k][i]);
+        }
+    }
+    for (i=0; i<NUM_REFS; i++) {
+        free(self->ref_buffer[i]);
+    }
+    free(self->buffer_streams);
+    STReverb_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+STReverb_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i, j, k, din;
+    long maxsize;
+    MYFLT roomSize = 1.0;
+    MYFLT firstRefTmp = -3.0;
+    PyObject *inputtmp, *input_streamtmp, *inpostmp=NULL, *revtimetmp=NULL, *cutofftmp=NULL, *mixtmp=NULL;
+    STReverb *self;
+    self = (STReverb *)type->tp_alloc(type, 0);
+
+    self->inpos = PyFloat_FromDouble(0.5);
+    self->revtime = PyFloat_FromDouble(0.5);
+    self->cutoff = PyFloat_FromDouble(5000.0);
+    self->mix = PyFloat_FromDouble(0.5);
+    self->total_signal[0] = self->total_signal[1] = self->lastFreq = self->damp[0] = self->damp[1] = 0.0;
+    self->lastInpos = -1.0;
+	self->modebuffer[0] = 0;
+	self->modebuffer[1] = 0;
+	self->modebuffer[2] = 0;
+
+    INIT_OBJECT_COMMON
+
+    self->nyquist = self->sr * 0.49;
+    self->srfac = self->sr / 44100.0;
+
+    Stream_setFunctionPtr(self->stream, STReverb_compute_next_data_frame);
+    self->mode_func_ptr = STReverb_setProcMode;
+
+    static char *kwlist[] = {"input", "inpos", "revtime", "cutoff", "mix", "roomSize", "firstRefGain", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_O_OOOOFF, kwlist, &inputtmp, &inpostmp, &revtimetmp, &cutofftmp, &mixtmp, &roomSize, &firstRefTmp))
+        Py_RETURN_NONE;
+
+    INIT_INPUT_STREAM
+
+    if (inpostmp) {
+        PyObject_CallMethod((PyObject *)self, "setInpos", "O", inpostmp);
+    }
+
+    if (revtimetmp) {
+        PyObject_CallMethod((PyObject *)self, "setRevtime", "O", revtimetmp);
+    }
+
+    if (cutofftmp) {
+        PyObject_CallMethod((PyObject *)self, "setCutoff", "O", cutofftmp);
+    }
+
+    if (mixtmp) {
+        PyObject_CallMethod((PyObject *)self, "setMix", "O", mixtmp);
+    }
+
+    PyObject_CallMethod(self->server, "addStream", "O", self->stream);
+
+    self->firstRefGain = MYPOW(10.0, firstRefTmp * 0.05);
+    if (roomSize < 0.25)
+        roomSize = 0.25;
+    else if (roomSize > 4.0)
+        roomSize = 4.0;
+
+    self->avg_time = 0.0;
+    for (k=0; k<2; k++) {
+        din = k * 3;
+        for (i=0; i<8; i++) {
+            self->in_count[k][i] = 0;
+            self->lastSamples[k][i] = 0.0;
+            self->rnd[k][i] = self->rnd_value[k][i] = self->rnd_oldValue[k][i] = self->rnd_diff[k][i] = 0.0;
+            self->rnd_time[k][i] = 1.0;
+            self->rnd_timeInc[k][i] = reverbParams[i][2] * randomScaling / self->sr;
+            self->rnd_range[k][i] = reverbParams[i][1] * randomScaling * self->sr;
+            self->rnd_halfRange[k][i] = self->rnd_range[k][i] * 0.5;
+            self->delays[k][i] = reverbParams[i][din] * self->srfac * roomSize;
+            self->avg_time += self->delays[k][i] / self->sr;
+            self->size[k][i] = reverbParams[i][din] * self->srfac * roomSize + (int)(reverbParams[i][1] * self->sr + 0.5);
+            maxsize = reverbParams[i][din] * self->srfac * 4.0 + (int)(reverbParams[i][1] * self->sr + 0.5);
+            self->buffer[k][i] = (MYFLT *)realloc(self->buffer[k][i], (maxsize+1) * sizeof(MYFLT));
+            for (j=0; j<(maxsize+1); j++) {
+                self->buffer[k][i][j] = 0.;
+            }
+        }
+    }
+    self->avg_time /= 16.0;
+
+    for (k=0; k<NUM_REFS; k++) {
+        self->ref_in_count[k] = 0;
+        self->ref_size[k] = (int)(first_ref_delays[k] * self->srfac * roomSize + 0.5);
+        maxsize = (int)(first_ref_delays[k] * self->srfac * 4.0 + 0.5);
+        self->ref_buffer[k] = (MYFLT *)realloc(self->ref_buffer[k], (maxsize+1) * sizeof(MYFLT));
+        for (i=0; i<(maxsize+1); i++) {
+            self->ref_buffer[k][i] = 0.0;
+        }
+    }
+
+    for (k=0; k<2; k++) {
+        self->input_buffer[k] = (MYFLT *)realloc(self->input_buffer[k], self->bufsize * sizeof(MYFLT));
+        for (i=0; i<self->bufsize; i++) {
+            self->input_buffer[k][i] = 0.0;
+        }
+    }
+
+    self->buffer_streams = (MYFLT *)realloc(self->buffer_streams, 2 * self->bufsize * sizeof(MYFLT));
+    for (i=0; i<(2 * self->bufsize); i++) {
+        self->buffer_streams[i] = 0.0;
+    }
+
+    (*self->mode_func_ptr)(self);
+
+    return (PyObject *)self;
+}
+
+static PyObject * STReverb_getServer(STReverb* self) { GET_SERVER };
+static PyObject * STReverb_getStream(STReverb* self) { GET_STREAM };
+
+static PyObject * STReverb_play(STReverb *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * STReverb_stop(STReverb *self) { STOP };
+
+static PyObject *
+STReverb_reset(STReverb *self)
+{
+    int i, j, k, maxsize;
+    
+    for (k=0; k<2; k++) {
+        for (i=0; i<8; i++) {
+            self->in_count[k][i] = 0;
+            self->lastSamples[k][i] = 0.0;
+            for (j=0; j<self->size[k][i]; j++) {
+                self->buffer[k][i][j] = 0.;
+            }
+        }
+    }
+    for (k=0; k<NUM_REFS; k++) {
+        self->ref_in_count[k] = 0;
+        maxsize = (int)(first_ref_delays[k] * self->srfac * 4.0 + 0.5);
+        for (i=0; i<(maxsize+1); i++) {
+            self->ref_buffer[k][i] = 0.0;
+        }
+    }
+    for (k=0; k<2; k++) {
+        for (i=0; i<self->bufsize; i++) {
+            self->input_buffer[k][i] = 0.0;
+        }
+    }
+
+    for (i=0; i<(2 * self->bufsize); i++) {
+        self->buffer_streams[i] = 0.0;
+    }
+
+    self->total_signal[0] = self->total_signal[1] = 0.0;
+
+	Py_RETURN_NONE;
+}
+
+static PyObject *
+STReverb_setInpos(STReverb *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->inpos);
+	if (isNumber == 1) {
+		self->inpos = PyNumber_Float(tmp);
+        self->modebuffer[0] = 0;
+	}
+	else {
+		self->inpos = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->inpos, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->inpos_stream);
+        self->inpos_stream = (Stream *)streamtmp;
+		self->modebuffer[0] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+STReverb_setRevtime(STReverb *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->revtime);
+	if (isNumber == 1) {
+		self->revtime = PyNumber_Float(tmp);
+        self->modebuffer[1] = 0;
+	}
+	else {
+		self->revtime = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->revtime, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->revtime_stream);
+        self->revtime_stream = (Stream *)streamtmp;
+		self->modebuffer[1] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+STReverb_setCutoff(STReverb *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->cutoff);
+	if (isNumber == 1) {
+		self->cutoff = PyNumber_Float(tmp);
+        self->modebuffer[2] = 0;
+	}
+	else {
+		self->cutoff = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->cutoff, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->cutoff_stream);
+        self->cutoff_stream = (Stream *)streamtmp;
+		self->modebuffer[2] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+STReverb_setMix(STReverb *self, PyObject *arg)
+{
+	PyObject *tmp, *streamtmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	tmp = arg;
+	Py_INCREF(tmp);
+	Py_DECREF(self->mix);
+	if (isNumber == 1) {
+		self->mix = PyNumber_Float(tmp);
+        self->modebuffer[3] = 0;
+	}
+	else {
+		self->mix = tmp;
+        streamtmp = PyObject_CallMethod((PyObject *)self->mix, "_getStream", NULL);
+        Py_INCREF(streamtmp);
+        Py_XDECREF(self->mix_stream);
+        self->mix_stream = (Stream *)streamtmp;
+		self->modebuffer[3] = 1;
+	}
+
+    (*self->mode_func_ptr)(self);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+STReverb_setRoomSize(STReverb *self, PyObject *arg)
+{
+    int i, j, k, din;
+    long maxsize;
+	MYFLT roomSize;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	if (isNumber == 1) {
+        roomSize = PyFloat_AsDouble(arg);
+        if (roomSize < 0.25)
+            roomSize = 0.25;
+        else if (roomSize > 4.0)
+            roomSize = 4.0;
+
+        self->avg_time = 0.0;
+        for (k=0; k<2; k++) {
+            din = k * 3;
+            for (i=0; i<8; i++) {
+                self->in_count[k][i] = 0;
+                self->lastSamples[k][i] = 0.0;
+                self->rnd[k][i] = self->rnd_value[k][i] = self->rnd_oldValue[k][i] = self->rnd_diff[k][i] = 0.0;
+                self->rnd_time[k][i] = 1.0;
+                self->delays[k][i] = reverbParams[i][din] * self->srfac * roomSize;
+                self->avg_time += self->delays[k][i] / self->sr;
+                self->size[k][i] = reverbParams[i][din] * self->srfac * roomSize + (int)(reverbParams[i][1] * self->sr + 0.5);
+                maxsize = reverbParams[i][din] * self->srfac * 2 + (int)(reverbParams[i][1] * self->sr + 0.5);
+                for (j=0; j<(maxsize+1); j++) {
+                    self->buffer[k][i][j] = 0.;
+                }
+            }
+        }
+        self->avg_time /= 16.0;
+
+        for (k=0; k<NUM_REFS; k++) {
+            self->ref_in_count[k] = 0;
+            self->ref_size[k] = (int)(first_ref_delays[k] * self->srfac * roomSize + 0.5);
+            maxsize = (int)(first_ref_delays[k] * self->srfac * 2 + 0.5);
+            for (i=0; i<(maxsize+1); i++) {
+                self->ref_buffer[k][i] = 0.0;
+            }
+        }
+	}
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+STReverb_setFirstRefGain(STReverb *self, PyObject *arg)
+{
+	MYFLT tmp;
+
+    ASSERT_ARG_NOT_NULL
+
+	int isNumber = PyNumber_Check(arg);
+
+	if (isNumber == 1) {
+        tmp = PyFloat_AsDouble(arg);
+        self->firstRefGain = MYPOW(10.0, tmp * 0.05);
+	}
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyMemberDef STReverb_members[] = {
+{"server", T_OBJECT_EX, offsetof(STReverb, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(STReverb, stream), 0, "Stream object."},
+{"input", T_OBJECT_EX, offsetof(STReverb, input), 0, "Input sound object."},
+{"inpos", T_OBJECT_EX, offsetof(STReverb, inpos), 0, "Position left-right of the source."},
+{"revtime", T_OBJECT_EX, offsetof(STReverb, revtime), 0, "Reverb duration value."},
+{"cutoff", T_OBJECT_EX, offsetof(STReverb, cutoff), 0, "STReverb lowpass filter cutoff."},
+{"mix", T_OBJECT_EX, offsetof(STReverb, mix), 0, "Balance between dry and wet signals."},
+{NULL}  /* Sentinel */
+};
+
+static PyMethodDef STReverb_methods[] = {
+{"getServer", (PyCFunction)STReverb_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)STReverb_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)STReverb_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"stop", (PyCFunction)STReverb_stop, METH_NOARGS, "Stops computing."},
+{"reset", (PyCFunction)STReverb_reset, METH_NOARGS, "Reset the delay line."},
+{"setInpos", (PyCFunction)STReverb_setInpos, METH_O, "Sets position of the source between 0 -> 1."},
+{"setRevtime", (PyCFunction)STReverb_setRevtime, METH_O, "Sets reverb duration in seconds."},
+{"setCutoff", (PyCFunction)STReverb_setCutoff, METH_O, "Sets lowpass filter cutoff."},
+{"setMix", (PyCFunction)STReverb_setMix, METH_O, "Sets balance between dry and wet signals."},
+{"setFirstRefGain", (PyCFunction)STReverb_setFirstRefGain, METH_O, "Sets gain of the first reflexions."},
+{"setRoomSize", (PyCFunction)STReverb_setRoomSize, METH_O, "Sets room size scaler."},
+{NULL}  /* Sentinel */
+};
+
+PyTypeObject STReverbType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.STReverb_base",         /*tp_name*/
+sizeof(STReverb),         /*tp_basicsize*/
+0,                         /*tp_itemsize*/
+(destructor)STReverb_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*/
+"STReverb objects. Waveguide-based reverberation network.",           /* tp_doc */
+(traverseproc)STReverb_traverse,   /* tp_traverse */
+(inquiry)STReverb_clear,           /* tp_clear */
+0,		               /* tp_richcompare */
+0,		               /* tp_weaklistoffset */
+0,		               /* tp_iter */
+0,		               /* tp_iternext */
+STReverb_methods,             /* tp_methods */
+STReverb_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 */
+STReverb_new,                 /* tp_new */
+};
+
+/************************************************************************************************/
+/* STReverb streamer object */
+/************************************************************************************************/
+typedef struct {
+    pyo_audio_HEAD
+    STReverb *mainSplitter;
+    int modebuffer[2];
+    int chnl; // STRev order
+} STRev;
+
+static void STRev_postprocessing_ii(STRev *self) { POST_PROCESSING_II };
+static void STRev_postprocessing_ai(STRev *self) { POST_PROCESSING_AI };
+static void STRev_postprocessing_ia(STRev *self) { POST_PROCESSING_IA };
+static void STRev_postprocessing_aa(STRev *self) { POST_PROCESSING_AA };
+static void STRev_postprocessing_ireva(STRev *self) { POST_PROCESSING_IREVA };
+static void STRev_postprocessing_areva(STRev *self) { POST_PROCESSING_AREVA };
+static void STRev_postprocessing_revai(STRev *self) { POST_PROCESSING_REVAI };
+static void STRev_postprocessing_revaa(STRev *self) { POST_PROCESSING_REVAA };
+static void STRev_postprocessing_revareva(STRev *self) { POST_PROCESSING_REVAREVA };
+
+static void
+STRev_setProcMode(STRev *self)
+{
+    int muladdmode;
+    muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+	switch (muladdmode) {
+        case 0:
+            self->muladd_func_ptr = STRev_postprocessing_ii;
+            break;
+        case 1:
+            self->muladd_func_ptr = STRev_postprocessing_ai;
+            break;
+        case 2:
+            self->muladd_func_ptr = STRev_postprocessing_revai;
+            break;
+        case 10:
+            self->muladd_func_ptr = STRev_postprocessing_ia;
+            break;
+        case 11:
+            self->muladd_func_ptr = STRev_postprocessing_aa;
+            break;
+        case 12:
+            self->muladd_func_ptr = STRev_postprocessing_revaa;
+            break;
+        case 20:
+            self->muladd_func_ptr = STRev_postprocessing_ireva;
+            break;
+        case 21:
+            self->muladd_func_ptr = STRev_postprocessing_areva;
+            break;
+        case 22:
+            self->muladd_func_ptr = STRev_postprocessing_revareva;
+            break;
+    }
+}
+
+static void
+STRev_compute_next_data_frame(STRev *self)
+{
+    int i;
+    MYFLT *tmp;
+    int offset = self->chnl * self->bufsize;
+    tmp = STReverb_getSamplesBuffer((STReverb *)self->mainSplitter);
+    for (i=0; i<self->bufsize; i++) {
+        self->data[i] = tmp[i + offset];
+    }
+    (*self->muladd_func_ptr)(self);
+}
+
+static int
+STRev_traverse(STRev *self, visitproc visit, void *arg)
+{
+    pyo_VISIT
+    Py_VISIT(self->mainSplitter);
+    return 0;
+}
+
+static int
+STRev_clear(STRev *self)
+{
+    pyo_CLEAR
+    Py_CLEAR(self->mainSplitter);
+    return 0;
+}
+
+static void
+STRev_dealloc(STRev* self)
+{
+    pyo_DEALLOC
+    STRev_clear(self);
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static PyObject *
+STRev_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+    int i;
+    PyObject *maintmp=NULL, *multmp=NULL, *addtmp=NULL;
+    STRev *self;
+    self = (STRev *)type->tp_alloc(type, 0);
+
+	self->modebuffer[0] = 0;
+	self->modebuffer[1] = 0;
+
+    INIT_OBJECT_COMMON
+    Stream_setFunctionPtr(self->stream, STRev_compute_next_data_frame);
+    self->mode_func_ptr = STRev_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 = (STReverb *)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 * STRev_getServer(STRev* self) { GET_SERVER };
+static PyObject * STRev_getStream(STRev* self) { GET_STREAM };
+static PyObject * STRev_setMul(STRev *self, PyObject *arg) { SET_MUL };
+static PyObject * STRev_setAdd(STRev *self, PyObject *arg) { SET_ADD };
+static PyObject * STRev_setSub(STRev *self, PyObject *arg) { SET_SUB };
+static PyObject * STRev_setDiv(STRev *self, PyObject *arg) { SET_DIV };
+
+static PyObject * STRev_play(STRev *self, PyObject *args, PyObject *kwds) { PLAY };
+static PyObject * STRev_out(STRev *self, PyObject *args, PyObject *kwds) { OUT };
+static PyObject * STRev_stop(STRev *self) { STOP };
+
+static PyObject * STRev_multiply(STRev *self, PyObject *arg) { MULTIPLY };
+static PyObject * STRev_inplace_multiply(STRev *self, PyObject *arg) { INPLACE_MULTIPLY };
+static PyObject * STRev_add(STRev *self, PyObject *arg) { ADD };
+static PyObject * STRev_inplace_add(STRev *self, PyObject *arg) { INPLACE_ADD };
+static PyObject * STRev_sub(STRev *self, PyObject *arg) { SUB };
+static PyObject * STRev_inplace_sub(STRev *self, PyObject *arg) { INPLACE_SUB };
+static PyObject * STRev_div(STRev *self, PyObject *arg) { DIV };
+static PyObject * STRev_inplace_div(STRev *self, PyObject *arg) { INPLACE_DIV };
+
+static PyMemberDef STRev_members[] = {
+{"server", T_OBJECT_EX, offsetof(STRev, server), 0, "Pyo server."},
+{"stream", T_OBJECT_EX, offsetof(STRev, stream), 0, "Stream object."},
+{"mul", T_OBJECT_EX, offsetof(STRev, mul), 0, "Mul factor."},
+{"add", T_OBJECT_EX, offsetof(STRev, add), 0, "Add factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyMethodDef STRev_methods[] = {
+{"getServer", (PyCFunction)STRev_getServer, METH_NOARGS, "Returns server object."},
+{"_getStream", (PyCFunction)STRev_getStream, METH_NOARGS, "Returns stream object."},
+{"play", (PyCFunction)STRev_play, METH_VARARGS|METH_KEYWORDS, "Starts computing without sending sound to soundcard."},
+{"out", (PyCFunction)STRev_out, METH_VARARGS|METH_KEYWORDS, "Starts computing and sends sound to soundcard channel speficied by argument."},
+{"stop", (PyCFunction)STRev_stop, METH_NOARGS, "Stops computing."},
+{"setMul", (PyCFunction)STRev_setMul, METH_O, "Sets STRev mul factor."},
+{"setAdd", (PyCFunction)STRev_setAdd, METH_O, "Sets STRev add factor."},
+{"setSub", (PyCFunction)STRev_setSub, METH_O, "Sets inverse add factor."},
+{"setDiv", (PyCFunction)STRev_setDiv, METH_O, "Sets inverse mul factor."},
+{NULL}  /* Sentinel */
+};
+
+static PyNumberMethods STRev_as_number = {
+(binaryfunc)STRev_add,                      /*nb_add*/
+(binaryfunc)STRev_sub,                 /*nb_subtract*/
+(binaryfunc)STRev_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)STRev_inplace_add,              /*inplace_add*/
+(binaryfunc)STRev_inplace_sub,         /*inplace_subtract*/
+(binaryfunc)STRev_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)STRev_div,                       /*nb_true_divide*/
+0,     /*nb_inplace_floor_divide*/
+(binaryfunc)STRev_inplace_div,                       /*nb_inplace_true_divide*/
+0,                     /* nb_index */
+};
+
+PyTypeObject STRevType = {
+PyVarObject_HEAD_INIT(NULL, 0)
+"_pyo.STRev_base",         /*tp_name*/
+sizeof(STRev),         /*tp_basicsize*/
+0,                         /*tp_itemsize*/
+(destructor)STRev_dealloc, /*tp_dealloc*/
+0,                         /*tp_print*/
+0,                         /*tp_getattr*/
+0,                         /*tp_setattr*/
+0,                         /*tp_as_async (tp_compare in Python 2)*/
+0,                         /*tp_repr*/
+&STRev_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*/
+"STRev objects. Reads one channel from a STReverb object.",           /* tp_doc */
+(traverseproc)STRev_traverse,   /* tp_traverse */
+(inquiry)STRev_clear,           /* tp_clear */
+0,		               /* tp_richcompare */
+0,		               /* tp_weaklistoffset */
+0,		               /* tp_iter */
+0,		               /* tp_iternext */
+STRev_methods,             /* tp_methods */
+STRev_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 */
+STRev_new,                 /* tp_new */
+};
\ No newline at end of file
diff --git a/pyolib/snds/IRMediumHallStereo.wav "b/tests/b\303\251b\303\252tte/IRMediumHallStereo.wav"
similarity index 100%
copy from pyolib/snds/IRMediumHallStereo.wav
copy to "tests/b\303\251b\303\252tte/IRMediumHallStereo.wav"
diff --git "a/tests/b\303\251b\303\252tte/noise.aif" "b/tests/b\303\251b\303\252tte/noise.aif"
new file mode 100644
index 0000000..bcaf65a
Binary files /dev/null and "b/tests/b\303\251b\303\252tte/noise.aif" differ
diff --git a/pyolib/snds/transparent.aif "b/tests/b\303\251b\303\252tte/transparent.aif"
similarity index 100%
copy from pyolib/snds/transparent.aif
copy to "tests/b\303\251b\303\252tte/transparent.aif"
diff --git a/tests/encoding_test.py b/tests/encoding_test.py
new file mode 100644
index 0000000..e3629d7
--- /dev/null
+++ b/tests/encoding_test.py
@@ -0,0 +1,140 @@
+#! -*- encoding: utf-8 -*-
+import os
+import sys
+import locale
+from random import uniform
+from pyo import *
+
+### The encoding line is for E-Pyo tempfile only.
+### sys.getfilesystemencoding() should be used to set
+### the encoding line added by E-Pyo.
+
+print("Default encoding: ", sys.getdefaultencoding())
+print("File system encoding: ", sys.getfilesystemencoding())
+print("Locale preferred encoding: ", locale.getpreferredencoding())
+print("Locale default encoding: ", locale.getdefaultlocale())
+
+s = Server().boot()
+
+### Need a python layer to encode the path in python 3.
+# Python 3
+#p = 'bébêtte/noise.aif'.encode(sys.getfilesystemencoding())
+# Python 2
+p = 'bébêtte/noise.aif'
+
+########## SNDINFO ###############
+info = sndinfo(p)
+print("sndinfo output:\n", info)
+
+####### SAVEFILE ##############
+sr, dur, chnls, path = 44100, 5, 2, os.path.join("bébêtte", 'savefile.aif')
+samples = [[uniform(-0.5,0.5) for i in range(sr*dur)] for i in range(chnls)]
+savefile(samples=samples, path=path, sr=sr, channels=chnls, fileformat=1, sampletype=1)
+print("Savefile record:", os.path.isfile(os.path.join("bébêtte", 'savefile.aif')))
+
+####### SAVEFILEFROMTABLE #########
+home = os.path.expanduser('~')
+path1 = SNDS_PATH + '/transparent.aif'
+path2 = os.path.join("bébêtte", 'savefileFromTable.aif')
+t = SndTable(path1)
+savefileFromTable(table=t, path=path2, fileformat=1, sampletype=1)
+print("SavefileFromTable record:", os.path.isfile(os.path.join("bébêtte", 'savefileFromTable.aif')))
+
+##### UPSAMP/DOWNSAMP ######
+# upsample a signal 3 times
+upfile = os.path.join("bébêtte", 'upsamp.aif')
+upsamp(p, upfile, 2, 256)
+print("upsamp record:", os.path.isfile(os.path.join("bébêtte", 'upsamp.aif')))
+# downsample the upsampled signal 3 times
+downfile = os.path.join("bébêtte", 'downsamp.aif')
+downsamp(upfile, downfile, 3, 256)
+print("downsamp record:", os.path.isfile(os.path.join("bébêtte", 'downsamp.aif')))
+
+######### SfPlayer ###########
+sf1 = SfPlayer(p, mul=0.1)
+sf1.setPath(downfile)
+
+p2 = os.path.join("bébêtte", 'transparent.aif')
+######### SfMarkerShuffler ###########
+sf2 = SfMarkerShuffler(p2, mul=0.3)
+
+######### SfMarkerLooper ###########
+sf3 = SfMarkerLooper(p2, mul=.3)
+rnd = RandInt(len(sf3.getMarkers()), 2)
+sf3.mark = rnd
+
+######### SndTable ###########
+tab1 = SndTable(p)
+tab1.setSound(p2)
+tab1.append(p2, 0.2)
+tab1.insert(p2, 0.1, 0.1)
+tabplay = Osc(tab1, [tab1.getRate(), tab1.getRate() * 1.01], mul=0.5)
+
+######### CvlVerb impulse path ###########
+impl = os.path.join("bébêtte", 'IRMediumHallStereo.wav')
+cv = CvlVerb(tabplay, impl, size=1024, bal=0.7).out()
+
+######### Record ###########
+recfile = os.path.join("bébêtte", 'recfile.wav')
+rec = Record(cv, recfile, chnls=2, fileformat=0, sampletype=0, buffering=4, quality=0.40)
+recplay = None
+def reccallback():
+    global rec, recplay
+    rec.stop()
+    del rec
+#    recplay = SfPlayer(recfile, loop=True).out()
+#   print("Start playback!")
+#print("Recording 4 seconds of sounds...")
+after = CallAfter(reccallback, 4)
+
+######### Server ###########
+servrecfile = os.path.join("bébêtte", 'servrecfile.wav')
+#s.recordOptions(dur=-1, filename=servrecfile)
+servrecfile = os.path.join("bébêtte", 'servrecfile2.wav')
+s.recstart(servrecfile)
+
+s.gui(locals(), exit=False)
+
+def delfile(f):
+    if os.path.isfile(f):
+        os.remove(f)
+
+# On windows, we should delete Sf* objects before deleting the audio files.
+del sf1
+del recplay
+delfile(os.path.join("bébêtte", 'savefile.aif'))
+delfile(os.path.join("bébêtte", 'savefileFromTable.aif'))
+delfile(os.path.join("bébêtte", 'upsamp.aif'))
+delfile(os.path.join("bébêtte", 'downsamp.aif'))
+delfile(os.path.join("bébêtte", 'recfile.wav'))
+delfile(os.path.join("bébêtte", 'servrecfile.wav'))
+delfile(os.path.join("bébêtte", 'servrecfile2.wav'))
+
+"""
+1 - Adapt encoding line for E-Pyo tempfile. **done**
+
+2 - Use widestring in C layer.
+
+3 - "if sys.version > 2" -> path.encode(sys.getfilesystemencoding())
+    For python2, don't do anything.
+    Function stringencode(strng) in _core.py
+ 
+Objects with file input:
+sndinfo, savefile, savefileFromTable, upsamp, downsamp **done**
+Sf_family **done**
+CvlVerb **done**
+SndTable **done**
+Record **done**
+Server: recordOptions, recstart **Not working yet on Windows with python 3.5**
+
+ControlRead, ControlRec *nothing to do?*
+Expr *to_unicode?* *nothing to do?*
+NoteinRead, NoteinRec *nothing to do?*
+PyoTableObject: write, read *nothing to do?*
+PyoMatrixObject: write, read *nothing to do?*
+
+4 - For method of a C class, use stringencode(st) before the call and
+    PyArg_ParseTuple(args, "s#", &self->path, &psize) in the method body.
+    METH_VARARGS must be used as the method flag.
+
+"""
diff --git a/tests/test_portaudio_functions.py b/tests/test_portaudio_functions.py
new file mode 100644
index 0000000..eefaa2e
--- /dev/null
+++ b/tests/test_portaudio_functions.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python
+# encoding: utf-8
+from pyo import *
+
+print("------------- PA Version ---------------------")
+print('pa_get_version:', pa_get_version())
+print('pa_get_version_text:', pa_get_version_text())
+
+print("------------- Host API ---------------------")
+print('pa_count_host_apis:', pa_count_host_apis())
+print('pa_list_host_apis:')
+pa_list_host_apis()
+print('pa_get_default_host_api:', pa_get_default_host_api())
+
+print("--------------- Devices -------------------")
+print('pa_count_devices:', pa_count_devices())
+print('pa_list_devices:')
+pa_list_devices()
+print('pa_get_input_devices:')
+print(pa_get_input_devices())
+print('pa_get_default_input:', pa_get_default_input())
+print('pa_get_output_devices:')
+print(pa_get_output_devices())
+print('pa_get_default_output:', pa_get_default_output())
+
+print("--------------- Device Infos -------------------")
+print('pa_get_devices_infos:')
+inputs, outputs = pa_get_devices_infos()
+print('- Inputs:')
+for index in sorted(list(inputs.keys())):
+    print('  Device index:', index)
+    for key in ['name', 'host api index', 'default sr', 'latency']:
+        print('    %s:' % key, inputs[index][key])
+print('- Outputs:')
+for index in sorted(list(outputs.keys())):
+    print('  Device index:', index)
+    for key in ['name', 'host api index', 'default sr', 'latency']:
+        print('    %s:' % key, outputs[index][key])
+
+print("--------------- Channels -------------------")
+dev_list, dev_index =  pa_get_output_devices()
+for dev in dev_index:
+    print('Device index:', dev, 'Max outputs:', pa_get_output_max_channels(dev))
+
+dev_list, dev_index =  pa_get_input_devices()
+for dev in dev_index:
+    print('Device index:', dev, 'Max inputs:', pa_get_input_max_channels(dev))
diff --git a/utils/E-Pyo.py b/utils/E-Pyo.py
index e0b42f5..d545fbc 100755
--- a/utils/E-Pyo.py
+++ b/utils/E-Pyo.py
@@ -3,43 +3,134 @@
 """
 E-Pyo is a simple text editor especially configured to edit pyo audio programs.
 
-You can do absolutely everything you want to with this piece of software.
+You can do absolutely everything you want with this piece of software.
 
-Olivier Belanger - 2012
+Olivier Belanger - 2016
+
+TODO:
+    - Fix printing to pdf.
 
 """
+from __future__ import division
 from __future__ import with_statement
-import sys, os, string, inspect, keyword, wx, codecs, subprocess, unicodedata, contextlib, StringIO, shutil, copy, pprint, random, time, threading
-from types import UnicodeType, MethodType, ListType
+from __future__ import print_function
+import sys
+
+import os, inspect, keyword, wx, codecs, subprocess, unicodedata
+import contextlib, shutil, copy, pprint, random, time, threading
+from types import MethodType
 from wx.lib.wordwrap import wordwrap
 from wx.lib.embeddedimage import PyEmbeddedImage
 import wx.lib.colourselect as csel
 import wx.lib.scrolledpanel as scrolled
 import wx.lib.dialogs
-import wx.combo
-import wx.stc  as  stc
-import FlatNotebook as FNB
-from pyo import *
+import wx.stc as stc
+import wx.lib.agw.flatnotebook as FNB
+from pyo import * # what do we really need? OBJECTS_TREE, PYO_VERSION
 from PyoDoc import ManualFrame
 
-reload(sys)
-sys.setdefaultencoding("utf-8")
+if sys.version_info[0] < 3:
+    from StringIO import StringIO
+    unicode_t = unicode
+    reload(sys)
+    sys.setdefaultencoding("utf-8")
+else:
+    from io import StringIO as StringIO
+    unicode_t = str
+
+if "phoenix" in wx.version():
+    from wx.adv import AboutDialogInfo, AboutBox
+    from wx import ComboCtrl
+    from wx import ComboPopup
+    def packItemData(obj):
+        return obj
+    def unpackItemData(obj):
+        return obj
+else:
+    from wx import AboutDialogInfo, AboutBox
+    from wx.combo import ComboCtrl
+    from wx.combo import ComboPopup
+    def packItemData(obj):
+        return wx.TreeItemData(obj)
+    def unpackItemData(obj):
+        return obj.GetData()
+    wx.QueueEvent = wx.PostEvent
 
 ################## SETUP ##################
 PLATFORM = sys.platform
+
+# Not sure if ENCODING stuff is needed anymore with python3/wxpython phoenix.
 DEFAULT_ENCODING = sys.getdefaultencoding()
 ENCODING = sys.getfilesystemencoding()
 ENCODING_LIST = ["utf_8", "latin_1", "mac_roman", "cp1252", "cp1250", "utf_16"]
-ENCODING_DICT = {'cp-1250': 'cp1250', 'cp-1251': 'cp1251', 'cp-1252': 'cp1252', 'latin-1': 'latin_1', 
-                'mac-roman': 'mac_roman', 'utf-8': 'utf_8', 'utf-16': 'utf_16', 'utf-16 (Big Endian)': 'utf_16_be', 
-                'utf-16 (Little Endian)': 'utf_16_le', 'utf-32': 'utf_32', 'utf-32 (Big Endian)': 
-                'utf_32_be', 'utf-32 (Little Endian)': 'utf_32_le'}
+ENCODING_DICT = {'cp-1250': 'cp1250', 'cp-1251': 'cp1251', 'cp-1252': 'cp1252',
+                 'latin-1': 'latin_1', 'mac-roman': 'mac_roman',
+                 'utf-8': 'utf_8', 'utf-16': 'utf_16',
+                 'utf-16 (Big Endian)': 'utf_16_be',
+                 'utf-16 (Little Endian)': 'utf_16_le', 'utf-32': 'utf_32',
+                 'utf-32 (Big Endian)': 'utf_32_be',
+                 'utf-32 (Little Endian)': 'utf_32_le'}
 
 APP_NAME = 'E-Pyo'
 APP_VERSION = PYO_VERSION
 OSX_APP_BUNDLED = False
 WIN_APP_BUNDLED = False
 
+################## Utility Functions ##################
+ at contextlib.contextmanager
+def stdoutIO(stdout=None):
+    old = sys.stdout
+    if stdout is None:
+        stdout = StringIO()
+    sys.stdout = stdout
+    yield stdout
+    sys.stdout = old
+
+def ensureNFD(unistr):
+    if PLATFORM == 'win32' or PLATFORM.startswith('linux'):
+        encodings = [DEFAULT_ENCODING, ENCODING,
+                     'cp1252', 'iso-8859-1', 'utf-16']
+        format = 'NFC'
+    else:
+        encodings = [DEFAULT_ENCODING, ENCODING,
+                     'macroman', 'iso-8859-1', 'utf-16']
+        format = 'NFC'
+    decstr = unistr
+    if type(decstr) != unicode_t:
+        for encoding in encodings:
+            try:
+                decstr = decstr.decode(encoding)
+                break
+            except UnicodeDecodeError:
+                continue
+            except:
+                decstr = "UnableToDecodeString"
+                print("Unicode encoding not in a recognized format...")
+                break
+    if decstr == "UnableToDecodeString":
+        return unistr
+    else:
+        return unicodedata.normalize(format, decstr)
+
+def toSysEncoding(unistr):
+    try:
+        if PLATFORM == "win32":
+            unistr = unistr.encode(ENCODING)
+        else:
+            unistr = unicode(unistr)
+    except:
+        pass
+    return unistr
+
+def hex_to_rgb(value):
+    value = value.lstrip('#')
+    lv = len(value)
+    return tuple(int(value[i:i+lv // 3], 16) for i in range(0, lv, lv // 3))
+
+LOWERCASE = 'abcdefghijklmnopqrstuvwxyz'
+UPPERCASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+
+################## Paths ##################
 TEMP_PATH = os.path.join(os.path.expanduser('~'), '.epyo')
 if not os.path.isdir(TEMP_PATH):
     os.mkdir(TEMP_PATH)
@@ -49,15 +140,18 @@ if not os.path.isfile(PREFERENCES_PATH):
     with open(PREFERENCES_PATH, "w") as f:
         f.write("epyo_prefs = {}")
 
+epyo_prefs = {}
 with open(PREFERENCES_PATH, "r") as f:
     text = f.read()
-exec text in locals()
+spos = text.find("=")
+dictext = text[spos+1:]
+epyo_prefs = eval(dictext)
 PREFERENCES = copy.deepcopy(epyo_prefs)
 
 tmp_version = PREFERENCES.get("version", "no_version_pref")
 if tmp_version != APP_VERSION:
     tmp_version = APP_VERSION
-    print "Erasing preferences..."
+    print("Erasing preferences...")
     shutil.rmtree(os.path.join(TEMP_PATH, "doc"), True)
     PREFERENCES = {}
 PREFERENCES["version"] = tmp_version
@@ -72,10 +166,14 @@ if PLATFORM == "win32" and sys.executable.endswith("E-Pyo.exe"):
 
 if PLATFORM == "darwin" and '/%s.app' % APP_NAME in os.getcwd():
     OSX_APP_BUNDLED = True
-    
+
 # Check for which Python to use #
 if PLATFORM == "win32":
-    WHICH_PYTHON = PREFERENCES.get("which_python", "C:\Python%d%d\python.exe" % sys.version_info[:2])
+    #WHICH_PYTHON = PREFERENCES.get("which_python", sys.executable)
+    # This way of finding the python executable assume that python is in the PATH variable.
+    proc = subprocess.Popen('python -c "import sys; print(sys.executable)"', shell=False,
+                            universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    WHICH_PYTHON = proc.communicate()[0][:-1]
 else:
     WHICH_PYTHON = PREFERENCES.get("which_python", "")
 INSTALLATION_ERROR_MESSAGE = ""
@@ -83,13 +181,17 @@ CALLER_NEED_TO_INVOKE_32_BIT = False
 SET_32_BIT_ARCH = "export VERSIONER_PYTHON_PREFER_32_BIT=yes;"
 if WHICH_PYTHON == "":
     if OSX_APP_BUNDLED:
-        proc = subprocess.Popen(["export PATH=/usr/local/bin:$PATH;which python"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        proc = subprocess.Popen(["export PATH=/usr/local/bin:$PATH;which python"],
+                    shell=True, universal_newlines=True, stdout=subprocess.PIPE, 
+                    stderr=subprocess.PIPE)
         WHICH_PYTHON = proc.communicate()[0][:-1]
     elif PLATFORM == "darwin":
-        proc = subprocess.Popen(["which python"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+        proc = subprocess.Popen(["which python"], shell=True, universal_newlines=True,
+                                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
         WHICH_PYTHON = proc.communicate()[0][:-1]
-    elif PLATFORM == "linux2":
-        proc = subprocess.Popen(["which python"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+    elif PLATFORM.startswith("linux"):
+        proc = subprocess.Popen(["which python"], shell=True, universal_newlines=True,
+                                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
         WHICH_PYTHON = proc.communicate()[0][:-1]
     else:
         ### No more used on Windows ###
@@ -102,8 +204,11 @@ if WHICH_PYTHON == "":
                 if os.path.isfile("C:\Python2%d\python.exe" % i):
                     WHICH_PYTHON = "C:\Python2%d\python.exe" % i
                     break
+        ########################
         if WHICH_PYTHON == "":
-            INSTALLATION_ERROR_MESSAGE = "Python 2.x doesn't seem to be installed on this computer. Check your Python installation and try again."
+            INSTALLATION_ERROR_MESSAGE = ("Python 2.x doesn't seem to be installed " 
+                                          "on this computer. Check your Python "
+                                          "installation and try again.")
 
 # Check for WxPython / Pyo installation and architecture #
 if OSX_APP_BUNDLED:
@@ -112,35 +217,57 @@ if OSX_APP_BUNDLED:
     tmpexecpath = os.environ["EXECUTABLEPATH"]
     tmprscpath = os.environ["RESOURCEPATH"]
     tmpargv0 = os.environ["ARGVZERO"]
-    cmd = 'export -n PYTHONHOME PYTHONPATH EXECUTABLEPATH RESOURCEPATH ARGVZERO;env;%s -c "import pyo";export PYTHONHOME=%s;export PYTHONPATH=%s;export EXECUTABLEPATH=%s;export RESOURCEPATH=%s;export ARGVZERO=%s' % (WHICH_PYTHON, tmphome, tmppath, tmpexecpath, tmprscpath, tmpargv0)
-    cmd2 = 'export -n PYTHONHOME PYTHONPATH EXECUTABLEPATH RESOURCEPATH ARGVZERO;env;%s -c "import wx";export PYTHONHOME=%s;export PYTHONPATH=%s;export EXECUTABLEPATH=%s;export RESOURCEPATH=%s;export ARGVZERO=%s' % (WHICH_PYTHON, tmphome, tmppath, tmpexecpath, tmprscpath, tmpargv0)
+    cmd = ('export -n PYTHONHOME PYTHONPATH EXECUTABLEPATH RESOURCEPATH ARGVZERO;'
+           'env;%s -c "import pyo";export PYTHONHOME=%s;export PYTHONPATH=%s;'
+           'export EXECUTABLEPATH=%s;export RESOURCEPATH=%s;export ARGVZERO=%s' % 
+           (WHICH_PYTHON, tmphome, tmppath, tmpexecpath, tmprscpath, tmpargv0))
+    cmd2 = ('export -n PYTHONHOME PYTHONPATH EXECUTABLEPATH RESOURCEPATH ARGVZERO;'
+            'env;%s -c "import wx";export PYTHONHOME=%s;export PYTHONPATH=%s;'
+            'export EXECUTABLEPATH=%s;export RESOURCEPATH=%s;export ARGVZERO=%s' % 
+            (WHICH_PYTHON, tmphome, tmppath, tmpexecpath, tmprscpath, tmpargv0))
 else:
     cmd = '%s -c "import pyo"' % WHICH_PYTHON
     cmd2 = '%s -c "import wx"' % WHICH_PYTHON
 proc = subprocess.Popen([cmd], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 IMPORT_PYO_STDOUT, IMPORT_PYO_STDERR = proc.communicate()
+IMPORT_PYO_STDOUT = ensureNFD(IMPORT_PYO_STDOUT)
+IMPORT_PYO_STDERR = ensureNFD(IMPORT_PYO_STDERR)
 if "ImportError" in IMPORT_PYO_STDERR:
     if "No module named" in IMPORT_PYO_STDERR:
-        INSTALLATION_ERROR_MESSAGE = "Pyo is not installed in the current Python installation. Audio programs won't run.\n\nCurrent Python path: %s\n" % WHICH_PYTHON
-    elif "no appropriate 64-bit architecture" in IMPORT_PYO_STDERR or "but wrong architecture" in IMPORT_PYO_STDERR:
+        INSTALLATION_ERROR_MESSAGE = ("Pyo is not installed in the current Python "
+                                      "installation. Audio programs won't run.\n\n"
+                                      "Current Python path: %s\n" % WHICH_PYTHON)
+    elif ("no appropriate 64-bit architecture" in IMPORT_PYO_STDERR 
+      or "but wrong architecture" in IMPORT_PYO_STDERR):
         CALLER_NEED_TO_INVOKE_32_BIT = True
-        INSTALLATION_ERROR_MESSAGE = "The current Python installation is running in 64-bit mode but pyo installation is 32-bit.\n\n"
+        INSTALLATION_ERROR_MESSAGE = ("The current Python installation is running "
+                                      "in 64-bit mode but pyo installation is 32-bit.\n\n")
         if PLATFORM == "darwin":
-            INSTALLATION_ERROR_MESSAGE += "'VERSIONER_PYTHON_PREFER_32_BIT=yes' will be invoked before calling python executable.\n\n"
+            INSTALLATION_ERROR_MESSAGE += ("'VERSIONER_PYTHON_PREFER_32_BIT=yes' "
+                                           "will be invoked before calling python "
+                                           "executable.\n\n")
         INSTALLATION_ERROR_MESSAGE += "Current Python path: %s\n" % WHICH_PYTHON
 else:
     proc = subprocess.Popen([cmd2], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
     IMPORT_WX_STDOUT, IMPORT_WX_STDERR = proc.communicate()
+    IMPORT_WX_STDOUT = ensureNFD(IMPORT_WX_STDOUT)
+    IMPORT_WX_STDERR = ensureNFD(IMPORT_WX_STDERR)
     if "ImportError" in IMPORT_WX_STDERR:
         if "No module named" in IMPORT_WX_STDERR:
-            INSTALLATION_ERROR_MESSAGE = "WxPython is not installed in the current Python installation. It is needed by pyo to show graphical display.\n\nCurrent Python path: %s\n" % WHICH_PYTHON
+            INSTALLATION_ERROR_MESSAGE = ("WxPython is not installed in the current "
+                                          "Python installation. It is needed by pyo "
+                                          "to show graphical display.\n\nCurrent "
+                                          "Python path: %s\n" % WHICH_PYTHON)
         elif "no appropriate 64-bit architecture" in IMPORT_WX_STDERR:
             CALLER_NEED_TO_INVOKE_32_BIT = True
-            INSTALLATION_ERROR_MESSAGE = "The current Python installation is running in 64-bit mode but WxPython installation is 32-bit.\n\n"
+            INSTALLATION_ERROR_MESSAGE = ("The current Python installation is running in "
+                                          "64-bit mode but WxPython installation is 32-bit.\n\n")
             if PLATFORM == "darwin":
-                INSTALLATION_ERROR_MESSAGE += "'VERSIONER_PYTHON_PREFER_32_BIT=yes' will be invoked before calling python executable.\n\n"
+                INSTALLATION_ERROR_MESSAGE += ("'VERSIONER_PYTHON_PREFER_32_BIT=yes' "
+                                               "will be invoked before calling python "
+                                               "executable.\n\n")
             INSTALLATION_ERROR_MESSAGE += "Current Python path: %s\n" % WHICH_PYTHON
-        
+
 if OSX_APP_BUNDLED:
     EXAMPLE_PATH = os.path.join(os.getcwd(), "examples")
 elif WIN_APP_BUNDLED:
@@ -200,8 +327,8 @@ if not os.path.isdir(STYLES_PATH):
 DEFAULT_STYLE = os.path.join(STYLES_PATH, "Default")
 if not os.path.isfile(os.path.join(STYLES_PATH, "Default")):
     shutil.copy(os.path.join(os.getcwd(), "styles", "Default"), DEFAULT_STYLE)
-if PREFERENCES.has_key("pref_style"):
-    PREF_STYLE = os.path.join(STYLES_PATH, PREFERENCES["pref_style"])
+if "pref_style" in PREFERENCES:
+    PREF_STYLE = os.path.join(ensureNFD(STYLES_PATH), PREFERENCES["pref_style"])
 else:
     PREF_STYLE = DEFAULT_STYLE
 
@@ -216,70 +343,6 @@ if not os.path.isfile(MARKERS_FILE):
 BACKGROUND_SERVER_DEFAULT_ARGS = 'sr=44100, nchnls=2, buffersize=256, duplex=1, audio="portaudio", jackname="pyo"'
 BACKGROUND_SERVER_ARGS = PREFERENCES.get("background_server_args", BACKGROUND_SERVER_DEFAULT_ARGS)
 
-################## Utility Functions ##################
- at contextlib.contextmanager
-def stdoutIO(stdout=None):
-    old = sys.stdout
-    if stdout is None:
-        stdout = StringIO.StringIO()
-    sys.stdout = stdout
-    yield stdout
-    sys.stdout = old
-
-def convert_line_endings(temp, mode):
-    #modes:  0 - Unix, 1 - Mac, 2 - DOS
-    if mode == 0:
-        temp = string.replace(temp, '\r\n', '\n')
-        temp = string.replace(temp, '\r', '\n')
-    elif mode == 1:
-        temp = string.replace(temp, '\r\n', '\r')
-        temp = string.replace(temp, '\n', '\r')
-    elif mode == 2:
-        import re
-        temp = re.sub("\r(?!\n)|(?<!\r)\n", "\r\n", temp)
-    return temp
-
-def ensureNFD(unistr):
-    if PLATFORM in ['linux2', 'win32']:
-        encodings = [DEFAULT_ENCODING, ENCODING,
-                     'cp1252', 'latin_1', 'utf-16']
-        format = 'NFC'
-    else:
-        encodings = [DEFAULT_ENCODING, ENCODING,
-                     'macroman', 'latin_1', 'utf-16']
-        format = 'NFC'
-    decstr = unistr
-    if type(decstr) != UnicodeType:
-        for encoding in encodings:
-            try:
-                decstr = decstr.decode(encoding)
-                break
-            except UnicodeDecodeError:
-                continue
-            except:
-                decstr = "UnableToDecodeString"
-                print "Unicode encoding not in a recognized format..."
-                break
-    if decstr == "UnableToDecodeString":
-        return unistr
-    else:
-        return unicodedata.normalize(format, decstr)
-
-def toSysEncoding(unistr):
-    try:
-        if PLATFORM == "win32":
-            unistr = unistr.encode(ENCODING)
-        else:
-            unistr = unicode(unistr)
-    except:
-        pass
-    return unistr
-
-def hex_to_rgb(value):
-    value = value.lstrip('#')
-    lv = len(value)
-    return tuple(int(value[i:i+lv/3], 16) for i in range(0, lv, lv/3))
-
 ################## TEMPLATES ##################
 HEADER_TEMPLATE = """#!/usr/bin/env python
 # encoding: utf-8
@@ -300,7 +363,7 @@ s.gui(locals())
 CECILIA5_TEMPLATE = '''class Module(BaseModule):
     """
     Module's documentation
-    
+
     """
     def __init__(self):
         BaseModule.__init__(self)
@@ -331,7 +394,7 @@ ZYNE_TEMPLATE = '''class MySynth(BaseSynth):
 
 
 MODULES = {
-            "MySynth": { "title": "- Generic module -", "synth": MySynth, 
+            "MySynth": { "title": "- Generic module -", "synth": MySynth,
                     "p1": ["Ratio", 0.5, 0, 10, False, False],
                     "p2": ["Index", 5, 0, 20, False, False],
                     "p3": ["LP cutoff", 4000, 100, 15000, False, True]
@@ -355,18 +418,18 @@ class MyFrame(wx.Frame):
         self.freqPort = SigTo(value=250, time=0.05, init=250)
         self.sine = Sine(freq=self.freqPort, mul=0.3).mix(2).out()
 
-        self.onOffText = wx.StaticText(self.panel, id=-1, label="Audio", 
+        self.onOffText = wx.StaticText(self.panel, id=-1, label="Audio",
                                        pos=(28,10), size=wx.DefaultSize)
-        self.onOff = wx.ToggleButton(self.panel, id=-1, label="on / off", 
+        self.onOff = wx.ToggleButton(self.panel, id=-1, label="on / off",
                                      pos=(10,28), size=wx.DefaultSize)
         self.onOff.Bind(wx.EVT_TOGGLEBUTTON, self.handleAudio)
 
-        self.frTxt = wx.StaticText(self.panel, id=-1, label="Freq: 250.00", 
+        self.frTxt = wx.StaticText(self.panel, id=-1, label="Freq: 250.00",
                                       pos=(140,60), size=(250,50))
-        self.freq = wx.Slider(self.panel, id=-1, value=25000, minValue=5000, 
+        self.freq = wx.Slider(self.panel, id=-1, value=25000, minValue=5000,
                               maxValue=1000000, pos=(140,82), size=(250,50))
         self.freq.Bind(wx.EVT_SLIDER, self.changeFreq)
-        
+
     def handleAudio(self, evt):
         if evt.GetInt() == 1:
             s.start()
@@ -377,8 +440,8 @@ class MyFrame(wx.Frame):
         x = evt.GetInt() * 0.01
         self.frTxt.SetLabel("Freq: %.2f" % x)
         self.freqPort.value = x
-        
-app = wx.PySimpleApp()
+
+app = wx.App(False)
 mainFrame = MyFrame(None, title='Simple App', pos=(100,100), size=(500,300))
 mainFrame.Show()
 app.MainLoop()
@@ -396,14 +459,92 @@ class MyFrame(wx.Frame):
 
 
 if __name__ == "__main__":
-    app = wx.PySimpleApp()
+    app = wx.App(False)
     mainFrame = MyFrame(None, title='Simple App', pos=(100,100), size=(500,300))
     mainFrame.Show()
     app.MainLoop()
 '''
-TEMPLATE_NAMES = {93: "Header", 94: "Pyo", 95: "WxPython", 96: "Cecilia5", 97: "Zyne", 98: "Audio Interface"}
-TEMPLATE_DICT = {93: HEADER_TEMPLATE, 94: PYO_TEMPLATE, 95: WXPYTHON_TEMPLATE, 96: CECILIA5_TEMPLATE, 
-                97: ZYNE_TEMPLATE, 98: AUDIO_INTERFACE_TEMPLATE}
+
+RADIOPYO_TEMPLATE = '''#!/usr/bin/env python
+# encoding: utf-8
+"""
+Template for a RadioPyo song (version 1.0).
+
+A RadioPyo song is a musical python script using the python-pyo
+module to create the audio processing chain. You can connect to
+the radio here : http://radiopyo.acaia.ca/
+
+There is only a few rules:
+    1 - It must be a one-page script.
+    2 - No soundfile, only synthesis.
+    3 - The script must be finite in time, with fade-in and fade-out
+        to avoid clicks between pieces. Use the DURATION variable.
+
+belangeo - 2014
+
+"""
+from pyo import *
+
+################### USER-DEFINED VARIABLES ###################
+### READY is used to manage the server behaviour depending ###
+### of the context. Set this variable to True when the     ###
+### music is ready for the radio. TITLE and ARTIST are the ###
+### infos shown by the radio player. DURATION set the      ###
+### duration of the audio file generated for the streaming.###
+##############################################################
+READY = False           # Set to True when ready for the radio
+TITLE = "Song Title"    # The title of the music
+ARTIST = "Artist Name"  # Your artist name
+DURATION = 300          # The duration of the music in seconds
+##################### These are optional #####################
+GENRE = "Electronic"    # Kind of your music, if there is any
+DATE = 2014             # Year of creation
+
+####################### SERVER CREATION ######################
+if READY:
+    s = Server(duplex=0, audio="offline").boot()
+    s.recordOptions(dur=DURATION, filename="radiopyo.ogg", fileformat=7)
+else:
+    s = Server(duplex=0).boot()
+
+
+##################### PROCESSING SECTION #####################
+# global volume (should be used to control the overall sound)
+fade = Fader(fadein=0.001, fadeout=10, dur=DURATION).play()
+
+
+###
+### Insert your algorithms here...
+###
+
+
+#################### START THE PROCESSING ###################
+s.start()
+if not READY:
+    s.gui(locals())
+'''
+
+TEMPLATE_NAMES = {98: "Header", 97: "Pyo", 96: "WxPython", 95: "Cecilia5",
+                  94: "Zyne", 93: "Audio Interface", 92: "RadioPyo"}
+TEMPLATE_DICT = {98: HEADER_TEMPLATE, 97: PYO_TEMPLATE, 96: WXPYTHON_TEMPLATE,
+                 95: CECILIA5_TEMPLATE, 94: ZYNE_TEMPLATE,
+                 93: AUDIO_INTERFACE_TEMPLATE, 92: RADIOPYO_TEMPLATE}
+
+TEMPLATE_PATH = os.path.join(RESOURCES_PATH, "templates")
+if not os.path.isdir(TEMPLATE_PATH):
+    os.mkdir(TEMPLATE_PATH)
+
+templateid = 91
+template_files = sorted([f for f in os.listdir(TEMPLATE_PATH) if f.endswith(".py")])
+for f in template_files:
+    try:
+        with open(os.path.join(TEMPLATE_PATH, f)) as ftemp:
+            ftext = ftemp.read()
+        TEMPLATE_NAMES[templateid] = f.replace(".py", "")
+        TEMPLATE_DICT[templateid] = ftext
+        templateid -= 1
+    except:
+        pass
 
 ################## BUILTIN KEYWORDS COMPLETION ##################
 FROM_COMP = ''' `module` import `*`
@@ -415,7 +556,7 @@ RAISE_COMP = ''' Exception("`An exception occurred...`")
 TRY_COMP = ''':
     `expression`
 except:
-    `print "Ouch!"`
+    `print("Ouch!")`
 '''
 IF_COMP = ''' `expression1`:
     `pass`
@@ -435,16 +576,20 @@ CLASS_COMP = ''' `Cname`:
         `pass`
 '''
 FOR_COMP = """ i in range(`10`):
-    `print i`
+    `print(i)`
 """
 WHILE_COMP = """ `i` `>` `0`:
     `i -= 1`
-    `print i`
+    `print(i)`
 """
 ASSERT_COMP = ''' `expression` `>` `0`, "`expression should be positive`"
 '''
-BUILTINS_DICT = {"from": FROM_COMP, "try": TRY_COMP, "if": IF_COMP, "def": DEF_COMP, "class": CLASS_COMP, 
-                "for": FOR_COMP, "while": WHILE_COMP, "exec": EXEC_COMP, "raise": RAISE_COMP, "assert": ASSERT_COMP}
+
+# TODO: Python 3 syntax (if possible, compatible with python 2)
+BUILTINS_DICT = {"from": FROM_COMP, "try": TRY_COMP, "if": IF_COMP,
+                 "def": DEF_COMP, "class": CLASS_COMP, "for": FOR_COMP,
+                 "while": WHILE_COMP, "exec": EXEC_COMP, "raise": RAISE_COMP,
+                 "assert": ASSERT_COMP}
 
 ################## Interface Bitmaps ##################
 catalog = {}
@@ -523,6 +668,34 @@ folder_add_icon_png = PyEmbeddedImage(
     "P36+7719TjKZnJPvXwAAAP//AwDmNHbvm7mEowAAAABJRU5ErkJggg==")
 catalog['folder_add_icon.png'] = folder_add_icon_png
 
+refresh_tree_icon_png = PyEmbeddedImage(
+    "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABmJLR0QA/wD/AP+gvaeTAAAA"
+    "CXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3wIHETgo92WyxQAABKJJREFUSMfdlVtsVFUY"
+    "hb9zmTNnZtoOLRel3ATkASiYQMI1YkTxQVMaxMQbCGJCAiY8KAY0aIQYb5CoJEo0RlEgaUwD"
+    "clOUWwABBZFIgVKQi3RaZnqdmXbOOXPO2Wf7gFTRQcFH19NO9v7X+ve/VvLDP+C56qP/dM3U"
+    "dfX8GxRuAh/Xtox3jGhFxqNnxlXcDtu9KOpPH/hk3qR2gNtX15FcNJzZH+1n3fwpACzdepI3"
+    "KysKEy7bcwGAlYcb7n73XL72pTqRmfeT8KoO+fKefV4wZqdnD9/htg6qblv1zsSrTQ5+eccf"
+    "9VtrhxX8weI9F1k1dTAvbj0e0vv0W5qP9VhxNguXuyBpSbI5sC0QdgCuABmgOdaRUGvrDOe9"
+    "iibK3jImfDpvX7mae3tj5R2bCo5o+f7LPbqKSjekstaDZxqa6xoz+UxrVkbcrDZM2mYUoYMS"
+    "BTUGgQAEqmefCucS89yS0hfkbUWPxPymys4VE7cB6NeI+wwZw1MffmEmUsnX6r6srj935MBb"
+    "ttQbLMu2AmGEVE/cpvSf9ozoMWqBVDXQwlDcDzSTgNBIO9J/F64fI2HjZdqUgiPqXzE5nk6c"
+    "G9CVbq4DRKFQGKPnTveGzfxM6uE4KlBUDpEykBIUAYog3Fhbla+ZvgVA/XN14uTBTFe6+eQN"
+    "yAGke2LtZr1p3yxFc9JENJApIAU9NCg1oWcUQlp34yr/Ad7hVdvMY2umKyUh6F0MPRUozkJf"
+    "A8ojEOue/B8e3Az6DRlJ44VT9L5nTrh93KxXZWkcYhEwQxDSIepDvARKQ9f/4KHH59yUQOOF"
+    "U5RULYt33FVVE8SLpyphUMij+A6K70C+k7iaJQjcgiarQPgBwAYMIPS7GT7QXoSWGzreuZhs"
+    "N2WvgZNkJKqg6QI9JAgZgpAhZMgQpWUxmbnYWh8c/Cx9ncAr247NzI8bU7MrKchmBOm0oLMj"
+    "T77NQqa7UFsbftXPfTPJ/XZl062MtduDEyk3+LEZMi0BVspDpFxosSDroLZdOqEdWT3XPb+9"
+    "6VYD0S1Q36XK9mawExqyKYCOALpAcXzM0xsWWue3H/8vieuOacLWpNXgI68EkDHAVsGXSFTs"
+    "0YtqYlWfDwKIzFhfkCg+4dnu84BR9/1dwGsLIOVChwOWA0KA9EFYyEDcbkf6fxWdsX6UvWnW"
+    "VcKqDwDoe+8iADLfv8/AKQuifcfNDjfU7v67AHYg6XAgZ6PkLfByELigKBDkCQJvhKWXHQo/"
+    "XL0EILN5IQBX9q4GwJy8+Mlkp7eqvbHOLLhwzPnfVTrGgC1qrvOwmdz/ut1nYrUUfowgfzWs"
+    "0gPhgCJRpe+o0tmJyDfj5gYGrjVN5tqv6Gc3VXotZ44VNFn6gaH57bVm8uijua8XNpgPvHe/"
+    "WzJ0XRCIO8EHLQRGFIwwgaabAVSiBODbaIkfdoZ+2fR8vuVM7V+90a4dSkY8KGTnlTXW1qeT"
+    "AP75HQkjHN2oGGaRDPJjCRxQFTAMMIuguAxN11v1hsNLOL52uZequ3TDndzrsXW0Vs8GoOfw"
+    "qbTV7bnuUUnvQeX5itlPiOLysUTiUUXTknrq573O7jd2SEjzv8ZvVwomHyvQ89AAAAAASUVO"
+    "RK5CYII=")
+catalog['refresh_tree_icon.png'] = refresh_tree_icon_png
+
 file_delete_icon_png = PyEmbeddedImage(
     "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAABEZJREFU"
     "eJyMVG1MW1UYfm57b1vogNLSdbotdJNkyAp+TOrYogZd4uJ+6GaYyg81auLHj7lEEpdFjfqH"
@@ -639,17 +812,23 @@ KEY_COMMANDS = {
 "23. Alt + Shift + BACK": "Delete the word to the right of the caret",
 "24. Ctrl/Cmd + BACK": "Delete back from the current position to the start of the line",
 "25. Ctrl/Cmd + Shift + BACK": "Delete forwards from the current position to the end of the line",
-"26. TAB": "If selection is empty or all on one line replace the selection with a tab character. If more than one line selected, indent the lines. In the middle of a word, trig the AutoCompletion of pyo keywords. Just after a complete pyo keyword, insert its default arguments. Just after a complete python builtin keyword, insert a default structure snippet. Just after a variable name, representing a pyo object, followed by a dot, trig the AutoCompletion of the object's attributes.",
+"26. TAB": "If selection is empty or all on one line replace the selection with a tab character. If more than one line selected, indent the lines. In the middle of a word, trig the AutoCompletion of pyo keywords. Just after an open brace following a pyo keyword, insert its default arguments. Just after a complete python builtin keyword, insert a default structure snippet. Just after a variable name, representing a pyo object, followed by a dot, trig the AutoCompletion of the object's attributes.",
 "27. Shift + TAB": "Dedent the selected lines",
 "28. Alt + 'C'": "Line Copy",
 "29. Alt + 'D'": "Line Duplicate",
 "30. Alt + 'X'": "Line Cut",
 "31. Alt + 'V'": "Line Paste",
-"32. Alt + CLICK + DRAG": "Rectangular selection"
+"32. Alt + CLICK + DRAG": "Rectangular selection",
+"33. Shit + Return": "Show the init line of a pyo object in a tooltip",
+"34. Ctrl/Cmd + Return": "Show the __doc__ string of a python object, module or function",
+"35. CLICK in the most left margin": "Add a marker to the corresponding line",
+"36. Shift + CLICK on a marker": "Delete the marker"
 }
 
 ############## Allowed Extensions ##############
-ALLOWED_EXT = PREFERENCES.get("allowed_ext", ["py", "c5", "txt", "", "c", "h", "cpp", "hpp", "sh", "rst", "iss"])
+ALLOWED_EXT = PREFERENCES.get("allowed_ext",
+                              ["py", "c5", "txt", "", "c", "h", "cpp", "hpp", "zy", "bat",
+                               "sh", "rst", "iss", "sg", "md", "jsfx-inc", "lua", "css"])
 
 ############## Pyo keywords ##############
 tree = OBJECTS_TREE
@@ -685,29 +864,63 @@ elif wx.Platform == '__WXMAC__':
 else:
     FONT_SIZE = 8
     FONT_SIZE2 = 7
-    DEFAULT_FONT_FACE = 'Courier New'
+    DEFAULT_FONT_FACE = 'Monospace'
 
 
 STYLES_GENERALS = ['default', 'background', 'selback', 'caret']
-STYLES_TEXT_COMP = ['comment', 'commentblock', 'number', 'operator', 'string', 'triple', 'keyword', 'pyokeyword', 
-                'class', 'function', 'linenumber']
-STYLES_INTER_COMP = ['marginback', 'foldmarginback', 'markerfg', 'markerbg', 'bracelight', 'bracebad', 'lineedge']
-STYLES_LABELS = {'default': 'Foreground', 'background': 'Background', 'selback': 'Selection', 'caret': 'Caret',
-        'comment': 'Comment', 'commentblock': 'Comment Block', 'number': 'Number', 'string': 'String', 
-        'triple': 'Triple String', 'keyword': 'Python Keyword', 'pyokeyword': 'Pyo Keyword', 'class': 'Class Name', 
-        'function': 'Function Name', 'linenumber': 'Line Number', 'operator': 'Operator', 'foldmarginback': 'Folding Margin Background',
-        'marginback': 'Number Margin Background', 'markerfg': 'Marker Foreground', 'markerbg': 'Marker Background', 
-        'bracelight': 'Brace Match', 'bracebad': 'Brace Mismatch', 'lineedge': 'Line Edge'}
+STYLES_TEXT_COMP = ['comment', 'commentblock', 'number', 'operator', 'string',
+                    'triple', 'keyword', 'pyokeyword', 'class', 'function',
+                    'linenumber']
+STYLES_INTER_COMP = ['marginback', 'foldmarginback', 'markerfg', 'markerbg',
+                     'bracelight', 'bracebad', 'lineedge']
+STYLES_LABELS = {'default': 'Foreground', 'background': 'Background',
+                 'selback': 'Selection', 'caret': 'Caret', 'comment': 'Comment',
+                 'commentblock': 'Comment Block', 'number': 'Number',
+                 'string': 'String', 'triple': 'Triple String',
+                 'keyword': 'Python Keyword', 'pyokeyword': 'Pyo Keyword',
+                 'class': 'Class Name', 'function': 'Function Name',
+                 'linenumber': 'Line Number', 'operator': 'Operator',
+                 'foldmarginback': 'Folding Margin Background',
+                 'marginback': 'Number Margin Background',
+                 'markerfg': 'Marker Foreground', 'markerbg': 'Marker Background',
+                 'bracelight': 'Brace Match', 'bracebad': 'Brace Mismatch',
+                 'lineedge': 'Line Edge'}
 
 with open(PREF_STYLE) as f:
     text = f.read()
-exec text in locals()
-STYLES = copy.deepcopy(style)
-if not STYLES.has_key('face'):
+spos = text.find("=")
+dictext = text[spos+1:]
+style = eval(dictext)
+try:
+    STYLES = copy.deepcopy(style)
+except:
+    STYLES = {'background': {'colour': '#FFFFFF'},
+ 'bracebad': {'colour': '#DD0000'},
+ 'bracelight': {'colour': '#AABBDD'},
+ 'caret': {'colour': '#000000'},
+ 'class': {'bold': 1, 'colour': '#000097', 'italic': 0, 'underline': 0},
+ 'comment': {'bold': 0, 'colour': '#0066FF', 'italic': 1, 'underline': 0},
+ 'commentblock': {'bold': 0, 'colour': u'#468EFF', 'italic': 1, 'underline': 0},
+ 'default': {'bold': 0, 'colour': '#000000', 'italic': 0, 'underline': 0},
+ 'foldmarginback': {'colour': '#D0D0D0'},
+ 'function': {'bold': 1, 'colour': '#0000A2', 'italic': 0, 'underline': 0},
+ 'keyword': {'bold': 1, 'colour': '#0000FF', 'italic': 0, 'underline': 0},
+ 'lineedge': {'colour': '#DDDDDD'},
+ 'linenumber': {'bold': 0, 'colour': '#000000', 'italic': 0, 'underline': 0},
+ 'marginback': {'colour': '#B0B0B0'},
+ 'markerbg': {'colour': '#000000'},
+ 'markerfg': {'colour': '#CCCCCC'},
+ 'number': {'bold': 1, 'colour': '#0000CD', 'italic': 0, 'underline': 0},
+ 'operator': {'bold': 1, 'colour': '#000000', 'italic': 0, 'underline': 0},
+ 'pyokeyword': {'bold': 1, 'colour': '#5555FF', 'italic': 0, 'underline': 0},
+ 'selback': {'colour': '#C0DFFF'},
+ 'string': {'bold': 0, 'colour': '#036A07', 'italic': 0, 'underline': 0},
+ 'triple': {'bold': 0, 'colour': '#03BA07', 'italic': 0, 'underline': 0}}
+if 'face' not in STYLES:
     STYLES['face'] = DEFAULT_FONT_FACE
-if not STYLES.has_key('size'):
+if 'size' not in STYLES:
     STYLES['size'] = FONT_SIZE
-if not STYLES.has_key('size2'):
+if 'size2' not in STYLES:
     STYLES['size2'] = FONT_SIZE2
 
 STYLES_PREVIEW_TEXT = '''# Comment
@@ -736,10 +949,9 @@ class DataEvent(wx.PyEvent):
         self.SetEventType(wxDATA_EVENT)
         self.data = data
 
-    def Clone (self): 
+    def Clone (self):
         self.__class__ (self.GetId())
 
-
 class RunningThread(threading.Thread):
     def __init__(self, path, cwd, event_receiver):
         threading.Thread.__init__(self)
@@ -748,7 +960,7 @@ class RunningThread(threading.Thread):
         self.event_receiver = event_receiver
         self.terminated = False
         self.pid = None
-    
+
     def setFileName(self, filename):
         self.filename = filename
 
@@ -759,9 +971,9 @@ class RunningThread(threading.Thread):
         self.terminated = True
         if PLATFORM == "win32":
             try:
-                os.system("tskill %d" % self.proc.pid)
+                os.system("Taskkill /PID %d /F" % self.proc.pid)
             except:
-                print "'tskill' doesn't seem to be installed on the system. It is needed to be able to kill a process."
+                print('"Taskkill" does not succeed to kill the process %d.' % self.proc.pid)
         else:
             self.proc.terminate()
         if self.proc.poll() == None:
@@ -772,30 +984,50 @@ class RunningThread(threading.Thread):
             vars_to_remove = "PYTHONHOME PYTHONPATH EXECUTABLEPATH RESOURCEPATH ARGVZERO PYTHONOPTIMIZE"
             prelude = "export -n %s;export PATH=/usr/local/bin:/usr/local/lib:$PATH;" % vars_to_remove
             if CALLER_NEED_TO_INVOKE_32_BIT:
-                self.proc = subprocess.Popen(['%s%s%s "%s"' % (prelude, SET_32_BIT_ARCH, WHICH_PYTHON, self.path)], 
-                                shell=True, cwd=self.cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+                self.proc = subprocess.Popen(['%s%s%s -u "%s"' % (prelude, SET_32_BIT_ARCH, WHICH_PYTHON, self.path)], 
+                                             universal_newlines=True, shell=True, cwd=self.cwd, 
+                                             stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
             else:
-                self.proc = subprocess.Popen(['%s%s "%s"' % (prelude, WHICH_PYTHON, self.path)], cwd=self.cwd, 
-                                    shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+                self.proc = subprocess.Popen(['%s%s -u "%s"' % (prelude, WHICH_PYTHON, self.path)], 
+                                             cwd=self.cwd, universal_newlines=True, shell=True, 
+                                             stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
         elif PLATFORM == "darwin":
             if CALLER_NEED_TO_INVOKE_32_BIT:
-                self.proc = subprocess.Popen(['%s%s "%s"' % (SET_32_BIT_ARCH, WHICH_PYTHON, self.path)], 
-                                shell=True, cwd=self.cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+                self.proc = subprocess.Popen(['%s%s -u "%s"' % (SET_32_BIT_ARCH, WHICH_PYTHON, self.path)], 
+                                             universal_newlines=True, shell=True, cwd=self.cwd, 
+                                             stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
             else:
-                self.proc = subprocess.Popen(['%s "%s"' % (WHICH_PYTHON, self.path)], cwd=self.cwd, 
-                                shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+                self.proc = subprocess.Popen(['%s -u "%s"' % (WHICH_PYTHON, self.path)], cwd=self.cwd, 
+                                             universal_newlines=True, shell=True, stdout=subprocess.PIPE, 
+                                             stderr=subprocess.STDOUT)
         elif PLATFORM == "win32":
-            self.proc = subprocess.Popen([WHICH_PYTHON, self.path], cwd=self.cwd, shell=False, 
-                                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+            self.proc = subprocess.Popen([WHICH_PYTHON, "-u", self.path], cwd=ensureNFD(self.cwd), 
+                                                       universal_newlines=True,  shell=False, stdout=subprocess.PIPE, 
+                                                       stdin=subprocess.PIPE, stderr=subprocess.STDOUT)
         else:
-            self.proc = subprocess.Popen([WHICH_PYTHON, self.path], cwd=self.cwd, 
-                                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+            self.proc = subprocess.Popen([WHICH_PYTHON, "-u", self.path], cwd=self.cwd, universal_newlines=True,
+                                         stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
 
+        ltime = time.strftime('"%d %b %Y %H:%M:%S"', time.localtime())
+        header = '=== Output log of process "%s", launched: %s ===\n' % (self.filename, ltime)
+        data_event = DataEvent({"log": header, "pid": self.pid, "filename": self.filename, "active": True})
+        wx.QueueEvent(self.event_receiver, data_event)
         while self.proc.poll() == None and not self.terminated:
-            time.sleep(.25)
+            log = ""
+            for line in self.proc.stdout.readline():
+                log = log + str(line)
+            log = log.replace(">>> ", "").replace("... ", "")
+            data_event = DataEvent({"log": log, "pid": self.pid, "filename": self.filename, "active": True})
+            wx.QueueEvent(self.event_receiver, data_event)
+            sys.stdout.flush()
+            time.sleep(.01)
         stdout, stderr = self.proc.communicate()
-        header = '=== Output log of process "%s", launched: %s ===\n' % (self.filename, time.strftime('"%d %b %Y %H:%M:%S"', time.localtime()))
-        output = header + stdout + stderr
+        output = ""
+        if stdout is not None:
+            output = output + str(stdout)
+        if stderr is not None:
+            output = output + str(stderr)
+        output = output.replace(">>> ", "").replace("... ", "")
         if "StartNotification name = default" in output:
             output = output.replace("StartNotification name = default", "")
         if "epyo_tempfile.py" in output:
@@ -817,17 +1049,106 @@ class RunningThread(threading.Thread):
                     pos += 1
                 elinepos = pos
                 linenum = int(output[slinepos:elinepos].strip())
-                output = output[:slinepos] + str(linenum-2) + output[elinepos:]
+                output = output[:slinepos] + str(linenum-3) + output[elinepos:]
+            except:
+                pass
+        if self.terminated:
+            output = output + "\n=== Process killed. ==="
+        data_event = DataEvent({"log": output, "pid": self.pid,
+                                "filename": self.filename, "active": False})
+        wx.QueueEvent(self.event_receiver, data_event)
+
+class BackgroundServerThread(threading.Thread):
+    def __init__(self, cwd, event_receiver):
+        threading.Thread.__init__(self)
+        self.cwd = cwd
+        self.event_receiver = event_receiver
+        self.terminated = False
+        self.pid = None
+
+    def setPID(self, pid):
+        self.pid = pid
+
+    def kill(self):
+        self.terminated = True
+        self.proc.stdin.write("_quit_()\n")
+        if self.proc.poll() == None:
+            self.proc.kill()
+
+    def sendText(self, text):
+        for line in text.splitlines():
+            self.proc.stdin.write(line + "\n")
+        self.proc.stdin.write("\n")
+
+    def run(self):
+        if PLATFORM == "win32":
+            self.proc = subprocess.Popen([WHICH_PYTHON, '-i', '-u', os.path.join(TEMP_PATH, "background_server.py")],
+                                                        shell=True, cwd=ensureNFD(self.cwd), stdout=subprocess.PIPE, bufsize=0,
+                                                        universal_newlines=True, stdin=subprocess.PIPE, stderr=subprocess.STDOUT)
+        else:
+            self.proc = subprocess.Popen(["%s -i -u %s" % (WHICH_PYTHON, os.path.join(TEMP_PATH, "background_server.py"))],
+                                         bufsize=0, cwd=self.cwd, shell=True, stdout=subprocess.PIPE, universal_newlines=True,
+                                         stderr=subprocess.STDOUT, stdin=subprocess.PIPE)
+
+        ltime = time.strftime('"%d %b %Y %H:%M:%S"', time.localtime())
+        header = '=== Output log of background server, launched: %s ===\n' % ltime
+        data_event = DataEvent({"log": header, "pid": self.pid,
+                                "filename": 'background_server.py',
+                                "active": True})
+        wx.QueueEvent(self.event_receiver, data_event)
+        while self.proc.poll() == None and not self.terminated:
+            log = ""
+            for line in self.proc.stdout.readline():
+                log = log + str(line)
+            log = log.replace(">>> ", "").replace("... ", "")
+            data_event = DataEvent({"log": log, "pid": self.pid,
+                                    "filename": 'background_server.py',
+                                    "active": True})
+            wx.QueueEvent(self.event_receiver, data_event)
+            sys.stdout.flush()
+            time.sleep(.01)
+        stdout, stderr = self.proc.communicate()
+        output = ""
+        if stdout is not None:
+            output = output + str(stdout)
+        if stderr is not None:
+            output = output + str(stderr)
+        output = output.replace(">>> ", "").replace("... ", "")
+        if "StartNotification name = default" in output:
+            output = output.replace("StartNotification name = default", "")
+        if "background_server.py" in output:
+            try:
+                findpos = output.find("background_server.py")
+                pos = findpos
+                while (output[pos] != '"'):
+                    pos -= 1
+                startpos = pos + 1
+                pos = findpos
+                while (output[pos] != '"'):
+                    pos += 1
+                endpos = pos
+                output = output[:startpos] + self.filename + output[endpos:]
+                pos = startpos + len(self.filename)
+                slinepos = pos + 8
+                pos = slinepos
+                while (output[pos] != ',' and output[pos] != '\n'):
+                    pos += 1
+                elinepos = pos
+                linenum = int(output[slinepos:elinepos].strip())
+                output = output[:slinepos] + str(linenum-3) + output[elinepos:]
             except:
                 pass
         if self.terminated:
             output = output + "\n=== Process killed. ==="
-        data_event = DataEvent({"log": output, "pid": self.pid, "filename": self.filename})
-        wx.PostEvent(self.event_receiver, data_event)
+        data_event = DataEvent({"log": output, "pid": self.pid,
+                                "filename": 'background_server.py',
+                                "active": False})
+        wx.QueueEvent(self.event_receiver, data_event)
 
 class KeyCommandsFrame(wx.Frame):
     def __init__(self, parent):
-        wx.Frame.__init__(self, parent, wx.ID_ANY, title="Editor Key Commands List", size=(650,550))
+        wx.Frame.__init__(self, parent, wx.ID_ANY,
+                          title="Editor Key Commands List", size=(650,550))
         self.menuBar = wx.MenuBar()
         menu1 = wx.Menu()
         menu1.Append(351, "Close\tCtrl+W")
@@ -857,7 +1178,8 @@ class KeyCommandsFrame(wx.Frame):
         self.Hide()
 
 class EditorPreview(stc.StyledTextCtrl):
-    def __init__(self, parent, ID, pos=wx.DefaultPosition, size=wx.DefaultSize, style= wx.SUNKEN_BORDER | wx.WANTS_CHARS):
+    def __init__(self, parent, ID, pos=wx.DefaultPosition, size=wx.DefaultSize,
+                 style= wx.SUNKEN_BORDER | wx.WANTS_CHARS):
         stc.StyledTextCtrl.__init__(self, parent, ID, pos, size, style)
 
         self.SetSTCCursor(2)
@@ -879,7 +1201,6 @@ class EditorPreview(stc.StyledTextCtrl):
         self.SetProperty("fold", "1")
         self.SetProperty("tab.timmy.whinge.level", "1")
         self.SetMargins(5,5)
-        self.SetUseAntiAliasing(True)
         self.SetEdgeColour(STYLES["lineedge"]['colour'])
         self.SetEdgeMode(stc.STC_EDGE_LINE)
         self.SetEdgeColumn(60)
@@ -887,12 +1208,12 @@ class EditorPreview(stc.StyledTextCtrl):
         self.SetMarginWidth(0, 12)
         self.SetMarginMask(0, ~wx.stc.STC_MASK_FOLDERS)
         self.SetMarginSensitive(0, True)
-        
+
         self.SetMarginType(1, stc.STC_MARGIN_NUMBER)
         self.SetMarginWidth(1, 28)
         self.SetMarginMask(1, 0)
         self.SetMarginSensitive(1, False)
-        
+
         self.SetMarginType(2, stc.STC_MARGIN_SYMBOL)
         self.SetMarginWidth(2, 12)
         self.SetMarginMask(2, stc.STC_MASK_FOLDERS)
@@ -913,7 +1234,7 @@ class EditorPreview(stc.StyledTextCtrl):
                 st = "face:%s,fore:%s,size:%s" % (STYLES['face'], STYLES[forekey]['colour'], STYLES['size'])
             if backkey:
                 st += ",back:%s" % STYLES[backkey]['colour']
-            if STYLES[forekey].has_key('bold'):
+            if 'bold' in STYLES[forekey]:
                 if STYLES[forekey]['bold']:
                     st += ",bold"
                 if STYLES[forekey]['italic']:
@@ -923,7 +1244,7 @@ class EditorPreview(stc.StyledTextCtrl):
             return st
 
         self.StyleSetSpec(stc.STC_STYLE_DEFAULT, buildStyle('default', 'background'))
-        self.StyleClearAll()  # Reset all to be like the default
+        self.StyleClearAll() # Reset all to be like the default
         self.MarkerDefine(0, stc.STC_MARK_SHORTARROW, STYLES['markerbg']['colour'], STYLES['markerbg']['colour'])
         self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS, STYLES['markerfg']['colour'], STYLES['markerbg']['colour'])
         self.MarkerDefine(stc.STC_MARKNUM_FOLDER, stc.STC_MARK_BOXPLUS, STYLES['markerfg']['colour'], STYLES['markerbg']['colour'])
@@ -961,6 +1282,9 @@ class EditorPreview(stc.StyledTextCtrl):
         self.SetFoldMarginHiColour(True, STYLES['foldmarginback']['colour'])
         self.SetEdgeColumn(60)
 
+        # WxPython 3 needs the lexer to be set before folding property
+        self.SetProperty("fold", "1")
+
 class ComponentPanel(scrolled.ScrolledPanel):
     def __init__(self, parent, size):
         scrolled.ScrolledPanel.__init__(self, parent, wx.ID_ANY, pos=(0,0), size=size, style=wx.SUNKEN_BORDER)
@@ -974,22 +1298,22 @@ class ComponentPanel(scrolled.ScrolledPanel):
             box = wx.BoxSizer(wx.HORIZONTAL)
             label = wx.StaticText(self, wx.ID_ANY, label=STYLES_LABELS[component])
             box.Add(label, 1, wx.EXPAND|wx.TOP|wx.LEFT, 3)
-            btog = wx.ToggleButton(self, wx.ID_ANY, label="B", size=(20,20))
+            btog = wx.ToggleButton(self, wx.ID_ANY, label="B", size=(24,20))
             btog.SetValue(STYLES[component]['bold'])
             box.Add(btog, 0, wx.TOP|wx.ALIGN_RIGHT, 1)
             btog.Bind(wx.EVT_TOGGLEBUTTON, self.OnBToggleButton)
-            self.bTogRefs[btog] = component          
-            itog = wx.ToggleButton(self, wx.ID_ANY, label="I", size=(20,20))
+            self.bTogRefs[btog] = component
+            itog = wx.ToggleButton(self, wx.ID_ANY, label="I", size=(24,20))
             itog.SetValue(STYLES[component]['italic'])
-            box.Add(itog, 0, wx.TOP|wx.ALIGN_RIGHT, 1)            
+            box.Add(itog, 0, wx.TOP|wx.ALIGN_RIGHT, 1)
             itog.Bind(wx.EVT_TOGGLEBUTTON, self.OnIToggleButton)
-            self.iTogRefs[itog] = component          
-            utog = wx.ToggleButton(self, wx.ID_ANY, label="U", size=(20,20))
+            self.iTogRefs[itog] = component
+            utog = wx.ToggleButton(self, wx.ID_ANY, label="U", size=(24,20))
             utog.SetValue(STYLES[component]['underline'])
-            box.Add(utog, 0, wx.TOP|wx.ALIGN_RIGHT, 1)  
+            box.Add(utog, 0, wx.TOP|wx.ALIGN_RIGHT, 1)
             utog.Bind(wx.EVT_TOGGLEBUTTON, self.OnUToggleButton)
-            self.uTogRefs[utog] = component          
-            box.AddSpacer(20)          
+            self.uTogRefs[utog] = component
+            box.AddSpacer(20)
             selector = csel.ColourSelect(self, -1, "", hex_to_rgb(STYLES[component]['colour']), size=(20,20))
             box.Add(selector, 0, wx.TOP|wx.ALIGN_RIGHT, 1)
             selector.Bind(csel.EVT_COLOURSELECT, self.OnSelectColour)
@@ -1068,7 +1392,12 @@ class ColourEditor(wx.Frame):
 
         self.cur_style = ""
 
-        toolbar = self.CreateToolBar()
+        self.panel = wx.Panel(self)
+        self.panel.SetAutoLayout(True)
+        mainSizer = wx.BoxSizer(wx.VERTICAL)
+        self.panel.SetSizer(mainSizer)
+
+        toolbar = wx.ToolBar(self.panel, -1)
         saveButton = wx.Button(toolbar, wx.ID_ANY, label="Save Style")
         saveButton.Bind(wx.EVT_BUTTON, self.OnSave)
         toolbar.AddControl(saveButton)
@@ -1085,25 +1414,22 @@ class ColourEditor(wx.Frame):
         toolbar.AddControl(deleteButton)
         toolbar.Realize()
 
-        self.panel = wx.Panel(self)
-        self.panel.SetAutoLayout(True)
-        mainSizer = wx.BoxSizer(wx.VERTICAL)
-        self.panel.SetSizer(mainSizer)
+        mainSizer.Add(toolbar, 0, wx.EXPAND)
 
         enum = wx.FontEnumerator()
         enum.EnumerateFacenames(fixedWidthOnly=True)
         facelist = enum.GetFacenames()
         facelist.sort()
 
-        buttonData = [  (STYLES_GENERALS[0], STYLES['default']['colour'], (50, 20), STYLES_LABELS['default']),
-                        (STYLES_GENERALS[1], STYLES['background']['colour'], (50, 20), STYLES_LABELS['background']),
-                        (STYLES_GENERALS[2], STYLES['selback']['colour'], (50, 20), STYLES_LABELS['selback']),
-                        (STYLES_GENERALS[3], STYLES['caret']['colour'], (50, 20), STYLES_LABELS['caret']) ]
+        buttonData = [ (STYLES_GENERALS[0], STYLES['default']['colour'], (50, 24), STYLES_LABELS['default']),
+                       (STYLES_GENERALS[1], STYLES['background']['colour'], (50, 24), STYLES_LABELS['background']),
+                       (STYLES_GENERALS[2], STYLES['selback']['colour'], (50, 24), STYLES_LABELS['selback']),
+                       (STYLES_GENERALS[3], STYLES['caret']['colour'], (50, 24), STYLES_LABELS['caret']) ]
 
         self.buttonRefs = {}
 
         section1Sizer = wx.BoxSizer(wx.HORIZONTAL)
-        buttonSizer1 = wx.FlexGridSizer(1, 2, 25, 5)
+        buttonSizer1 = wx.FlexGridSizer(0, 2, 25, 5)
         for name, color, size, label in buttonData[:2]:
             b = csel.ColourSelect(self.panel, -1, "", hex_to_rgb(color), size=size)
             b.Bind(csel.EVT_COLOURSELECT, self.OnSelectColour)
@@ -1112,7 +1438,7 @@ class ColourEditor(wx.Frame):
                                 (b, 0, wx.LEFT|wx.RIGHT, 5)])
         section1Sizer.Add(buttonSizer1, 0, wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP|wx.ALIGN_LEFT, 10)
         section1Sizer.AddSpacer(110)
-        buttonSizer2 = wx.FlexGridSizer(1, 2, 25, 5)
+        buttonSizer2 = wx.FlexGridSizer(0, 2, 25, 5)
         for name, color, size, label in buttonData[2:4]:
             b = csel.ColourSelect(self.panel, -1, "", hex_to_rgb(color), size=size)
             b.Bind(csel.EVT_COLOURSELECT, self.OnSelectColour)
@@ -1126,7 +1452,7 @@ class ColourEditor(wx.Frame):
         mainSizer.Add(self.components, 1, wx.EXPAND|wx.LEFT|wx.RIGHT|wx.BOTTOM, 10)
 
         mainSizer.Add(wx.StaticLine(self.panel), 0, wx.LEFT|wx.RIGHT|wx.EXPAND, 10)
-        
+
         faceBox = wx.BoxSizer(wx.HORIZONTAL)
         faceLabel = wx.StaticText(self.panel, wx.ID_ANY, "Font Face:")
         faceBox.Add(faceLabel, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5)
@@ -1189,15 +1515,17 @@ class ColourEditor(wx.Frame):
         global STYLES
         stl = event.GetString()
         self.cur_style = stl
-        with open(os.path.join(STYLES_PATH, stl)) as f:
+        with open(os.path.join(ensureNFD(STYLES_PATH), stl)) as f:
             text = f.read()
-        exec text in locals()
+        spos = text.find("=")
+        dictext = text[spos+1:]
+        style = eval(dictext)
         STYLES = copy.deepcopy(style)
-        if not STYLES.has_key('face'):
+        if 'face' not in STYLES:
             STYLES['face'] = DEFAULT_FONT_FACE
-        if not STYLES.has_key('size'):
+        if 'size' not in STYLES:
             STYLES['size'] = FONT_SIZE
-        if not STYLES.has_key('size2'):
+        if 'size2' not in STYLES:
             STYLES['size2'] = FONT_SIZE2
         self.editorPreview.setStyle()
         for but, name in self.buttonRefs.items():
@@ -1241,7 +1569,7 @@ class SearchProjectPanel(scrolled.ScrolledPanel):
             self.Bind(wx.EVT_BUTTON, self.onOpenFile, id=BUTID)
             BUTID += 1
             fileText = wx.StaticText(self, wx.ID_ANY, label="File : %s" % file)
-            off = (but.GetSize()[1] - textY) / 2
+            off = (but.GetSize()[1] - textY) // 2
             box.Add(fileText, 1, wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, off)
             mainSizer.Add(box, 1, wx.LEFT|wx.RIGHT|wx.EXPAND, 10)
             for i in range(len(self.dict[file][0])):
@@ -1260,7 +1588,7 @@ class SearchProjectPanel(scrolled.ScrolledPanel):
         for f in self.files:
             num_rows += len(self.dict[f][0])
         self.SetMaxSize((-1, max(h*num_rows, self.GetSize()[1])))
-    
+
     def onOpenFile(self, evt):
         filename = self.root + self.files[evt.GetId() - 25000]
         self.GetParent().GetParent().panel.addPage(filename)
@@ -1268,6 +1596,7 @@ class SearchProjectPanel(scrolled.ScrolledPanel):
 class SearchProjectFrame(wx.Frame):
     def __init__(self, parent, root, dict, size=(500,500)):
         wx.Frame.__init__(self, parent, wx.ID_ANY, size=size)
+        self.SetTitle('Search Results in Project "%s"' % os.path.split(root)[1])
         self.menuBar = wx.MenuBar()
         menu1 = wx.Menu()
         menu1.Append(351, "Close\tCtrl+W")
@@ -1294,37 +1623,42 @@ class SnippetTree(wx.Panel):
         self.sizer = wx.BoxSizer(wx.VERTICAL)
 
         toolbarbox = wx.BoxSizer(wx.HORIZONTAL)
-        self.toolbar = wx.ToolBar(self, -1, size=(-1,36))
+        self.toolbar = wx.ToolBar(self, -1)
         self.toolbar.SetToolBitmapSize(tsize)
-        self.toolbar.AddLabelTool(SNIPPET_ADD_FOLDER_ID, "Add Category", folder_add_bmp, shortHelp="Add a New Category")
-        self.toolbar.AddLabelTool(SNIPPET_DEL_FILE_ID, "Delete", file_add_bmp, shortHelp="Delete Snippet or Category")
+
+        if "phoenix" not in wx.version():
+            self.toolbar.AddLabelTool(SNIPPET_ADD_FOLDER_ID, "Add Category", folder_add_bmp, shortHelp="Add a New Category")
+            self.toolbar.AddLabelTool(SNIPPET_DEL_FILE_ID, "Delete", file_add_bmp, shortHelp="Delete Snippet or Category")
+        else:
+            self.toolbar.AddTool(SNIPPET_ADD_FOLDER_ID, "Add Category", folder_add_bmp, shortHelp="Add a New Category")
+            self.toolbar.AddTool(SNIPPET_DEL_FILE_ID, "Delete", file_add_bmp, shortHelp="Delete Snippet or Category")
+
         self.toolbar.EnableTool(SNIPPET_DEL_FILE_ID, False)
         self.toolbar.Realize()
         toolbarbox.Add(self.toolbar, 1, wx.ALIGN_LEFT | wx.EXPAND, 0)
 
-        wx.EVT_TOOL(self, SNIPPET_ADD_FOLDER_ID, self.onAdd)
-        wx.EVT_TOOL(self, SNIPPET_DEL_FILE_ID, self.onDelete)
+        self.Bind(wx.EVT_TOOL, self.onAdd, id=SNIPPET_ADD_FOLDER_ID)
+        self.Bind(wx.EVT_TOOL, self.onDelete, id=SNIPPET_DEL_FILE_ID)
 
         self.sizer.Add(toolbarbox, 0, wx.EXPAND)
 
         self.tree = wx.TreeCtrl(self, -1, (0, 26), size, wx.TR_DEFAULT_STYLE|wx.TR_HIDE_ROOT|wx.SUNKEN_BORDER|wx.EXPAND)
 
         if wx.Platform == '__WXMAC__':
-            self.tree.SetFont(wx.Font(11, wx.ROMAN, wx.NORMAL, wx.NORMAL, face=snip_faces['face']))
+            self.tree.SetFont(wx.Font(11, wx.ROMAN, wx.NORMAL, wx.NORMAL, False, snip_faces['face']))
         else:
-            self.tree.SetFont(wx.Font(8, wx.ROMAN, wx.NORMAL, wx.NORMAL, face=snip_faces['face']))
+            self.tree.SetFont(wx.Font(8, wx.ROMAN, wx.NORMAL, wx.NORMAL, False, snip_faces['face']))
 
         self.sizer.Add(self.tree, 1, wx.EXPAND)
         self.SetSizer(self.sizer)
 
         isz = (12,12)
         self.il = wx.ImageList(isz[0], isz[1])
-        self.fldridx     = self.il.Add(wx.ArtProvider_GetBitmap(wx.ART_FOLDER,      wx.ART_OTHER, isz))
-        self.fldropenidx = self.il.Add(wx.ArtProvider_GetBitmap(wx.ART_FILE_OPEN,   wx.ART_OTHER, isz))
-        self.fileidx     = self.il.Add(wx.ArtProvider_GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, isz))
+        self.fldridx = self.il.Add(wx.ArtProvider.GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, isz))
+        self.fldropenidx = self.il.Add(wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_OTHER, isz))
+        self.fileidx = self.il.Add(wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, isz))
 
         self.tree.SetImageList(self.il)
-        self.tree.SetSpacing(12)
         self.tree.SetIndent(6)
 
         self.root = self.tree.AddRoot("EPyo_Snippet_tree", self.fldridx, self.fldropenidx, None)
@@ -1412,7 +1746,7 @@ class SnippetTree(wx.Panel):
             name = self.tree.GetItemText(item)
             ritem = self.tree.GetItemParent(item)
             category = self.tree.GetItemText(ritem)
-        self.GetParent().GetParent().onLoad(name, category)
+            self.GetParent().GetParent().onLoad(name, category)
 
     def select(self, item):
         self.tree.SelectItem(item)
@@ -1507,13 +1841,12 @@ class SnippetFrame(wx.Frame):
         saveButton = wx.Button(self.toolbar, wx.ID_ANY, label="Save Snippet")
         self.toolbar.AddControl(saveButton)
         self.Bind(wx.EVT_BUTTON, self.onSave, id=saveButton.GetId())
+        self.toolbar.Realize()
 
         toolbarBox.Add(self.toolbar, 1, wx.ALIGN_LEFT|wx.EXPAND|wx.LEFT, 5)
 
         toolbar2 = wx.ToolBar(self.panel, -1)
         self.tagButton = wx.Button(toolbar2, wx.ID_ANY, label="Tag Selection")
-        X = self.tagButton.GetSize()[0]
-        toolbar2.SetSize((X+8, 40))
         toolbar2.AddControl(self.tagButton)
         self.Bind(wx.EVT_BUTTON, self.onTagSelection, id=self.tagButton.GetId())
         toolbar2.Realize()
@@ -1550,16 +1883,15 @@ class SnippetFrame(wx.Frame):
             self.entry.InsertText(select[0], "`")
 
     def onLoad(self, name, category):
-        if os.path.isfile(os.path.join(SNIPPETS_PATH, category, name)):
+        if os.path.isfile(os.path.join(ensureNFD(SNIPPETS_PATH), category, name)):
             self.snippet_name = name
             self.category_name = category
-            with codecs.open(os.path.join(SNIPPETS_PATH, self.category_name, self.snippet_name), "r", encoding="utf-8") as f:
+            with codecs.open(os.path.join(ensureNFD(SNIPPETS_PATH), self.category_name, self.snippet_name), "r", encoding="utf-8") as f:
                 text = f.read()
-            exec text in locals()
-            try:
-                self.entry.SetTextUTF8(snippet["value"])
-            except:
-                self.entry.SetText(snippet["value"])
+            spos = text.find("=")
+            dictext = text[spos+1:]
+            snippet = eval(dictext)
+            self.entry.SetText(snippet["value"])
             if snippet["shortcut"]:
                 self.short.SetValue(snippet["shortcut"])
                 self.short.SetForegroundColour("#000000")
@@ -1568,8 +1900,9 @@ class SnippetFrame(wx.Frame):
                 self.short.SetForegroundColour("#AAAAAA")
 
     def onSave(self, evt):
-        dlg = wx.SingleChoiceDialog(self, 'Choose the Snippet Category', 
+        dlg = wx.SingleChoiceDialog(self, 'Choose the Snippet Category',
                                     'Snippet Category', SNIPPETS_CATEGORIES, wx.OK)
+        dlg.SetSize((250,300))
         dlg.CenterOnParent()
         if dlg.ShowModal() == wx.ID_OK:
             category = dlg.GetStringSelection()
@@ -1585,7 +1918,7 @@ class SnippetFrame(wx.Frame):
                 short = self.short.GetValue()
                 if short == "Type your shortcut...":
                     short = ""
-                dic = {'shortcut': short, 'value': self.entry.GetTextUTF8()}
+                dic = {'shortcut': short, 'value': self.entry.GetText()}
                 with codecs.open(os.path.join(SNIPPETS_PATH, category, name), "w", encoding="utf-8") as f:
                     f.write("snippet = %s" % pprint.pformat(dic))
                 self.snippet_tree.addItem(name, category)
@@ -1621,7 +1954,7 @@ class SnippetFrame(wx.Frame):
             if txt == "":
                 return
             ch = chr(key)
-            if ch in string.lowercase:
+            if ch in LOWERCASE:
                 ch = ch.upper()
             txt += ch
             self.short.SetValue(txt)
@@ -1630,9 +1963,9 @@ class SnippetFrame(wx.Frame):
         else:
             evt.Skip()
 
-class FileSelectorCombo(wx.combo.ComboCtrl):
+class FileSelectorCombo(ComboCtrl):
     def __init__(self, *args, **kw):
-        wx.combo.ComboCtrl.__init__(self, *args, **kw)
+        ComboCtrl.__init__(self, *args, **kw)
         w, h = 12, 14
         bmp = wx.EmptyBitmap(w,h)
         dc = wx.MemoryDC(bmp)
@@ -1643,14 +1976,18 @@ class FileSelectorCombo(wx.combo.ComboCtrl):
 
         dc.SetBrush(wx.Brush("#444444"))
         dc.SetPen(wx.Pen("#444444"))
-        dc.DrawPolygon([wx.Point(4,h/2-2), wx.Point(w/2,2), wx.Point(w-4,h/2-2)])
-        dc.DrawPolygon([wx.Point(4,h/2+2), wx.Point(w/2,h-2), wx.Point(w-4,h/2+2)])
+        dc.DrawPolygon([wx.Point(4, h // 2 - 2), wx.Point(w // 2, 2), wx.Point(w - 4, h // 2 - 2)])
+        dc.DrawPolygon([wx.Point(4, h // 2 + 2), wx.Point(w // 2, h - 2), wx.Point(w - 4, h // 2 + 2)])
         del dc
 
         bmp.SetMaskColour(bgcolor)
         self.SetButtonBitmaps(bmp, True)
 
-class TreeCtrlComboPopup(wx.combo.ComboPopup):
+class TreeCtrlComboPopup(ComboPopup):
+    def __init__(self):
+        ComboPopup.__init__(self)
+        self.tree = None
+
     def Init(self):
         self.value = None
         self.curitem = None
@@ -1669,63 +2006,55 @@ class TreeCtrlComboPopup(wx.combo.ComboPopup):
         self.tree.SetFont(font)
         self.tree.Bind(wx.EVT_MOTION, self.OnMotion)
         self.tree.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
+        return True
 
     def GetControl(self):
         return self.tree
 
-    def GetStringValue(self):
-        if self.value:
-            return self.tree.GetItemText(self.value)
-        return ""
-
     def OnPopup(self):
         self.tree.DeleteAllItems()
-        editor = self.GetCombo().GetParent().GetParent().panel.editor
+        if "phoenix" in wx.version():
+            editor = self.GetComboCtrl().GetParent().GetParent().panel.editor
+        else:
+            editor = self.GetCombo().GetParent().GetParent().panel.editor
         count = editor.GetLineCount()
         for i in range(count):
-            text = editor.GetLineUTF8(i)
+            text = editor.GetLine(i)
             if text.startswith("class "):
                 text = text.replace("class ", "")
                 text = text[0:text.find(":")]
                 if len(text) > 50:
                     text = text[:50] + "...)"
-                item = self.AddItem(text, None, wx.TreeItemData(i))
+                item = self.AddItem(text, None, packItemData(i))
             elif text.startswith("def "):
                 text = text.replace("def ", "")
                 text = text[0:text.find(":")]
                 if len(text) > 50:
                     text = text[:50] + "...)"
-                item = self.AddItem(text, None, wx.TreeItemData(i))
+                item = self.AddItem(text, None, packItemData(i))
             elif text.lstrip().startswith("def "):
                 indent = editor.GetLineIndentation(i)
                 text = text.lstrip().replace("def ", "")
                 text = " "*indent + text[0:text.find(":")]
                 if len(text) > 50:
                     text = text[:50] + "...)"
-                item = self.AddItem(text, None, wx.TreeItemData(i))
+                item = self.AddItem(text, None, packItemData(i))
         self.tree.SetSize((400, 500))
 
     def SetStringValue(self, value):
-        root = self.tree.GetRootItem()
-        if not root:
-            return
-        found = self.FindItem(root, value)
-        if found:
-            self.value = found
-            self.tree.SelectItem(found)
+        if self.curitem is not None:
+            self.tree.SelectItem(self.curitem)
 
     def GetAdjustedSize(self, minWidth, prefHeight, maxHeight):
         return wx.Size(minWidth, min(200, maxHeight))
 
-    def FindItem(self, parentItem, text):
-        item, cookie = self.tree.GetFirstChild(parentItem)
-        while item:
-            if self.tree.GetItemText(item) == text:
-                return item
-            if self.tree.ItemHasChildren(item):
-                item = self.FindItem(item, text)
-            item, cookie = self.tree.GetNextChild(parentItem, cookie)
-        return wx.TreeItemId();
+    def FindItem(self, *args):
+        "Dummy with variable size args needed to avoid error on both classic and phoenix."
+        return True
+
+    def GetStringValue(self):
+        if self.curitem is not None:
+            return self.tree.GetItemText(self.curitem)
 
     def AddItem(self, value, parent=None, data=None):
         if not parent:
@@ -1740,22 +2069,22 @@ class TreeCtrlComboPopup(wx.combo.ComboPopup):
         item, flags = self.tree.HitTest(evt.GetPosition())
         if item and flags & wx.TREE_HITTEST_ONITEMLABEL:
             self.tree.SelectItem(item)
-            self.curitem = item
         evt.Skip()
 
     def OnLeftDown(self, evt):
         item, flags = self.tree.HitTest(evt.GetPosition())
         if item and flags & wx.TREE_HITTEST_ONITEMLABEL:
             self.curitem = item
-            self.value = item
             self.Dismiss()
-            editor = self.GetCombo().GetParent().GetParent().panel.editor
-            line = self.tree.GetPyData(item)
+            if "phoenix" in wx.version():
+                editor = self.GetComboCtrl().GetParent().GetParent().panel.editor
+            else:
+                editor = self.GetCombo().GetParent().GetParent().panel.editor
+            line = unpackItemData(self.tree.GetItemData(item))
             editor.GotoLine(line)
-            halfNumLinesOnScreen = editor.LinesOnScreen() / 2
+            halfNumLinesOnScreen = editor.LinesOnScreen() // 2
             editor.ScrollToLine(line - halfNumLinesOnScreen)
             wx.CallAfter(editor.SetFocus)
-        evt.Skip()
 
 class MainFrame(wx.Frame):
     def __init__(self, parent, ID, title, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE):
@@ -1765,6 +2094,14 @@ class MainFrame(wx.Frame):
 
         EVT_DATA_EVENT(self, self.format_outputLog)
 
+        if sys.platform == "darwin":
+            accel_ctrl = wx.ACCEL_CMD
+        else:
+            accel_ctrl = wx.ACCEL_CTRL
+        # To set up an accelerator key
+        #aEntry = wx.AcceleratorEntry(accel_ctrl|wx.ACCEL_SHIFT, wx.WXK_UP, 602)
+        # "\t%s" % aEntry.ToString()
+
         self.snippet_frame = SnippetFrame(self, title='Snippet Editor', pos=(25,25), size=(700,450))
         self.style_frame = ColourEditor(self, title='Style Editor', pos=(100,100), size=(500,550))
         self.style_frame.setCurrentStyle(PREF_STYLE)
@@ -1773,6 +2110,7 @@ class MainFrame(wx.Frame):
         self.server_pipe = None
         self.back_server_started = False
 
+        self.master_document = None
         self.processID = 0
         self.processes = {}
         self.filters = {}
@@ -1789,9 +2127,9 @@ class MainFrame(wx.Frame):
         menu1.Append(wx.ID_NEW, "New\tCtrl+N")
         self.Bind(wx.EVT_MENU, self.new, id=wx.ID_NEW)
         self.submenu1 = wx.Menu()
-        for key, name in sorted(TEMPLATE_NAMES.items()):
+        for key, name in sorted(TEMPLATE_NAMES.items(), reverse=True):
             self.submenu1.Append(key, "%s Template" % name)
-        menu1.AppendMenu(99, "New From Template", self.submenu1)
+        menu1.AppendSubMenu(self.submenu1, "New From Template")
         self.Bind(wx.EVT_MENU, self.newFromTemplate, id=min(TEMPLATE_NAMES.keys()), id2=max(TEMPLATE_NAMES.keys()))
         menu1.Append(wx.ID_OPEN, "Open\tCtrl+O")
         self.Bind(wx.EVT_MENU, self.open, id=wx.ID_OPEN)
@@ -1815,7 +2153,7 @@ class MainFrame(wx.Frame):
         if ID_OPEN_RECENT > 2000:
             for i in range(2000, ID_OPEN_RECENT):
                 self.Bind(wx.EVT_MENU, self.openRecent, id=i)
-        menu1.AppendMenu(1999, "Open Recent...", self.submenu2)
+        menu1.AppendSubMenu(self.submenu2, "Open Recent...")
         menu1.AppendSeparator()
         menu1.Append(wx.ID_CLOSE, "Close\tCtrl+W")
         self.Bind(wx.EVT_MENU, self.close, id=wx.ID_CLOSE)
@@ -1825,11 +2163,14 @@ class MainFrame(wx.Frame):
         self.Bind(wx.EVT_MENU, self.save, id=wx.ID_SAVE)
         menu1.Append(wx.ID_SAVEAS, "Save As...\tShift+Ctrl+S")
         self.Bind(wx.EVT_MENU, self.saveas, id=wx.ID_SAVEAS)
-        menu1.AppendSeparator()
-        menu1.Append(wx.ID_PREVIEW, "Print Preview")
-        self.Bind(wx.EVT_MENU, self.OnPrintPreview, id=wx.ID_PREVIEW)
-        menu1.Append(wx.ID_PRINT, "Print\tCtrl+P")
-        self.Bind(wx.EVT_MENU, self.OnPrint, id=wx.ID_PRINT)
+        menu1.Append(100, "Save As Template...")
+        self.Bind(wx.EVT_MENU, self.saveasTemplate, id=100)
+        # TODO : printing not working well enough
+        #menu1.AppendSeparator()
+        #menu1.Append(wx.ID_PREVIEW, "Print Preview")
+        #self.Bind(wx.EVT_MENU, self.OnPrintPreview, id=wx.ID_PREVIEW)
+        #menu1.Append(wx.ID_PRINT, "Print\tCtrl+P")
+        #self.Bind(wx.EVT_MENU, self.OnPrint, id=wx.ID_PRINT)
         if sys.platform != "darwin":
             menu1.AppendSeparator()
         prefItem = menu1.Append(wx.ID_PREFERENCES, "Preferences...\tCtrl+;")
@@ -1868,20 +2209,35 @@ class MainFrame(wx.Frame):
         menu2.Append(107, "Remove Trailing White Space")
         self.Bind(wx.EVT_MENU, self.removeTrailingWhiteSpace, id=107)
         menu2.AppendSeparator()
-        menu2.Append(103, "Collapse/Expand\tCtrl+I")
+        menu2.Append(103, "Fold All\tCtrl+I")
         self.Bind(wx.EVT_MENU, self.fold, id=103)
+        menu2.Append(104, "Expand All\tShift+Ctrl+I")
+        self.Bind(wx.EVT_MENU, self.fold, id=104)
+        menu2.Append(105, "Fold/Expand Current Scope\tCtrl+8")
+        self.Bind(wx.EVT_MENU, self.foldExpandScope, id=105)
         menu2.Append(108, "Un/Comment Selection\tCtrl+J")
         self.Bind(wx.EVT_MENU, self.OnComment, id=108)
-        menu2.Append(114, "Show AutoCompletion\tCtrl+K")
-        self.Bind(wx.EVT_MENU, self.autoComp, id=114)
         menu2.Append(121, "Insert File Path...\tShift+Ctrl+P")
         self.Bind(wx.EVT_MENU, self.insertPath, id=121)
         menu2.AppendSeparator()
-        menu2.Append(170, "Convert Selection to Uppercase\tCtrl+U")
-        menu2.Append(171, "Convert Selection to Lowercase\tShift+Ctrl+U")
+        submenublk = wx.Menu()
+        submenublk.Append(400, "Insert Code Block Head\tCtrl+B")
+        submenublk.Append(401, "Insert Code Block Tail\tShift+Ctrl+B")
+        submenublk.Append(402, "Select Code Block\tCtrl+,")
+        self.Bind(wx.EVT_MENU, self.onCodeBlock, id=400, id2=402)
+        menu2.AppendSubMenu(submenublk, "Code Blocks")
+        menu2.AppendSeparator()
+        menu2.Append(114, "Auto Complete container syntax", kind=wx.ITEM_CHECK)
+        self.Bind(wx.EVT_MENU, self.autoCompContainer, id=114)
+        menu2.Check(114, PREFERENCES.get("auto_comp_container", 0))
+        menu2.AppendSeparator()
+        submenu2 = wx.Menu()
+        submenu2.Append(170, "Convert Selection to Uppercase\tCtrl+U")
+        submenu2.Append(171, "Convert Selection to Lowercase\tShift+Ctrl+U")
         self.Bind(wx.EVT_MENU, self.upperLower, id=170, id2=171)
-        menu2.Append(172, "Convert Tabs to Spaces")
+        submenu2.Append(172, "Convert Tabs to Spaces")
         self.Bind(wx.EVT_MENU, self.tabsToSpaces, id=172)
+        menu2.AppendSubMenu(submenu2, "Text Converters")
         menu2.AppendSeparator()
         menu2.Append(140, "Goto line...\tCtrl+L")
         self.Bind(wx.EVT_MENU, self.gotoLine, id=140)
@@ -1898,22 +2254,25 @@ class MainFrame(wx.Frame):
         self.Bind(wx.EVT_MENU, self.showFind, id=wx.ID_FIND)
         self.menuBar.Append(menu2, 'Code')
 
-        menu3 = wx.Menu()
-        menu3.Append(300, "Run\tCtrl+R")
+        self.menu3 = wx.Menu()
+        self.menu3.Append(299, "Set Current Document as Master")
+        self.Bind(wx.EVT_MENU, self.setMasterDocument, id=299)
+        self.menu3.AppendSeparator()
+        self.menu3.Append(300, "Run\tCtrl+R")
         self.Bind(wx.EVT_MENU, self.runner, id=300)
-        menu3.Append(301, "Run Selection\tShift+Ctrl+R")
+        self.menu3.Append(301, "Run Selection\tShift+Ctrl+R")
         self.Bind(wx.EVT_MENU, self.runSelection, id=301)
-        menu3.Append(302, "Run Line/Selection as Pyo\tCtrl+E")
+        self.menu3.Append(302, "Run Line/Selection as Pyo\tCtrl+E")
         self.Bind(wx.EVT_MENU, self.runSelectionAsPyo, id=302)
-        menu3.Append(303, "Execute Line/Selection as Python\tShift+Ctrl+E")
+        self.menu3.Append(303, "Execute Line/Selection as Python\tShift+Ctrl+E")
         self.Bind(wx.EVT_MENU, self.execSelection, id=303)
-        menu3.AppendSeparator()
-        self.backServerItem = menu3.Append(304, "Start Pyo Background Server")
+        self.menu3.AppendSeparator()
+        self.backServerItem = self.menu3.Append(304, "Start Pyo Background Server")
         self.Bind(wx.EVT_MENU, self.startStopBackgroundServer, id=304)
-        self.sendToServerItem = menu3.Append(305, "Send Line/Selection to Pyo Background Server\tCtrl+T")
+        self.sendToServerItem = self.menu3.Append(305, "Send Line/Selection to Pyo Background Server\tCtrl+.")
         self.sendToServerItem.Enable(False)
         self.Bind(wx.EVT_MENU, self.sendSelectionToBackgroundServer, id=305)
-        self.menuBar.Append(menu3, 'Process')
+        self.menuBar.Append(self.menu3, 'Process')
 
         menu4 = wx.Menu()
         menu4.Append(wx.ID_ZOOM_IN, "Zoom in\tCtrl+=")
@@ -1941,6 +2300,10 @@ class MainFrame(wx.Frame):
         self.Bind(wx.EVT_MENU, self.showDocFrame, id=190)
         menu4.Append(180, "Open Documentation for Pyo Object Under Caret\tCtrl+D")
         self.Bind(wx.EVT_MENU, self.showDoc, id=180)
+        menu4.Append(181, "Show args for Pyo Object Under Caret\tShift+Return")
+        self.Bind(wx.EVT_MENU, self.showArgs, id=181)
+        menu4.Append(182, "Show __doc__ String for Word Under Caret\tCtrl+Return")
+        self.Bind(wx.EVT_MENU, self.showDocString, id=182)
         menu4.AppendSeparator()
         menu4.Append(185, "Rebuild Documentation")
         self.Bind(wx.EVT_MENU, self.rebuildDoc, id=185)
@@ -1963,11 +2326,6 @@ class MainFrame(wx.Frame):
         self.makeSnippetMenu()
         self.menuBar.Append(self.menu7, "Snippets")
 
-        if sys.platform == "darwin":
-            accel_ctrl = wx.ACCEL_CMD
-        else:
-            accel_ctrl = wx.ACCEL_CTRL
-
         menu8 = wx.Menu()
         menu8.Append(600, "Add Marker to Current Line\tShift+Ctrl+M")
         self.Bind(wx.EVT_MENU, self.addMarker, id=600)
@@ -1976,21 +2334,19 @@ class MainFrame(wx.Frame):
         menu8.Append(604, "Delete All Markers")
         self.Bind(wx.EVT_MENU, self.deleteAllMarkers, id=604)
         menu8.AppendSeparator()
-        aEntry = wx.AcceleratorEntry(accel_ctrl|wx.ACCEL_SHIFT, wx.WXK_UP, 602)
-        menu8.Append(602, 'Navigate Markers Upward\t%s' % aEntry.ToString())
-        aEntry = wx.AcceleratorEntry(accel_ctrl|wx.ACCEL_SHIFT, wx.WXK_DOWN, 603)
-        menu8.Append(603, 'Navigate Markers Downward\t%s' % aEntry.ToString())
+        menu8.Append(602, 'Navigate Markers Upward\tCtrl+9')
+        menu8.Append(603, 'Navigate Markers Downward\tCtrl+0')
         self.Bind(wx.EVT_MENU, self.navigateMarkers, id=602, id2=603)
         self.menuBar.Append(menu8, "Markers")
 
         self.menu6 = wx.Menu()
         ID_EXAMPLE = 1000
         for folder in EXAMPLE_FOLDERS:
-            exmenu = wx.Menu(title=folder.lower())
+            exmenu = wx.Menu(folder.lower())
             for ex in sorted([exp for exp in os.listdir(os.path.join(EXAMPLE_PATH, folder.lower())) if exp[0] != "." and not exp.endswith("pyc")]):
                 exmenu.Append(ID_EXAMPLE, ex)
                 ID_EXAMPLE += 1
-            self.menu6.AppendMenu(-1, folder, exmenu)
+            self.menu6.AppendSubMenu(exmenu, folder)
             ID_EXAMPLE += 1
         self.Bind(wx.EVT_MENU, self.openExample, id=1000, id2=ID_EXAMPLE)
         self.menuBar.Append(self.menu6, "Pyo Examples")
@@ -2001,10 +2357,10 @@ class MainFrame(wx.Frame):
         self.Bind(wx.EVT_MENU, self.openFilters, id=11998)
         self.filters_menu.Append(11999, "Rebuild Filters Menu")
         self.Bind(wx.EVT_MENU, self.buildFilterMenu, id=11999)
-        self.filters_menu.AppendSeparator() 
+        self.filters_menu.AppendSeparator()
         self.buildFilterMenu()
         self.menuBar.Append(self.filters_menu, "Filters")
-            
+
         windowMenu = wx.Menu()
         aEntry = wx.AcceleratorEntry(wx.ACCEL_CTRL, wx.WXK_TAB, 10001)
         windowMenu.Append(10001, 'Navigate Tabs Forward\t%s' % aEntry.ToString())
@@ -2028,22 +2384,23 @@ class MainFrame(wx.Frame):
 
         self.SetMenuBar(self.menuBar)
 
+        self.status = self.CreateStatusBar()
+        self.status.Bind(wx.EVT_SIZE, self.StatusOnSize)
+        self.status.SetFieldsCount(3)
+
         if PLATFORM == "darwin":
             ststyle = wx.TE_PROCESS_ENTER|wx.NO_BORDER
-            sth = 17
+            sth = self.status.GetSize()[1] #16
             cch = -1
-        elif PLATFORM == "linux2":
+        elif PLATFORM.startswith("linux"):
             ststyle = wx.TE_PROCESS_ENTER|wx.SIMPLE_BORDER
-            sth = 20
-            cch = 21
+            sth = self.status.GetSize()[1]+1 #20
+            cch = self.status.GetSize()[1] #21
         elif PLATFORM == "win32":
             ststyle = wx.TE_PROCESS_ENTER|wx.SIMPLE_BORDER
             sth = 20
             cch = 20
 
-        self.status = self.CreateStatusBar()
-        self.status.Bind(wx.EVT_SIZE, self.StatusOnSize)
-        self.status.SetFieldsCount(3)
         self.field1X, field1Y = self.status.GetTextExtent("Quick Search:")
         self.status.SetStatusWidths([self.field1X+9,-1,-2])
         self.status.SetStatusText("Quick Search:", 0)
@@ -2079,12 +2436,12 @@ class MainFrame(wx.Frame):
         if PLATFORM == "darwin":
             yoff1 = -1
             yoff2 = -5
-        elif PLATFORM == "linux2":
-            yoff1 = 1
-            yoff2 = 0
-        elif PLATFORM == "win32":
+        elif PLATFORM.startswith("linux"):
             yoff1 = -2
-            yoff2 = -2
+            yoff2 = -1
+        elif PLATFORM == "win32":
+            yoff1 = 0
+            yoff2 = -1
 
         self.status.SetStatusText("Quick Search:", 0)
         rect = self.status.GetFieldRect(1)
@@ -2093,13 +2450,29 @@ class MainFrame(wx.Frame):
         if rect.x > self.field1X+160:
             self.cc.SetPosition((rect.x, rect.y+yoff2))
 
+    def onCodeBlock(self, evt):
+        if evt.GetId() == 400:
+            self.panel.editor.insertBlockHead()
+        elif evt.GetId() == 401:
+            self.panel.editor.insertBlockTail()
+        elif evt.GetId() == 402:
+            self.panel.editor.selectCodeBlock()
+
+    def setMasterDocument(self, evt):
+        if self.master_document == None:
+            self.master_document = self.panel.editor.path
+            self.menu3.SetLabel(299, "Revert Master Document to None")
+        else:
+            self.master_document = None
+            self.menu3.SetLabel(299, "Set Current Document as Master")
+
     def StatusOnSize(self, evt):
         self.Reposition()
 
     def rebuildStyleMenu(self):
         items = self.menu5.GetMenuItems()
         for item in items:
-            self.menu5.DeleteItem(item)
+            self.menu5.Delete(item.GetId())
         ID_STYLE = 500
         for st in [f for f in os.listdir(STYLES_PATH) if f[0] != "."]:
             self.menu5.Append(ID_STYLE, st, "", wx.ITEM_RADIO)
@@ -2113,18 +2486,21 @@ class MainFrame(wx.Frame):
     def reloadSnippetMenu(self):
         items = self.menu7.GetMenuItems()
         for item in items:
-            self.menu7.DeleteItem(item)
+            self.menu7.Delete(item.GetId())
         self.makeSnippetMenu()
 
     def makeSnippetMenu(self):
         itemId = 30000
+        accel_entries = []
         for cat in SNIPPETS_CATEGORIES:
             submenu = wx.Menu(title=cat)
             files = [f for f in os.listdir(os.path.join(SNIPPETS_PATH, cat))]
             for file in files:
                 with open(os.path.join(SNIPPETS_PATH, cat, file), "r") as f:
                     text = f.read()
-                exec text in locals()
+                spos = text.find("=")
+                dictext = text[spos+1:]
+                snippet = eval(dictext)
                 short = snippet["shortcut"]
                 accel = 0
                 if "Shift" in short:
@@ -2147,14 +2523,18 @@ class MainFrame(wx.Frame):
                 short = short.replace("-", "")
                 if short != "":
                     accel_tuple = wx.AcceleratorEntry(accel, ord(short), itemId)
+                    accel_entries.append(accel_tuple)
                     short = accel_tuple.ToString()
                     submenu.Append(itemId, "%s\t%s" % (file, short))
                 else:
                     submenu.Append(itemId, file)
                 self.Bind(wx.EVT_MENU, self.insertSnippet, id=itemId)
                 itemId += 1
-            self.menu7.AppendMenu(itemId, cat, submenu)
-            itemId += 1
+            self.menu7.AppendSubMenu(submenu, cat)
+        if accel_entries != []:
+            accel_table = wx.AcceleratorTable(accel_entries)
+            self.SetAcceleratorTable(accel_table)
+
         self.menu7.AppendSeparator()
         self.menu7.Append(51, "Open Snippet Editor")
         self.Bind(wx.EVT_MENU, self.showSnippetEditor, id=51)
@@ -2167,7 +2547,7 @@ class MainFrame(wx.Frame):
         self.panel.editor.Copy()
 
     def listCopy(self, evt):
-        text = self.panel.editor.GetSelectedTextUTF8()
+        text = self.panel.editor.GetSelectedText()
         self.pastingList.append(toSysEncoding(text))
 
     def paste(self, evt):
@@ -2181,23 +2561,25 @@ class MainFrame(wx.Frame):
 
     def saveListPaste(self, evt):
         if self.pastingList != []:
-            dlg = wx.FileDialog(self, message="Save file as ...", 
-                defaultDir=os.path.expanduser('~'), style=wx.SAVE)
+            dlg = wx.FileDialog(self, message="Save file as ...",
+                                defaultDir=os.path.expanduser('~'),
+                                style=wx.FD_SAVE)
             if dlg.ShowModal() == wx.ID_OK:
                 path = ensureNFD(dlg.GetPath())
                 with open(path, "w") as f:
                     f.write(str(self.pastingList))
 
     def loadListPaste(self, evt):
-        dlg = wx.FileDialog(self, message="Choose a file", 
-            defaultDir=os.path.expanduser("~"), style=wx.OPEN)
+        dlg = wx.FileDialog(self, message="Choose a file",
+                            defaultDir=os.path.expanduser("~"),
+                            style=wx.FD_OPEN)
         if dlg.ShowModal() == wx.ID_OK:
             path = dlg.GetPath()
             self.pastingList = []
             with open(path, "r") as f:
                 try:
                     pastingList = eval(f.read())
-                    if type(pastingList) == ListType:
+                    if type(pastingList) == list:
                         self.pastingList = pastingList
                 except:
                     f.seek(0)
@@ -2225,7 +2607,7 @@ class MainFrame(wx.Frame):
         if self.ID_FILTERS != 12000:
             for i in range(12000, self.ID_FILTERS):
                 self.filters_menu.Delete(i)
-        ID_FILTERS = 12000       
+        ID_FILTERS = 12000
         with open(FILTERS_FILE, "r") as f:
             for line in f.readlines():
                 if line.startswith("def "):
@@ -2241,19 +2623,22 @@ class MainFrame(wx.Frame):
         self.panel.addPage(FILTERS_FILE)
 
     def applyFilter(self, evt):
-        execfile(FILTERS_FILE, {}, locals())
+        with open(FILTERS_FILE, "r") as f:
+            text = f.read()
+        functions = {}
+        exec(text, functions)
         filter = self.filters[evt.GetId()]
-        try:
-            text = self.panel.editor.GetSelectedTextUTF8()
-        except:
-            text = self.panel.editor.GetSelectedText()
+        text = self.panel.editor.GetSelectedText()
         if text == "":
-            dlg = wx.MessageDialog(self, "You must select some text to apply a filter...", "No selected text!", style=wx.OK|wx.STAY_ON_TOP)
+            dlg = wx.MessageDialog(self,
+                                   "You must select some text to apply a filter...",
+                                   "No selected text!",
+                                   style=wx.OK | wx.STAY_ON_TOP)
             dlg.ShowModal()
             dlg.Destroy()
         else:
-            self.panel.editor.ReplaceSelection(locals()[filter](text))
-        
+            self.panel.editor.ReplaceSelection(functions[filter](text))
+
     def undo(self, evt):
         if evt.GetId() == wx.ID_UNDO:
             self.panel.editor.Undo()
@@ -2294,7 +2679,6 @@ class MainFrame(wx.Frame):
     def addMarker(self, evt):
         line = self.panel.editor.GetCurrentLine()
         self.panel.editor.addMarker(line)
-        self.panel.editor.addMarkerComment(line)
 
     def deleteMarker(self, evt):
         line = self.panel.editor.GetCurrentLine()
@@ -2317,25 +2701,37 @@ class MainFrame(wx.Frame):
                 val = int(dlg.GetValue())
             except:
                 val = -1
-            dlg.Destroy()
+        dlg.Destroy()
         if val != -1:
-            pos = self.panel.editor.FindColumn(val-1, 0)
-            self.panel.editor.SetCurrentPos(pos)
-            self.panel.editor.EnsureVisible(val)
-            self.panel.editor.EnsureCaretVisible()
+            val -= 1
+            pos = self.panel.editor.FindColumn(val, 0)
+            self.panel.editor.GotoLine(val)
+            first = self.panel.editor.GetFirstVisibleLine()
+            if val == first:
+                self.panel.editor.LineScroll(0, -self.panel.editor.LinesOnScreen() // 2)
+            else:
+                self.panel.editor.LineScroll(0, self.panel.editor.LinesOnScreen() // 2)
+            #self.panel.editor.SetCurrentPos(pos)
+            #self.panel.editor.EnsureVisible(val)
+            #self.panel.editor.EnsureCaretVisible()
             wx.CallAfter(self.panel.editor.SetAnchor, pos)
 
     def OnComment(self, evt):
         self.panel.editor.OnComment()
 
     def fold(self, event):
-        self.panel.editor.FoldAll()
+        if event.GetId() == 103:
+            self.panel.editor.FoldAll()
+        else:
+            self.panel.editor.ExpandAll()
 
-    def autoComp(self, evt):
-        try:
-            self.panel.editor.showAutoComp()
-        except AttributeError:
-            pass
+    def foldExpandScope(self, evt):
+        self.panel.editor.foldExpandCurrentScope()
+
+    def autoCompContainer(self, evt):
+        state = evt.GetInt()
+        PREFERENCES["auto_comp_container"] = state
+        self.panel.editor.showAutoCompContainer(state)
 
     def showFind(self, evt):
         self.panel.editor.OnShowFindReplace()
@@ -2350,7 +2746,7 @@ class MainFrame(wx.Frame):
         word = self.panel.editor.getWordUnderCaret()
         self.status_search.SetValue(word)
         self.onQuickSearchEnter(None)
-        
+
     def onQuickSearchEnter(self, evt):
         str = self.status_search.GetValue()
         self.panel.editor.SetFocus()
@@ -2367,7 +2763,7 @@ class MainFrame(wx.Frame):
     def searchInProject(self, evt):
         ok = False
         search = ""
-        choices = self.panel.project.projectDict.keys()
+        choices = list(self.panel.project.projectDict.keys())
         if len(choices) == 0:
             dlg = wx.MessageDialog(self, 'You must load at least one folder to use the "Search in Project Files" option.',
                                     'No project folder', wx.OK | wx.ICON_INFORMATION)
@@ -2389,11 +2785,12 @@ class MainFrame(wx.Frame):
                 search = dlg.GetValue()
             dlg.Destroy()
             if search:
-                wx.CallAfter(self.doSearchInProject, rootdir, search)
-    
+                wx.CallAfter(self.doSearchInProject, rootdir, ensureNFD(search))
+
     def doSearchInProject(self, rootdir, search):
         result = {}
-        filters = ["build"]
+        filters = ["build", "__pycache__"]
+        busy = wx.BusyCursor()
         for root, dirs, files in os.walk(rootdir):
             if os.path.split(root)[1].startswith("."):
                 filters.append(os.path.split(root)[1])
@@ -2409,57 +2806,67 @@ class MainFrame(wx.Frame):
                 filepath = os.path.join(root, file).replace(rootdir, "")
                 if filepath.endswith("~"):
                     continue
-                with open(os.path.join(root, file), "r") as f:
-                    for i, line in enumerate(f.readlines()):
-                        if "\0" in line:
-                            # binary file detected
-                            break
-                        if search.encode("utf-8").lower() in line.lower():
-                            if not result.has_key(filepath):
-                                result[filepath] = ([], [])
-                            result[filepath][0].append(i+1)
-                            if len(line) < 50:
-                                result[filepath][1].append(line.strip().replace("\n", ""))
-                            else:
-                                pos = line.lower().find(search.encode("utf-8").lower())
-                                p1 = pos - 25
-                                if p1 < 0:
-                                    p1, pre = 0, ""
-                                else:
-                                    pre = "... "
-                                p2 = pos + 25
-                                if p2 >= len(line):
-                                    p2, post = len(line), ""
+                try:
+                    with open(os.path.join(root, file), "r") as f:
+                        for i, line in enumerate(f.readlines()):
+                            if "\0" in line:
+                                # binary file detected
+                                break
+                            if search.lower() in line.lower():
+                                if filepath not in result:
+                                    result[filepath] = ([], [])
+                                result[filepath][0].append(i+1)
+                                if len(line) < 50:
+                                    result[filepath][1].append(line.strip().replace("\n", ""))
                                 else:
-                                    post = " ..."
-                                result[filepath][1].append(pre + line[p1:p2].strip().replace("\n", "") + post)
+                                    pos = line.lower().find(search.lower())
+                                    p1 = pos - 25
+                                    if p1 < 0:
+                                        p1, pre = 0, ""
+                                    else:
+                                        pre = "... "
+                                    p2 = pos + 25
+                                    if p2 >= len(line):
+                                        p2, post = len(line), ""
+                                    else:
+                                        post = " ..."
+                                    result[filepath][1].append(pre + line[p1:p2].strip().replace("\n", "") + post)
+                except:
+                    pass
+        del busy
         if result:
             f = SearchProjectFrame(self, rootdir, result)
 
     def insertPath(self, evt):
-        dlg = wx.FileDialog(self, message="Choose a file", 
+        dlg = wx.FileDialog(self, message="Choose a file",
                             defaultDir=PREFERENCES.get("insert_path", os.path.expanduser("~")),
-                            defaultFile="", style=wx.OPEN | wx.MULTIPLE)
+                            defaultFile="", style=wx.FD_OPEN | wx.FD_MULTIPLE)
         if dlg.ShowModal() == wx.ID_OK:
             paths = dlg.GetPaths()
             if len(paths) == 1:
                 text = ensureNFD(paths[0])
+                if PLATFORM == "win32":
+                    text = text.replace("\\", "/")
                 self.panel.editor.ReplaceSelection("'" + text + "'")
             else:
                 text = ", ".join(["'"+ensureNFD(path)+"'" for path in paths])
+                if PLATFORM == "win32":
+                    text = text.replace("\\", "/")
                 self.panel.editor.ReplaceSelection("[" + text + "]")
             PREFERENCES["insert_path"] = os.path.split(paths[0])[0]
         dlg.Destroy()
 
     def insertSnippet(self, evt):
         id = evt.GetId()
-        menu = self.menu7 #event.GetEventObject()
+        menu = self.menu7
         item = menu.FindItemById(id)
         name = item.GetLabel()
         category = item.GetMenu().GetTitle()
-        with codecs.open(os.path.join(SNIPPETS_PATH, category, name), "r", encoding="utf-8") as f:
+        with codecs.open(os.path.join(ensureNFD(SNIPPETS_PATH), category, name), "r", encoding="utf-8") as f:
             text = f.read()
-        exec text in locals()
+        spos = text.find("=")
+        dictext = text[spos+1:]
+        snippet = eval(dictext)
         self.panel.editor.insertSnippet(snippet["value"])
 
     def openStyleEditor(self, evt):
@@ -2471,18 +2878,20 @@ class MainFrame(wx.Frame):
         st = menu.FindItemById(id).GetLabel()
         self.setStyle(st, fromMenu=True)
         self.style_frame.setCurrentStyle(st)
-        
+
     def setStyle(self, st, fromMenu=False):
         global STYLES
-        with open(os.path.join(STYLES_PATH, st)) as f:
+        with open(os.path.join(ensureNFD(STYLES_PATH), st)) as f:
             text = f.read()
-        exec text in locals()
+        spos = text.find("=")
+        dictext = text[spos+1:]
+        style = eval(dictext)
         STYLES = copy.deepcopy(style)
-        if not STYLES.has_key('face'):
+        if 'face' not in STYLES:
             STYLES['face'] = DEFAULT_FONT_FACE
-        if not STYLES.has_key('size'):
+        if 'size' not in STYLES:
             STYLES['size'] = FONT_SIZE
-        if not STYLES.has_key('size2'):
+        if 'size2' not in STYLES:
             STYLES['size2'] = FONT_SIZE2
 
         for i in range(self.panel.notebook.GetPageCount()):
@@ -2539,11 +2948,11 @@ class MainFrame(wx.Frame):
             if not self.panel.splitter.IsSplit():
                 self.panel.splitter.SplitVertically(self.panel.left_splitter, self.panel.right_splitter, 175)
                 h = self.panel.GetSize()[1]
-                self.panel.left_splitter.SplitHorizontally(self.panel.project, self.panel.markers, h*3/4)
+                self.panel.left_splitter.SplitHorizontally(self.panel.project, self.panel.markers, h * 3 // 4)
                 self.panel.left_splitter.Unsplit(self.panel.markers)
             else:
                 h = self.panel.GetSize()[1]
-                self.panel.left_splitter.SplitHorizontally(self.panel.project, self.panel.markers, h*3/4)
+                self.panel.left_splitter.SplitHorizontally(self.panel.project, self.panel.markers, h * 3 // 4)
         else:
             if self.panel.markers.IsShown():
                 self.panel.left_splitter.Unsplit(self.panel.project)
@@ -2559,11 +2968,11 @@ class MainFrame(wx.Frame):
             if not self.panel.splitter.IsSplit():
                 self.panel.splitter.SplitVertically(self.panel.left_splitter, self.panel.right_splitter, 175)
                 h = self.panel.GetSize()[1]
-                self.panel.left_splitter.SplitHorizontally(self.panel.project, self.panel.markers, h*3/4)
+                self.panel.left_splitter.SplitHorizontally(self.panel.project, self.panel.markers, h * 3 // 4)
                 self.panel.left_splitter.Unsplit(self.panel.project)
             else:
                 h = self.panel.GetSize()[1]
-                self.panel.left_splitter.SplitHorizontally(self.panel.project, self.panel.markers, h*3/4)
+                self.panel.left_splitter.SplitHorizontally(self.panel.project, self.panel.markers, h * 3 // 4)
         else:
             if self.panel.project.IsShown():
                 self.panel.left_splitter.Unsplit(self.panel.markers)
@@ -2577,7 +2986,7 @@ class MainFrame(wx.Frame):
             if self.panel.outputlog.IsShownOnScreen():
                 return
             h = self.panel.GetSize()[1]
-            self.panel.right_splitter.SplitHorizontally(self.panel.notebook, self.panel.outputlog, h*4/5 - h)
+            self.panel.right_splitter.SplitHorizontally(self.panel.notebook, self.panel.outputlog, h * 4 // 5 - h)
         else:
             if not self.panel.outputlog.IsShownOnScreen():
                 return
@@ -2611,10 +3020,13 @@ class MainFrame(wx.Frame):
         subId2 = 2000
         if lines != []:
             for item in self.submenu2.GetMenuItems():
-                self.submenu2.DeleteItem(item)
+                self.submenu2.Delete(item.GetId())
             for file in lines:
                 self.submenu2.Append(subId2, toSysEncoding(file))
                 subId2 += 1
+        if subId2 > 2000:
+            for i in range(2000, subId2):
+                self.Bind(wx.EVT_MENU, self.openRecent, id=i)
 
     def openRecent(self, event):
         menu = self.GetMenuBar()
@@ -2623,9 +3035,9 @@ class MainFrame(wx.Frame):
         self.panel.addPage(ensureNFD(file))
 
     def open(self, event, encoding=None):
-        dlg = wx.FileDialog(self, message="Choose a file", 
+        dlg = wx.FileDialog(self, message="Choose a file",
             defaultDir=PREFERENCES.get("open_file_path", os.path.expanduser("~")),
-            defaultFile="", style=wx.OPEN | wx.MULTIPLE)
+            defaultFile="", style=wx.FD_OPEN | wx.FD_MULTIPLE)
         if dlg.ShowModal() == wx.ID_OK:
             paths = dlg.GetPaths()
             for path in paths:
@@ -2654,7 +3066,7 @@ class MainFrame(wx.Frame):
         item = menu.FindItemById(id)
         filename = item.GetLabel()
         folder = item.GetMenu().GetTitle()
-        path = os.path.join(EXAMPLE_PATH, folder, filename)
+        path = os.path.join(ensureNFD(EXAMPLE_PATH), folder, filename)
         self.panel.addPage(ensureNFD(path))
 
     def openTutorial(self, event):
@@ -2663,9 +3075,9 @@ class MainFrame(wx.Frame):
             self.panel.addPage(os.path.join(os.getcwd(), "Resources", filename))
         else:
             self.panel.addPage(os.path.join(os.getcwd(), filename))
-        
+
     def openFolder(self, event):
-        dlg = wx.DirDialog(self, message="Choose a folder", 
+        dlg = wx.DirDialog(self, message="Choose a folder",
             defaultPath=PREFERENCES.get("open_folder_path", os.path.expanduser("~")),
             style=wx.DD_DEFAULT_STYLE)
         if dlg.ShowModal() == wx.ID_OK:
@@ -2688,9 +3100,11 @@ class MainFrame(wx.Frame):
 
     def saveas(self, event):
         deffile = os.path.split(self.panel.editor.path)[1]
-        dlg = wx.FileDialog(self, message="Save file as ...", 
-            defaultDir=PREFERENCES.get("save_file_path", os.path.expanduser("~")),
-            defaultFile=deffile, style=wx.SAVE)
+        dlg = wx.FileDialog(self, message="Save file as ...",
+                            defaultDir=PREFERENCES.get("save_file_path",
+                                                       os.path.expanduser("~")),
+                            defaultFile=deffile,
+                            style=wx.FD_SAVE)
         dlg.SetFilterIndex(0)
         if dlg.ShowModal() == wx.ID_OK:
             path = ensureNFD(dlg.GetPath())
@@ -2707,12 +3121,25 @@ class MainFrame(wx.Frame):
             PREFERENCES["save_file_path"] = os.path.split(path)[0]
         dlg.Destroy()
 
+    def saveasTemplate(self, event):
+        dlg = wx.TextEntryDialog(self, 'Give a name to your template:', 'Save file as template...')
+        if dlg.ShowModal() == wx.ID_OK:
+            fname = dlg.GetValue()
+            if not fname.endswith(".py"):
+                fname = fname + ".py"
+            text = self.panel.editor.GetText()
+            with open(os.path.join(TEMPLATE_PATH, fname), "w") as f:
+                f.write(text)
+        dlg.Destroy()
+
     def close(self, event):
         action = self.panel.editor.close()
         if action == 'delete':
+            self.panel.close_from_menu = True
             self.panel.deletePage()
         else:
             pass
+        self.panel.close_from_menu = False
 
     def closeAll(self, event):
         count = self.panel.notebook.GetPageCount()
@@ -2723,35 +3150,62 @@ class MainFrame(wx.Frame):
 
     ### Run actions ###
     def getCurrentWorkingDirectory(self):
-        path = ensureNFD(self.panel.editor.path)
+        if self.master_document != None:
+            path = ensureNFD(self.master_document)
+        else:
+            path = ensureNFD(self.panel.editor.path)
         cwd = os.path.expanduser("~")
         if os.path.isfile(path):
             try:
                 cwd = toSysEncoding(os.path.split(path)[0])
             except:
                 pass
-        return cwd
+        return ensureNFD(cwd)
 
     def addCwdToSysPath(self, text):
         cwd = self.getCurrentWorkingDirectory()
-        check = True
+        if sys.platform == "win32":
+            cwd = cwd.replace("/", "\\")
+            cwd = cwd.replace("\\", "\\\\")
+        check1 = check2 = True
+        is_future = '__future__' in text
+        future_found = not is_future
+        is_sys_import = 'import sys' in text
+        sys_found = not is_sys_import
         newtext = ""
         for line in text.splitlines():
-            if check and not line.startswith("#"):
-                newtext += '# encoding: utf-8\nimport sys\nsys.path.append("%s")\n' % cwd
-                check = False
+            if check1:
+                if not line.startswith("#"):
+                    if not '# encoding:' in text:
+                        newtext += '# -*- encoding: %s -*-\n' % sys.getfilesystemencoding()
+                    check1 = False
+            if not check1 and check2:
+                if is_future and '__future__' in line:
+                    future_found = True
+                if future_found and not '__future__' in line:
+                    if not is_sys_import:
+                        newtext += 'import sys\nsys.path.append("%s")\n' % cwd
+                        check2 = False
+                    elif is_sys_import and 'import sys' in line:
+                        sys_found = True
+                    elif sys_found:
+                        newtext += 'sys.path.append("%s")\n' % cwd
+                        check2 = False
             newtext += line + "\n"
         return newtext
 
     def format_outputLog(self, evt):
         data = evt.data
-        self.panel.outputlog.setLog(data["log"])
-        self.panel.outputlog.removeProcess(data["pid"], data["filename"])
+        self.panel.outputlog.appendToLog(data["log"])
+        if not data["active"]:
+            self.panel.outputlog.removeProcess(data["pid"], data["filename"])
 
     def run(self, path):
         cwd = self.getCurrentWorkingDirectory()
         th = RunningThread(path, cwd, self)
-        if "Untitled-" in self.panel.editor.path:
+        if self.master_document != None:
+            filename = os.path.split(self.master_document)[1]
+        elif "Untitled-" in self.panel.editor.path:
             filename = self.panel.editor.path
         else:
             filename = os.path.split(self.panel.editor.path)[1]
@@ -2763,7 +3217,11 @@ class MainFrame(wx.Frame):
         th.start()
 
     def runner(self, event):
-        text = self.panel.editor.GetTextUTF8()
+        if self.master_document != None:
+            with open(self.master_document, "r") as f:
+                text = f.read()
+        else:
+            text = self.panel.editor.GetText()
         if text != "":
             text = self.addCwdToSysPath(text)
             with open(TEMP_FILE, "w") as f:
@@ -2771,7 +3229,7 @@ class MainFrame(wx.Frame):
             self.run(TEMP_FILE)
 
     def runSelection(self, event):
-        text = self.panel.editor.GetSelectedTextUTF8()
+        text = self.panel.editor.GetSelectedText()
         if text != "":
             text = self.addCwdToSysPath(text)
             with open(TEMP_FILE, "w") as f:
@@ -2779,11 +3237,11 @@ class MainFrame(wx.Frame):
             self.run(TEMP_FILE)
 
     def runSelectionAsPyo(self, event):
-        text = self.panel.editor.GetSelectedTextUTF8()
+        text = self.panel.editor.GetSelectedText()
         if text == "":
             pos = self.panel.editor.GetCurrentPos()
             line = self.panel.editor.LineFromPosition(pos)
-            text = self.panel.editor.GetLineUTF8(line)
+            text = self.panel.editor.GetLine(line)
         text = self.addCwdToSysPath(text)
         with open(TEMP_FILE, "w") as f:
             f.write("from pyo import *\ns = Server().boot()\n")
@@ -2792,13 +3250,13 @@ class MainFrame(wx.Frame):
         self.run(TEMP_FILE)
 
     def execSelection(self, event):
-        text = self.panel.editor.GetSelectedTextUTF8()
+        text = self.panel.editor.GetSelectedText()
         if text == "":
             pos = self.panel.editor.GetCurrentPos()
             line = self.panel.editor.LineFromPosition(pos)
-            text = self.panel.editor.GetLineUTF8(line)
-            if not text.startswith("print"):
-                text = "print " + text
+            text = self.panel.editor.GetLine(line)
+            if not text.startswith("print("):
+                text = "print(" + text + ")"
         else:
             pos = self.panel.editor.GetSelectionEnd()
         line = self.panel.editor.LineFromPosition(pos)
@@ -2806,75 +3264,97 @@ class MainFrame(wx.Frame):
         self.panel.editor.SetCurrentPos(pos)
         self.panel.editor.addText("\n", False)
         with stdoutIO() as s:
-            exec text
+            exec(text)
         self.panel.editor.addText(s.getvalue())
 
+    def prepareBackgroundServer(self):
+        outDriverIndex = -1
+        preferedDriver = PREFERENCES.get("background_server_out_device", "")
+        if preferedDriver != "":
+            driverList, driverIndexes = pa_get_output_devices()
+            driverList = [ensureNFD(driver) for driver in driverList]
+            if preferedDriver and preferedDriver in driverList:
+                outDriverIndex = driverIndexes[driverList.index(preferedDriver)]
+
+        inDriverIndex = -1
+        preferedDriver = PREFERENCES.get("background_server_in_device", "")
+        if preferedDriver != "":
+            driverList, driverIndexes = pa_get_input_devices()
+            driverList = [ensureNFD(driver) for driver in driverList]
+            if preferedDriver and preferedDriver in driverList:
+                inDriverIndex = driverIndexes[driverList.index(preferedDriver)]
+
+        midiOutDriverIndex = -1
+        preferedDriver = PREFERENCES.get("background_server_midiout_device", "")
+        if preferedDriver != "":
+            driverList, driverIndexes = pm_get_output_devices()
+            driverList = [ensureNFD(driver) for driver in driverList]
+            if preferedDriver and preferedDriver in driverList:
+                midiOutDriverIndex = driverIndexes[driverList.index(preferedDriver)]
+
+        midiInDriverIndex = -1
+        preferedDriver = PREFERENCES.get("background_server_midiin_device", "")
+        if preferedDriver != "":
+            driverList, driverIndexes = pm_get_input_devices()
+            driverList = [ensureNFD(driver) for driver in driverList]
+            if preferedDriver and preferedDriver in driverList:
+                midiInDriverIndex = driverIndexes[driverList.index(preferedDriver)]
+
+        with open(os.path.join(TEMP_PATH, "background_server.py"), "w") as f:
+            f.write("print('Starting background server...')\nimport time, sys, os\nsys.path.append(os.getcwd())\nfrom pyo import *\n")
+            f.write("s = Server(%s)\n" % BACKGROUND_SERVER_ARGS)
+            if outDriverIndex != -1:
+                f.write("s.setOutputDevice(%d)\n" % outDriverIndex)
+            if inDriverIndex != -1:
+                f.write("s.setInputDevice(%d)\n" % inDriverIndex)
+            if midiOutDriverIndex != -1:
+                f.write("s.setMidiOutputDevice(%d)\n" % midiOutDriverIndex)
+            if midiInDriverIndex != -1:
+                f.write("s.setMidiInputDevice(%d)\n" % midiInDriverIndex)
+            f.write("s.boot()\ns.start()\n\n")
+            f.write("def _quit_():\n    s.stop()\n    time.sleep(0.25)\n    exit()\n")
+
+    def resetBackgroundServerMenu(self):
+        self.back_server_started = False
+        self.backServerItem.SetItemLabel("Start Pyo Background Server")
+        self.sendToServerItem.Enable(False)
+
     def startStopBackgroundServer(self, evt):
         if not self.back_server_started:
-            outDriverIndex = -1
-            preferedDriver = PREFERENCES.get("background_server_out_device", "")
-            if preferedDriver != "":
-                driverList, driverIndexes = pa_get_output_devices()
-                driverList = [ensureNFD(driver) for driver in driverList]
-                if preferedDriver and preferedDriver in driverList:
-                    outDriverIndex = driverIndexes[driverList.index(preferedDriver)]
-
-            inDriverIndex = -1
-            preferedDriver = PREFERENCES.get("background_server_in_device", "")
-            if preferedDriver != "":
-                driverList, driverIndexes = pa_get_input_devices()
-                driverList = [ensureNFD(driver) for driver in driverList]
-                if preferedDriver and preferedDriver in driverList:
-                    inDriverIndex = driverIndexes[driverList.index(preferedDriver)]
-
-            midiInDriverIndex = -1
-            preferedDriver = PREFERENCES.get("background_server_midiin_device", "")
-            if preferedDriver != "":
-                driverList, driverIndexes = pm_get_input_devices()
-                driverList = [ensureNFD(driver) for driver in driverList]
-                if preferedDriver and preferedDriver in driverList:
-                    midiInDriverIndex = driverIndexes[driverList.index(preferedDriver)]
-
-            with open(os.path.join(TEMP_PATH, "background_server.py"), "w") as f:
-                f.write("print 'Starting background server...'\nimport time\nfrom pyo import *\n")
-                f.write("s = Server(%s)\n" % BACKGROUND_SERVER_ARGS)
-                if outDriverIndex != -1:
-                    f.write("s.setOutputDevice(%d)\n" % outDriverIndex)
-                if inDriverIndex != -1:
-                    f.write("s.setInputDevice(%d)\n" % inDriverIndex)
-                if midiInDriverIndex != -1:
-                    f.write("s.setMidiInputDevice(%d)\n" % midiInDriverIndex)
-                f.write("s.boot()\ns.start()\n")
-            if PLATFORM == "win32":
-                self.server_pipe = subprocess.Popen([WHICH_PYTHON, '-i', 'background_server.py'], 
-                                        shell=True, cwd=TEMP_PATH, stdin=subprocess.PIPE).stdin
-            else:
-                self.server_pipe = subprocess.Popen(["%s -i %s" % (WHICH_PYTHON, os.path.join(TEMP_PATH, "background_server.py"))], 
-                                        shell=True, stdin=subprocess.PIPE).stdin
+            self.prepareBackgroundServer()
+            cwd = self.getCurrentWorkingDirectory()
+            th = BackgroundServerThread(cwd, self)
+            th.setPID(1000)
+            self.processes[1000] = [th, 'background_server.py']
+            self.panel.outputlog.addProcess(1000, 'background_server.py')
+            th.start()
             self.back_server_started = True
             self.backServerItem.SetItemLabel("Stop Pyo Background Server")
             self.sendToServerItem.Enable(True)
         else:
-            try:
-                self.server_pipe.write("print 'Closing background server...'\ns.stop()\ntime.sleep(0.25)\n")
-                self.server_pipe.close()
-            except IOError:
-                pass
-            self.server_pipe = None
+            self.processes[1000][0].kill()
             self.back_server_started = False
             self.backServerItem.SetItemLabel("Start Pyo Background Server")
             self.sendToServerItem.Enable(False)
 
     def sendSelectionToBackgroundServer(self, evt):
-        text = self.panel.editor.GetSelectedTextUTF8()
+        end = None
+        text = self.panel.editor.GetSelectedText()
         if text == "":
             pos = self.panel.editor.GetCurrentPos()
             line = self.panel.editor.LineFromPosition(pos)
-            text = self.panel.editor.GetLineUTF8(line)
-        if self.server_pipe != None:
-            for line in text.splitlines():
-                self.server_pipe.write(line + "\n")
-            self.server_pipe.write("\n")
+            text = self.panel.editor.GetLine(line)
+        else:
+            end = self.panel.editor.GetSelectionEnd()
+        if self.back_server_started:
+            self.processes[1000][0].sendText(text)
+        if end != None:
+            self.panel.editor.SetCurrentPos(end)
+        self.panel.editor.LineDown()
+        line = self.panel.editor.GetCurrentLine()
+        pos = self.panel.editor.PositionFromLine(line)
+        self.panel.editor.SetCurrentPos(pos)
+        self.panel.editor.SetSelectionEnd(pos)
 
     def buildDoc(self):
         self.doc_frame = ManualFrame(osx_app_bundled=OSX_APP_BUNDLED, which_python=WHICH_PYTHON,
@@ -2899,21 +3379,32 @@ class MainFrame(wx.Frame):
         except:
             pass
         self.buildDoc()
-        
+
+    def showArgs(self, evt):
+        self.panel.editor.onShowTip()
+
+    def showDocString(self, evt):
+        self.panel.editor.onShowDocString()
+
     def onShowEditorKeyCommands(self, evt):
         if not self.keyCommandsFrame.IsShown():
             self.keyCommandsFrame.CenterOnParent()
             self.keyCommandsFrame.Show()
 
     def onHelpAbout(self, evt):
-        info = wx.AboutDialogInfo()
+        info = AboutDialogInfo()
         info.Name = APP_NAME
         info.Version = APP_VERSION
-        info.Copyright = u"(C) 2012 Olivier Belanger"
+        info.Copyright = u"(C) 2016 Olivier Belanger"
         info.Description = "E-Pyo is a text editor especially configured to edit pyo audio programs.\n\n"
-        wx.AboutBox(info)
+        AboutBox(info)
 
     def OnClose(self, event):
+        msg = "You are about to leave E-Pyo. Is this really what you want to do?"
+        dlg = wx.MessageDialog(self, msg, "Warning!", wx.YES_NO|wx.ICON_QUESTION)
+        if dlg.ShowModal() != wx.ID_YES:
+            event.StopPropagation()
+            return
         if self.back_server_started == True:
             try:
                 self.startStopBackgroundServer(None)
@@ -2980,6 +3471,7 @@ class MainPanel(wx.Panel):
         wx.Panel.__init__(self, parent, size=size, style=wx.SUNKEN_BORDER)
 
         self.new_inc = 0
+        self.close_from_menu = False
         self.mainFrame = parent
         mainBox = wx.BoxSizer(wx.HORIZONTAL)
 
@@ -2988,17 +3480,16 @@ class MainPanel(wx.Panel):
 
         self.left_splitter = wx.SplitterWindow(self.splitter, -1, style=wx.SP_LIVE_UPDATE|wx.SP_3DSASH)
         self.right_splitter = wx.SplitterWindow(self.splitter, -1, style=wx.SP_LIVE_UPDATE|wx.SP_3DSASH)
-        #self.right_splitter.SetMinimumPaneSize(150)
 
         self.project = ProjectTree(self.left_splitter, self, (-1, -1))
         self.markers = MarkersPanel(self.left_splitter, self, (-1, -1))
 
-        self.notebook = FNB.FlatNotebook(self.right_splitter, size=(-1,-1), 
-                        style=FNB.FNB_FF2|FNB.FNB_X_ON_TAB|FNB.FNB_NO_X_BUTTON|FNB.FNB_DROPDOWN_TABS_LIST|FNB.FNB_HIDE_ON_SINGLE_TAB)
+        self.notebook = FNB.FlatNotebook(self.right_splitter, size=(-1,-1))
+        self.notebook.SetAGWWindowStyleFlag(FNB.FNB_FANCY_TABS|FNB.FNB_X_ON_TAB|FNB.FNB_NO_X_BUTTON|FNB.FNB_DROPDOWN_TABS_LIST|FNB.FNB_HIDE_ON_SINGLE_TAB)
         self.addNewPage()
         self.outputlog = OutputLogPanel(self.right_splitter, self, size=(-1,150))
 
-        self.right_splitter.SplitHorizontally(self.notebook, self.outputlog, (self.GetSize()[1]*4/5) - self.GetSize()[1])
+        self.right_splitter.SplitHorizontally(self.notebook, self.outputlog, (self.GetSize()[1] * 4 // 5) - self.GetSize()[1])
 
         self.splitter.SplitVertically(self.left_splitter, self.right_splitter, 175)
         self.splitter.Unsplit(self.left_splitter)
@@ -3006,8 +3497,8 @@ class MainPanel(wx.Panel):
         mainBox.Add(self.splitter, 1, wx.EXPAND)
         self.SetSizer(mainBox)
 
-        self.Bind(FNB.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.onPageChange)
-        self.Bind(FNB.EVT_FLATNOTEBOOK_PAGE_CLOSING, self.onClosingPage)
+        self.notebook.Bind(FNB.EVT_FLATNOTEBOOK_PAGE_CHANGED, self.onPageChange)
+        self.notebook.Bind(FNB.EVT_FLATNOTEBOOK_PAGE_CLOSING, self.onClosingPage)
 
     def addNewPage(self):
         title = "Untitled-%i.py" % self.new_inc
@@ -3035,6 +3526,11 @@ class MainPanel(wx.Panel):
                 except:
                     continue
         editor.setText(ensureNFD(text))
+
+        # Scan the entire document (needed for FoldAll to fold everything)
+        editor.GotoLine(editor.GetLineCount())
+        wx.CallAfter(editor.GotoLine, 0)
+
         editor.path = file
         editor.saveMark = True
         editor.EmptyUndoBuffer()
@@ -3053,11 +3549,16 @@ class MainPanel(wx.Panel):
         if founded:
             with open(os.path.join(MARKERS_PATH, marker_file), "r") as f:
                 text = f.read()
-            exec text in locals()
+            spos = text.find("=")
+            dictext = text[spos+1:]
+            markers = eval(dictext)
             self.editor.setMarkers(copy.deepcopy(markers))
 
     def onClosingPage(self, evt):
-        action = self.editor.closeNoCancel()
+        if not self.close_from_menu:
+            action = self.editor.close()
+            if action == "keep":
+                evt.Veto()
 
     def deletePage(self):
         select = self.notebook.GetSelection()
@@ -3097,9 +3598,25 @@ class MainPanel(wx.Panel):
             ed = self.notebook.GetPage(i)
             ed.Close()
 
+#######################################################
+### The idea of EditorPanel is to allow multiple views
+### at the same time in a single notebook page.
+### Also: A tree view of classes and functions of the file
+### Not yet implemented... ( TODO )
+#######################################################
+class EditorPanel(wx.Panel):
+    def __init__(self, parent):
+        wx.Panel.__init__(self, parent, -1)
+        self.editor = Editor(parent, -1, size=(0, -1))
+        self.editor2 = Editor(parent, -1, size=(0, -1))
+        box = wx.BoxSizer(wx.HORIZONTAL)
+        box.Add(self.editor, 1, wx.ALL|wx.EXPAND, 5)
+        box.Add(self.editor2, 1, wx.ALL|wx.EXPAND, 5)
+        self.SetSizerAndFit(box)
+
 class Editor(stc.StyledTextCtrl):
-    def __init__(self, parent, ID, pos=wx.DefaultPosition, size=wx.DefaultSize, style= wx.NO_BORDER | wx.WANTS_CHARS,
-                 setTitle=None, getTitle=None):
+    def __init__(self, parent, ID, pos=wx.DefaultPosition, size=wx.DefaultSize,
+                 style= wx.NO_BORDER | wx.WANTS_CHARS, setTitle=None, getTitle=None):
         stc.StyledTextCtrl.__init__(self, parent, ID, pos, size, style)
 
         dt = MyFileDropTarget(self)
@@ -3122,8 +3639,10 @@ class Editor(stc.StyledTextCtrl):
         self.markers_dict = {}
         self.current_marker = -1
         self.objs_attr_dict = {}
+        self.auto_comp_container = PREFERENCES.get("auto_comp_container", 0)
+
 
-        self.alphaStr = string.lowercase + string.uppercase + '0123456789'
+        self.alphaStr = LOWERCASE + UPPERCASE + '0123456789'
 
         self.Colourise(0, -1)
         self.SetCurrentPos(0)
@@ -3148,9 +3667,8 @@ class Editor(stc.StyledTextCtrl):
         self.SetProperty("fold", "1")
         self.SetProperty("tab.timmy.whinge.level", "1")
         self.SetMargins(5, 5)
-        self.SetUseAntiAliasing(True)
         self.SetEdgeColour(STYLES["lineedge"]['colour'])
-        self.SetEdgeColumn(78)
+        self.SetEdgeColumn(80)
 
         self.SetMarginType(0, stc.STC_MARGIN_SYMBOL)
         self.SetMarginWidth(0, 12)
@@ -3168,22 +3686,17 @@ class Editor(stc.StyledTextCtrl):
         self.SetMarginSensitive(2, True)
 
         self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
+        self.Bind(wx.EVT_CHAR, self.OnChar)
         self.Bind(stc.EVT_STC_UPDATEUI, self.OnUpdateUI)
         self.Bind(stc.EVT_STC_MARGINCLICK, self.OnMarginClick)
         self.Bind(wx.EVT_CLOSE, self.OnClose)
-        self.Bind(wx.EVT_FIND, self.OnFind)
-        self.Bind(wx.EVT_FIND_NEXT, self.OnFind)
-        self.Bind(wx.EVT_FIND_REPLACE, self.OnFind)
-        self.Bind(wx.EVT_FIND_REPLACE_ALL, self.OnFind)
-        self.Bind(wx.EVT_FIND_CLOSE, self.OnFindClose)
+        self.Bind(wx.EVT_LEFT_DCLICK, self.OnDoubleClick)
 
         self.EmptyUndoBuffer()
         self.SetFocus()
         self.setStyle()
 
         # Remove unwanted KeyCommands
-        self.CmdKeyClear(stc.STC_KEY_UP, stc.STC_SCMOD_CTRL)
-        self.CmdKeyClear(stc.STC_KEY_DOWN, stc.STC_SCMOD_CTRL)
         self.CmdKeyClear(stc.STC_KEY_RIGHT, stc.STC_SCMOD_ALT)
         self.CmdKeyClear(stc.STC_KEY_LEFT, stc.STC_SCMOD_ALT)
         self.CmdKeyClear(stc.STC_KEY_RIGHT, stc.STC_SCMOD_SHIFT | stc.STC_SCMOD_ALT)
@@ -3192,20 +3705,10 @@ class Editor(stc.StyledTextCtrl):
         self.CmdKeyClear(stc.STC_KEY_LEFT, stc.STC_SCMOD_CTRL)
         self.CmdKeyClear(stc.STC_KEY_RIGHT, stc.STC_SCMOD_SHIFT | stc.STC_SCMOD_CTRL)
         self.CmdKeyClear(stc.STC_KEY_LEFT, stc.STC_SCMOD_SHIFT | stc.STC_SCMOD_CTRL)
-        self.CmdKeyClear(stc.STC_KEY_HOME, 0)
-        self.CmdKeyClear(stc.STC_KEY_HOME, stc.STC_SCMOD_ALT)
-        self.CmdKeyClear(stc.STC_KEY_HOME, stc.STC_SCMOD_CTRL)
-        self.CmdKeyClear(stc.STC_KEY_HOME, stc.STC_SCMOD_SHIFT)
-        self.CmdKeyClear(stc.STC_KEY_HOME, stc.STC_SCMOD_ALT | stc.STC_SCMOD_SHIFT)
-        self.CmdKeyClear(stc.STC_KEY_HOME, stc.STC_SCMOD_CTRL | stc.STC_SCMOD_SHIFT)
-        self.CmdKeyClear(stc.STC_KEY_END, 0)
-        self.CmdKeyClear(stc.STC_KEY_END, stc.STC_SCMOD_ALT)
-        self.CmdKeyClear(stc.STC_KEY_END, stc.STC_SCMOD_CTRL)
-        self.CmdKeyClear(stc.STC_KEY_END, stc.STC_SCMOD_SHIFT)
-        self.CmdKeyClear(stc.STC_KEY_END, stc.STC_SCMOD_ALT | stc.STC_SCMOD_SHIFT)
-        self.CmdKeyClear(stc.STC_KEY_END, stc.STC_SCMOD_CTRL | stc.STC_SCMOD_SHIFT)
         self.CmdKeyClear(stc.STC_KEY_DELETE, 0)
         self.CmdKeyClear(stc.STC_KEY_DELETE, stc.STC_SCMOD_SHIFT)
+        self.CmdKeyClear(stc.STC_KEY_DELETE, stc.STC_SCMOD_CTRL)
+        self.CmdKeyClear(stc.STC_KEY_DELETE, stc.STC_SCMOD_SHIFT | stc.STC_SCMOD_CTRL)
         self.CmdKeyClear(stc.STC_KEY_BACK, stc.STC_SCMOD_ALT)
         self.CmdKeyClear(stc.STC_KEY_BACK, stc.STC_SCMOD_SHIFT)
         self.CmdKeyClear(stc.STC_KEY_BACK, stc.STC_SCMOD_CTRL)
@@ -3213,22 +3716,19 @@ class Editor(stc.StyledTextCtrl):
         self.CmdKeyClear(stc.STC_KEY_INSERT, 0)
         self.CmdKeyClear(stc.STC_KEY_INSERT, stc.STC_SCMOD_SHIFT)
         self.CmdKeyClear(stc.STC_KEY_INSERT, stc.STC_SCMOD_CTRL)
-        self.CmdKeyClear(ord('Z'), stc.STC_SCMOD_CTRL)
         self.CmdKeyClear(ord('Y'), stc.STC_SCMOD_CTRL)
-        self.CmdKeyClear(ord('X'), stc.STC_SCMOD_CTRL)
-        self.CmdKeyClear(ord('C'), stc.STC_SCMOD_CTRL)
-        self.CmdKeyClear(ord('V'), stc.STC_SCMOD_CTRL)
-        self.CmdKeyClear(ord('A'), stc.STC_SCMOD_CTRL)
+        self.CmdKeyClear(ord('D'), stc.STC_SCMOD_CTRL)
         self.CmdKeyClear(ord('L'), stc.STC_SCMOD_CTRL)
         self.CmdKeyClear(ord('T'), stc.STC_SCMOD_CTRL)
-        self.CmdKeyClear(ord('U'), stc.STC_SCMOD_CTRL)
         self.CmdKeyClear(ord('L'), stc.STC_SCMOD_CTRL | stc.STC_SCMOD_SHIFT)
-        self.CmdKeyClear(ord('U'), stc.STC_SCMOD_CTRL | stc.STC_SCMOD_SHIFT)
         self.CmdKeyClear(stc.STC_KEY_RETURN, stc.STC_SCMOD_SHIFT)
         self.CmdKeyClear(stc.STC_KEY_ADD, stc.STC_SCMOD_CTRL)
         self.CmdKeyClear(stc.STC_KEY_SUBTRACT, stc.STC_SCMOD_CTRL)
         self.CmdKeyClear(stc.STC_KEY_DIVIDE, stc.STC_SCMOD_CTRL)
 
+        self.CmdKeyAssign(ord('U'), stc.STC_SCMOD_CTRL, stc.STC_CMD_UPPERCASE)
+        self.CmdKeyAssign(ord('U'), stc.STC_SCMOD_CTRL | stc.STC_SCMOD_SHIFT, stc.STC_CMD_LOWERCASE)
+
         wx.CallAfter(self.SetAnchor, 0)
         self.Refresh()
 
@@ -3240,7 +3740,7 @@ class Editor(stc.StyledTextCtrl):
                 st = "face:%s,fore:%s,size:%s" % (STYLES['face'], STYLES[forekey]['colour'], STYLES['size'])
             if backkey:
                 st += ",back:%s" % STYLES[backkey]['colour']
-            if STYLES[forekey].has_key('bold'):
+            if 'bold' in STYLES[forekey]:
                 if STYLES[forekey]['bold']:
                     st += ",bold"
                 if STYLES[forekey]['italic']:
@@ -3248,8 +3748,9 @@ class Editor(stc.StyledTextCtrl):
                 if STYLES[forekey]['underline']:
                     st += ",underline"
             return st
+
         self.StyleSetSpec(stc.STC_STYLE_DEFAULT, buildStyle('default', 'background'))
-        self.StyleClearAll()  # Reset all to be like the default
+        self.StyleClearAll() # Reset all to be like the default
 
         self.MarkerDefine(0, stc.STC_MARK_SHORTARROW, STYLES['markerbg']['colour'], STYLES['markerbg']['colour'])
         self.MarkerDefine(stc.STC_MARKNUM_FOLDEROPEN, stc.STC_MARK_BOXMINUS, STYLES['markerfg']['colour'], STYLES['markerbg']['colour'])
@@ -3266,9 +3767,24 @@ class Editor(stc.StyledTextCtrl):
         self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, buildStyle('default', 'bracebad') + ",bold")
 
         ext = os.path.splitext(self.path)[1].strip(".")
+        if ext == "":
+            try:
+                with open(self.path, "r") as f:
+                    fline = f.readline()
+                    if fline.startswith("#!"):
+                        fline = fline.replace("/", " ")
+                        last = fline.split()[-1]
+                        ext = {"python": "py", "bash": "sh", "sh": "sh"}.get(last, "")
+                    else:
+                        text = f.read()
+                        if "desc:" in text:
+                            ext = "jsfx"
+            except:
+                pass
         if ext in ["py", "pyw", "c5"]:
             self.SetLexer(stc.STC_LEX_PYTHON)
-            self.SetKeyWords(0, " ".join(keyword.kwlist) + " None True False ")
+            self.SetStyleBits(self.GetStyleBitsNeeded())
+            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'))
@@ -3286,6 +3802,11 @@ class Editor(stc.StyledTextCtrl):
             self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, buildStyle('commentblock'))
         elif ext in ["c", "cc", "cpp", "cxx", "cs", "h", "hh", "hpp", "hxx"]:
             self.SetLexer(stc.STC_LEX_CPP)
+            self.SetStyleBits(self.GetStyleBitsNeeded())
+            self.SetProperty('fold.comment', '1')
+            self.SetProperty('fold.preprocessor', '1')
+            self.SetProperty('fold.compact', '1')
+            self.SetProperty('styling.within.preprocessor', '0')
             self.SetKeyWords(0, "auto break case char const continue default do double else enum extern float for goto if int long \
             register return short signed sizeof static struct switch typedef union unsigned void volatile while ")
             self.StyleSetSpec(stc.STC_C_DEFAULT, buildStyle('default'))
@@ -3302,6 +3823,7 @@ class Editor(stc.StyledTextCtrl):
             self.StyleSetSpec(stc.STC_C_PREPROCESSOR, buildStyle('commentblock'))
         elif ext == "sh":
             self.SetLexer(stc.STC_LEX_BASH)
+            self.SetStyleBits(self.GetStyleBitsNeeded())
             self.SetKeyWords(0, "! [[ ]] case do done elif else esac fi for function if in select then time until while { } \
             alias bg bind break builtin caller cd command compgen complete compopt continue declare dirs disown echo enable \
             eval exec exit export fc fg getopts hash help history jobs kill let local logout mapfile popd printf pushd pwd \
@@ -3316,12 +3838,155 @@ class Editor(stc.StyledTextCtrl):
             self.StyleSetSpec(stc.STC_SH_IDENTIFIER, buildStyle('default'))
             self.StyleSetSpec(stc.STC_SH_PARAM, buildStyle('default'))
             self.StyleSetSpec(stc.STC_SH_SCALAR, buildStyle('function'))
+        elif ext in ["jsfx", "jsfx-inc"]:
+            self.SetLexer(stc.STC_LEX_CPP)
+            self.SetStyleBits(self.GetStyleBitsNeeded())
+            self.SetProperty('fold.comment', '1')
+            self.SetProperty('fold.preprocessor', '1')
+            self.SetProperty('fold.compact', '1')
+            self.SetProperty('styling.within.preprocessor', '0')
+            self.SetKeyWords(1, "abs acos asin atan atan2 atexit ceil convolve_c cos defer eval exp fclose feof fflush \
+                                 fft fft_ipermute fft_permute fgetc floor fopen fprintf fread freembuf fseek ftell fwrite \
+                                 gfx_aaaaa gfx_arc gfx_blit gfx_blit gfx_blitext gfx_blurto gfx_circle gfx_deltablit \
+                                 gfx_drawchar gfx_drawnumber gfx_drawstr gfx_getchar gfx_getfont gfx_getimgdim gfx_getpixel \
+                                 gfx_gradrect gfx_init gfx_line gfx_lineto gfx_loadimg gfx_measurestr gfx_muladdrect gfx_printf \
+                                 gfx_quit gfx_rect gfx_rectto gfx_roundrect gfx_setfont gfx_setimgdim gfx_setpixel gfx_transformblit \
+                                 gfx_update ifft invsqrt log log10 match matchi max memcpy memset min pow printf rand sign sin sleep \
+                                 sprintf sqr sqrt stack_exch stack_peek stack_pop stack_push str_delsub str_getchar str_insert \
+                                 str_setchar str_setlen strcat strcmp strcpy strcpy_from strcpy_substr stricmp strlen strncat strncmp \
+                                 strncpy strnicmp tan tcp_close tcp_connect tcp_listen tcp_listen_end tcp_recv tcp_send tcp_set_block \
+                                 time time_precise")
+            self.SetKeyWords(0, "loop while function local static instance this global globals _global gfx_r gfx_g gfx_b gfx_a gfx_w \
+                                 gfx_h gfx_x gfx_y gfx_mode gfx_clear gfx_dest gfx_texth mouse_x mouse_y mouse_cap mouse_wheel mouse_hwheel \
+                                 @init @slider @sample @block @serialize @gfx import desc slider1 slider2 slider3 slider4 slider5 \
+                                 slider6 slider7 slider8 slider9 slider10 slider11 slider12 slider13 slider14 slider15 slider16 in_pin \
+                                 out_pin filename ")
+            self.StyleSetSpec(stc.STC_C_DEFAULT, buildStyle('default'))
+            self.StyleSetSpec(stc.STC_C_COMMENT, buildStyle('comment'))
+            self.StyleSetSpec(stc.STC_C_COMMENTDOC, buildStyle('comment'))
+            self.StyleSetSpec(stc.STC_C_COMMENTLINE, buildStyle('comment'))
+            self.StyleSetSpec(stc.STC_C_COMMENTLINEDOC, buildStyle('comment'))
+            self.StyleSetSpec(stc.STC_C_NUMBER, buildStyle('number'))
+            self.StyleSetSpec(stc.STC_C_STRING, buildStyle('string'))
+            self.StyleSetSpec(stc.STC_C_CHARACTER, buildStyle('string'))
+            self.StyleSetSpec(stc.STC_C_WORD, buildStyle('keyword'))
+            self.StyleSetSpec(stc.STC_C_WORD2, buildStyle('pyokeyword'))
+            self.StyleSetSpec(stc.STC_C_OPERATOR, buildStyle('operator'))
+            self.StyleSetSpec(stc.STC_C_IDENTIFIER, buildStyle('default'))
+            self.StyleSetSpec(stc.STC_C_PREPROCESSOR, buildStyle('commentblock'))
+        elif ext == "md":
+            self.SetLexer(stc.STC_LEX_MARKDOWN)
+            self.SetStyleBits(self.GetStyleBitsNeeded())
+            self.StyleSetSpec(stc.STC_MARKDOWN_DEFAULT, buildStyle('default'))
+            self.StyleSetSpec(stc.STC_MARKDOWN_LINE_BEGIN, buildStyle('default'))
+            self.StyleSetSpec(stc.STC_MARKDOWN_STRONG1, buildStyle('default') + ",italic,bold")
+            self.StyleSetSpec(stc.STC_MARKDOWN_STRONG2, buildStyle('default') + ",italic,bold")
+            self.StyleSetSpec(stc.STC_MARKDOWN_EM1, buildStyle('default') + ",italic")
+            self.StyleSetSpec(stc.STC_MARKDOWN_EM2, buildStyle('default') + ",italic")
+            self.StyleSetSpec(stc.STC_MARKDOWN_HEADER1, buildStyle('comment') + ", bold")
+            self.StyleSetSpec(stc.STC_MARKDOWN_HEADER2, buildStyle('comment'))
+            self.StyleSetSpec(stc.STC_MARKDOWN_HEADER3, buildStyle('commentblock') + ", bold")
+            self.StyleSetSpec(stc.STC_MARKDOWN_HEADER4, buildStyle('commentblock') + ", bold")
+            self.StyleSetSpec(stc.STC_MARKDOWN_HEADER5, buildStyle('commentblock'))
+            self.StyleSetSpec(stc.STC_MARKDOWN_HEADER6, buildStyle('commentblock'))
+            self.StyleSetSpec(stc.STC_MARKDOWN_PRECHAR, buildStyle('default'))
+            self.StyleSetSpec(stc.STC_MARKDOWN_ULIST_ITEM, buildStyle('string'))
+            self.StyleSetSpec(stc.STC_MARKDOWN_OLIST_ITEM, buildStyle('triple'))
+            self.StyleSetSpec(stc.STC_MARKDOWN_BLOCKQUOTE, buildStyle('string'))
+            self.StyleSetSpec(stc.STC_MARKDOWN_STRIKEOUT, buildStyle('string'))
+            self.StyleSetSpec(stc.STC_MARKDOWN_HRULE, buildStyle('triple'))
+            self.StyleSetSpec(stc.STC_MARKDOWN_LINK, buildStyle('function'))
+            self.StyleSetSpec(stc.STC_MARKDOWN_CODE, buildStyle('default') + ",italic,bold")
+            self.StyleSetSpec(stc.STC_MARKDOWN_CODE2, buildStyle('default') + ",italic,bold")
+            self.StyleSetSpec(stc.STC_MARKDOWN_CODEBK, buildStyle('default') + ",italic,bold")
+        elif ext == "lua":
+            self.SetLexer(stc.STC_LEX_LUA)
+            self.SetStyleBits(self.GetStyleBitsNeeded())
+            self.SetKeyWords(0, "and break do else elseif for if in nil not or \
+                        repeat then until while function local end return true false ")
+            self.StyleSetSpec(stc.STC_LUA_DEFAULT, buildStyle('default'))
+            self.StyleSetSpec(stc.STC_LUA_COMMENT, buildStyle('comment'))
+            self.StyleSetSpec(stc.STC_LUA_COMMENTLINE, buildStyle('comment'))
+            self.StyleSetSpec(stc.STC_LUA_COMMENTDOC, buildStyle('commentblock'))
+            self.StyleSetSpec(stc.STC_LUA_NUMBER, buildStyle('number'))
+            self.StyleSetSpec(stc.STC_LUA_WORD, buildStyle('keyword'))
+            self.StyleSetSpec(stc.STC_LUA_STRING, buildStyle('string'))
+            self.StyleSetSpec(stc.STC_LUA_CHARACTER, buildStyle('string'))
+            self.StyleSetSpec(stc.STC_LUA_LITERALSTRING, buildStyle('triple'))
+            self.StyleSetSpec(stc.STC_LUA_PREPROCESSOR, buildStyle('default') + ",italic")
+            self.StyleSetSpec(stc.STC_LUA_OPERATOR, buildStyle('operator'))
+            self.StyleSetSpec(stc.STC_LUA_IDENTIFIER, buildStyle('default'))
+            self.StyleSetSpec(stc.STC_LUA_STRINGEOL, buildStyle('default') + ",bold")
+            self.StyleSetSpec(stc.STC_LUA_WORD2, buildStyle('pyokeyword'))
+            self.StyleSetSpec(stc.STC_LUA_WORD3, buildStyle('pyokeyword'))
+            self.StyleSetSpec(stc.STC_LUA_WORD4, buildStyle('pyokeyword'))
+            self.StyleSetSpec(stc.STC_LUA_WORD5, buildStyle('pyokeyword'))
+            self.StyleSetSpec(stc.STC_LUA_WORD6, buildStyle('pyokeyword'))
+            self.StyleSetSpec(stc.STC_LUA_WORD7, buildStyle('pyokeyword'))
+            self.StyleSetSpec(stc.STC_LUA_WORD8, buildStyle('pyokeyword'))
+            self.StyleSetSpec(stc.STC_LUA_LABEL, buildStyle('default') + ",italic,bold")
 
         self.SetEdgeColour(STYLES["lineedge"]['colour'])
         self.SetCaretForeground(STYLES['caret']['colour'])
         self.SetSelBackground(1, STYLES['selback']['colour'])
         self.SetFoldMarginColour(True, STYLES['foldmarginback']['colour'])
         self.SetFoldMarginHiColour(True, STYLES['foldmarginback']['colour'])
+        self.CallTipSetForeground(STYLES['default']['colour'])
+        self.CallTipSetBackground(STYLES['background']['colour'])
+
+        # WxPython 3 needs the lexer to be set before folding property
+        self.SetProperty("fold", "1")
+
+    def insertBlockHead(self):
+        pos = self.PositionFromLine(self.GetCurrentLine())
+        if self.GetLine(self.GetCurrentLine()).strip() == "":
+            self.InsertText(pos, "#-->")
+        else:
+            self.InsertText(pos, "#-->\n")
+
+    def insertBlockTail(self):
+        pos = self.GetLineEndPosition(self.GetCurrentLine())
+        if self.GetLine(self.GetCurrentLine()).strip() == "":
+            self.InsertText(pos, "#<--")
+        else:
+            self.InsertText(pos, "\n#<--")
+
+    def selectCodeBlock(self):
+        self.OnDoubleClick(None)
+
+    def OnDoubleClick(self, evt):
+        """
+        Double-click used to select chunk of code between #--> and #<--
+        """
+        if "#-->" in self.GetLine(self.GetCurrentLine()):
+            first = self.GetCurrentLine()
+            last = self.GetLineCount()
+            self.LineDown()
+            while (self.GetCurrentLine() < self.GetLineCount()):
+                if "#<--" in self.GetLine(self.GetCurrentLine()):
+                    last = self.GetCurrentLine() - 1
+                    break
+                self.LineDown()
+            self.SetSelection(self.GetLineEndPosition(first)+1,
+                              self.GetLineEndPosition(last)+1)
+            if evt is not None:
+                evt.StopPropagation()
+        elif "#<--" in self.GetLine(self.GetCurrentLine()):
+            first = 0
+            last = self.GetCurrentLine() - 1
+            self.LineUp()
+            while (self.GetCurrentLine() > 0):
+                if "#-->" in self.GetLine(self.GetCurrentLine()):
+                    first = self.GetCurrentLine()
+                    break
+                self.LineUp()
+            self.SetSelection(self.GetLineEndPosition(first)+1,
+                              self.GetLineEndPosition(last)+1)
+            if evt is not None:
+                evt.StopPropagation()
+        else:
+            if evt is not None:
+                evt.Skip()
 
     def OnQuickSearch(self, str, next=True):
         if self.GetSelection() != (0,0):
@@ -3344,14 +4009,18 @@ class Editor(stc.StyledTextCtrl):
                 self.SearchAnchor()
                 res = self.SearchPrev(stc.STC_FIND_MATCHCASE, str)
         line = self.GetCurrentLine()
-        halfNumLinesOnScreen = self.LinesOnScreen() / 2
+        halfNumLinesOnScreen = self.LinesOnScreen() // 2
         self.ScrollToLine(line - halfNumLinesOnScreen)
 
     def OnShowFindReplace(self):
-        data = wx.FindReplaceData()
-        self.findReplace = wx.FindReplaceDialog(self, data, "Find & Replace", wx.FR_REPLACEDIALOG | wx.FR_NOUPDOWN)
-        self.findReplace.data = data  # save a reference to it...
-        self.findReplace.Show(True)
+        self.data = wx.FindReplaceData()
+        dlg = wx.FindReplaceDialog(self, self.data, "Find & Replace", wx.FR_REPLACEDIALOG | wx.FR_NOUPDOWN)
+        dlg.Bind(wx.EVT_FIND, self.OnFind)
+        dlg.Bind(wx.EVT_FIND_NEXT, self.OnFind)
+        dlg.Bind(wx.EVT_FIND_REPLACE, self.OnFind)
+        dlg.Bind(wx.EVT_FIND_REPLACE_ALL, self.OnFind)
+        dlg.Bind(wx.EVT_FIND_CLOSE, self.OnFindClose)
+        dlg.Show(True)
 
     def OnFind(self, evt):
         map = { wx.wxEVT_COMMAND_FIND : "FIND",
@@ -3359,41 +4028,50 @@ class Editor(stc.StyledTextCtrl):
                 wx.wxEVT_COMMAND_FIND_REPLACE : "REPLACE",
                 wx.wxEVT_COMMAND_FIND_REPLACE_ALL : "REPLACE_ALL" }
 
-        et = evt.GetEventType()
+        evtType = evt.GetEventType()
         findTxt = evt.GetFindString()
+        newTxt = evt.GetReplaceString()
+        findStrLen = len(findTxt)
+        newStrLen = len(newTxt)
+        diffLen = newStrLen - findStrLen
 
         selection = self.GetSelection()
         if selection[0] == selection[1]:
             selection = (0, self.GetLength())
 
-        if map[et] == 'FIND':
+        if map[evtType] == 'FIND':
             startpos = self.FindText(selection[0], selection[1], findTxt, evt.GetFlags())
             endpos = startpos+len(findTxt)
             self.anchor1 = endpos
             self.anchor2 = selection[1]
             self.SetSelection(startpos, endpos)
-        elif map[et] == 'FIND_NEXT':
+        elif map[evtType] == 'FIND_NEXT':
             startpos = self.FindText(self.anchor1, self.anchor2, findTxt, evt.GetFlags())
             endpos = startpos+len(findTxt)
             self.anchor1 = endpos
             self.SetSelection(startpos, endpos)
-        elif map[et] == 'REPLACE':
-            startpos = self.FindText(selection[0], selection[1], findTxt)
-            endpos = startpos+len(findTxt)
+        elif map[evtType] == 'REPLACE':
+            startpos = self.FindText(selection[0], selection[1], findTxt, evt.GetFlags())
             if startpos != -1:
+                endpos = startpos+len(findTxt)
                 self.SetSelection(startpos, endpos)
-                self.ReplaceSelection(evt.GetReplaceString())
-        elif map[et] == 'REPLACE_ALL':
-            self.anchor1 = selection[0]
+                self.ReplaceSelection(newTxt)
+                self.anchor1 = startpos + newStrLen + 1
+                self.anchor2 += diffLen
+        elif map[evtType] == 'REPLACE_ALL':
+            self.anchor1 = startpos = selection[0]
             self.anchor2 = selection[1]
-            startpos = selection[0]
             while startpos != -1:
-                startpos = self.FindText(self.anchor1, self.anchor2, findTxt)
-                endpos = startpos+len(findTxt)
-                self.anchor1 = endpos
+                startpos = self.FindText(self.anchor1, self.anchor2, findTxt, evt.GetFlags())
                 if startpos != -1:
+                    endpos = startpos+len(findTxt)
                     self.SetSelection(startpos, endpos)
-                    self.ReplaceSelection(evt.GetReplaceString())
+                    self.ReplaceSelection(newTxt)
+                    self.anchor1 = startpos + newStrLen + 1
+                    self.anchor2 += diffLen
+        line = self.GetCurrentLine()
+        halfNumLinesOnScreen = self.LinesOnScreen() // 2
+        self.ScrollToLine(line - halfNumLinesOnScreen)
 
     def OnFindClose(self, evt):
         evt.GetDialog().Destroy()
@@ -3407,22 +4085,20 @@ class Editor(stc.StyledTextCtrl):
             self.SetEdgeMode(stc.STC_EDGE_LINE)
         else:
             self.SetEdgeMode(stc.STC_EDGE_NONE)
-        
+
     def removeTrailingWhiteSpace(self):
-        text = self.GetTextUTF8()
+        text = self.GetText()
         lines = [line.rstrip() for line in text.splitlines(False)]
         text= "\n".join(lines)
         self.setText(text, False)
 
     def tabsToSpaces(self):
-        text = self.GetTextUTF8()
+        text = self.GetText()
         text = text.replace("\t", "    ")
         self.setText(text, False)
 
     ### Save and Close file ###
     def saveMyFile(self, file):
-        #with codecs.open(file, "w", encoding="utf-8") as f:
-         #   f.write(self.GetTextUTF8())
         self.SaveFile(file)
         self.path = file
         self.saveMark = False
@@ -3452,42 +4128,18 @@ class Editor(stc.StyledTextCtrl):
             for line in lines:
                 f.write("%s=%s\n" % (line[0], line[1]))
 
-    def closeNoCancel(self):
-        if self.GetModify():
-            if not self.path: f = "Untitled"
-            else: f = self.path
-            dlg = wx.MessageDialog(None, 'file ' + f + ' has been modified. Do you want to save?', 
-                                   'Warning!', wx.YES | wx.NO)
-            but = dlg.ShowModal()
-            if but == wx.ID_YES:
-                dlg.Destroy()
-                if not self.path or "Untitled-" in self.path:
-                    dlg2 = wx.FileDialog(None, message="Save file as ... (the file will be closed even if you pressed Cancel!)", defaultDir=os.getcwd(), 
-                                         defaultFile="", style=wx.SAVE|wx.FD_OVERWRITE_PROMPT)
-                    dlg2.SetFilterIndex(0)
-                    if dlg2.ShowModal() == wx.ID_OK:
-                        path = dlg2.GetPath()
-                        self.SaveFile(path)
-                        dlg2.Destroy()
-                    else:
-                        dlg2.Destroy()
-                else:
-                    self.SaveFile(self.path)
-            elif but == wx.ID_NO:
-                dlg.Destroy()
-
     def close(self):
         if self.GetModify():
             if not self.path: f = "Untitled"
             else: f = self.path
-            dlg = wx.MessageDialog(None, 'file ' + f + ' has been modified. Do you want to save?', 
+            dlg = wx.MessageDialog(None, 'file ' + f + ' has been modified. Do you want to save?',
                                    'Warning!', wx.YES | wx.NO | wx.CANCEL)
             but = dlg.ShowModal()
             if but == wx.ID_YES:
                 dlg.Destroy()
                 if not self.path or "Untitled-" in self.path:
-                    dlg2 = wx.FileDialog(None, message="Save file as ...", defaultDir=os.getcwd(), 
-                                         defaultFile="", style=wx.SAVE|wx.FD_OVERWRITE_PROMPT)
+                    dlg2 = wx.FileDialog(None, message="Save file as ...", defaultDir=os.getcwd(),
+                                         defaultFile="", style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
                     dlg2.SetFilterIndex(0)
                     if dlg2.ShowModal() == wx.ID_OK:
                         path = dlg2.GetPath()
@@ -3512,13 +4164,13 @@ class Editor(stc.StyledTextCtrl):
         if self.GetModify():
             if not self.path: f = "Untitled"
             else: f = os.path.split(self.path)[1]
-            dlg = wx.MessageDialog(None, 'file ' + f + ' has been modified. Do you want to save?', 
+            dlg = wx.MessageDialog(None, 'file ' + f + ' has been modified. Do you want to save?',
                                    'Warning!', wx.YES | wx.NO)
             if dlg.ShowModal() == wx.ID_YES:
                 dlg.Destroy()
                 if not self.path or "Untitled-" in self.path:
                     dlg2 = wx.FileDialog(None, message="Save file as ...", defaultDir=os.getcwd(),
-                                         defaultFile="", style=wx.SAVE|wx.FD_OVERWRITE_PROMPT)
+                                         defaultFile="", style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT)
                     dlg2.SetFilterIndex(0)
 
                     if dlg2.ShowModal() == wx.ID_OK:
@@ -3542,30 +4194,21 @@ class Editor(stc.StyledTextCtrl):
 
     ### Text Methods ###
     def addText(self, text, update=True):
-        try:
-            self.AddTextUTF8(text)
-        except:
-            self.AddText(text)
+        self.AddText(text)
         if update:
             count = self.GetLineCount()
             for i in range(count):
                 self.updateVariableDict(i)
 
     def insertText(self, pos, text, update=True):
-        try:
-            self.InsertTextUTF8(pos, text)
-        except:
-            self.InsertText(pos, text)
+        self.InsertText(pos, text)
         if update:
             count = self.GetLineCount()
             for i in range(count):
                 self.updateVariableDict(i)
 
     def setText(self, text, update=True):
-        try:
-            self.SetTextUTF8(text)
-        except:
-            self.SetText(text)
+        self.SetText(text)
         if update:
             count = self.GetLineCount()
             for i in range(count):
@@ -3592,15 +4235,18 @@ class Editor(stc.StyledTextCtrl):
         caretPos = self.GetCurrentPos()
         startpos = self.WordStartPosition(caretPos, True)
         endpos = self.WordEndPosition(caretPos, True)
-        currentword = self.GetTextRangeUTF8(startpos, endpos)
+        currentword = self.GetTextRange(startpos, endpos)
         return currentword
 
+    def showAutoCompContainer(self, state):
+        self.auto_comp_container = state
+
     def showAutoComp(self):
         propagate = True
         charBefore = " "
         caretPos = self.GetCurrentPos()
         if caretPos > 0:
-            charBefore = self.GetTextRangeUTF8(caretPos - 1, caretPos)
+            charBefore = self.GetTextRange(caretPos - 1, caretPos)
         currentword = self.getWordUnderCaret()
         if charBefore in self.alphaStr:
             list = ''
@@ -3612,15 +4258,27 @@ class Editor(stc.StyledTextCtrl):
                 propagate = False
         return propagate
 
-    def insertDefArgs(self, currentword):
+    def insertDefArgs(self, currentword, charat):
         propagate = True
+        braceend = True
+        currentword = ""
+        if charat == ord("("):
+            pos = self.GetCurrentPos()
+            if chr(self.GetCharAt(pos)) == ')':
+                braceend = False
+            startpos = self.WordStartPosition(pos-2, True)
+            endpos = self.WordEndPosition(pos-2, True)
+            currentword = self.GetTextRange(startpos, endpos)
         for word in PYO_WORDLIST:
             if word == currentword:
                 text = class_args(eval(word)).replace(word, "")
                 self.args_buffer = text.replace("(", "").replace(")", "").split(",")
                 self.args_buffer = [arg.strip() for arg in self.args_buffer]
                 self.args_line_number = [self.GetCurrentLine(), self.GetCurrentLine()+1]
-                self.insertText(self.GetCurrentPos(), text, False)
+                if braceend:
+                    self.insertText(self.GetCurrentPos(), text[1:], False)
+                else:
+                    self.insertText(self.GetCurrentPos(), text[1:-1], False)
                 self.selection = self.GetSelectedText()
                 wx.CallAfter(self.navigateArgs)
                 propagate = False
@@ -3689,7 +4347,7 @@ class Editor(stc.StyledTextCtrl):
             self.SetCurrentPos(pos)
             wx.CallAfter(self.SetAnchor, self.GetCurrentPos())
         else:
-            self.selection = self.GetSelectedTextUTF8()
+            self.selection = self.GetSelectedText()
             pos = self.GetSelectionStart()
             wx.CallAfter(self.navigateSnips, pos)
 
@@ -3713,7 +4371,7 @@ class Editor(stc.StyledTextCtrl):
         while charat == ord("."):
             startpos = self.WordStartPosition(pos-2, True)
             endpos = self.WordEndPosition(pos-2, True)
-            currentword = "%s.%s" % (self.GetTextRangeUTF8(startpos, endpos), currentword)
+            currentword = "%s.%s" % (self.GetTextRange(startpos, endpos), currentword)
             pos = startpos - 1
             charat = self.GetCharAt(pos)
         if currentword != "":
@@ -3737,7 +4395,7 @@ class Editor(stc.StyledTextCtrl):
         return propagate
 
     def updateVariableDict(self, line):
-        text = self.GetLineUTF8(line).replace(" ", "")
+        text = self.GetLine(line).replace(" ", "")
         egpos = text.find("=")
         brpos = text.find("(")
         if egpos != -1 and brpos != -1:
@@ -3750,17 +4408,17 @@ class Editor(stc.StyledTextCtrl):
     def processReturn(self):
         prevline = self.GetCurrentLine() - 1
         self.updateVariableDict(prevline)
-        if self.GetLineUTF8(prevline).strip().endswith(":"):
+        if self.GetLine(prevline).strip().endswith(":"):
             indent = self.GetLineIndentation(prevline)
             self.addText(" "*(indent+4), False)
-        elif self.GetLineIndentation(prevline) != 0 and self.GetLineUTF8(prevline).strip() != "":
+        elif self.GetLineIndentation(prevline) != 0 and self.GetLine(prevline).strip() != "":
             indent = self.GetLineIndentation(prevline)
             self.addText(" "*indent, False)
 
     def processTab(self, currentword, autoCompActive, charat, pos):
         propagate = self.showAutoComp()
         if propagate:
-            propagate = self.insertDefArgs(currentword)
+            propagate = self.insertDefArgs(currentword, charat)
             if propagate:
                 propagate = self.checkForBuiltinComp()
                 if propagate:
@@ -3775,23 +4433,58 @@ class Editor(stc.StyledTextCtrl):
         except:
             pass
 
-    def navigateMarkers(self, down=True):
-        if self.markers_dict != {}:
-            llen = len(self.markers_dict)
-            keys = sorted(self.markers_dict.keys())
-            if down:
-                self.current_marker += 1
-            else:
-                self.current_marker -= 1
-            if self.current_marker < 0:
-                self.current_marker = llen - 1
-            elif self.current_marker >= llen:
-                self.current_marker = 0
-            line = keys[self.current_marker]
-            self.GotoLine(line)
-            halfNumLinesOnScreen = self.LinesOnScreen() / 2
-            self.ScrollToLine(line - halfNumLinesOnScreen)
-            self.GetParent().GetParent().GetParent().GetParent().markers.setSelected(self.current_marker)
+    def onShowDocString(self):
+        if self.GetSelectedText() != "":
+            currentword = self.GetSelectedText()
+        else:
+            currentword = self.getWordUnderCaret()
+            firstCaretPos = self.GetCurrentPos()
+            caretPos = self.GetCurrentPos()
+            startpos = self.WordStartPosition(caretPos, True)
+            while chr(self.GetCharAt(startpos-1)) == ".":
+                self.GotoPos(startpos-2)
+                parent = self.getWordUnderCaret()
+                currentword = parent + "." + currentword
+                caretPos = self.GetCurrentPos()
+                startpos = self.WordStartPosition(caretPos, True)
+            self.GotoPos(firstCaretPos)
+        lineCount = self.GetLineCount()
+        text = ""
+        for i in range(lineCount):
+            line = self.GetLine(i)
+            if "import " in line:
+                text = text + line
+        try:
+            exec(text, locals())
+            docstr = eval(currentword).__doc__
+            dlg = wx.lib.dialogs.ScrolledMessageDialog(self, docstr, "__doc__ string for %s" % currentword, size=(700,500))
+            dlg.CenterOnParent()
+            dlg.ShowModal()
+        except:
+            pass
+
+    def OnChar(self, evt):
+        propagate = True
+
+        if self.auto_comp_container:
+            if chr(evt.GetKeyCode()) in ['[', '{', '(', '"', '`']:
+                if chr(evt.GetKeyCode()) == '[':
+                    self.AddText('[]')
+                elif chr(evt.GetKeyCode()) == '{':
+                    self.AddText('{}')
+                elif chr(evt.GetKeyCode()) == '(':
+                    self.AddText('()')
+                elif chr(evt.GetKeyCode()) == '"':
+                    self.AddText('""')
+                elif chr(evt.GetKeyCode()) == '`':
+                    self.AddText('``')
+                self.CharLeft()
+                propagate = False
+
+        if propagate:
+            evt.Skip()
+        else:
+            evt.StopPropagation()
 
     def OnKeyDown(self, evt):
         if PLATFORM == "darwin":
@@ -3807,6 +4500,10 @@ class Editor(stc.StyledTextCtrl):
         elif evt.GetKeyCode() == wx.WXK_RETURN and evt.ShiftDown():
             self.onShowTip()
             propagate = False
+        # Stop propagation on Tip Show of __doc__ string --- Ctrl+Return
+        elif evt.GetKeyCode() == wx.WXK_RETURN and ControlDown():
+            self.onShowDocString()
+            propagate = False
 
         # Move and/or Select one word left or right --- (Shift+)Alt+Arrows left/right
         elif evt.GetKeyCode() == wx.WXK_LEFT and evt.AltDown() and evt.ShiftDown():
@@ -3832,6 +4529,11 @@ class Editor(stc.StyledTextCtrl):
             self.CmdKeyExecute(stc.STC_CMD_LINEEND)
             propagate = False
 
+        # Delete forward DELETE
+        elif evt.GetKeyCode() == wx.WXK_DELETE:
+            self.CmdKeyExecute(stc.STC_CMD_CHARRIGHT)
+            self.CmdKeyExecute(stc.STC_CMD_DELETEBACK)
+            propagate = False
         # Delete the word to the right of the caret --- Shift+Alt+BACK
         elif evt.GetKeyCode() == wx.WXK_BACK and evt.AltDown() and evt.ShiftDown():
             self.DelWordRight()
@@ -3863,12 +4565,21 @@ class Editor(stc.StyledTextCtrl):
                 self.Paste()
             propagate = False
 
+        # Show documentation for pyo object under the caret
+        elif evt.GetKeyCode() == ord('D') and ControlDown():
+            self.GetParent().GetParent().GetParent().GetParent().GetParent().showDoc(None)
+            propagate = False
+        # Goto line
+        elif evt.GetKeyCode() == ord('L') and ControlDown():
+            self.GetParent().GetParent().GetParent().GetParent().GetParent().gotoLine(None)
+            propagate = False
+
         # Process Return key --- automatic indentation
         elif evt.GetKeyCode() == wx.WXK_RETURN:
             wx.CallAfter(self.processReturn)
         # Process Tab key --- AutoCompletion, Insert object's args, snippet for builtin keywords
         elif evt.GetKeyCode() == wx.WXK_TAB:
-            autoCompActive =  self.AutoCompActive()
+            autoCompActive = self.AutoCompActive()
             currentword = self.getWordUnderCaret()
             currentline = self.GetCurrentLine()
             charat = self.GetCharAt(self.GetCurrentPos()-1)
@@ -3928,7 +4639,7 @@ class Editor(stc.StyledTextCtrl):
         if braceAtCaret >= 0:
             braceOpposite = self.BraceMatch(braceAtCaret)
 
-        if braceAtCaret != -1  and braceOpposite == -1:
+        if braceAtCaret != -1 and braceOpposite == -1:
             self.BraceBadLight(braceAtCaret)
         else:
             self.BraceHighlight(braceAtCaret, braceOpposite)
@@ -3938,11 +4649,7 @@ class Editor(stc.StyledTextCtrl):
             self.args_buffer = []
             self.quit_navigate_args = False
 
-        # if self.endOfLine:
-        #     for i in range(self.GetLineCount()):
-        #         pos = self.GetLineEndPosition(i)
-        #         if self.GetCharAt(pos-1) != 172:
-        #             self.InsertTextUTF8(pos, "¬")
+        self.moveMarkers()
         self.checkScrollbar()
         self.OnModified()
         evt.Skip()
@@ -3964,102 +4671,135 @@ class Editor(stc.StyledTextCtrl):
         for i in range(self.firstLine, self.endLine+1):
             lineLen = len(self.GetLine(i))
             pos = self.PositionFromLine(i)
-            if self.GetTextRangeUTF8(pos,pos+1) != '#' and lineLen > 2:
+            if self.GetTextRange(pos,pos+1) != '#' and lineLen > 2:
                 self.insertText(pos, '#', False)
-            elif self.GetTextRangeUTF8(pos,pos+1) == '#':
+            elif self.GetTextRange(pos,pos+1) == '#':
                 self.GotoPos(pos+1)
                 self.DelWordLeft()
 
+    def navigateMarkers(self, down=True):
+        if self.markers_dict != {}:
+            llen = len(self.markers_dict)
+            swap = [(x[1], x[0]) for x in self.markers_dict.items()]
+            handles = [x[1] for x in sorted(swap)]
+            if down:
+                self.current_marker += 1
+            else:
+                self.current_marker -= 1
+            if self.current_marker < 0:
+                self.current_marker = llen - 1
+            elif self.current_marker >= llen:
+                self.current_marker = 0
+            handle = handles[self.current_marker]
+            line = self.markers_dict[handle][0]
+            self.GotoLine(line)
+            halfNumLinesOnScreen = self.LinesOnScreen() // 2
+            self.ScrollToLine(line - halfNumLinesOnScreen)
+            self.GetParent().GetParent().GetParent().GetParent().markers.setSelected(handle)
+
     def setMarkers(self, dic):
+        try:
+            key = list(dic.keys())[0]
+        except:
+            return
+        if type(dic[key]) != list:
+            return
         self.markers_dict = dic
-        for line in self.markers_dict.keys():
+        for handle in self.markers_dict.keys():
+            line = self.markers_dict[handle][0]
             self.MarkerAdd(line, 0)
         self.GetParent().GetParent().GetParent().GetParent().markers.setDict(self.markers_dict)
 
-    def addMarker(self, line):
-        if line not in self.markers_dict.keys():
-            self.MarkerAdd(line, 0)
-            self.markers_dict[line] = ""
+    def moveMarkers(self):
+        dict = {}
+        for handle in self.markers_dict.keys():
+            line = self.MarkerLineFromHandle(handle)
+            comment = self.markers_dict[handle][1]
+            dict[handle] = [line, comment]
+        if dict != self.markers_dict:
+            self.markers_dict = dict
             self.GetParent().GetParent().GetParent().GetParent().markers.setDict(self.markers_dict)
-            return True
+
+    def addMarker(self, line):
+        if not self.MarkerGet(line):
+            handle = self.MarkerAdd(line, 0)
+            self.markers_dict[handle] = [line, ""]
+        comment = ""
+        dlg = wx.TextEntryDialog(self, 'Enter a comment for that marker:', 'Marker Comment')
+        if dlg.ShowModal() == wx.ID_OK:
+            comment = dlg.GetValue()
+            dlg.Destroy()
         else:
-            return False
+            dlg.Destroy()
+            return
+        self.markers_dict[handle][1] = comment
+        self.GetParent().GetParent().GetParent().GetParent().markers.setDict(self.markers_dict)
 
     def deleteMarker(self, line):
-        if line in self.markers_dict.keys():
-            del self.markers_dict[line]
-            self.MarkerDelete(line, 0)
-            self.GetParent().GetParent().GetParent().GetParent().markers.setDict(self.markers_dict)
+        for handle in self.markers_dict.keys():
+            if line == self.markers_dict[handle][0]:
+                del self.markers_dict[handle]
+                self.MarkerDeleteHandle(handle)
+                self.GetParent().GetParent().GetParent().GetParent().markers.setDict(self.markers_dict)
 
     def deleteAllMarkers(self):
         self.markers_dict = {}
         self.MarkerDeleteAll(0)
         self.GetParent().GetParent().GetParent().GetParent().markers.setDict(self.markers_dict)
 
-    def addMarkerComment(self, line):
-        if line in self.markers_dict.keys():
-            comment = ""
-            dlg = wx.TextEntryDialog(self, 'Enter a comment for that marker:', 'Marker Comment')
-            if dlg.ShowModal() == wx.ID_OK:
-                comment = dlg.GetValue()
-                dlg.Destroy()
-            else:
-                dlg.Destroy()
-                return
-            self.markers_dict[line] = comment
-            self.GetParent().GetParent().GetParent().GetParent().markers.setDict(self.markers_dict)
-
     def OnMarginClick(self, evt):
         if evt.GetMargin() == 0:
-            if PLATFORM == "darwin":
-                modif = evt.GetAlt
-            else:
-                modif = evt.GetControl
             lineClicked = self.LineFromPosition(evt.GetPosition())
-            if modif():
+            if evt.GetShift():
                 self.deleteMarker(lineClicked)
-            elif evt.GetShift():
-                self.addMarkerComment(lineClicked)
             else:
-                ok = self.addMarker(lineClicked)
-                if ok:
-                    self.addMarkerComment(lineClicked)
+                self.addMarker(lineClicked)
         elif evt.GetMargin() == 2:
             if evt.GetShift() and evt.GetControl():
-                self.FoldAll()
+                self.ToggleFoldAll()
             else:
                 lineClicked = self.LineFromPosition(evt.GetPosition())
-
                 if self.GetFoldLevel(lineClicked) & stc.STC_FOLDLEVELHEADERFLAG:
-                    if evt.GetShift():
-                        self.SetFoldExpanded(lineClicked, True)
-                        self.Expand(lineClicked, True, True, 1)
-                    elif evt.GetControl():
-                        if self.GetFoldExpanded(lineClicked):
-                            self.SetFoldExpanded(lineClicked, False)
-                            self.Expand(lineClicked, False, True, 0)
-                        else:
-                            self.SetFoldExpanded(lineClicked, True)
-                            self.Expand(lineClicked, True, True, 100)
-                    else:
-                        self.ToggleFold(lineClicked)
+                    self.ToggleFold(lineClicked)
 
     def FoldAll(self):
         lineCount = self.GetLineCount()
-        expanding = True
+        lineNum = 0
+        while lineNum < lineCount:
+            level = self.GetFoldLevel(lineNum)
+            if level & stc.STC_FOLDLEVELHEADERFLAG and \
+               (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
+                lastChild = self.GetLastChild(lineNum, -1)
+                self.SetFoldExpanded(lineNum, False)
+                if lastChild > lineNum:
+                    self.HideLines(lineNum+1, lastChild)
+            lineNum = lineNum + 1
 
+    def ExpandAll(self):
+        lineCount = self.GetLineCount()
+        lineNum = 0
+        while lineNum < lineCount:
+            level = self.GetFoldLevel(lineNum)
+            if level & stc.STC_FOLDLEVELHEADERFLAG and \
+               (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
+                self.SetFoldExpanded(lineNum, True)
+                lineNum = self.Expand(lineNum, True)
+                lineNum = lineNum - 1
+            lineNum = lineNum + 1
+
+    def ToggleFoldAll(self):
+        lineCount = self.GetLineCount()
+        expanding = True
         # find out if we are folding or unfolding
         for lineNum in range(lineCount):
             if self.GetFoldLevel(lineNum) & stc.STC_FOLDLEVELHEADERFLAG:
                 expanding = not self.GetFoldExpanded(lineNum)
                 break
-
         lineNum = 0
         while lineNum < lineCount:
             level = self.GetFoldLevel(lineNum)
             if level & stc.STC_FOLDLEVELHEADERFLAG and \
                (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
-
                 if expanding:
                     self.SetFoldExpanded(lineNum, True)
                     lineNum = self.Expand(lineNum, True)
@@ -4071,6 +4811,16 @@ class Editor(stc.StyledTextCtrl):
                         self.HideLines(lineNum+1, lastChild)
             lineNum = lineNum + 1
 
+    def foldExpandCurrentScope(self):
+        line = self.GetCurrentLine()
+        while (line >= 0):
+            level = self.GetFoldLevel(line)
+            if level & stc.STC_FOLDLEVELHEADERFLAG and (level & stc.STC_FOLDLEVELNUMBERMASK) == stc.STC_FOLDLEVELBASE:
+                self.ToggleFold(line)
+                self.GotoLine(line)
+                break
+            line -= 1
+
     def Expand(self, line, doExpand, force=False, visLevels=0, level=-1):
         lastChild = self.GetLastChild(line, level)
         line = line + 1
@@ -4110,7 +4860,7 @@ class SimpleEditor(stc.StyledTextCtrl):
 
         self.panel = parent
 
-        self.alphaStr = string.lowercase + string.uppercase + '0123456789'
+        self.alphaStr = LOWERCASE + UPPERCASE + '0123456789'
 
         self.Colourise(0, -1)
         self.SetCurrentPos(0)
@@ -4129,7 +4879,6 @@ class SimpleEditor(stc.StyledTextCtrl):
         self.SetEdgeMode(0)
         self.SetWrapMode(stc.STC_WRAP_WORD)
 
-        self.SetUseAntiAliasing(True)
         self.SetEdgeColour(STYLES["lineedge"]['colour'])
         self.SetEdgeColumn(78)
         self.SetReadOnly(True)
@@ -4143,7 +4892,7 @@ class SimpleEditor(stc.StyledTextCtrl):
                 st = "face:%s,fore:%s,size:%s" % (STYLES['face'], STYLES[forekey]['colour'], STYLES['size'])
             if backkey:
                 st += ",back:%s" % STYLES[backkey]['colour']
-            if STYLES[forekey].has_key('bold'):
+            if 'bold' in STYLES[forekey]:
                 if STYLES[forekey]['bold']:
                     st += ",bold"
                 if STYLES[forekey]['italic']:
@@ -4152,7 +4901,7 @@ class SimpleEditor(stc.StyledTextCtrl):
                     st += ",underline"
             return st
         self.StyleSetSpec(stc.STC_STYLE_DEFAULT, buildStyle('default', 'background'))
-        self.StyleClearAll()  # Reset all to be like the default
+        self.StyleClearAll() # Reset all to be like the default
 
         self.StyleSetSpec(stc.STC_STYLE_DEFAULT, buildStyle('default', 'background'))
         self.StyleSetSpec(stc.STC_STYLE_LINENUMBER, buildStyle('linenumber', 'marginback', True))
@@ -4167,6 +4916,12 @@ class OutputLogEditor(SimpleEditor):
     def __init__(self, parent, ID=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, style= wx.NO_BORDER):
         SimpleEditor.__init__(self, parent=parent, ID=ID, pos=pos, size=size, style=style)
 
+    def appendToLog(self, text):
+        self.SetReadOnly(False)
+        self.AppendText(text)
+        self.GotoLine(self.GetLineCount())
+        self.SetReadOnly(True)
+
     def setLog(self, text):
         self.SetReadOnly(False)
         self.SetText(text)
@@ -4184,37 +4939,37 @@ class OutputLogPanel(wx.Panel):
         self.sizer = wx.BoxSizer(wx.VERTICAL)
 
         toolbarbox = wx.BoxSizer(wx.HORIZONTAL)
-        self.toolbar = wx.ToolBar(self, -1, size=(-1,36))
+        self.toolbar = wx.ToolBar(self, -1)
         self.toolbar.SetMargins((5, 0))
         font, psize = self.toolbar.GetFont(), self.toolbar.GetFont().GetPointSize()
         if PLATFORM == "darwin":
             font.SetPointSize(psize-1)
         self.toolbar.SetToolBitmapSize(tsize)
-        
+
         if PLATFORM == "win32":
             self.toolbar.AddSeparator()
-        title = wx.StaticText(self.toolbar, -1, "Output panel")
+        title = wx.StaticText(self.toolbar, -1, " Output panel")
         title.SetFont(font)
         self.toolbar.AddControl(title)
         self.toolbar.AddSeparator()
         if PLATFORM == "win32":
             self.toolbar.AddSeparator()
-        self.processPopup = wx.Choice(self.toolbar, -1, choices=[])
+        self.processPopup = wx.Choice(self.toolbar, -1, choices=[], size=(150, -1))
         self.processPopup.SetFont(font)
         self.toolbar.AddControl(self.processPopup)
         if PLATFORM == "win32":
             self.toolbar.AddSeparator()
-        self.processKill = wx.Button(self.toolbar, -1, label="Kill", size=(40,-1))
-        self.processKill.SetFont(font)        
+        self.processKill = wx.Button(self.toolbar, -1, label="Kill", size=(40, self.processPopup.GetSize()[1]))
+        self.processKill.SetFont(font)
         self.toolbar.AddControl(self.processKill)
         self.processKill.Bind(wx.EVT_BUTTON, self.killProcess)
         if PLATFORM == "win32":
             self.toolbar.AddSeparator()
-        self.runningLabel = wx.StaticText(self.toolbar, -1, "Running: 0")
+        self.runningLabel = wx.StaticText(self.toolbar, -1, " Running: 0")
         self.runningLabel.SetFont(font)
         self.toolbar.AddControl(self.runningLabel)
         self.toolbar.AddSeparator()
-        self.copyLog = wx.Button(self.toolbar, -1, label="Copy log", size=(70,-1))
+        self.copyLog = wx.Button(self.toolbar, -1, label="Copy log", size=(70,self.processPopup.GetSize()[1]))
         self.copyLog.SetFont(font)
         self.toolbar.AddControl(self.copyLog)
         self.copyLog.Bind(wx.EVT_BUTTON, self.onCopy)
@@ -4231,13 +4986,18 @@ class OutputLogPanel(wx.Panel):
         self.toolbar.Realize()
         toolbarbox.Add(self.toolbar, 1, wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL | wx.EXPAND, 0)
 
-        tb2 = wx.ToolBar(self, -1, size=(-1,36))
-        tb2.SetToolBitmapSize(tsize)
-        tb2.AddLabelTool(17, "Close Panel", close_panel_bmp, shortHelp="Close Panel")
+        tb2 = wx.ToolBar(self, -1, size=(-1,32))
+        if PLATFORM == "darwin":
+            tb2.SetToolBitmapSize(tsize)
+        tb2.AddSeparator()
+        if "phoenix" not in wx.version():
+            tb2.AddLabelTool(17, "Close Panel", close_panel_bmp, shortHelp="Close Panel")
+        else:
+            tb2.AddTool(17, "Close Panel", close_panel_bmp, shortHelp="Close Panel")
         tb2.Realize()
         toolbarbox.Add(tb2, 0, wx.ALIGN_RIGHT, 0)
 
-        wx.EVT_TOOL(self, 17, self.onCloseOutputPanel)
+        self.Bind(wx.EVT_TOOL, self.onCloseOutputPanel, id=17)
 
         self.sizer.Add(toolbarbox, 0, wx.EXPAND)
 
@@ -4258,14 +5018,15 @@ class OutputLogPanel(wx.Panel):
         self.processPopup.Append("%d :: %s" % (procID, filename))
         self.processPopup.SetStringSelection("%d :: %s" % (procID, filename))
         self.running += 1
-        self.runningLabel.SetLabel("Running: %d" % self.running)
+        self.runningLabel.SetLabel(" Running: %d" % self.running)
+        self.editor.setLog("")
 
     def removeProcess(self, procID, filename):
         str = "%d :: %s" % (procID, filename)
         del self.mainPanel.mainFrame.processes[procID]
         self.processPopup.Delete(self.processPopup.GetItems().index(str))
         self.running -= 1
-        self.runningLabel.SetLabel("Running: %d" % self.running)
+        self.runningLabel.SetLabel(" Running: %d" % self.running)
 
     def killProcess(self, evt):
         str = self.processPopup.GetStringSelection()
@@ -4273,6 +5034,11 @@ class OutputLogPanel(wx.Panel):
             procID = int(str.split("::")[0].strip())
             thread = self.mainPanel.mainFrame.processes[procID][0]
             thread.kill()
+            if procID == 1000:
+                self.mainPanel.mainFrame.resetBackgroundServerMenu()
+
+    def appendToLog(self, text):
+        self.editor.appendToLog(text)
 
     def setLog(self, text):
         self.editor.setLog(text)
@@ -4312,10 +5078,7 @@ class PastingListEditorFrame(wx.Frame):
                 self.editors.append(editor)
                 if not line.endswith("\n"):
                     line = line + "\n"
-                try:
-                    editor.AddTextUTF8(line)
-                except:
-                    editor.AddText(line)
+                editor.AddText(line)
 
         Y = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y)
         if heightSum > Y - 100:
@@ -4329,77 +5092,104 @@ class PastingListEditorFrame(wx.Frame):
     def close(self, evt):
         pastingList = []
         for editor in self.editors:
-            text = editor.GetTextUTF8()
+            text = editor.GetText()
             if text.replace("\n", "").strip() != "":
                 pastingList.append(text)
         self.parent.pastingList = pastingList
         self.Destroy()
- 
+
 TOOL_ADD_FILE_ID = 10
 TOOL_ADD_FOLDER_ID = 11
+TOOL_REFRESH_TREE_ID = 12
 class ProjectTree(wx.Panel):
     """Project panel"""
     def __init__(self, parent, mainPanel, size):
-        wx.Panel.__init__(self, parent, -1, size=size, style=wx.WANTS_CHARS | wx.SUNKEN_BORDER | wx.EXPAND)
+        wx.Panel.__init__(self, parent, -1, size=size,
+                          style=wx.WANTS_CHARS|wx.SUNKEN_BORDER|wx.EXPAND)
         self.SetMinSize((150, -1))
         self.mainPanel = mainPanel
 
         self.projectDict = {}
-        self.selected = None
+        self.selectedItem = None
         self.edititem = self.editfolder = self.itempath = self.scope = None
 
         tsize = (24, 24)
         file_add_bmp = catalog['file_add_icon.png'].GetBitmap()
         folder_add_bmp = catalog['folder_add_icon.png'].GetBitmap()
         close_panel_bmp = catalog['close_panel_icon.png'].GetBitmap()
+        refresh_tree_bmp = catalog['refresh_tree_icon.png'].GetBitmap()
 
         self.sizer = wx.BoxSizer(wx.VERTICAL)
 
         toolbarbox = wx.BoxSizer(wx.HORIZONTAL)
         self.toolbar = wx.ToolBar(self, -1, size=(-1,36))
         self.toolbar.SetToolBitmapSize(tsize)
-        self.toolbar.AddLabelTool(TOOL_ADD_FILE_ID, "Add File", file_add_bmp, shortHelp="Add File")
+
+        if "phoenix" not in wx.version():
+            self.toolbar.AddLabelTool(TOOL_ADD_FILE_ID, "Add File",
+                                      file_add_bmp, shortHelp="Add File")
+            self.toolbar.AddLabelTool(TOOL_ADD_FOLDER_ID, "Add Folder",
+                                      folder_add_bmp, shortHelp="Add Folder")
+            self.toolbar.AddLabelTool(TOOL_REFRESH_TREE_ID, "Refresh Tree",
+                                      refresh_tree_bmp, shortHelp="Refresh Tree")
+        else:
+            self.toolbar.AddTool(TOOL_ADD_FILE_ID, "Add File",
+                                      file_add_bmp, shortHelp="Add File")
+            self.toolbar.AddTool(TOOL_ADD_FOLDER_ID, "Add Folder",
+                                      folder_add_bmp, shortHelp="Add Folder")
+            self.toolbar.AddTool(TOOL_REFRESH_TREE_ID, "Refresh Tree",
+                                      refresh_tree_bmp, shortHelp="Refresh Tree")
+
         self.toolbar.EnableTool(TOOL_ADD_FILE_ID, False)
-        self.toolbar.AddLabelTool(TOOL_ADD_FOLDER_ID, "Add Folder", folder_add_bmp, shortHelp="Add Folder")
         self.toolbar.Realize()
         toolbarbox.Add(self.toolbar, 1, wx.ALIGN_LEFT | wx.EXPAND, 0)
 
         tb2 = wx.ToolBar(self, -1, size=(-1,36))
         tb2.SetToolBitmapSize(tsize)
-        tb2.AddLabelTool(15, "Close Panel", close_panel_bmp, shortHelp="Close Panel")
+
+        if "phoenix" not in wx.version():
+            tb2.AddLabelTool(15, "Close Panel", close_panel_bmp, shortHelp="Close Panel")
+        else:
+            tb2.AddTool(15, "Close Panel", close_panel_bmp, shortHelp="Close Panel")
+
         tb2.Realize()
         toolbarbox.Add(tb2, 0, wx.ALIGN_RIGHT, 0)
 
-        wx.EVT_TOOL(self, TOOL_ADD_FILE_ID, self.onAdd)
-        wx.EVT_TOOL(self, TOOL_ADD_FOLDER_ID, self.onAdd)
-        wx.EVT_TOOL(self, 15, self.onCloseProjectPanel)
+        self.Bind(wx.EVT_TOOL, self.onAdd, id=TOOL_ADD_FILE_ID)
+        self.Bind(wx.EVT_TOOL, self.onAdd, id=TOOL_ADD_FOLDER_ID)
+        self.Bind(wx.EVT_TOOL, self.onRefresh, id=TOOL_REFRESH_TREE_ID)
+        self.Bind(wx.EVT_TOOL, self.onCloseProjectPanel, id=15)
 
         self.sizer.Add(toolbarbox, 0, wx.EXPAND)
 
-        self.tree = wx.TreeCtrl(self, -1, (0, 26), size, wx.TR_DEFAULT_STYLE|wx.TR_HIDE_ROOT|wx.SUNKEN_BORDER|wx.EXPAND)
+        stls = wx.TR_DEFAULT_STYLE|wx.TR_HIDE_ROOT|wx.SUNKEN_BORDER|wx.EXPAND
+        self.tree = wx.TreeCtrl(self, -1, (0, 26), size, stls)
         self.tree.SetBackgroundColour(STYLES['background']['colour'])
 
         if PLATFORM == 'darwin':
-            self.tree.SetFont(wx.Font(11, wx.ROMAN, wx.NORMAL, wx.NORMAL, face=STYLES['face']))
-        elif PLATFORM == 'win32':
-            self.tree.SetFont(wx.Font(8, wx.ROMAN, wx.NORMAL, wx.NORMAL, face=STYLES['face']))
+            pt = 11
         else:
-            self.tree.SetFont(wx.Font(8, wx.ROMAN, wx.NORMAL, wx.NORMAL, face=STYLES['face']))
+            pt = 8
+        fnt = wx.Font(pt, wx.ROMAN, wx.NORMAL, wx.NORMAL, False, STYLES['face'])
+        self.tree.SetFont(fnt)
 
         self.sizer.Add(self.tree, 1, wx.EXPAND)
         self.SetSizer(self.sizer)
 
         isz = (12,12)
         self.il = wx.ImageList(isz[0], isz[1])
-        self.fldridx     = self.il.Add(wx.ArtProvider_GetBitmap(wx.ART_FOLDER,      wx.ART_OTHER, isz))
-        self.fldropenidx = self.il.Add(wx.ArtProvider_GetBitmap(wx.ART_FILE_OPEN,   wx.ART_OTHER, isz))
-        self.fileidx     = self.il.Add(wx.ArtProvider_GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, isz))
+        bmp = wx.ArtProvider.GetBitmap(wx.ART_FOLDER, wx.ART_OTHER, isz)
+        self.fldridx = self.il.Add(bmp)
+        bmp = wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_OTHER, isz)
+        self.fldropenidx = self.il.Add(bmp)
+        bmp = wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, isz)
+        self.fileidx = self.il.Add(bmp)
 
         self.tree.SetImageList(self.il)
-        self.tree.SetSpacing(12)
         self.tree.SetIndent(6)
 
-        self.root = self.tree.AddRoot("EPyo_Project_tree", self.fldridx, self.fldropenidx, None)
+        self.root = self.tree.AddRoot("EPyo_Project_tree", self.fldridx,
+                                      self.fldropenidx, None)
         self.tree.SetItemTextColour(self.root, STYLES['default']['colour'])
 
         self.tree.Bind(wx.EVT_TREE_END_LABEL_EDIT, self.OnEndEdit)
@@ -4407,65 +5197,82 @@ class ProjectTree(wx.Panel):
         self.tree.Bind(wx.EVT_LEFT_DOWN, self.OnLeftClick)
         self.tree.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick)
 
+    def _tree_analyze(self, item, expanded_list):
+        if self.tree.ItemHasChildren(item):
+            it, cookie = self.tree.GetFirstChild(item)
+            while it.IsOk():
+                if self.tree.ItemHasChildren(it) and self.tree.IsExpanded(it):
+                    parent = self.tree.GetItemText(self.tree.GetItemParent(it))
+                    expanded_list.append((parent, self.tree.GetItemText(it)))
+                    self._tree_analyze(it, expanded_list)
+                it, cookie = self.tree.GetNextChild(item, cookie)
+
+    def _tree_restore(self, item, expanded_list):
+        if self.tree.ItemHasChildren(item):
+            it, cookie = self.tree.GetFirstChild(item)
+            while it.IsOk():
+                if self.tree.ItemHasChildren(it):
+                    parent = self.tree.GetItemText(self.tree.GetItemParent(it))
+                    if (parent, self.tree.GetItemText(it)) in expanded_list:
+                        self.tree.Expand(it)
+                    self._tree_restore(it, expanded_list)
+                it, cookie = self.tree.GetNextChild(item, cookie)
+
+    def onRefresh(self, evt):
+        expanded = []
+        self._tree_analyze(self.root, expanded)
+        self.tree.DeleteAllItems()
+        self.root = self.tree.AddRoot("EPyo_Project_tree", self.fldridx,
+                                      self.fldropenidx, None)
+        for folder, path in self.projectDict.items():
+            self.loadFolder(path)
+        self._tree_restore(self.root, expanded)
+
     def loadFolder(self, dirPath):
         folderName = os.path.split(dirPath)[1]
         self.projectDict[folderName] = dirPath
-        projectDir = {}
         self.mainPanel.mainFrame.showProjectTree(True)
-        for root, dirs, files in os.walk(dirPath):
-            if os.path.split(root)[1][0] != '.' and os.path.split(root)[1] != "build":
-                if root == dirPath:
-                    child = self.tree.AppendItem(self.root, folderName, self.fldridx, self.fldropenidx, None)
-                    self.tree.SetItemTextColour(child, STYLES['default']['colour'])
-                    if dirs:
-                        ddirs = [dir for dir in dirs if dir[0] != '.' and dir != "build"]
-                        for dir in sorted(ddirs):
-                            subfol = self.tree.AppendItem(child, "%s" % dir, self.fldridx, self.fldropenidx, None)
-                            projectDir[dir] = subfol
-                            self.tree.SetItemTextColour(subfol, STYLES['default']['colour'])
-                    if files:
-                        ffiles = [file for file in files if file[0] != '.' and not file.endswith("~") and os.path.splitext(file)[1].strip(".") in ALLOWED_EXT]
-                        for file in sorted(ffiles):
-                            item = self.tree.AppendItem(child, "%s" % file, self.fileidx, self.fileidx, None)
-                            self.tree.SetItemTextColour(item, STYLES['default']['colour'])
-                else:
-                    if os.path.split(root)[1] in projectDir.keys():
-                        parent = projectDir[os.path.split(root)[1]]
-                        if dirs:
-                            ddirs = [dir for dir in dirs if dir[0] != '.' and "build/" not in root]
-                            for dir in sorted(ddirs):
-                                subfol = self.tree.AppendItem(parent, "%s" % dir, self.fldridx, self.fldropenidx, None)
-                                projectDir[dir] = subfol
-                                self.tree.SetItemTextColour(subfol, STYLES['default']['colour'])
-                        if files:
-                            ffiles = [file for file in files if file[0] != '.' and not file.endswith("~") and os.path.splitext(file)[1].strip(".") in ALLOWED_EXT]
-                            for file in sorted(ffiles):
-                                item = self.tree.AppendItem(parent, "%s" % file, self.fileidx, self.fileidx, None)
-                                self.tree.SetItemTextColour(item, STYLES['default']['colour'])
-        self.tree.SortChildren(self.root)
-        self.tree.SortChildren(child)
+        item = self.tree.AppendItem(self.root, folderName, self.fldridx,
+                                    self.fldropenidx, None)
+        self.tree.SetItemData(item, packItemData(dirPath))
+        self.tree.SetItemTextColour(item, STYLES['default']['colour'])
+        self.buildRecursiveTree(dirPath, item)
+
+    def buildRecursiveTree(self, dir, item):
+        elems = [f for f in os.listdir(dir) if f[0] != "."]
+        for elem in sorted(elems):
+            child = None
+            path = os.path.join(dir, elem)
+            if os.path.isfile(path):
+                if not path.endswith("~") and \
+                       os.path.splitext(path)[1].strip(".") in ALLOWED_EXT:
+                    child = self.tree.AppendItem(item, elem, self.fileidx,
+                                                 self.fileidx)
+                    self.tree.SetItemData(child, packItemData(os.path.join(dir, path)))
+            elif os.path.isdir(path):
+                if elem not in ["build", "__pycache__"]:
+                    child = self.tree.AppendItem(item, elem, self.fldridx,
+                                                 self.fldropenidx)
+                    self.tree.SetItemData(child, packItemData(os.path.join(dir, path)))
+                    self.buildRecursiveTree(path, child)
+            if child is not None:
+                self.tree.SetItemTextColour(child, STYLES['default']['colour'])
 
     def onAdd(self, evt):
         id = evt.GetId()
         treeItemId = self.tree.GetSelection()
-        if self.selected != None:
-            for dirPath in self.projectDict.keys():
-                for root, dirs, files in os.walk(self.projectDict[dirPath]):
-                    if self.selected == os.path.split(root)[1]:
-                        self.scope = root
-                        break
-                    elif self.selected in dirs:
-                        self.scope = os.path.join(root, self.selected)
-                        break
-                    elif self.selected in files:
-                        self.scope = root
-                        treeItemId = self.tree.GetItemParent(treeItemId)
-                        break
-                if self.scope != None:
-                    break
-        elif self.selected == None and id == TOOL_ADD_FOLDER_ID:
-            dlg = wx.DirDialog(self, "Choose a directory where to save your folder:",
-                              defaultPath=os.path.expanduser("~"), style=wx.DD_DEFAULT_STYLE)
+        if self.selectedItem != None:
+            selPath = unpackItemData(self.tree.GetItemData(self.selectedItem))
+            if os.path.isdir(selPath):
+                self.scope = selPath
+            elif os.path.isfile(selPath):
+                treeItemId = self.tree.GetItemParent(treeItemId)
+                self.scope = unpackItemData(self.tree.GetItemData(treeItemId))
+        elif self.selectedItem == None and id == TOOL_ADD_FOLDER_ID:
+            dlg = wx.DirDialog(self,
+                               "Choose directory where to save your folder:",
+                               defaultPath=os.path.expanduser("~"),
+                               style=wx.DD_DEFAULT_STYLE)
             if dlg.ShowModal() == wx.ID_OK:
                 self.scope = dlg.GetPath()
                 dlg.Destroy()
@@ -4474,11 +5281,14 @@ class ProjectTree(wx.Panel):
                 return
             treeItemId = self.tree.GetRootItem()
         if id == TOOL_ADD_FILE_ID:
-            item = self.tree.AppendItem(treeItemId, "Untitled", self.fileidx, self.fileidx, None)
+            item = self.tree.AppendItem(treeItemId, "Untitled", self.fileidx,
+                                        self.fileidx, None)
             self.edititem = item
         else:
-            item = self.tree.AppendItem(treeItemId, "Untitled", self.fldridx, self.fldropenidx, None)
+            item = self.tree.AppendItem(treeItemId, "Untitled", self.fldridx,
+                                        self.fldropenidx, None)
             self.editfolder = item
+        self.tree.SetItemData(item, packItemData(os.path.join(self.scope, "Untitled")))
         self.tree.SetItemTextColour(item, STYLES['default']['colour'])
         self.tree.EnsureVisible(item)
         if PLATFORM == "darwin":
@@ -4507,14 +5317,8 @@ class ProjectTree(wx.Panel):
     def OnRightDown(self, event):
         pt = event.GetPosition();
         self.edititem, flags = self.tree.HitTest(pt)
-        item = self.edititem
-        if item:
-            itemlist = []
-            while self.tree.GetItemText(item) not in self.projectDict.keys():
-                itemlist.insert(0, self.tree.GetItemText(item))
-                item = self.tree.GetItemParent(item)
-            itemlist.insert(0, self.projectDict[self.tree.GetItemText(item)])
-            self.itempath = os.path.join(*itemlist)
+        if self.edititem:
+            self.itempath = unpackItemData(self.tree.GetItemData(self.edititem))
             self.select(self.edititem)
             self.tree.EditLabel(self.edititem)
         else:
@@ -4524,14 +5328,18 @@ class ProjectTree(wx.Panel):
         if self.edititem and self.itempath:
             self.select(self.edititem)
             head, tail = os.path.split(self.itempath)
-            newpath = os.path.join(head, event.GetLabel())
-            os.rename(self.itempath, newpath)
+            newlabel = event.GetLabel()
+            if newlabel != "":
+                newpath = os.path.join(head, event.GetLabel())
+                os.rename(self.itempath, newpath)
+                self.tree.SetItemData(self.edititem, packItemData(newpath))
         elif self.edititem and self.scope:
             newitem = event.GetLabel()
             if not newitem:
                 newitem = "Untitled"
                 wx.CallAfter(self.tree.SetItemText, self.edititem, newitem)
             newpath = os.path.join(self.scope, newitem)
+            self.tree.SetItemData(self.edititem, packItemData(newpath))
             f = open(newpath, "w")
             f.close()
             self.mainPanel.addPage(newpath)
@@ -4541,8 +5349,9 @@ class ProjectTree(wx.Panel):
                 newitem = "Untitled"
                 wx.CallAfter(self.tree.SetItemText, self.editfolder, newitem)
             newpath = os.path.join(self.scope, newitem)
+            self.tree.SetItemData(self.editfolder, packItemData(newpath))
             os.mkdir(newpath)
-            if self.selected == None:
+            if self.selectedItem == None:
                 self.projectDict[newitem] = self.scope
         self.edititem = self.editfolder = self.itempath = self.scope = None
 
@@ -4568,30 +5377,17 @@ class ProjectTree(wx.Panel):
     def openPage(self, item):
         hasChild = self.tree.ItemHasChildren(item)
         if not hasChild:
-            parent = None
-            ritem = item
-            filename = self.tree.GetItemText(ritem)
-            while self.tree.GetItemParent(ritem) != self.tree.GetRootItem():
-                ritem = self.tree.GetItemParent(ritem)
-                parent = self.tree.GetItemText(ritem)
-                filename = os.path.join(parent, filename)
-            dirPath = os.path.split(self.projectDict[parent])[0]
-            path = os.path.join(dirPath, filename)
-#            for root, dirs, files in os.walk(dirPath):
-#                if files:
-#                    for file in files:
-#                        if file == self.tree.GetItemText(item):
-#                            path = os.path.join(root, file)
+            path = unpackItemData(self.tree.GetItemData(item))
             self.mainPanel.addPage(path)
 
     def select(self, item):
         self.tree.SelectItem(item)
-        self.selected = self.tree.GetItemText(item)
+        self.selectedItem = item
         self.toolbar.EnableTool(TOOL_ADD_FILE_ID, True)
 
     def unselect(self):
         self.tree.UnselectAll()
-        self.selected = None
+        self.selectedItem = None
         self.toolbar.EnableTool(TOOL_ADD_FILE_ID, False)
 
     def onCloseProjectPanel(self, evt):
@@ -4599,7 +5395,8 @@ class ProjectTree(wx.Panel):
 
 class MarkersListScroll(scrolled.ScrolledPanel):
     def __init__(self, parent, id=-1, pos=(25,25), size=(500,400)):
-        scrolled.ScrolledPanel.__init__(self, parent, wx.ID_ANY, pos=(0,0), size=size, style=wx.SUNKEN_BORDER)
+        scrolled.ScrolledPanel.__init__(self, parent, wx.ID_ANY, pos=(0,0),
+                                        size=size, style=wx.SUNKEN_BORDER)
         self.parent = parent
         self.SetBackgroundColour(STYLES['background']['colour'])
         self.arrow_bit = catalog['left_arrow.png'].GetBitmap()
@@ -4612,9 +5409,9 @@ class MarkersListScroll(scrolled.ScrolledPanel):
         self.selected2 = None
 
         if wx.Platform == '__WXMAC__':
-            self.font = wx.Font(11, wx.ROMAN, wx.NORMAL, wx.NORMAL, face=STYLES['face'])
+            self.font = wx.Font(11, wx.ROMAN, wx.NORMAL, wx.NORMAL, False, STYLES['face'])
         else:
-            self.font = wx.Font(8, wx.ROMAN, wx.NORMAL, wx.NORMAL, face=STYLES['face'])
+            self.font = wx.Font(8, wx.ROMAN, wx.NORMAL, wx.NORMAL, False, STYLES['face'])
 
         self.SetSizer(self.box)
         self.SetAutoLayout(1)
@@ -4623,16 +5420,18 @@ class MarkersListScroll(scrolled.ScrolledPanel):
     def setDict(self, dic):
         self.row_dict = dic
         self.box.Clear(True)
-        for i, key in enumerate(sorted(self.row_dict.keys())):
+        swap = [(x[1], x[0]) for x in self.row_dict.items()]
+        handles = [x[1] for x in sorted(swap)]
+        for i in handles:
             label = wx.StaticBitmap(self, wx.ID_ANY)
             label.SetBitmap(self.arrow_bit)
-            self.box.Add(label, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 2, userData=(i,key))
-            line = wx.StaticText(self, wx.ID_ANY, label=str(key+1))
+            self.box.Add(label, 0, wx.LEFT|wx.ALIGN_CENTER_VERTICAL, 2, userData=(i,self.row_dict[i][0]))
+            line = wx.StaticText(self, wx.ID_ANY, label=str(self.row_dict[i][0]+1))
             line.SetFont(self.font)
-            self.box.Add(line, 0, wx.ALIGN_LEFT|wx.TOP, 3, userData=(i,key))
-            comment = wx.StaticText(self, wx.ID_ANY, label=self.row_dict[key])
+            self.box.Add(line, 0, wx.ALIGN_LEFT|wx.TOP, 3, userData=(i,self.row_dict[i][0]))
+            comment = wx.StaticText(self, wx.ID_ANY, label=self.row_dict[i][1])
             comment.SetFont(self.font)
-            self.box.Add(comment, 1, wx.EXPAND|wx.ALIGN_LEFT|wx.TOP, 3, userData=(i,key))
+            self.box.Add(comment, 1, wx.EXPAND|wx.ALIGN_LEFT|wx.TOP, 3, userData=(i,self.row_dict[i][0]))
             self.box.Layout()
             label.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
             line.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
@@ -4652,16 +5451,17 @@ class MarkersListScroll(scrolled.ScrolledPanel):
                     self.selected = item.GetUserData()[0]
                     line = item.GetUserData()[1]
                     editor.GotoLine(line)
-                    halfNumLinesOnScreen = editor.LinesOnScreen() / 2
+                    halfNumLinesOnScreen = editor.LinesOnScreen() // 2
                     editor.ScrollToLine(line - halfNumLinesOnScreen)
                 else:
-                    line = sorted(self.row_dict.keys())[self.selected]
+                    line = self.row_dict[self.selected][0]
                     self.selected2 = item.GetUserData()[0]
                     line2 = item.GetUserData()[1]
-                    editor.GotoLine(line)
-                    halfNumLinesOnScreen = editor.LinesOnScreen() / 2
-                    editor.ScrollToLine(line - halfNumLinesOnScreen)
-                    editor.SetSelection(editor.PositionFromLine(line), editor.PositionFromLine(line2+1))
+                    l1, l2 = min(line, line2), max(line, line2)
+                    editor.GotoLine(l1)
+                    halfNumLinesOnScreen = editor.LinesOnScreen() // 2
+                    editor.ScrollToLine(l1 - halfNumLinesOnScreen)
+                    editor.SetSelection(editor.PositionFromLine(l1), editor.PositionFromLine(l2+1))
                 break
         self.setColour()
 
@@ -4699,18 +5499,28 @@ class MarkersPanel(wx.Panel):
         toolbarbox = wx.BoxSizer(wx.HORIZONTAL)
         self.toolbar = wx.ToolBar(self, -1, size=(-1,36))
         self.toolbar.SetToolBitmapSize(tsize)
-        self.toolbar.AddLabelTool(TOOL_DELETE_ALL_MARKERS_ID, "Delete All Markers", delete_all_markers, shortHelp="Delete All Markers")
+
+        if "phoenix" not in wx.version():
+            self.toolbar.AddLabelTool(TOOL_DELETE_ALL_MARKERS_ID, "Delete All Markers", delete_all_markers, shortHelp="Delete All Markers")
+        else:
+            self.toolbar.AddTool(TOOL_DELETE_ALL_MARKERS_ID, "Delete All Markers", delete_all_markers, shortHelp="Delete All Markers")
+
         self.toolbar.Realize()
         toolbarbox.Add(self.toolbar, 1, wx.ALIGN_LEFT | wx.EXPAND, 0)
 
         tb2 = wx.ToolBar(self, -1, size=(-1,36))
         tb2.SetToolBitmapSize(tsize)
-        tb2.AddLabelTool(16, "Close Panel", close_panel_bmp, shortHelp="Close Panel")
+
+        if "phoenix" not in wx.version():
+            tb2.AddLabelTool(16, "Close Panel", close_panel_bmp, shortHelp="Close Panel")
+        else:
+            tb2.AddTool(16, "Close Panel", close_panel_bmp, shortHelp="Close Panel")
+
         tb2.Realize()
         toolbarbox.Add(tb2, 0, wx.ALIGN_RIGHT, 0)
 
-        wx.EVT_TOOL(self, TOOL_DELETE_ALL_MARKERS_ID, self.onDeleteAll)
-        wx.EVT_TOOL(self, 16, self.onCloseMarkersPanel)
+        self.Bind(wx.EVT_TOOL, self.onDeleteAll, id=TOOL_DELETE_ALL_MARKERS_ID)
+        self.Bind(wx.EVT_TOOL, self.onCloseMarkersPanel, id=16)
 
         self.sizer.Add(toolbarbox, 0, wx.EXPAND)
 
@@ -4736,12 +5546,12 @@ class PreferencesDialog(wx.Dialog):
     def __init__(self):
         wx.Dialog.__init__(self, None, wx.ID_ANY, 'E-Pyo Preferences')
         mainSizer = wx.BoxSizer(wx.VERTICAL)
-        mainSizer.AddSpacer((-1,10))
+        mainSizer.AddSpacer(10)
         font, entryfont, pointsize = self.GetFont(), self.GetFont(), self.GetFont().GetPointSize()
-        
+
         font.SetWeight(wx.BOLD)
-        if PLATFORM == "linux2":
-            entryfont.SetPointSize(pointsize-1)
+        if PLATFORM.startswith("linux"):
+            entryfont.SetPointSize(pointsize)
         elif PLATFORM == "win32":
             entryfont.SetPointSize(pointsize)
         else:
@@ -4759,7 +5569,7 @@ class PreferencesDialog(wx.Dialog):
         ctrlSizer.Add(self.entry_exe, 0, wx.ALL|wx.EXPAND, 5)
         but = wx.Button(self, id=wx.ID_ANY, label="Choose...")
         but.Bind(wx.EVT_BUTTON, self.setExecutable)
-        ctrlSizer.Add(but, 0, wx.ALL, 5)            
+        ctrlSizer.Add(but, 0, wx.ALL, 5)
         but2 = wx.Button(self, id=wx.ID_ANY, label="Revert")
         but2.Bind(wx.EVT_BUTTON, self.revertExecutable)
         ctrlSizer.Add(but2, 0, wx.ALL, 5)
@@ -4777,15 +5587,15 @@ class PreferencesDialog(wx.Dialog):
         ctrlSizer.Add(self.entry_res, 0, wx.ALL|wx.EXPAND, 5)
         but = wx.Button(self, id=wx.ID_ANY, label="Choose...")
         but.Bind(wx.EVT_BUTTON, self.setResourcesFolder)
-        ctrlSizer.Add(but, 0, wx.ALL, 5)            
+        ctrlSizer.Add(but, 0, wx.ALL, 5)
         but2 = wx.Button(self, id=wx.ID_ANY, label="Revert")
         but2.Bind(wx.EVT_BUTTON, self.revertResourcesFolder)
-        ctrlSizer.Add(but2, 0, wx.ALL, 5)            
+        ctrlSizer.Add(but2, 0, wx.ALL, 5)
         mainSizer.Add(ctrlSizer, 0, wx.BOTTOM|wx.LEFT|wx.RIGHT, 5)
 
         mainSizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.BOTTOM|wx.LEFT|wx.RIGHT, 5)
 
-        lbl = wx.StaticText(self, label="Background Pyo Server")
+        lbl = wx.StaticText(self, label="=== Background Pyo Server ===")
         lbl.SetFont(font)
         mainSizer.Add(lbl, 0, wx.BOTTOM|wx.LEFT|wx.RIGHT, 10)
 
@@ -4796,59 +5606,76 @@ class PreferencesDialog(wx.Dialog):
         self.server_args = wx.TextCtrl(self, size=(500,-1), value=BACKGROUND_SERVER_ARGS)
         self.server_args.SetFont(entryfont)
         ctrlSizer.Add(self.server_args, 0, wx.ALL|wx.EXPAND, 5)
-        but = wx.Button(self, id=wx.ID_ANY, label="Restore default args")
+        but = wx.Button(self, id=wx.ID_ANY, label=" Restore default args ")
         but.Bind(wx.EVT_BUTTON, self.setServerDefaultArgs)
-        ctrlSizer.Add(but, 0, wx.ALL, 5)            
+        ctrlSizer.Add(but, 0, wx.ALL, 5)
         mainSizer.Add(ctrlSizer, 0, wx.BOTTOM|wx.LEFT|wx.RIGHT, 5)
 
-        popupSizer = wx.FlexGridSizer(2, 3, 5, 10)
-        for label in ["Output Driver", "Input Driver", "Midi Interface"]:
+        popupSizer = wx.FlexGridSizer(2, 4, 5, 10)
+        for label in ["Input Driver", "Output Driver", "Midi Input", "Midi Output"]:
             lbl = wx.StaticText(self, label=label)
             lbl.SetFont(font)
             popupSizer.Add(lbl)
 
-        preferedDriver = PREFERENCES.get("background_server_out_device", "")
-        driverList, driverIndexes = pa_get_output_devices()
-        driverList = [ensureNFD(driver) for driver in driverList]
-        defaultDriver = pa_get_default_output()
-        self.popupOutDriver = wx.Choice(self, choices=driverList)
-        popupSizer.Add(self.popupOutDriver)
-        if preferedDriver and preferedDriver in driverList:
-            driverIndex = driverIndexes[driverList.index(preferedDriver)]
-            self.popupOutDriver.SetStringSelection(preferedDriver)
-        elif defaultDriver:
-            self.popupOutDriver.SetSelection(driverIndexes.index(defaultDriver))
-
+        cX = 160
         preferedDriver = PREFERENCES.get("background_server_in_device", "")
         driverList, driverIndexes = pa_get_input_devices()
         driverList = [ensureNFD(driver) for driver in driverList]
         defaultDriver = pa_get_default_input()
-        self.popupInDriver = wx.Choice(self, choices=driverList)
-        popupSizer.Add(self.popupInDriver)
+        self.popupInDriver = wx.Choice(self, choices=driverList, size=(cX,-1))
+        popupSizer.Add(self.popupInDriver, 1, wx.EXPAND, 5)
         if preferedDriver and preferedDriver in driverList:
             driverIndex = driverIndexes[driverList.index(preferedDriver)]
             self.popupInDriver.SetStringSelection(preferedDriver)
-        elif defaultDriver:
+        elif defaultDriver >= 0:
             self.popupInDriver.SetSelection(driverIndexes.index(defaultDriver))
 
+        preferedDriver = PREFERENCES.get("background_server_out_device", "")
+        driverList, driverIndexes = pa_get_output_devices()
+        driverList = [ensureNFD(driver) for driver in driverList]
+        defaultDriver = pa_get_default_output()
+        self.popupOutDriver = wx.Choice(self, choices=driverList, size=(cX,-1))
+        popupSizer.Add(self.popupOutDriver, 1, wx.EXPAND, 5)
+        if preferedDriver and preferedDriver in driverList:
+            driverIndex = driverIndexes[driverList.index(preferedDriver)]
+            self.popupOutDriver.SetStringSelection(preferedDriver)
+        elif defaultDriver >= 0:
+            self.popupOutDriver.SetSelection(driverIndexes.index(defaultDriver))
+
+        # TODO: Added "all" interfaces option in input and output
         preferedDriver = PREFERENCES.get("background_server_midiin_device", "")
         driverList, driverIndexes = pm_get_input_devices()
         driverList = [ensureNFD(driver) for driver in driverList]
         if driverList != []:
             defaultDriver = pm_get_default_input()
-            self.popupMidiInDriver = wx.Choice(self, choices=driverList)
-            popupSizer.Add(self.popupMidiInDriver)
+            self.popupMidiInDriver = wx.Choice(self, choices=driverList, size=(cX,-1))
             if preferedDriver and preferedDriver in driverList:
                 driverIndex = driverIndexes[driverList.index(preferedDriver)]
                 self.popupMidiInDriver.SetStringSelection(preferedDriver)
-            elif defaultDriver:
+            elif defaultDriver >= 0:
                 self.popupMidiInDriver.SetSelection(driverIndexes.index(defaultDriver))
         else:
             self.popupMidiInDriver = wx.Choice(self, choices=["No Interface"])
-            popupSizer.Add(self.popupMidiInDriver)
             self.popupMidiInDriver.SetSelection(0)
+        popupSizer.Add(self.popupMidiInDriver, 1, wx.EXPAND, 5)
 
-        mainSizer.Add(popupSizer, 0, wx.BOTTOM|wx.LEFT|wx.RIGHT, 10)
+        preferedDriver = PREFERENCES.get("background_server_midiout_device", "")
+        driverList, driverIndexes = pm_get_output_devices()
+        driverList = [ensureNFD(driver) for driver in driverList]
+        if driverList != []:
+            defaultDriver = pm_get_default_output()
+            self.popupMidiOutDriver = wx.Choice(self, choices=driverList, size=(cX,-1))
+            if preferedDriver and preferedDriver in driverList:
+                driverIndex = driverIndexes[driverList.index(preferedDriver)]
+                self.popupMidiOutDriver.SetStringSelection(preferedDriver)
+            elif defaultDriver >= 0:
+                self.popupMidiOutDriver.SetSelection(driverIndexes.index(defaultDriver))
+        else:
+            self.popupMidiOutDriver = wx.Choice(self, choices=["No Interface"])
+            self.popupMidiOutDriver.SetSelection(0)
+        popupSizer.Add(self.popupMidiOutDriver, 1, wx.EXPAND, 5)
+
+        mainSizer.Add(popupSizer, 0, wx.EXPAND|wx.BOTTOM|wx.LEFT|wx.RIGHT, 10)
 
         mainSizer.Add(wx.StaticLine(self, -1), 0, wx.EXPAND|wx.BOTTOM|wx.LEFT|wx.RIGHT, 5)
 
@@ -4858,12 +5685,12 @@ class PreferencesDialog(wx.Dialog):
         ctrlSizer = wx.BoxSizer(wx.HORIZONTAL)
         self.entry_ext = wx.TextCtrl(self, size=(500,-1), value=", ".join(ALLOWED_EXT))
         self.entry_ext.SetFont(entryfont)
-        ctrlSizer.Add(self.entry_ext, 0, wx.ALL|wx.EXPAND, 5)
-        mainSizer.Add(ctrlSizer, 0, wx.BOTTOM|wx.LEFT|wx.RIGHT, 5)
+        ctrlSizer.Add(self.entry_ext, 1, wx.ALL|wx.EXPAND, 5)
+        mainSizer.Add(ctrlSizer, 0, wx.EXPAND|wx.BOTTOM|wx.LEFT|wx.RIGHT, 5)
 
         btnSizer = self.CreateButtonSizer(wx.CANCEL|wx.OK)
- 
-        mainSizer.AddSpacer((-1,5))
+
+        mainSizer.AddSpacer(5)
         mainSizer.Add(wx.StaticLine(self), 1, wx.EXPAND|wx.ALL, 2)
         mainSizer.Add(btnSizer, 0, wx.ALL | wx.ALIGN_RIGHT, 5)
         self.SetSizer(mainSizer)
@@ -4891,7 +5718,7 @@ class PreferencesDialog(wx.Dialog):
 
     def setServerDefaultArgs(self, evt):
         self.server_args.SetValue(BACKGROUND_SERVER_DEFAULT_ARGS)
-    
+
     def writePrefs(self):
         global ALLOWED_EXT, WHICH_PYTHON, RESOURCES_PATH, SNIPPETS_PATH, STYLES_PATH, BACKGROUND_SERVER_ARGS
 
@@ -4901,7 +5728,7 @@ class PreferencesDialog(wx.Dialog):
 
         res_folder = self.entry_res.GetValue()
         if os.path.isdir(res_folder):
-            if res_folder != RESOURCES_PATH:
+            if res_folder != ensureNFD(RESOURCES_PATH):
                 RESOURCES_PATH = PREFERENCES["resources_path"] = res_folder
                 # snippets
                 old_snippets_path = SNIPPETS_PATH
@@ -4931,37 +5758,41 @@ class PreferencesDialog(wx.Dialog):
 
         extensions = [ext.strip() for ext in self.entry_ext.GetValue().split(",")]
         ALLOWED_EXT = PREFERENCES["allowed_ext"] = extensions
-        
+
         server_args = self.server_args.GetValue()
         BACKGROUND_SERVER_ARGS = PREFERENCES["background_server_args"] = server_args
-        
+
         PREFERENCES["background_server_out_device"] = self.popupOutDriver.GetStringSelection()
         PREFERENCES["background_server_in_device"] = self.popupInDriver.GetStringSelection()
         midiDevice = self.popupMidiInDriver.GetStringSelection()
         if midiDevice != "No Interface":
             PREFERENCES["background_server_midiin_device"] = midiDevice
+        midiDevice = self.popupMidiOutDriver.GetStringSelection()
+        if midiDevice != "No Interface":
+            PREFERENCES["background_server_midiout_device"] = midiDevice
 
 class STCPrintout(wx.Printout):
     """Specific printing support of the wx.StyledTextCtrl for the wxPython
     framework
 
     This class can be used for both printing to a printer and for print preview
-    functions.  Unless otherwise specified, the print is scaled based on the
+    functions. Unless otherwise specified, the print is scaled based on the
     size of the current font used in the STC so that specifying a larger font
     produces a larger font in the printed output (and correspondingly fewer
-    lines per page).  Alternatively, you can eihdec specify the number of
+    lines per page). Alternatively, you can eihdec specify the number of
     lines per page, or you can specify the print font size in points which
     produces a constant number of lines per inch regardless of the paper size.
 
     Note that line wrapping in the source STC is currently ignored and lines
-    will be truncated at the right margin instead of wrapping.  The STC doesn't
+    will be truncated at the right margin instead of wrapping. The STC doesn't
     provide a convenient method for determining where line breaks occur within
     a wrapped line, so it may be a difficult task to ever implement printing
     with line wrapping using the wx.StyledTextCtrl.FormatRange method.
     """
-    debuglevel = 0
+    debuglevel = 1
 
-    def __init__(self, stc, page_setup_data=None, print_mode=None, title=None, border=False, lines_per_page=None, output_point_size=None):
+    def __init__(self, stc, page_setup_data=None, print_mode=None, title=None,
+                 border=False, lines_per_page=None, output_point_size=None):
         """Constructor.
 
         @param stc: wx.StyledTextCtrl to print
@@ -4970,7 +5801,7 @@ class STCPrintout(wx.Printout):
         is used to determine the margins of the page.
 
         @kwarg print_mode: optional; of the wx.stc.STC_PRINT_*
-        flags indicating how to render color text.  Defaults to
+        flags indicating how to render color text. Defaults to
         wx.stc.STC_PRINT_COLOURONWHITEDEFAULTBG
 
         @kwarg title: optional text string to use as the title which will be
@@ -4980,14 +5811,14 @@ class STCPrintout(wx.Printout):
         border around the text on each page
 
         @kwarg lines_per_page: optional integer that will force the page to
-        contain the specified number of lines.  Either of C{output_point_size}
+        contain the specified number of lines. Either of C{output_point_size}
         and C{lines_per_page} fully specifies the page, so if both are
         specified, C{lines_per_page} will be used.
 
         @kwarg output_point_size: optional integer that will force the output
-        text to be drawn in the specified point size.  (Note that there are
+        text to be drawn in the specified point size. (Note that there are
         72 points per inch.) If not specified, the point size of the text in
-        the STC will be used unless C{lines_per_page} is specified.  Either of
+        the STC will be used unless C{lines_per_page} is specified. Either of
         C{output_point_size} and C{lines_per_page} fully specifies the page,
         so if both are specified, C{lines_per_page} will be used.
         """
@@ -5022,6 +5853,7 @@ class STCPrintout(wx.Printout):
         except (TypeError, ValueError):
             self.user_lines_per_page = None
 
+        self.page_count = 2
         self.border_around_text = border
 
         self.setHeaderFont()
@@ -5043,11 +5875,11 @@ class STCPrintout(wx.Printout):
         logical coordinates.
         """
         if self.debuglevel > 0:
-            print
+            print()
 
         dc.SetFont(self.stc.GetFont())
 
-        # Calculate pixels per inch of the various devices.  The dc_ppi will be
+        # Calculate pixels per inch of the various devices. The dc_ppi will be
         # equivalent to the page or screen PPI if the target is the printer or
         # a print preview, respectively.
         page_ppi_x, page_ppi_y = self.GetPPIPrinter()
@@ -5058,10 +5890,10 @@ class STCPrintout(wx.Printout):
             print("screen ppi: %dx%d" % (screen_ppi_x, screen_ppi_y))
             print("dc ppi: %dx%d" % (dc_ppi_x, dc_ppi_y))
 
-        # Calculate paper size.  Note that this is the size in pixels of the
+        # Calculate paper size. Note that this is the size in pixels of the
         # entire paper, which may be larger than the printable range of the
-        # printer.  We need to use the entire paper size because we calculate
-        # margins ourselves.  Note that GetPageSizePixels returns the
+        # printer. We need to use the entire paper size because we calculate
+        # margins ourselves. Note that GetPageSizePixels returns the
         # dimensions of the printable area.
         px, py, pw, ph = self.GetPaperRectPixels()
         page_width_inch = float(pw) / page_ppi_x
@@ -5118,7 +5950,7 @@ class STCPrintout(wx.Printout):
         @param dc: the Device Context
 
         @param usable_page_height_mm: height in mm of the printable part of the
-        page (i.e.  with the border height removed)
+        page (i.e. with the border height removed)
 
         @returns: the number of lines on the page
         """
@@ -5131,7 +5963,7 @@ class STCPrintout(wx.Printout):
         else:
             points_per_line = font.GetPointSize()
 
-        # desired lines per mm based on point size.  Note: printer points are
+        # desired lines per mm based on point size. Note: printer points are
         # defined as 72 points per inch
         lines_per_inch = 72.0 / float(points_per_line)
 
@@ -5159,7 +5991,7 @@ class STCPrintout(wx.Printout):
         # actual line height in pixels according to the DC
         dc_pixels_per_line = dc.GetCharHeight()
 
-        # actual line height in pixels according to the STC.  This can be
+        # actual line height in pixels according to the STC. This can be
         # different from dc_pixels_per_line even though it is the same font.
         # Don't know why this is the case; maybe because the STC takes into
         # account additional spacing?
@@ -5303,7 +6135,7 @@ class STCPrintout(wx.Printout):
         dc.SetFont(self.getHeaderFont())
         dc.SetTextForeground ("black")
         dum, yoffset = dc.GetTextExtent(".")
-        yoffset /= 2
+        yoffset = yoffset // 2
         if self.title:
             title_w, title_h = dc.GetTextExtent(self.title)
             dc.DrawText(self.title, self.x1, self.y1 - title_h - yoffset)
@@ -5351,7 +6183,8 @@ class STCPrintout(wx.Printout):
         if self.border_around_text:
             dc.SetPen(wx.BLACK_PEN)
             dc.SetBrush(wx.TRANSPARENT_BRUSH)
-            dc.DrawRectangle(self.x1, self.y1, self.x2 - self.x1 + 1, self.y2 - self.y1 + 1)
+            dc.DrawRectangle(self.x1, self.y1, self.x2 - self.x1 + 1,
+                             self.y2 - self.y1 + 1)
 
 class MyFileDropTarget(wx.FileDropTarget):
     def __init__(self, window):
@@ -5367,6 +6200,39 @@ class MyFileDropTarget(wx.FileDropTarget):
                 self.window.GetTopLevelParent().panel.addPage(file)
             else:
                 pass
+        return True
+
+class EPyoApp(wx.App):
+    def __init__(self, *args, **kwargs):
+        wx.App.__init__(self, *args, **kwargs)
+
+    def OnInit(self):
+        X = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_X)
+        Y = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y)
+        if X < 850: X -= 50
+        else: X = 850
+        if Y < 750: Y -= 50
+        else: Y = 750
+        self.frame = MainFrame(None, -1, title='E-Pyo Editor',
+                               pos=(10,25), size=(X, Y))
+        self.frame.Show()
+        return True
+
+    def MacOpenFiles(self, filenames):
+        if type(filenames) != list:
+            filenames = [filenames]
+        for filename in filenames:
+            if os.path.isdir(filename):
+                self.frame.panel.project.loadFolder(filename)
+                sys.path.append(filename)
+            elif os.path.isfile(filename):
+                self.frame.panel.addPage(filename)
+
+    def MacReopenApp(self):
+        try:
+            self.frame.Raise()
+        except:
+            pass
 
 if __name__ == '__main__':
     filesToOpen = []
@@ -5381,12 +6247,5 @@ if __name__ == '__main__':
             else:
                 pass
 
-    app = wx.PySimpleApp()
-    X,Y = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_X), wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y)
-    if X < 850: X -= 50
-    else: X = 850
-    if Y < 750: Y -= 50
-    else: Y = 750
-    frame = MainFrame(None, -1, title='E-Pyo Editor', pos=(10,25), size=(X, Y))
-    frame.Show()
-    app.MainLoop()
+    app = EPyoApp(redirect=False)
+    app.MainLoop()
\ No newline at end of file
diff --git a/utils/E-PyoIcon.png b/utils/E-PyoIcon.png
new file mode 100644
index 0000000..f971f13
Binary files /dev/null and b/utils/E-PyoIcon.png differ
diff --git a/utils/FlatNotebook.py b/utils/FlatNotebook.py
deleted file mode 100755
index f4c7d34..0000000
--- a/utils/FlatNotebook.py
+++ /dev/null
@@ -1,4940 +0,0 @@
-# --------------------------------------------------------------------------- #
-# FLATNOTEBOOK Widget wxPython IMPLEMENTATION
-#
-# Original C++ Code From Eran. You Can Find It At:
-#
-# http://wxforum.shadonet.com/viewtopic.php?t=5761&start=0
-#
-# License: wxWidgets license
-#
-#
-# Python Code By:
-#
-# Andrea Gavana, @ 02 Oct 2006
-# Latest Revision: 30 May 2008, 23.00 GMT
-#
-#
-# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
-# Write To Me At:
-#
-# andrea.gavana at gmail.com
-# gavana at kpo.kz
-#
-# Or, Obviously, To The wxPython Mailing List!!!
-#
-#
-# End Of Comments
-# --------------------------------------------------------------------------- #
-
-"""
-The FlatNotebook is a full implementation of the wx.Notebook, and designed to be
-a drop-in replacement for wx.Notebook. The API functions are similar so one can
-expect the function to behave in the same way. 
-
-Some features:
-
-  - The buttons are highlighted a la Firefox style
-  - The scrolling is done for bulks of tabs (so, the scrolling is faster and better)
-  - The buttons area is never overdrawn by tabs (unlike many other implementations I saw)
-  - It is a generic control
-  - Currently there are 5 differnt styles - VC8, VC 71, Standard, Fancy and Firefox 2;
-  - Mouse middle click can be used to close tabs
-  - A function to add right click menu for tabs (simple as SetRightClickMenu)
-  - All styles has bottom style as well (they can be drawn in the bottom of screen)
-  - An option to hide 'X' button or navigation buttons (separately)
-  - Gradient coloring of the selected tabs and border
-  - Support for drag 'n' drop of tabs, both in the same notebook or to another notebook
-  - Possibility to have closing button on the active tab directly
-  - Support for disabled tabs
-  - Colours for active/inactive tabs, and captions
-  - Background of tab area can be painted in gradient (VC8 style only)
-  - Colourful tabs - a random gentle colour is generated for each new tab (very cool, VC8 style only)
-
-
-And much more.
-
-
-License And Version:
-
-FlatNotebook Is Freeware And Distributed Under The wxPython License. 
-
-Latest Revision: Andrea Gavana @ 30 May 2008, 23.00 GMT
-
-Version 2.5.
-
- at undocumented: FNB_HEIGHT_SPACER, VERTICAL_BORDER_PADDING, VC8_SHAPE_LEN,
-    wxEVT*, left_arrow_*, right_arrow*, x_button*, down_arrow*,
-    FNBDragInfo, FNBDropTarget, GetMondrian*
-"""
-
-__docformat__ = "epytext"
-
-
-#----------------------------------------------------------------------
-# Beginning Of FLATNOTEBOOK wxPython Code
-#----------------------------------------------------------------------
-
-import wx
-import random
-import math
-import weakref
-import cPickle
-
-if wx.Platform == '__WXMAC__':
-    import Carbon.Appearance
-
-# Check for the new method in 2.7 (not present in 2.6.3.3)
-if wx.VERSION_STRING < "2.7":
-    wx.Rect.Contains = lambda self, point: wx.Rect.Inside(self, point)
-
-FNB_HEIGHT_SPACER = 10
-
-# Use Visual Studio 2003 (VC7.1) style for tabs
-FNB_VC71 = 1
-"""Use Visual Studio 2003 (VC7.1) style for tabs"""
-
-# Use fancy style - square tabs filled with gradient coloring
-FNB_FANCY_TABS = 2
-"""Use fancy style - square tabs filled with gradient coloring"""
-
-# Draw thin border around the page
-FNB_TABS_BORDER_SIMPLE = 4
-"""Draw thin border around the page"""
-
-# Do not display the 'X' button
-FNB_NO_X_BUTTON = 8
-"""Do not display the 'X' button"""
-
-# Do not display the Right / Left arrows
-FNB_NO_NAV_BUTTONS = 16
-"""Do not display the right/left arrows"""
-
-# Use the mouse middle button for cloing tabs
-FNB_MOUSE_MIDDLE_CLOSES_TABS = 32
-"""Use the mouse middle button for cloing tabs"""
-
-# Place tabs at bottom - the default is to place them
-# at top
-FNB_BOTTOM = 64
-"""Place tabs at bottom - the default is to place them at top"""
-
-# Disable dragging of tabs
-FNB_NODRAG = 128
-"""Disable dragging of tabs"""
-
-# Use Visual Studio 2005 (VC8) style for tabs
-FNB_VC8 = 256
-"""Use Visual Studio 2005 (VC8) style for tabs"""
-
-# Firefox 2 tabs style
-FNB_FF2 = 131072
-"""Use Firefox 2 style for tabs"""
-
-# Place 'X' on a tab
-FNB_X_ON_TAB = 512
-"""Place 'X' close button on the active tab"""
-
-FNB_BACKGROUND_GRADIENT = 1024
-"""Use gradients to paint the tabs background"""
-
-FNB_COLORFUL_TABS = 2048
-"""Use colourful tabs (VC8 style only)"""
-
-# Style to close tab using double click - styles 1024, 2048 are reserved
-FNB_DCLICK_CLOSES_TABS = 4096
-"""Style to close tab using double click"""
-
-FNB_SMART_TABS = 8192
-"""Use Smart Tabbing, like Alt+Tab on Windows"""
-
-FNB_DROPDOWN_TABS_LIST = 16384
-"""Use a dropdown menu on the left in place of the arrows"""
-
-FNB_ALLOW_FOREIGN_DND = 32768
-"""Allows drag 'n' drop operations between different L{FlatNotebook}s"""
-
-FNB_HIDE_ON_SINGLE_TAB = 65536
-"""Hides the Page Container when there is one or fewer tabs"""
-
-VERTICAL_BORDER_PADDING = 4
-
-# Button size is a 16x16 xpm bitmap
-BUTTON_SPACE = 16
-"""Button size is a 16x16 xpm bitmap"""
-
-VC8_SHAPE_LEN = 16
-
-MASK_COLOR  = wx.Colour(0, 128, 128)
-"""Mask colour for the arrow bitmaps"""
-
-# Button status
-FNB_BTN_PRESSED = 2
-"""Navigation button is pressed"""
-FNB_BTN_HOVER = 1
-"""Navigation button is hovered"""
-FNB_BTN_NONE = 0
-"""No navigation"""
-
-# Hit Test results
-FNB_TAB = 1             # On a tab
-"""Indicates mouse coordinates inside a tab"""
-FNB_X = 2               # On the X button
-"""Indicates mouse coordinates inside the I{X} region"""
-FNB_TAB_X = 3           # On the 'X' button (tab's X button)
-"""Indicates mouse coordinates inside the I{X} region in a tab"""
-FNB_LEFT_ARROW = 4      # On the rotate left arrow button
-"""Indicates mouse coordinates inside the left arrow region"""
-FNB_RIGHT_ARROW = 5     # On the rotate right arrow button
-"""Indicates mouse coordinates inside the right arrow region"""
-FNB_DROP_DOWN_ARROW = 6 # On the drop down arrow button
-"""Indicates mouse coordinates inside the drop down arrow region"""
-FNB_NOWHERE = 0         # Anywhere else
-"""Indicates mouse coordinates not on any tab of the notebook"""
-
-FNB_DEFAULT_STYLE = FNB_MOUSE_MIDDLE_CLOSES_TABS | FNB_HIDE_ON_SINGLE_TAB
-"""L{FlatNotebook} default style"""
-
-# FlatNotebook Events:
-# wxEVT_FLATNOTEBOOK_PAGE_CHANGED: Event Fired When You Switch Page;
-# wxEVT_FLATNOTEBOOK_PAGE_CHANGING: Event Fired When You Are About To Switch
-# Pages, But You Can Still "Veto" The Page Changing By Avoiding To Call
-# event.Skip() In Your Event Handler;
-# wxEVT_FLATNOTEBOOK_PAGE_CLOSING: Event Fired When A Page Is Closing, But
-# You Can Still "Veto" The Page Changing By Avoiding To Call event.Skip()
-# In Your Event Handler;
-# wxEVT_FLATNOTEBOOK_PAGE_CLOSED: Event Fired When A Page Is Closed.
-# wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU: Event Fired When A Menu Pops-up In A Tab.
-
-wxEVT_FLATNOTEBOOK_PAGE_CHANGED = wx.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED
-wxEVT_FLATNOTEBOOK_PAGE_CHANGING = wx.wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING
-wxEVT_FLATNOTEBOOK_PAGE_CLOSING = wx.NewEventType()
-wxEVT_FLATNOTEBOOK_PAGE_CLOSED = wx.NewEventType()
-wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU = wx.NewEventType()
-
-#-----------------------------------#
-#        FlatNotebookEvent
-#-----------------------------------#
-
-EVT_FLATNOTEBOOK_PAGE_CHANGED = wx.EVT_NOTEBOOK_PAGE_CHANGED
-"""Notify client objects when the active page in L{FlatNotebook} 
-has changed."""
-EVT_FLATNOTEBOOK_PAGE_CHANGING = wx.EVT_NOTEBOOK_PAGE_CHANGING
-"""Notify client objects when the active page in L{FlatNotebook} 
-is about to change."""
-EVT_FLATNOTEBOOK_PAGE_CLOSING = wx.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CLOSING, 1)
-"""Notify client objects when a page in L{FlatNotebook} is closing."""
-EVT_FLATNOTEBOOK_PAGE_CLOSED = wx.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CLOSED, 1)
-"""Notify client objects when a page in L{FlatNotebook} has been closed."""
-EVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU = wx.PyEventBinder(wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU, 1)
-"""Notify client objects when a pop-up menu should appear next to a tab."""
-
-
-# Some icons in XPM format
-
-left_arrow_disabled_xpm = [
-    "    16    16        8            1",
-    "` c #008080",
-    ". c #555555",
-    "# c #000000",
-    "a c #000000",
-    "b c #000000",
-    "c c #000000",
-    "d c #000000",
-    "e c #000000",
-    "````````````````",
-    "````````````````",
-    "````````````````",
-    "````````.```````",
-    "```````..```````",
-    "``````.`.```````",
-    "`````.``.```````",
-    "````.```.```````",
-    "`````.``.```````",
-    "``````.`.```````",
-    "```````..```````",
-    "````````.```````",
-    "````````````````",
-    "````````````````",
-    "````````````````",
-    "````````````````"
-    ]
-
-x_button_pressed_xpm = [
-    "    16    16        8            1",
-    "` c #008080",
-    ". c #4766e0",
-    "# c #9e9ede",
-    "a c #000000",
-    "b c #000000",
-    "c c #000000",
-    "d c #000000",
-    "e c #000000",
-    "````````````````",
-    "`..............`",
-    "`.############.`",
-    "`.############.`",
-    "`.############.`",
-    "`.###aa####aa#.`",
-    "`.####aa##aa##.`",
-    "`.#####aaaa###.`",
-    "`.######aa####.`",
-    "`.#####aaaa###.`",
-    "`.####aa##aa##.`",
-    "`.###aa####aa#.`",
-    "`.############.`",
-    "`..............`",
-    "````````````````",
-    "````````````````"
-    ]
-
-
-left_arrow_xpm = [
-    "    16    16        8            1",
-    "` c #008080",
-    ". c #555555",
-    "# c #000000",
-    "a c #000000",
-    "b c #000000",
-    "c c #000000",
-    "d c #000000",
-    "e c #000000",
-    "````````````````",
-    "````````````````",
-    "````````````````",
-    "````````.```````",
-    "```````..```````",
-    "``````...```````",
-    "`````....```````",
-    "````.....```````",
-    "`````....```````",
-    "``````...```````",
-    "```````..```````",
-    "````````.```````",
-    "````````````````",
-    "````````````````",
-    "````````````````",
-    "````````````````"
-    ]
-
-x_button_hilite_xpm = [
-    "    16    16        8            1",
-    "` c #008080",
-    ". c #4766e0",
-    "# c #c9dafb",
-    "a c #000000",
-    "b c #000000",
-    "c c #000000",
-    "d c #000000",
-    "e c #000000",
-    "````````````````",
-    "`..............`",
-    "`.############.`",
-    "`.############.`",
-    "`.##aa####aa##.`",
-    "`.###aa##aa###.`",
-    "`.####aaaa####.`",
-    "`.#####aa#####.`",
-    "`.####aaaa####.`",
-    "`.###aa##aa###.`",
-    "`.##aa####aa##.`",
-    "`.############.`",
-    "`.############.`",
-    "`..............`",
-    "````````````````",
-    "````````````````"
-    ]
-
-x_button_xpm = [
-    "    16    16        8            1",
-    "` c #008080",
-    ". c #555555",
-    "# c #000000",
-    "a c #000000",
-    "b c #000000",
-    "c c #000000",
-    "d c #000000",
-    "e c #000000",
-    "````````````````",
-    "````````````````",
-    "````````````````",
-    "````````````````",
-    "````..````..````",
-    "`````..``..`````",
-    "``````....``````",
-    "```````..```````",
-    "``````....``````",
-    "`````..``..`````",
-    "````..````..````",
-    "````````````````",
-    "````````````````",
-    "````````````````",
-    "````````````````",
-    "````````````````"
-    ]
-
-left_arrow_pressed_xpm = [
-    "    16    16        8            1",
-    "` c #008080",
-    ". c #4766e0",
-    "# c #9e9ede",
-    "a c #000000",
-    "b c #000000",
-    "c c #000000",
-    "d c #000000",
-    "e c #000000",
-    "````````````````",
-    "`..............`",
-    "`.############.`",
-    "`.############.`",
-    "`.#######a####.`",
-    "`.######aa####.`",
-    "`.#####aaa####.`",
-    "`.####aaaa####.`",
-    "`.###aaaaa####.`",
-    "`.####aaaa####.`",
-    "`.#####aaa####.`",
-    "`.######aa####.`",
-    "`.#######a####.`",
-    "`..............`",
-    "````````````````",
-    "````````````````"
-    ]
-
-left_arrow_hilite_xpm = [
-    "    16    16        8            1",
-    "` c #008080",
-    ". c #4766e0",
-    "# c #c9dafb",
-    "a c #000000",
-    "b c #000000",
-    "c c #000000",
-    "d c #000000",
-    "e c #000000",
-    "````````````````",
-    "`..............`",
-    "`.############.`",
-    "`.######a#####.`",
-    "`.#####aa#####.`",
-    "`.####aaa#####.`",
-    "`.###aaaa#####.`",
-    "`.##aaaaa#####.`",
-    "`.###aaaa#####.`",
-    "`.####aaa#####.`",
-    "`.#####aa#####.`",
-    "`.######a#####.`",
-    "`.############.`",
-    "`..............`",
-    "````````````````",
-    "````````````````"
-    ]
-
-right_arrow_disabled_xpm = [
-    "    16    16        8            1",
-    "` c #008080",
-    ". c #555555",
-    "# c #000000",
-    "a c #000000",
-    "b c #000000",
-    "c c #000000",
-    "d c #000000",
-    "e c #000000",
-    "````````````````",
-    "````````````````",
-    "````````````````",
-    "```````.````````",
-    "```````..```````",
-    "```````.`.``````",
-    "```````.``.`````",
-    "```````.```.````",
-    "```````.``.`````",
-    "```````.`.``````",
-    "```````..```````",
-    "```````.````````",
-    "````````````````",
-    "````````````````",
-    "````````````````",
-    "````````````````"
-    ]
-
-right_arrow_hilite_xpm = [
-    "    16    16        8            1",
-    "` c #008080",
-    ". c #4766e0",
-    "# c #c9dafb",
-    "a c #000000",
-    "b c #000000",
-    "c c #000000",
-    "d c #000000",
-    "e c #000000",
-    "````````````````",
-    "`..............`",
-    "`.############.`",
-    "`.####a#######.`",
-    "`.####aa######.`",
-    "`.####aaa#####.`",
-    "`.####aaaa####.`",
-    "`.####aaaaa###.`",
-    "`.####aaaa####.`",
-    "`.####aaa#####.`",
-    "`.####aa######.`",
-    "`.####a#######.`",
-    "`.############.`",
-    "`..............`",
-    "````````````````",
-    "````````````````"
-    ]
-
-right_arrow_pressed_xpm = [
-    "    16    16        8            1",
-    "` c #008080",
-    ". c #4766e0",
-    "# c #9e9ede",
-    "a c #000000",
-    "b c #000000",
-    "c c #000000",
-    "d c #000000",
-    "e c #000000",
-    "````````````````",
-    "`..............`",
-    "`.############.`",
-    "`.############.`",
-    "`.#####a######.`",
-    "`.#####aa#####.`",
-    "`.#####aaa####.`",
-    "`.#####aaaa###.`",
-    "`.#####aaaaa##.`",
-    "`.#####aaaa###.`",
-    "`.#####aaa####.`",
-    "`.#####aa#####.`",
-    "`.#####a######.`",
-    "`..............`",
-    "````````````````",
-    "````````````````"
-    ]
-
-
-right_arrow_xpm = [
-    "    16    16        8            1",
-    "` c #008080",
-    ". c #555555",
-    "# c #000000",
-    "a c #000000",
-    "b c #000000",
-    "c c #000000",
-    "d c #000000",
-    "e c #000000",
-    "````````````````",
-    "````````````````",
-    "````````````````",
-    "```````.````````",
-    "```````..```````",
-    "```````...``````",
-    "```````....`````",
-    "```````.....````",
-    "```````....`````",
-    "```````...``````",
-    "```````..```````",
-    "```````.````````",
-    "````````````````",
-    "````````````````",
-    "````````````````",
-    "````````````````"
-    ]
-
-down_arrow_hilite_xpm = [
-    "    16    16        8            1",
-    "` c #008080",
-    ". c #4766e0",
-    "# c #c9dafb",
-    "a c #000000",
-    "b c #000000",
-    "c c #000000",
-    "d c #000000",
-    "e c #000000",
-    "````````````````",
-    "``.............`",
-    "``.###########.`",
-    "``.###########.`",
-    "``.###########.`",
-    "``.#aaaaaaaaa#.`",
-    "``.##aaaaaaa##.`",
-    "``.###aaaaa###.`",
-    "``.####aaa####.`",
-    "``.#####a#####.`",
-    "``.###########.`",
-    "``.###########.`",
-    "``.###########.`",
-    "``.............`",
-    "````````````````",
-    "````````````````"
-    ]
-
-down_arrow_pressed_xpm = [
-    "    16    16        8            1",
-    "` c #008080",
-    ". c #4766e0",
-    "# c #9e9ede",
-    "a c #000000",
-    "b c #000000",
-    "c c #000000",
-    "d c #000000",
-    "e c #000000",
-    "````````````````",
-    "``.............`",
-    "``.###########.`",
-    "``.###########.`",
-    "``.###########.`",
-    "``.###########.`",
-    "``.###########.`",
-    "``.#aaaaaaaaa#.`",
-    "``.##aaaaaaa##.`",
-    "``.###aaaaa###.`",
-    "``.####aaa####.`",
-    "``.#####a#####.`",
-    "``.###########.`",
-    "``.............`",
-    "````````````````",
-    "````````````````"
-    ]
-
-
-down_arrow_xpm = [
-    "    16    16        8            1",
-    "` c #008080",
-    ". c #000000",
-    "# c #000000",
-    "a c #000000",
-    "b c #000000",
-    "c c #000000",
-    "d c #000000",
-    "e c #000000",
-    "````````````````",
-    "````````````````",
-    "````````````````",
-    "````````````````",
-    "````````````````",
-    "````````````````",
-    "````.........```",
-    "`````.......````",
-    "``````.....`````",
-    "```````...``````",
-    "````````.```````",
-    "````````````````",
-    "````````````````",
-    "````````````````",
-    "````````````````",
-    "````````````````"
-    ]
-
-
-#----------------------------------------------------------------------
-def GetMondrianData():
-    return \
-'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00 \x08\x06\x00\
-\x00\x00szz\xf4\x00\x00\x00\x04sBIT\x08\x08\x08\x08|\x08d\x88\x00\x00\x00qID\
-ATX\x85\xed\xd6;\n\x800\x10E\xd1{\xc5\x8d\xb9r\x97\x16\x0b\xad$\x8a\x82:\x16\
-o\xda\x84pB2\x1f\x81Fa\x8c\x9c\x08\x04Z{\xcf\xa72\xbcv\xfa\xc5\x08 \x80r\x80\
-\xfc\xa2\x0e\x1c\xe4\xba\xfaX\x1d\xd0\xde]S\x07\x02\xd8>\xe1wa-`\x9fQ\xe9\
-\x86\x01\x04\x10\x00\\(Dk\x1b-\x04\xdc\x1d\x07\x14\x98;\x0bS\x7f\x7f\xf9\x13\
-\x04\x10@\xf9X\xbe\x00\xc9 \x14K\xc1<={\x00\x00\x00\x00IEND\xaeB`\x82' 
-
-
-def GetMondrianBitmap():
-    return wx.BitmapFromImage(GetMondrianImage().Scale(16, 16))
-
-
-def GetMondrianImage():
-    import cStringIO
-    stream = cStringIO.StringIO(GetMondrianData())
-    return wx.ImageFromStream(stream)
-
-
-def GetMondrianIcon():
-    icon = wx.EmptyIcon()
-    icon.CopyFromBitmap(GetMondrianBitmap())
-    return icon
-#----------------------------------------------------------------------
-
-
-def LightColour(color, percent):
-    """ Brighten input colour by percent. """
-    
-    end_color = wx.WHITE
-    
-    rd = end_color.Red() - color.Red()
-    gd = end_color.Green() - color.Green()
-    bd = end_color.Blue() - color.Blue()
-
-    high = 100
-
-    # We take the percent way of the color from color -. white
-    i = percent
-    r = color.Red() + ((i*rd*100)/high)/100
-    g = color.Green() + ((i*gd*100)/high)/100
-    b = color.Blue() + ((i*bd*100)/high)/100
-    return wx.Colour(r, g, b)
-
-
-def RandomColour(): 
-    """ Creates a random colour. """
-    
-    r = random.randint(0, 255) # Random value betweem 0-255
-    g = random.randint(0, 255) # Random value betweem 0-255
-    b = random.randint(0, 255) # Random value betweem 0-255
-
-    return wx.Colour(r, g, b)
-
-
-def PaintStraightGradientBox(dc, rect, startColor, endColor, vertical=True):
-    """ Draws a gradient colored box from startColor to endColor. """
-
-    rd = endColor.Red() - startColor.Red()
-    gd = endColor.Green() - startColor.Green()
-    bd = endColor.Blue() - startColor.Blue()
-
-    # Save the current pen and brush
-    savedPen = dc.GetPen()
-    savedBrush = dc.GetBrush()
-
-    if vertical:
-        high = rect.GetHeight()-1
-    else:
-        high = rect.GetWidth()-1
-
-    if high < 1:
-        return
-
-    for i in xrange(high+1):
-    
-        r = startColor.Red() + ((i*rd*100)/high)/100
-        g = startColor.Green() + ((i*gd*100)/high)/100
-        b = startColor.Blue() + ((i*bd*100)/high)/100
-
-        p = wx.Pen(wx.Colour(r, g, b))
-        dc.SetPen(p)
-
-        if vertical:
-            dc.DrawLine(rect.x, rect.y+i, rect.x+rect.width, rect.y+i)
-        else:
-            dc.DrawLine(rect.x+i, rect.y, rect.x+i, rect.y+rect.height)
-    
-    # Restore the pen and brush
-    dc.SetPen(savedPen)
-    dc.SetBrush(savedBrush)
-
-
-
-# -----------------------------------------------------------------------------
-# Util functions
-# -----------------------------------------------------------------------------
-
-def DrawButton(dc, rect, focus, upperTabs):
-
-    # Define the rounded rectangle base on the given rect
-    # we need an array of 9 points for it
-    regPts = [wx.Point() for indx in xrange(9)]
-
-    if focus:
-        if upperTabs:
-            leftPt = wx.Point(rect.x, rect.y + (rect.height / 10)*8)
-            rightPt = wx.Point(rect.x + rect.width - 2, rect.y + (rect.height / 10)*8)
-        else:
-            leftPt = wx.Point(rect.x, rect.y + (rect.height / 10)*5)
-            rightPt = wx.Point(rect.x + rect.width - 2, rect.y + (rect.height / 10)*5)
-    else:
-        leftPt = wx.Point(rect.x, rect.y + (rect.height / 2))
-        rightPt = wx.Point(rect.x + rect.width - 2, rect.y + (rect.height / 2))
-
-    # Define the top region
-    top = wx.RectPP(rect.GetTopLeft(), rightPt)
-    bottom = wx.RectPP(leftPt, rect.GetBottomRight())
-
-    topStartColor = wx.WHITE
-
-    if not focus:
-        topStartColor = LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE), 50)
-
-    topEndColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)
-    bottomStartColor = topEndColor
-    bottomEndColor = topEndColor
-
-    # Incase we use bottom tabs, switch the colors
-    if upperTabs:
-        if focus:
-            PaintStraightGradientBox(dc, top, topStartColor, topEndColor)
-            PaintStraightGradientBox(dc, bottom, bottomStartColor, bottomEndColor)
-        else:
-            PaintStraightGradientBox(dc, top, topEndColor , topStartColor)
-            PaintStraightGradientBox(dc, bottom, bottomStartColor, bottomEndColor)
-
-    else:
-        if focus:
-            PaintStraightGradientBox(dc, bottom, topEndColor, bottomEndColor)
-            PaintStraightGradientBox(dc, top,topStartColor,  topStartColor)
-        else:
-            PaintStraightGradientBox(dc, bottom, bottomStartColor, bottomEndColor)
-            PaintStraightGradientBox(dc, top, topEndColor, topStartColor)
-    
-    dc.SetBrush(wx.TRANSPARENT_BRUSH)
-
-
-# ---------------------------------------------------------------------------- #
-# Class FNBDropSource
-# Gives Some Custom UI Feedback during the DnD Operations
-# ---------------------------------------------------------------------------- #
-
-class FNBDropSource(wx.DropSource):
-    """
-    Give some custom UI feedback during the drag and drop operation in this
-    function. It is called on each mouse move, so your implementation must
-    not be too slow.
-    """
-    
-    def __init__(self, win):
-        """ Default class constructor. Used internally. """
-        
-        wx.DropSource.__init__(self, win)
-        self._win = win
-
-
-    def GiveFeedback(self, effect):
-        """ Provides user with a nice feedback when tab is being dragged. """
-
-        self._win.DrawDragHint()
-        return False
-
-
-# ---------------------------------------------------------------------------- #
-# Class FNBDragInfo
-# Stores All The Information To Allow Drag And Drop Between Different
-# FlatNotebooks.
-# ---------------------------------------------------------------------------- #
-
-class FNBDragInfo:
-
-    _map = weakref.WeakValueDictionary()
-
-    def __init__(self, container, pageindex):
-        """ Default class constructor. """
-        
-        self._id = id(container)
-        FNBDragInfo._map[self._id] = container
-        self._pageindex = pageindex
-
-
-    def GetContainer(self):
-        """ Returns the L{FlatNotebook} page (usually a panel). """
-        
-        return FNBDragInfo._map.get(self._id, None)
-
-
-    def GetPageIndex(self):
-        """ Returns the page index associated with a page. """
-
-        return self._pageindex        
-
-
-# ---------------------------------------------------------------------------- #
-# Class FNBDropTarget
-# Simply Used To Handle The OnDrop() Method When Dragging And Dropping Between
-# Different FlatNotebooks.
-# ---------------------------------------------------------------------------- #
-
-class FNBDropTarget(wx.DropTarget):
-
-    def __init__(self, parent):
-        """ Default class constructor. """
-        
-        wx.DropTarget.__init__(self)
-
-        self._parent = parent
-        self._dataobject = wx.CustomDataObject(wx.CustomDataFormat("FlatNotebook"))
-        self.SetDataObject(self._dataobject)
-
-
-    def OnData(self, x, y, dragres):
-        """ Handles the OnData() method to call the real DnD routine. """
-        
-        if not self.GetData():
-            return wx.DragNone
-
-        draginfo = self._dataobject.GetData()
-        drginfo = cPickle.loads(draginfo)
-        
-        return self._parent.OnDropTarget(x, y, drginfo.GetPageIndex(), drginfo.GetContainer())
-
-
-# ---------------------------------------------------------------------------- #
-# Class PageInfo
-# Contains parameters for every FlatNotebook page
-# ---------------------------------------------------------------------------- #
-
-class PageInfo:
-    """
-    This class holds all the information (caption, image, etc...) belonging to a
-    single tab in L{FlatNotebook}.
-    """
-    
-    def __init__(self, caption="", imageindex=-1, tabangle=0, enabled=True):
-        """
-        Default Class Constructor.
-
-        Parameters:
-        @param caption: the tab caption;
-        @param imageindex: the tab image index based on the assigned (set) wx.ImageList (if any);
-        @param tabangle: the tab angle (only on standard tabs, from 0 to 15 degrees);
-        @param enabled: sets enabled or disabled the tab.
-        """
-
-        self._strCaption = caption
-        self._TabAngle = tabangle
-        self._ImageIndex = imageindex
-        self._bEnabled = enabled
-        self._pos = wx.Point(-1, -1)
-        self._size = wx.Size(-1, -1)
-        self._region = wx.Region()
-        self._xRect = wx.Rect()
-        self._color = None
-        self._hasFocus = False
-
-
-    def SetCaption(self, value):
-        """ Sets the tab caption. """
-        
-        self._strCaption = value
-
-
-    def GetCaption(self):
-        """ Returns the tab caption. """
-
-        return self._strCaption
-
-
-    def SetPosition(self, value):
-        """ Sets the tab position. """
-
-        self._pos = value
-
-
-    def GetPosition(self):
-        """ Returns the tab position. """
-
-        return self._pos
-
-
-    def SetSize(self, value):
-        """ Sets the tab size. """
-
-        self._size = value
-
-
-    def GetSize(self):
-        """ Returns the tab size. """
-
-        return self._size
-
-
-    def SetTabAngle(self, value):
-        """ Sets the tab header angle (0 <= tab <= 15 degrees). """
-
-        self._TabAngle = min(45, value)
-
-
-    def GetTabAngle(self):
-        """ Returns the tab angle. """
-
-        return self._TabAngle
-
-    
-    def SetImageIndex(self, value):
-        """ Sets the tab image index. """
-
-        self._ImageIndex = value
-
-
-    def GetImageIndex(self):
-        """ Returns the tab umage index. """
-
-        return self._ImageIndex
-
-
-    def GetEnabled(self):
-        """ Returns whether the tab is enabled or not. """
-
-        return self._bEnabled 
-
-
-    def EnableTab(self, enabled):
-        """ Sets the tab enabled or disabled. """
-
-        self._bEnabled = enabled 
-
-
-    def SetRegion(self, points=[]):
-        """ Sets the tab region. """
-        
-        self._region = wx.RegionFromPoints(points) 
-
-
-    def GetRegion(self):
-        """ Returns the tab region. """
-
-        return self._region  
-
-
-    def SetXRect(self, xrect):
-        """ Sets the button 'X' area rect. """
-
-        self._xRect = xrect 
-
-
-    def GetXRect(self):
-        """ Returns the button 'X' area rect. """
-
-        return self._xRect 
-
-
-    def GetColour(self):
-        """ Returns the tab colour. """
-
-        return self._color 
-
-
-    def SetColour(self, color):
-        """ Sets the tab colour. """
-
-        self._color = color 
-
-
-# ---------------------------------------------------------------------------- #
-# Class FlatNotebookEvent
-# ---------------------------------------------------------------------------- #
-
-class FlatNotebookEvent(wx.PyCommandEvent):
-    """
-    This events will be sent when a EVT_FLATNOTEBOOK_PAGE_CHANGED,
-    EVT_FLATNOTEBOOK_PAGE_CHANGING, EVT_FLATNOTEBOOK_PAGE_CLOSING,
-    EVT_FLATNOTEBOOK_PAGE_CLOSED and EVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU is
-    mapped in the parent.
-    """
-        
-    def __init__(self, eventType, id=1, nSel=-1, nOldSel=-1):
-        """ Default class constructor. """
-
-        wx.PyCommandEvent.__init__(self, eventType, id)
-        self._eventType = eventType
-
-        self.notify = wx.NotifyEvent(eventType, id)
-
-
-    def GetNotifyEvent(self):
-        """Returns the actual wx.NotifyEvent."""
-        
-        return self.notify
-
-
-    def IsAllowed(self):
-        """Returns whether the event is allowed or not."""
-
-        return self.notify.IsAllowed()
-
-
-    def Veto(self):
-        """Vetos the event."""
-
-        self.notify.Veto()
-
-
-    def Allow(self):
-        """The event is allowed."""
-
-        self.notify.Allow()
-
-
-    def SetSelection(self, nSel):
-        """ Sets event selection. """
-        
-        self._selection = nSel
-        
-
-    def SetOldSelection(self, nOldSel):
-        """ Sets old event selection. """
-        
-        self._oldselection = nOldSel
-
-
-    def GetSelection(self):
-        """ Returns event selection. """
-        
-        return self._selection
-        
-
-    def GetOldSelection(self):
-        """ Returns old event selection """
-        
-        return self._oldselection
-
-
-# ---------------------------------------------------------------------------- #
-# Class TabNavigatorWindow
-# ---------------------------------------------------------------------------- #
-
-class TabNavigatorWindow(wx.Dialog):
-    """
-    This class is used to create a modal dialog that enables "Smart Tabbing",
-    similar to what you would get by hitting Alt+Tab on Windows.
-    """
-
-    def __init__(self, parent=None, icon=None):
-        """ Default class constructor. Used internally."""
-
-        wx.Dialog.__init__(self, parent, wx.ID_ANY, "", style=0)
-
-        self._selectedItem = -1
-        self._indexMap = []
-        
-        if icon is None:
-            self._bmp = GetMondrianBitmap()
-        else:
-            self._bmp = icon
-
-        sz = wx.BoxSizer(wx.VERTICAL)
-        
-        self._listBox = wx.ListBox(self, wx.ID_ANY, wx.DefaultPosition, wx.Size(200, 150), [], wx.LB_SINGLE | wx.NO_BORDER)
-        
-        mem_dc = wx.MemoryDC()
-        mem_dc.SelectObject(wx.EmptyBitmap(1,1))
-        font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
-        font.SetWeight(wx.BOLD)
-        mem_dc.SetFont(font)
-
-        panelHeight = mem_dc.GetCharHeight()
-        panelHeight += 4 # Place a spacer of 2 pixels
-
-        # Out signpost bitmap is 24 pixels
-        if panelHeight < 24:
-            panelHeight = 24
-        
-        self._panel = wx.Panel(self, wx.ID_ANY, wx.DefaultPosition, wx.Size(200, panelHeight))
-
-        sz.Add(self._panel)
-        sz.Add(self._listBox, 1, wx.EXPAND)
-        
-        self.SetSizer(sz)
-
-        # Connect events to the list box
-        self._listBox.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
-        self._listBox.Bind(wx.EVT_NAVIGATION_KEY, self.OnNavigationKey)
-        self._listBox.Bind(wx.EVT_LISTBOX_DCLICK, self.OnItemSelected)
-        
-        # Connect paint event to the panel
-        self._panel.Bind(wx.EVT_PAINT, self.OnPanelPaint)
-        self._panel.Bind(wx.EVT_ERASE_BACKGROUND, self.OnPanelEraseBg)
-
-        self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))
-        self._listBox.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))
-        self.PopulateListControl(parent)
-        
-        self.GetSizer().Fit(self)
-        self.GetSizer().SetSizeHints(self)
-        self.GetSizer().Layout()
-        self.Centre()
-
-        # Set focus on the list box to avoid having to click on it to change
-        # the tab selection under GTK.
-        self._listBox.SetFocus()
-
-
-    def OnKeyUp(self, event):
-        """Handles the wx.EVT_KEY_UP for the L{TabNavigatorWindow}."""
-        
-        if event.GetKeyCode() == wx.WXK_CONTROL:
-            self.CloseDialog()
-
-
-    def OnNavigationKey(self, event):
-        """Handles the wx.EVT_NAVIGATION_KEY for the L{TabNavigatorWindow}. """
-
-        selected = self._listBox.GetSelection()
-        bk = self.GetParent()
-        maxItems = bk.GetPageCount()
-            
-        if event.GetDirection():
-        
-            # Select next page
-            if selected == maxItems - 1:
-                itemToSelect = 0
-            else:
-                itemToSelect = selected + 1
-        
-        else:
-        
-            # Previous page
-            if selected == 0:
-                itemToSelect = maxItems - 1
-            else:
-                itemToSelect = selected - 1
-        
-        self._listBox.SetSelection(itemToSelect)
-
-
-    def PopulateListControl(self, book):
-        """Populates the L{TabNavigatorWindow} listbox with a list of tabs."""
-
-        selection = book.GetSelection()
-        count = book.GetPageCount()
-        
-        self._listBox.Append(book.GetPageText(selection))
-        self._indexMap.append(selection)
-        
-        prevSel = book.GetPreviousSelection()
-        
-        if prevSel != wx.NOT_FOUND:
-        
-            # Insert the previous selection as second entry 
-            self._listBox.Append(book.GetPageText(prevSel))
-            self._indexMap.append(prevSel)
-        
-        for c in xrange(count):
-        
-            # Skip selected page
-            if c == selection:
-                continue
-
-            # Skip previous selected page as well
-            if c == prevSel:
-                continue
-
-            self._listBox.Append(book.GetPageText(c))
-            self._indexMap.append(c)
-
-        # Select the next entry after the current selection
-        self._listBox.SetSelection(0)
-        dummy = wx.NavigationKeyEvent()
-        dummy.SetDirection(True)
-        self.OnNavigationKey(dummy)
-
-
-    def OnItemSelected(self, event):
-        """Handles the wx.EVT_LISTBOX_DCLICK event for the wx.ListBox inside L{TabNavigatorWindow}. """
-
-        self.CloseDialog()
-
-
-    def CloseDialog(self):
-        """Closes the L{TabNavigatorWindow} dialog, setting selection in L{FlatNotebook}."""
-
-        bk = self.GetParent()
-        self._selectedItem = self._listBox.GetSelection()
-        iter = self._indexMap[self._selectedItem]
-        self.EndModal(wx.ID_OK)
-        wx.CallAfter(bk._pages.FireEvent, iter)
-        self.Destroy()
-        
-
-    def OnPanelPaint(self, event):
-        """Handles the wx.EVT_PAINT event for L{TabNavigatorWindow} top panel. """
-
-        dc = wx.PaintDC(self._panel)
-        rect = self._panel.GetClientRect()
-
-        bmp = wx.EmptyBitmap(rect.width, rect.height)
-
-        mem_dc = wx.MemoryDC()
-        mem_dc.SelectObject(bmp)
-
-        endColour = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)
-        startColour = LightColour(endColour, 50)
-        PaintStraightGradientBox(mem_dc, rect, startColour, endColour)
-
-        # Draw the caption title and place the bitmap
-        # get the bitmap optimal position, and draw it
-        bmpPt, txtPt = wx.Point(), wx.Point()
-        bmpPt.y = (rect.height - self._bmp.GetHeight())/2
-        bmpPt.x = 3
-        mem_dc.DrawBitmap(self._bmp, bmpPt.x, bmpPt.y, True)
-
-        # get the text position, and draw it
-        font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
-        font.SetWeight(wx.BOLD)
-        mem_dc.SetFont(font)
-        fontHeight = mem_dc.GetCharHeight()
-        
-        txtPt.x = bmpPt.x + self._bmp.GetWidth() + 4
-        txtPt.y = (rect.height - fontHeight)/2
-        mem_dc.SetTextForeground(wx.WHITE)
-        mem_dc.DrawText("Opened tabs:", txtPt.x, txtPt.y)
-        mem_dc.SelectObject(wx.NullBitmap)
-        
-        dc.DrawBitmap(bmp, 0, 0)
-
-
-    def OnPanelEraseBg(self, event):
-        """Handles the wx.EVT_ERASE_BACKGROUND event for L{TabNavigatorWindow} top panel. """
-
-        pass
-
-
-# ---------------------------------------------------------------------------- #
-# Class FNBRenderer
-# ---------------------------------------------------------------------------- #
-
-class FNBRenderer:
-    """
-    Parent class for the 4 renderers defined: I{Standard}, I{VC71}, I{Fancy}
-    and I{VC8}. This class implements the common methods of all 4 renderers.
-    """
-
-    def __init__(self):
-        """Default class constructor. """
-        
-        self._tabHeight = None
-
-        if wx.Platform == "__WXMAC__":
-            # Hack to get proper highlight color for focus rectangle from
-            # current theme by creating a theme brush and getting its color.
-            # kThemeBrushFocusHighlight is available on Mac OS 8.5 and higher
-            brush = wx.BLACK_BRUSH
-            brush.MacSetTheme(Carbon.Appearance.kThemeBrushFocusHighlight)
-            self._focusPen = wx.Pen(brush.GetColour(), 2, wx.SOLID)
-        else:
-            self._focusPen = wx.Pen(wx.BLACK, 1, wx.USER_DASH)
-            self._focusPen.SetDashes([1, 1])
-            self._focusPen.SetCap(wx.CAP_BUTT)
-
-
-    def GetLeftButtonPos(self, pageContainer):
-        """ Returns the left button position in the navigation area. """
-
-        pc = pageContainer
-        style = pc.GetParent().GetWindowStyleFlag()
-        rect = pc.GetClientRect()
-        clientWidth = rect.width
-        
-        if style & FNB_NO_X_BUTTON and (style & FNB_DROPDOWN_TABS_LIST != FNB_DROPDOWN_TABS_LIST):
-            return clientWidth - 38
-        else:
-            return clientWidth - 54
-
-
-    def GetRightButtonPos(self, pageContainer):
-        """ Returns the right button position in the navigation area. """
-
-        pc = pageContainer
-        style = pc.GetParent().GetWindowStyleFlag()
-        rect = pc.GetClientRect()
-        clientWidth = rect.width
-        
-        if style & FNB_NO_X_BUTTON and (style & FNB_DROPDOWN_TABS_LIST != FNB_DROPDOWN_TABS_LIST):
-            return clientWidth - 22
-        else:
-            return clientWidth - 38
-
-
-    def GetDropArrowButtonPos(self, pageContainer):
-        """ Returns the drop down button position in the navigation area. """
-
-        pc = pageContainer
-        style = pc.GetParent().GetWindowStyleFlag()
-        rect = pc.GetClientRect()
-        clientWidth = rect.width
-
-        if style & FNB_DROPDOWN_TABS_LIST != FNB_DROPDOWN_TABS_LIST:
-            return clientWidth
-        else:
-            return clientWidth - 22
-
-
-    def GetXPos(self, pageContainer):
-        """ Returns the 'X' button position in the navigation area. """
-
-        pc = pageContainer
-        style = pc.GetParent().GetWindowStyleFlag()
-        rect = pc.GetClientRect()
-        clientWidth = rect.width
-        
-        if style & FNB_NO_X_BUTTON:
-            return clientWidth
-        else:
-            return clientWidth - 22
-
-
-    def GetButtonsAreaLength(self, pageContainer):
-        """ Returns the navigation area width. """
-
-        pc = pageContainer
-        style = pc.GetParent().GetWindowStyleFlag()
-
-        # ''
-        if style & FNB_NO_NAV_BUTTONS and style & FNB_NO_X_BUTTON and not style & FNB_DROPDOWN_TABS_LIST:
-            return 0
-
-        # 'x'        
-        elif style & FNB_NO_NAV_BUTTONS and not style & FNB_NO_X_BUTTON and not style & FNB_DROPDOWN_TABS_LIST:
-            return 22
-        
-        # '<>'
-        if not style & FNB_NO_NAV_BUTTONS and style & FNB_NO_X_BUTTON and not style & FNB_DROPDOWN_TABS_LIST:
-            return 53 - 16
-        
-        # 'vx'
-        if style & FNB_DROPDOWN_TABS_LIST and not style & FNB_NO_X_BUTTON:
-            return 22 + 16
-
-        # 'v'
-        if style & FNB_DROPDOWN_TABS_LIST and style & FNB_NO_X_BUTTON and style & FNB_NO_NAV_BUTTONS:
-            return 22
-
-        # '<>v'
-        if style & FNB_DROPDOWN_TABS_LIST and style & FNB_NO_X_BUTTON and not style & FNB_NO_NAV_BUTTONS:
-            return 53
-        
-        # '<>x'
-        return 53
-
-
-    def DrawArrowAccordingToState(self, dc, pc, rect):
-
-        lightFactor = (pc.HasFlag(FNB_BACKGROUND_GRADIENT) and [70] or [0])[0]
-        PaintStraightGradientBox(dc, rect, pc._tabAreaColor, LightColour(pc._tabAreaColor, lightFactor))
-
-    
-    def DrawLeftArrow(self, pageContainer, dc):
-        """ Draw the left navigation arrow. """
-
-        pc = pageContainer
-        
-        style = pc.GetParent().GetWindowStyleFlag()
-        if style & FNB_NO_NAV_BUTTONS:
-            return
-
-        # Make sure that there are pages in the container
-        if not pc._pagesInfoVec:
-            return
-
-        # Set the bitmap according to the button status
-        if pc._nLeftButtonStatus == FNB_BTN_HOVER:
-            arrowBmp = wx.BitmapFromXPMData(left_arrow_hilite_xpm)
-        elif pc._nLeftButtonStatus == FNB_BTN_PRESSED:
-            arrowBmp = wx.BitmapFromXPMData(left_arrow_pressed_xpm)
-        else:
-            arrowBmp = wx.BitmapFromXPMData(left_arrow_xpm)
-
-        if pc._nFrom == 0:
-            # Handle disabled arrow
-            arrowBmp = wx.BitmapFromXPMData(left_arrow_disabled_xpm)
-        
-        arrowBmp.SetMask(wx.Mask(arrowBmp, MASK_COLOR))
-
-        # Erase old bitmap
-        posx = self.GetLeftButtonPos(pc)
-        self.DrawArrowAccordingToState(dc, pc, wx.Rect(posx, 6, 16, 14))
-        
-        # Draw the new bitmap
-        dc.DrawBitmap(arrowBmp, posx, 6, True)
-
-
-    def DrawRightArrow(self, pageContainer, dc):
-        """ Draw the right navigation arrow. """
-
-        pc = pageContainer
-        
-        style = pc.GetParent().GetWindowStyleFlag()
-        if style & FNB_NO_NAV_BUTTONS:
-            return
-
-        # Make sure that there are pages in the container
-        if not pc._pagesInfoVec:
-            return
-
-        # Set the bitmap according to the button status
-        if pc._nRightButtonStatus == FNB_BTN_HOVER:        
-            arrowBmp = wx.BitmapFromXPMData(right_arrow_hilite_xpm)
-        elif pc._nRightButtonStatus == FNB_BTN_PRESSED:
-            arrowBmp = wx.BitmapFromXPMData(right_arrow_pressed_xpm)
-        else:
-            arrowBmp = wx.BitmapFromXPMData(right_arrow_xpm)
-
-        # Check if the right most tab is visible, if it is
-        # don't rotate right anymore
-        if pc._pagesInfoVec[-1].GetPosition() != wx.Point(-1, -1):
-            arrowBmp = wx.BitmapFromXPMData(right_arrow_disabled_xpm)
-        
-        arrowBmp.SetMask(wx.Mask(arrowBmp, MASK_COLOR))
-
-        # erase old bitmap
-        posx = self.GetRightButtonPos(pc)
-        self.DrawArrowAccordingToState(dc, pc, wx.Rect(posx, 6, 16, 14))
-
-        # Draw the new bitmap
-        dc.DrawBitmap(arrowBmp, posx, 6, True)
-
-
-    def DrawDropDownArrow(self, pageContainer, dc):
-        """ Draws the drop-down arrow in the navigation area. """
-
-        pc = pageContainer
-        
-        # Check if this style is enabled
-        style = pc.GetParent().GetWindowStyleFlag()
-        if not style & FNB_DROPDOWN_TABS_LIST:
-            return
-
-        # Make sure that there are pages in the container
-        if not pc._pagesInfoVec:
-            return
-
-        if pc._nArrowDownButtonStatus == FNB_BTN_HOVER:
-            downBmp = wx.BitmapFromXPMData(down_arrow_hilite_xpm)
-        elif pc._nArrowDownButtonStatus == FNB_BTN_PRESSED:
-            downBmp = wx.BitmapFromXPMData(down_arrow_pressed_xpm)
-        else:
-            downBmp = wx.BitmapFromXPMData(down_arrow_xpm)
-
-        downBmp.SetMask(wx.Mask(downBmp, MASK_COLOR))
-
-        # erase old bitmap
-        posx = self.GetDropArrowButtonPos(pc)
-        self.DrawArrowAccordingToState(dc, pc, wx.Rect(posx, 6, 16, 14))
-
-        # Draw the new bitmap
-        dc.DrawBitmap(downBmp, posx, 6, True)
-
-
-    def DrawX(self, pageContainer, dc):
-        """ Draw the 'X' navigation button in the navigation area. """
-
-        pc = pageContainer
-        
-        # Check if this style is enabled
-        style = pc.GetParent().GetWindowStyleFlag()
-        if style & FNB_NO_X_BUTTON:
-            return
-
-        # Make sure that there are pages in the container
-        if not pc._pagesInfoVec:
-            return
-
-        # Set the bitmap according to the button status
-        if pc._nXButtonStatus == FNB_BTN_HOVER:
-            xbmp = wx.BitmapFromXPMData(x_button_hilite_xpm)
-        elif pc._nXButtonStatus == FNB_BTN_PRESSED:
-            xbmp = wx.BitmapFromXPMData(x_button_pressed_xpm)
-        else:
-            xbmp = wx.BitmapFromXPMData(x_button_xpm)
-
-        xbmp.SetMask(wx.Mask(xbmp, MASK_COLOR))
-        
-        # erase old bitmap
-        posx = self.GetXPos(pc) 
-        self.DrawArrowAccordingToState(dc, pc, wx.Rect(posx, 6, 16, 14))
-
-        # Draw the new bitmap
-        dc.DrawBitmap(xbmp, posx, 6, True)
-
-
-    def DrawTabX(self, pageContainer, dc, rect, tabIdx, btnStatus):
-        """ Draws the 'X' in the selected tab. """
-
-        pc = pageContainer
-        if not pc.HasFlag(FNB_X_ON_TAB):
-            return
-
-        # We draw the 'x' on the active tab only
-        if tabIdx != pc.GetSelection() or tabIdx < 0:
-            return
-
-        # Set the bitmap according to the button status
-        
-        if btnStatus == FNB_BTN_HOVER:
-            xBmp = wx.BitmapFromXPMData(x_button_hilite_xpm)
-        elif btnStatus == FNB_BTN_PRESSED:
-            xBmp = wx.BitmapFromXPMData(x_button_pressed_xpm)
-        else:
-            xBmp = wx.BitmapFromXPMData(x_button_xpm)
-
-        # Set the masking
-        xBmp.SetMask(wx.Mask(xBmp, MASK_COLOR))
-
-        # Draw the new bitmap
-        dc.DrawBitmap(xBmp, rect.x, rect.y, True)
-
-        # Update the vector
-        rr = wx.Rect(rect.x, rect.y, 14, 13)
-        pc._pagesInfoVec[tabIdx].SetXRect(rr)
-
-
-    def DrawTabsLine(self, pageContainer, dc, selTabX1=-1, selTabX2=-1):
-        """ Draws a line over the tabs. """
-
-        pc = pageContainer
-        
-        clntRect = pc.GetClientRect()
-        clientRect3 = wx.Rect(0, 0, clntRect.width, clntRect.height)
-
-        if pc.HasFlag(FNB_FF2):
-            if not pc.HasFlag(FNB_BOTTOM):
-                fillColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)
-            else:
-                fillColor = wx.WHITE
-
-            dc.SetPen(wx.Pen(fillColor))
-
-            if pc.HasFlag(FNB_BOTTOM):
-
-                dc.DrawLine(1, 0, clntRect.width-1, 0)
-                dc.DrawLine(1, 1, clntRect.width-1, 1)
-
-                dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)))
-                dc.DrawLine(1, 2, clntRect.width-1, 2)
-
-                dc.SetPen(wx.Pen(fillColor))
-                dc.DrawLine(selTabX1 + 2, 2, selTabX2 - 1, 2)
-                
-            else:
-                
-                dc.DrawLine(1, clntRect.height, clntRect.width-1, clntRect.height)
-                dc.DrawLine(1, clntRect.height-1, clntRect.width-1, clntRect.height-1)
-
-                dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)))
-                dc.DrawLine(1, clntRect.height-2, clntRect.width-1, clntRect.height-2)
-
-                dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)))
-                dc.DrawLine(selTabX1 + 2, clntRect.height-2, selTabX2-1, clntRect.height-2)
-
-        else:
-            
-            if pc.HasFlag(FNB_BOTTOM):
-            
-                clientRect = wx.Rect(0, 2, clntRect.width, clntRect.height - 2)
-                clientRect2 = wx.Rect(0, 1, clntRect.width, clntRect.height - 1)
-            
-            else:
-            
-                clientRect = wx.Rect(0, 0, clntRect.width, clntRect.height - 2)
-                clientRect2 = wx.Rect(0, 0, clntRect.width, clntRect.height - 1)
-            
-            dc.SetBrush(wx.TRANSPARENT_BRUSH)
-            dc.SetPen(wx.Pen(pc.GetSingleLineBorderColour()))
-            dc.DrawRectangleRect(clientRect2)
-            dc.DrawRectangleRect(clientRect3)
-
-            dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)))
-            dc.DrawRectangleRect(clientRect)
-
-            if not pc.HasFlag(FNB_TABS_BORDER_SIMPLE):
-            
-                dc.SetPen(wx.Pen((pc.HasFlag(FNB_VC71) and [wx.Colour(247, 243, 233)] or [pc._tabAreaColor])[0]))
-                dc.DrawLine(0, 0, 0, clientRect.height+1)
-                
-                if pc.HasFlag(FNB_BOTTOM):
-                
-                    dc.DrawLine(0, clientRect.height+1, clientRect.width, clientRect.height+1)
-                
-                else:
-                    
-                    dc.DrawLine(0, 0, clientRect.width, 0)
-                    
-                dc.DrawLine(clientRect.width - 1, 0, clientRect.width - 1, clientRect.height+1)
-
-
-    def CalcTabWidth(self, pageContainer, tabIdx, tabHeight):
-        """ Calculates the width of the input tab. """
-
-        pc = pageContainer
-        dc = wx.MemoryDC()
-        dc.SelectObject(wx.EmptyBitmap(1,1))
-
-        boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
-        boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
-
-        if pc.IsDefaultTabs():
-            shapePoints = int(tabHeight*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi))
-
-        # Calculate the text length using the bold font, so when selecting a tab
-        # its width will not change
-        dc.SetFont(boldFont)
-        width, pom = dc.GetTextExtent(pc.GetPageText(tabIdx))
-
-        # Set a minimum size to a tab
-        if width < 20:
-            width = 20
-
-        tabWidth = 2*pc._pParent.GetPadding() + width
-
-        # Style to add a small 'x' button on the top right
-        # of the tab
-        if pc.HasFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection():
-            # The xpm image that contains the 'x' button is 9 pixels
-            spacer = 9
-            if pc.HasFlag(FNB_VC8):
-                spacer = 4
-
-            tabWidth += pc._pParent.GetPadding() + spacer
-        
-        if pc.IsDefaultTabs():
-            # Default style
-            tabWidth += 2*shapePoints
-
-        hasImage = pc._ImageList != None and pc._pagesInfoVec[tabIdx].GetImageIndex() != -1
-
-        # For VC71 style, we only add the icon size (16 pixels)
-        if hasImage:
-        
-            if not pc.IsDefaultTabs():
-                tabWidth += 16 + pc._pParent.GetPadding()
-            else:
-                # Default style
-                tabWidth += 16 + pc._pParent.GetPadding() + shapePoints/2
-        
-        return tabWidth
-
-
-    def CalcTabHeight(self, pageContainer):
-        """ Calculates the height of the input tab. """
-
-        if self._tabHeight:
-            return self._tabHeight
-
-        pc = pageContainer
-        dc = wx.MemoryDC()
-        dc.SelectObject(wx.EmptyBitmap(1,1))
-
-        # For GTK it seems that we must do this steps in order
-        # for the tabs will get the proper height on initialization
-        # on MSW, preforming these steps yields wierd results
-        normalFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
-        boldFont = normalFont
-
-        if "__WXGTK__" in wx.PlatformInfo:
-            boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
-            dc.SetFont(boldFont)
-
-        height = dc.GetCharHeight()
-        
-        tabHeight = height + FNB_HEIGHT_SPACER # We use 8 pixels as padding
-        if "__WXGTK__" in wx.PlatformInfo:
-            # On GTK the tabs are should be larger
-            tabHeight += 6
-
-        self._tabHeight = tabHeight
-        
-        return tabHeight
-
-
-    def DrawTabs(self, pageContainer, dc):
-        """ Actually draws the tabs in L{FlatNotebook}."""
-
-        pc = pageContainer
-        if "__WXMAC__" in wx.PlatformInfo:
-            # Works well on MSW & GTK, however this lines should be skipped on MAC
-            if not pc._pagesInfoVec or pc._nFrom >= len(pc._pagesInfoVec):
-                pc.Hide()
-                return
-            
-        # Get the text hight
-        tabHeight = self.CalcTabHeight(pageContainer)
-        style = pc.GetParent().GetWindowStyleFlag()
-
-        # Calculate the number of rows required for drawing the tabs
-        rect = pc.GetClientRect()
-        clientWidth = rect.width
-
-        # Set the maximum client size
-        pc.SetSizeHints(self.GetButtonsAreaLength(pc), tabHeight)
-        borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
-
-        if style & FNB_VC71:
-            backBrush = wx.Brush(wx.Colour(247, 243, 233))
-        else:
-            backBrush = wx.Brush(pc._tabAreaColor)
-
-        noselBrush = wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE))
-        selBrush = wx.Brush(pc._activeTabColor)
-
-        size = pc.GetSize()
-
-        # Background
-        dc.SetTextBackground((style & FNB_VC71 and [wx.Colour(247, 243, 233)] or [pc.GetBackgroundColour()])[0])
-        dc.SetTextForeground(pc._activeTextColor)
-        dc.SetBrush(backBrush)
-
-        # If border style is set, set the pen to be border pen
-        if pc.HasFlag(FNB_TABS_BORDER_SIMPLE):
-            dc.SetPen(borderPen)
-        else:
-            colr = (pc.HasFlag(FNB_VC71) and [wx.Colour(247, 243, 233)] or [pc.GetBackgroundColour()])[0]
-            dc.SetPen(wx.Pen(colr))
-
-        if pc.HasFlag(FNB_FF2):
-            lightFactor = (pc.HasFlag(FNB_BACKGROUND_GRADIENT) and [70] or [0])[0]
-            PaintStraightGradientBox(dc, pc.GetClientRect(), pc._tabAreaColor, LightColour(pc._tabAreaColor, lightFactor))
-            dc.SetBrush(wx.TRANSPARENT_BRUSH)
-
-        dc.DrawRectangle(0, 0, size.x, size.y)
-
-        # We always draw the bottom/upper line of the tabs
-        # regradless the style
-        dc.SetPen(borderPen)
-
-        if not pc.HasFlag(FNB_FF2):
-            self.DrawTabsLine(pc, dc)
-
-        # Restore the pen
-        dc.SetPen(borderPen)
-
-        if pc.HasFlag(FNB_VC71):
-        
-            greyLineYVal  = (pc.HasFlag(FNB_BOTTOM) and [0] or [size.y - 2])[0]
-            whiteLineYVal = (pc.HasFlag(FNB_BOTTOM) and [3] or [size.y - 3])[0]
-
-            pen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))
-            dc.SetPen(pen)
-
-            # Draw thik grey line between the windows area and
-            # the tab area
-            for num in xrange(3):
-                dc.DrawLine(0, greyLineYVal + num, size.x, greyLineYVal + num)
-
-            wbPen = (pc.HasFlag(FNB_BOTTOM) and [wx.BLACK_PEN] or [wx.WHITE_PEN])[0]
-            dc.SetPen(wbPen)
-            dc.DrawLine(1, whiteLineYVal, size.x - 1, whiteLineYVal)
-
-            # Restore the pen
-            dc.SetPen(borderPen)
-        
-        # Draw labels
-        normalFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
-        boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
-        boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
-        dc.SetFont(boldFont)
-
-        posx = pc._pParent.GetPadding()
-
-        # Update all the tabs from 0 to 'pc._nFrom' to be non visible
-        for i in xrange(pc._nFrom):
-        
-            pc._pagesInfoVec[i].SetPosition(wx.Point(-1, -1))
-            pc._pagesInfoVec[i].GetRegion().Clear()
-
-        count = pc._nFrom
-        
-        #----------------------------------------------------------
-        # Go over and draw the visible tabs
-        #----------------------------------------------------------
-        x1 = x2 = -1
-        for i in xrange(pc._nFrom, len(pc._pagesInfoVec)):
-        
-            dc.SetPen(borderPen)
-
-            if not pc.HasFlag(FNB_FF2):
-                dc.SetBrush((i==pc.GetSelection() and [selBrush] or [noselBrush])[0])
-
-            # Now set the font to the correct font
-            dc.SetFont((i==pc.GetSelection() and [boldFont] or [normalFont])[0])
-
-            # Add the padding to the tab width
-            # Tab width:
-            # +-----------------------------------------------------------+
-            # | PADDING | IMG | IMG_PADDING | TEXT | PADDING | x |PADDING |
-            # +-----------------------------------------------------------+
-            tabWidth = self.CalcTabWidth(pageContainer, i, tabHeight)
-
-            # Check if we can draw more
-            if posx + tabWidth + self.GetButtonsAreaLength(pc) >= clientWidth:
-                break
-
-            count = count + 1
-            
-            # By default we clean the tab region
-            pc._pagesInfoVec[i].GetRegion().Clear()
-
-            # Clean the 'x' buttn on the tab.
-            # A 'Clean' rectangle, is a rectangle with width or height
-            # with values lower than or equal to 0
-            pc._pagesInfoVec[i].GetXRect().SetSize(wx.Size(-1, -1))
-
-            # Draw the tab (border, text, image & 'x' on tab)
-            self.DrawTab(pc, dc, posx, i, tabWidth, tabHeight, pc._nTabXButtonStatus)
-
-            if pc.GetSelection() == i:
-                x1 = posx
-                x2 = posx + tabWidth + 2
-
-            # Restore the text forground
-            dc.SetTextForeground(pc._activeTextColor)
-
-            # Update the tab position & size
-            posy = (pc.HasFlag(FNB_BOTTOM) and [0] or [VERTICAL_BORDER_PADDING])[0]
-
-            pc._pagesInfoVec[i].SetPosition(wx.Point(posx, posy))
-            pc._pagesInfoVec[i].SetSize(wx.Size(tabWidth, tabHeight))
-            self.DrawFocusRectangle(dc, pc, pc._pagesInfoVec[i])
-
-            posx += tabWidth
-        
-        # Update all tabs that can not fit into the screen as non-visible
-        for i in xrange(count, len(pc._pagesInfoVec)):
-            pc._pagesInfoVec[i].SetPosition(wx.Point(-1, -1))
-            pc._pagesInfoVec[i].GetRegion().Clear()
-        
-        # Draw the left/right/close buttons
-        # Left arrow
-        self.DrawLeftArrow(pc, dc)
-        self.DrawRightArrow(pc, dc)
-        self.DrawX(pc, dc)
-        self.DrawDropDownArrow(pc, dc)
-
-        if pc.HasFlag(FNB_FF2):
-            self.DrawTabsLine(pc, dc, x1, x2)
-
-
-    def DrawFocusRectangle(self, dc, pageContainer, page):
-        """ Draws a focus rectangle like the native Notebooks. """
-        
-        if not page._hasFocus:
-            return
-
-        tabPos = wx.Point(*page.GetPosition())
-        if pageContainer.GetParent().GetWindowStyleFlag() & FNB_VC8:
-            vc8ShapeLen = self.CalcTabHeight(pageContainer) - VERTICAL_BORDER_PADDING - 2
-            tabPos.x += vc8ShapeLen
-            
-        rect = wx.RectPS(tabPos, page.GetSize())
-        rect = wx.Rect(rect.x+2, rect.y+2, rect.width-4, rect.height-8)
-
-        if wx.Platform == '__WXMAC__':
-            rect.SetWidth(rect.GetWidth() + 1)
-
-        dc.SetBrush(wx.TRANSPARENT_BRUSH)
-        dc.SetPen(self._focusPen)
-        dc.DrawRoundedRectangleRect(rect, 2)
-        
-
-    def DrawDragHint(self, pc, tabIdx):
-        """
-        Draws tab drag hint, the default implementation is to do nothing.
-        You can override this function to provide a nice feedback to user.
-        """
-        
-        pass
-
-
-    def NumberTabsCanFit(self, pageContainer, fr=-1):
-
-        pc = pageContainer
-        
-        rect = pc.GetClientRect()
-        clientWidth = rect.width
-
-        vTabInfo = []
-
-        tabHeight = self.CalcTabHeight(pageContainer)
-
-        # The drawing starts from posx 
-        posx = pc._pParent.GetPadding()
-
-        if fr < 0:
-            fr = pc._nFrom
-
-        for i in xrange(fr, len(pc._pagesInfoVec)):
-
-            tabWidth = self.CalcTabWidth(pageContainer, i, tabHeight) 
-            if posx + tabWidth + self.GetButtonsAreaLength(pc) >= clientWidth:
-                break; 
-
-            # Add a result to the returned vector 
-            tabRect = wx.Rect(posx, VERTICAL_BORDER_PADDING, tabWidth , tabHeight)
-            vTabInfo.append(tabRect)
-
-            # Advance posx 
-            posx += tabWidth + FNB_HEIGHT_SPACER
-
-        return vTabInfo
-
-    
-# ---------------------------------------------------------------------------- #
-# Class FNBRendererMgr
-# A manager that handles all the renderers defined below and calls the
-# appropriate one when drawing is needed
-# ---------------------------------------------------------------------------- #
-
-class FNBRendererMgr:
-    """
-    This class represents a manager that handles all the 4 renderers defined
-    and calls the appropriate one when drawing is needed.
-    """
-
-    def __init__(self):
-        """ Default class constructor. """
-        
-        # register renderers
-
-        self._renderers = {}        
-        self._renderers.update({-1: FNBRendererDefault()})
-        self._renderers.update({FNB_VC71: FNBRendererVC71()})
-        self._renderers.update({FNB_FANCY_TABS: FNBRendererFancy()})
-        self._renderers.update({FNB_VC8: FNBRendererVC8()})
-        self._renderers.update({FNB_FF2: FNBRendererFirefox2()})
-
-
-    def GetRenderer(self, style):
-        """ Returns the current renderer based on the style selected. """
-
-        if style & FNB_VC71:
-            return self._renderers[FNB_VC71]
-
-        if style & FNB_FANCY_TABS:
-            return self._renderers[FNB_FANCY_TABS]
-
-        if style & FNB_VC8:
-            return self._renderers[FNB_VC8]
-
-        if style & FNB_FF2:
-            return self._renderers[FNB_FF2]
-
-        # the default is to return the default renderer
-        return self._renderers[-1]
-
-
-#------------------------------------------
-# Default renderer 
-#------------------------------------------
-
-class FNBRendererDefault(FNBRenderer):
-    """
-    This class handles the drawing of tabs using the I{Standard} renderer.
-    """
-    
-    def __init__(self):
-        """ Default class constructor. """
-
-        FNBRenderer.__init__(self)
-        
-
-    def DrawTab(self, pageContainer, dc, posx, tabIdx, tabWidth, tabHeight, btnStatus):
-        """ Draws a tab using the I{Standard} style. """
-
-        # Default style
-        borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
-        pc = pageContainer 
-
-        tabPoints = [wx.Point() for ii in xrange(7)]
-        tabPoints[0].x = posx
-        tabPoints[0].y = (pc.HasFlag(FNB_BOTTOM) and [2] or [tabHeight - 2])[0]
-
-        tabPoints[1].x = int(posx+(tabHeight-2)*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi))
-        tabPoints[1].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - (VERTICAL_BORDER_PADDING+2)] or [(VERTICAL_BORDER_PADDING+2)])[0]
-
-        tabPoints[2].x = tabPoints[1].x+2
-        tabPoints[2].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0]
-
-        tabPoints[3].x = int(posx+tabWidth-(tabHeight-2)*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi))-2
-        tabPoints[3].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0]
-
-        tabPoints[4].x = tabPoints[3].x+2
-        tabPoints[4].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - (VERTICAL_BORDER_PADDING+2)] or [(VERTICAL_BORDER_PADDING+2)])[0]
-
-        tabPoints[5].x = int(tabPoints[4].x+(tabHeight-2)*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi))
-        tabPoints[5].y = (pc.HasFlag(FNB_BOTTOM) and [2] or [tabHeight - 2])[0]
-
-        tabPoints[6].x = tabPoints[0].x
-        tabPoints[6].y = tabPoints[0].y
-        
-        if tabIdx == pc.GetSelection():
-        
-            # Draw the tab as rounded rectangle
-            dc.DrawPolygon(tabPoints)
-        
-        else:
-        
-            if tabIdx != pc.GetSelection() - 1:
-            
-                # Draw a vertical line to the right of the text
-                pt1x = tabPoints[5].x
-                pt1y = (pc.HasFlag(FNB_BOTTOM) and [4] or [tabHeight - 6])[0]
-                pt2x = tabPoints[5].x
-                pt2y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - 4] or [4])[0]
-                dc.DrawLine(pt1x, pt1y, pt2x, pt2y)
-
-        if tabIdx == pc.GetSelection():
-        
-            savePen = dc.GetPen()
-            whitePen = wx.Pen(wx.WHITE)
-            whitePen.SetWidth(1)
-            dc.SetPen(whitePen)
-
-            secPt = wx.Point(tabPoints[5].x + 1, tabPoints[5].y)
-            dc.DrawLine(tabPoints[0].x, tabPoints[0].y, secPt.x, secPt.y)
-
-            # Restore the pen
-            dc.SetPen(savePen)
-        
-        # -----------------------------------
-        # Text and image drawing
-        # -----------------------------------
-
-        # Text drawing offset from the left border of the
-        # rectangle
-        
-        # The width of the images are 16 pixels
-        padding = pc.GetParent().GetPadding()
-        shapePoints = int(tabHeight*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi))
-        hasImage = pc._pagesInfoVec[tabIdx].GetImageIndex() != -1
-        imageYCoord = (pc.HasFlag(FNB_BOTTOM) and [6] or [8])[0]
-
-        if hasImage:
-            textOffset = 2*pc._pParent._nPadding + 16 + shapePoints/2 
-        else:
-            textOffset = pc._pParent._nPadding + shapePoints/2 
-
-        textOffset += 2
-
-        if tabIdx != pc.GetSelection():
-        
-            # Set the text background to be like the vertical lines
-            dc.SetTextForeground(pc._pParent.GetNonActiveTabTextColour())
-        
-        if hasImage:
-        
-            imageXOffset = textOffset - 16 - padding
-            pc._ImageList.Draw(pc._pagesInfoVec[tabIdx].GetImageIndex(), dc,
-                                     posx + imageXOffset, imageYCoord,
-                                     wx.IMAGELIST_DRAW_TRANSPARENT, True)
-        
-        dc.DrawText(pc.GetPageText(tabIdx), posx + textOffset, imageYCoord)
-
-        # draw 'x' on tab (if enabled)
-        if pc.HasFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection():
-        
-            textWidth, textHeight = dc.GetTextExtent(pc.GetPageText(tabIdx))
-            tabCloseButtonXCoord = posx + textOffset + textWidth + 1
-
-            # take a bitmap from the position of the 'x' button (the x on tab button)
-            # this bitmap will be used later to delete old buttons
-            tabCloseButtonYCoord = imageYCoord
-            x_rect = wx.Rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16)
-
-            # Draw the tab
-            self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus)            
-        
-
-#------------------------------------------
-# Firefox2 renderer 
-#------------------------------------------
-class FNBRendererFirefox2(FNBRenderer):
-    """
-    This class handles the drawing of tabs using the I{Firefox 2} renderer.
-    """
-    
-    def __init__(self):
-        """ Default class constructor. """
-
-        FNBRenderer.__init__(self)
-
-        
-    def DrawTab(self, pageContainer, dc, posx, tabIdx, tabWidth, tabHeight, btnStatus):
-        """ Draws a tab using the I{Firefox 2} style. """
-
-        borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
-        pc = pageContainer
-
-        tabPoints = [wx.Point() for indx in xrange(7)]
-        tabPoints[0].x = posx + 2
-        tabPoints[0].y = (pc.HasFlag(FNB_BOTTOM) and [2] or [tabHeight - 2])[0]
-
-        tabPoints[1].x = tabPoints[0].x
-        tabPoints[1].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - (VERTICAL_BORDER_PADDING+2)] or [(VERTICAL_BORDER_PADDING+2)])[0]
-
-        tabPoints[2].x = tabPoints[1].x+2
-        tabPoints[2].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0]
-
-        tabPoints[3].x = posx + tabWidth - 2
-        tabPoints[3].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0]
-
-        tabPoints[4].x = tabPoints[3].x + 2
-        tabPoints[4].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - (VERTICAL_BORDER_PADDING+2)] or [(VERTICAL_BORDER_PADDING+2)])[0]
-
-        tabPoints[5].x = tabPoints[4].x
-        tabPoints[5].y = (pc.HasFlag(FNB_BOTTOM) and [2] or [tabHeight - 2])[0]
-
-        tabPoints[6].x = tabPoints[0].x
-        tabPoints[6].y = tabPoints[0].y
-
-        #------------------------------------
-        # Paint the tab with gradient
-        #------------------------------------
-        rr = wx.RectPP(tabPoints[2], tabPoints[5])
-        DrawButton(dc, rr, pc.GetSelection() == tabIdx , not pc.HasFlag(FNB_BOTTOM))
-
-        dc.SetBrush(wx.TRANSPARENT_BRUSH)
-        dc.SetPen(borderPen)
-
-        # Draw the tab as rounded rectangle
-        dc.DrawPolygon(tabPoints)
-
-        # -----------------------------------
-        # Text and image drawing
-        # -----------------------------------
-
-        # The width of the images are 16 pixels
-        padding = pc.GetParent().GetPadding()
-        shapePoints = int(tabHeight*math.tan(float(pc._pagesInfoVec[tabIdx].GetTabAngle())/180.0*math.pi))
-        hasImage = pc._pagesInfoVec[tabIdx].GetImageIndex() != -1
-        imageYCoord = (pc.HasFlag(FNB_BOTTOM) and [6] or [8])[0]
-
-        if hasImage:
-            textOffset = 2*padding + 16 + shapePoints/2 
-        else:
-            textOffset = padding + shapePoints/2
-            
-        textOffset += 2
-
-        if tabIdx != pc.GetSelection():
-        
-            # Set the text background to be like the vertical lines
-            dc.SetTextForeground(pc._pParent.GetNonActiveTabTextColour())
-
-        if hasImage:
-            imageXOffset = textOffset - 16 - padding
-            pc._ImageList.Draw(pc._pagesInfoVec[tabIdx].GetImageIndex(), dc,
-                               posx + imageXOffset, imageYCoord,
-                               wx.IMAGELIST_DRAW_TRANSPARENT, True)
-        
-        dc.DrawText(pc.GetPageText(tabIdx), posx + textOffset, imageYCoord)
-
-        # draw 'x' on tab (if enabled)
-        if pc.HasFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection():
-        
-            textWidth, textHeight = dc.GetTextExtent(pc.GetPageText(tabIdx))
-            tabCloseButtonXCoord = posx + textOffset + textWidth + 1
-
-            # take a bitmap from the position of the 'x' button (the x on tab button)
-            # this bitmap will be used later to delete old buttons
-            tabCloseButtonYCoord = imageYCoord
-            x_rect = wx.Rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16)
-
-            # Draw the tab
-            self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus)
-        
-
-#------------------------------------------------------------------
-# Visual studio 7.1 
-#------------------------------------------------------------------
-
-class FNBRendererVC71(FNBRenderer):
-    """
-    This class handles the drawing of tabs using the I{VC71} renderer.
-    """
-
-    def __init__(self):
-        """ Default class constructor. """
-
-        FNBRenderer.__init__(self)
-
-
-    def DrawTab(self, pageContainer, dc, posx, tabIdx, tabWidth, tabHeight, btnStatus):
-        """ Draws a tab using the I{VC71} style. """
-
-        # Visual studio 7.1 style
-        borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
-        pc = pageContainer
-
-        dc.SetPen((tabIdx == pc.GetSelection() and [wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))] or [borderPen])[0])
-        dc.SetBrush((tabIdx == pc.GetSelection() and [wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))] or [wx.Brush(wx.Colour(247, 243, 233))])[0])
-
-        if tabIdx == pc.GetSelection():
-        
-            posy = (pc.HasFlag(FNB_BOTTOM) and [0] or [VERTICAL_BORDER_PADDING])[0]
-            tabH = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - 5] or [tabHeight - 3])[0]
-            dc.DrawRectangle(posx, posy, tabWidth, tabH) 
-
-            # Draw a black line on the left side of the
-            # rectangle
-            dc.SetPen(wx.BLACK_PEN)
-
-            blackLineY1 = VERTICAL_BORDER_PADDING
-            blackLineY2 = tabH
-            dc.DrawLine(posx + tabWidth, blackLineY1, posx + tabWidth, blackLineY2)
-
-            # To give the tab more 3D look we do the following
-            # Incase the tab is on top,
-            # Draw a thik white line on topof the rectangle
-            # Otherwise, draw a thin (1 pixel) black line at the bottom
-
-            pen = wx.Pen((pc.HasFlag(FNB_BOTTOM) and [wx.BLACK] or [wx.WHITE])[0])
-            dc.SetPen(pen)
-            whiteLinePosY = (pc.HasFlag(FNB_BOTTOM) and [blackLineY2] or [VERTICAL_BORDER_PADDING ])[0]
-            dc.DrawLine(posx , whiteLinePosY, posx + tabWidth + 1, whiteLinePosY)
-
-            # Draw a white vertical line to the left of the tab
-            dc.SetPen(wx.WHITE_PEN)
-            if not pc.HasFlag(FNB_BOTTOM):
-                blackLineY2 += 1
-                
-            dc.DrawLine(posx, blackLineY1, posx, blackLineY2)
-        
-        else:
-        
-            # We dont draw a rectangle for non selected tabs, but only
-            # vertical line on the left
-
-            blackLineY1 = (pc.HasFlag(FNB_BOTTOM) and [VERTICAL_BORDER_PADDING + 2] or [VERTICAL_BORDER_PADDING + 1])[0]
-            blackLineY2 = pc.GetSize().y - 5 
-            dc.DrawLine(posx + tabWidth, blackLineY1, posx + tabWidth, blackLineY2)
-        
-        # -----------------------------------
-        # Text and image drawing
-        # -----------------------------------
-
-        # Text drawing offset from the left border of the
-        # rectangle
-        
-        # The width of the images are 16 pixels
-        padding = pc.GetParent().GetPadding()
-        hasImage = pc._pagesInfoVec[tabIdx].GetImageIndex() != -1
-        imageYCoord = (pc.HasFlag(FNB_BOTTOM) and [5] or [8])[0]
-
-        if hasImage:
-            textOffset = 2*pc._pParent._nPadding + 16
-        else:
-            textOffset = pc._pParent._nPadding
-
-        if tabIdx != pc.GetSelection():
-        
-            # Set the text background to be like the vertical lines
-            dc.SetTextForeground(pc._pParent.GetNonActiveTabTextColour())
-        
-        if hasImage:
-        
-            imageXOffset = textOffset - 16 - padding
-            pc._ImageList.Draw(pc._pagesInfoVec[tabIdx].GetImageIndex(), dc,
-                                     posx + imageXOffset, imageYCoord,
-                                     wx.IMAGELIST_DRAW_TRANSPARENT, True)
-        
-        dc.DrawText(pc.GetPageText(tabIdx), posx + textOffset, imageYCoord)
-        
-        # draw 'x' on tab (if enabled)
-        if pc.HasFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection():
-        
-            textWidth, textHeight = dc.GetTextExtent(pc.GetPageText(tabIdx))
-            tabCloseButtonXCoord = posx + textOffset + textWidth + 1
-
-            # take a bitmap from the position of the 'x' button (the x on tab button)
-            # this bitmap will be used later to delete old buttons
-            tabCloseButtonYCoord = imageYCoord
-            x_rect = wx.Rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16)
-
-            # Draw the tab
-            self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus)                    
-
-
-#------------------------------------------------------------------
-# Fancy style
-#------------------------------------------------------------------
-
-class FNBRendererFancy(FNBRenderer):
-    """
-    This class handles the drawing of tabs using the I{Fancy} renderer.
-    """
-
-    def __init__(self):
-        """ Default class constructor. """
-
-        FNBRenderer.__init__(self)
-
-
-    def DrawTab(self, pageContainer, dc, posx, tabIdx, tabWidth, tabHeight, btnStatus):
-        """ Draws a tab using the I{Fancy} style, similar to VC71 but with gradients. """
-
-        # Fancy tabs - like with VC71 but with the following differences:
-        # - The Selected tab is colored with gradient color
-        borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
-        pc = pageContainer
-
-        pen = (tabIdx == pc.GetSelection() and [wx.Pen(pc._pParent.GetBorderColour())] or [wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE))])[0]
-
-        if tabIdx == pc.GetSelection():
-        
-            posy = (pc.HasFlag(FNB_BOTTOM) and [2] or [VERTICAL_BORDER_PADDING])[0]
-            th = tabHeight - 5
-
-            rect = wx.Rect(posx, posy, tabWidth, th)
-
-            col2 = (pc.HasFlag(FNB_BOTTOM) and [pc._pParent.GetGradientColourTo()] or [pc._pParent.GetGradientColourFrom()])[0]
-            col1 = (pc.HasFlag(FNB_BOTTOM) and [pc._pParent.GetGradientColourFrom()] or [pc._pParent.GetGradientColourTo()])[0]
-
-            PaintStraightGradientBox(dc, rect, col1, col2)
-            dc.SetBrush(wx.TRANSPARENT_BRUSH)
-            dc.SetPen(pen)
-            dc.DrawRectangleRect(rect)
-
-            # erase the bottom/top line of the rectangle
-            dc.SetPen(wx.Pen(pc._pParent.GetGradientColourFrom()))
-            if pc.HasFlag(FNB_BOTTOM):
-                dc.DrawLine(rect.x, 2, rect.x + rect.width, 2)
-            else:
-                dc.DrawLine(rect.x, rect.y + rect.height - 1, rect.x + rect.width, rect.y + rect.height - 1)
-        
-        else:
-        
-            # We dont draw a rectangle for non selected tabs, but only
-            # vertical line on the left
-            dc.SetPen(borderPen)
-            dc.DrawLine(posx + tabWidth, VERTICAL_BORDER_PADDING + 3, posx + tabWidth, tabHeight - 4)
-        
-
-        # -----------------------------------
-        # Text and image drawing
-        # -----------------------------------
-
-        # Text drawing offset from the left border of the
-        # rectangle
-        
-        # The width of the images are 16 pixels
-        padding = pc.GetParent().GetPadding()
-        hasImage = pc._pagesInfoVec[tabIdx].GetImageIndex() != -1
-        imageYCoord = (pc.HasFlag(FNB_BOTTOM) and [6] or [8])[0]
-
-        if hasImage:
-            textOffset = 2*pc._pParent._nPadding + 16
-        else:
-            textOffset = pc._pParent._nPadding 
-
-        textOffset += 2
-
-        if tabIdx != pc.GetSelection():
-        
-            # Set the text background to be like the vertical lines
-            dc.SetTextForeground(pc._pParent.GetNonActiveTabTextColour())
-        
-        if hasImage:
-        
-            imageXOffset = textOffset - 16 - padding
-            pc._ImageList.Draw(pc._pagesInfoVec[tabIdx].GetImageIndex(), dc,
-                                     posx + imageXOffset, imageYCoord,
-                                     wx.IMAGELIST_DRAW_TRANSPARENT, True)
-        
-        dc.DrawText(pc.GetPageText(tabIdx), posx + textOffset, imageYCoord)
-        
-        # draw 'x' on tab (if enabled)
-        if pc.HasFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection():
-        
-            textWidth, textHeight = dc.GetTextExtent(pc.GetPageText(tabIdx))
-            tabCloseButtonXCoord = posx + textOffset + textWidth + 1
-
-            # take a bitmap from the position of the 'x' button (the x on tab button)
-            # this bitmap will be used later to delete old buttons
-            tabCloseButtonYCoord = imageYCoord
-            x_rect = wx.Rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16)
-
-            # Draw the tab
-            self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus)            
-        
-
-#------------------------------------------------------------------
-# Visual studio 2005 (VS8)
-#------------------------------------------------------------------
-class FNBRendererVC8(FNBRenderer):    
-    """
-    This class handles the drawing of tabs using the I{VC8} renderer.
-    """
-
-    def __init__(self):
-        """ Default class constructor. """
-
-        FNBRenderer.__init__(self)
-        self._first = True
-        self._factor = 1
-
-        
-    def DrawTabs(self, pageContainer, dc):
-        """ Draws all the tabs using VC8 style. Overloads The DrawTabs method in parent class. """
-
-        pc = pageContainer
-
-        if "__WXMAC__" in wx.PlatformInfo:
-            # Works well on MSW & GTK, however this lines should be skipped on MAC
-            if not pc._pagesInfoVec or pc._nFrom >= len(pc._pagesInfoVec):
-                pc.Hide()
-                return
-            
-        # Get the text hight
-        tabHeight = self.CalcTabHeight(pageContainer)
-
-        # Set the font for measuring the tab height
-        normalFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
-        boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
-        boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
-
-        # Calculate the number of rows required for drawing the tabs
-        rect = pc.GetClientRect()
-
-        # Set the maximum client size
-        pc.SetSizeHints(self.GetButtonsAreaLength(pc), tabHeight)
-        borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
-
-        # Create brushes
-        backBrush = wx.Brush(pc._tabAreaColor)
-        noselBrush = wx.Brush(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE))
-        selBrush = wx.Brush(pc._activeTabColor)
-        size = pc.GetSize()
-
-        # Background
-        dc.SetTextBackground(pc.GetBackgroundColour())
-        dc.SetTextForeground(pc._activeTextColor)
-        
-        # If border style is set, set the pen to be border pen
-        if pc.HasFlag(FNB_TABS_BORDER_SIMPLE):
-            dc.SetPen(borderPen)
-        else:
-            dc.SetPen(wx.TRANSPARENT_PEN)
-
-        lightFactor = (pc.HasFlag(FNB_BACKGROUND_GRADIENT) and [70] or [0])[0]
-        
-        # For VC8 style, we color the tab area in gradient coloring
-        lightcolour = LightColour(pc._tabAreaColor, lightFactor)
-        PaintStraightGradientBox(dc, pc.GetClientRect(), pc._tabAreaColor, lightcolour)
-
-        dc.SetBrush(wx.TRANSPARENT_BRUSH)
-        dc.DrawRectangle(0, 0, size.x, size.y)
-    
-        # We always draw the bottom/upper line of the tabs
-        # regradless the style
-        dc.SetPen(borderPen)
-        self.DrawTabsLine(pc, dc)
-
-        # Restore the pen
-        dc.SetPen(borderPen)
-
-        # Draw labels
-        dc.SetFont(boldFont)
-
-        # Update all the tabs from 0 to 'pc.self._nFrom' to be non visible
-        for i in xrange(pc._nFrom):
-        
-            pc._pagesInfoVec[i].SetPosition(wx.Point(-1, -1))
-            pc._pagesInfoVec[i].GetRegion().Clear()
-        
-        # Draw the visible tabs, in VC8 style, we draw them from right to left
-        vTabsInfo = self.NumberTabsCanFit(pc)
-
-        activeTabPosx = 0
-        activeTabWidth = 0
-        activeTabHeight = 0
-
-        for cur in xrange(len(vTabsInfo)-1, -1, -1):
-        
-            # 'i' points to the index of the currently drawn tab
-            # in pc.GetPageInfoVector() vector
-            i = pc._nFrom + cur
-            dc.SetPen(borderPen)
-            dc.SetBrush((i==pc.GetSelection() and [selBrush] or [noselBrush])[0])
-
-            # Now set the font to the correct font
-            dc.SetFont((i==pc.GetSelection() and [boldFont] or [normalFont])[0])
-
-            # Add the padding to the tab width
-            # Tab width:
-            # +-----------------------------------------------------------+
-            # | PADDING | IMG | IMG_PADDING | TEXT | PADDING | x |PADDING |
-            # +-----------------------------------------------------------+
-
-            tabWidth = self.CalcTabWidth(pageContainer, i, tabHeight)
-            posx = vTabsInfo[cur].x
-
-            # By default we clean the tab region
-            # incase we use the VC8 style which requires
-            # the region, it will be filled by the function
-            # drawVc8Tab
-            pc._pagesInfoVec[i].GetRegion().Clear()
-            
-            # Clean the 'x' buttn on the tab 
-            # 'Clean' rectanlge is a rectangle with width or height
-            # with values lower than or equal to 0
-            pc._pagesInfoVec[i].GetXRect().SetSize(wx.Size(-1, -1))
-
-            # Draw the tab
-            # Incase we are drawing the active tab
-            # we need to redraw so it will appear on top
-            # of all other tabs
-
-            # when using the vc8 style, we keep the position of the active tab so we will draw it again later
-            if i == pc.GetSelection() and pc.HasFlag(FNB_VC8):
-            
-                activeTabPosx = posx
-                activeTabWidth = tabWidth
-                activeTabHeight = tabHeight
-            
-            else:
-            
-                self.DrawTab(pc, dc, posx, i, tabWidth, tabHeight, pc._nTabXButtonStatus)
-            
-            # Restore the text forground
-            dc.SetTextForeground(pc._activeTextColor)
-
-            # Update the tab position & size
-            pc._pagesInfoVec[i].SetPosition(wx.Point(posx, VERTICAL_BORDER_PADDING))
-            pc._pagesInfoVec[i].SetSize(wx.Size(tabWidth, tabHeight))
-        
-        # Incase we are in VC8 style, redraw the active tab (incase it is visible)
-        if pc.GetSelection() >= pc._nFrom and pc.GetSelection() < pc._nFrom + len(vTabsInfo):
-        
-            self.DrawTab(pc, dc, activeTabPosx, pc.GetSelection(), activeTabWidth, activeTabHeight, pc._nTabXButtonStatus)
-        
-        # Update all tabs that can not fit into the screen as non-visible
-        for xx in xrange(pc._nFrom + len(vTabsInfo), len(pc._pagesInfoVec)):
-        
-            pc._pagesInfoVec[xx].SetPosition(wx.Point(-1, -1))
-            pc._pagesInfoVec[xx].GetRegion().Clear()
-        
-        # Draw the left/right/close buttons 
-        # Left arrow
-        self.DrawLeftArrow(pc, dc)
-        self.DrawRightArrow(pc, dc)
-        self.DrawX(pc, dc)
-        self.DrawDropDownArrow(pc, dc)
-
-
-    def DrawTab(self, pageContainer, dc, posx, tabIdx, tabWidth, tabHeight, btnStatus):
-        """ Draws a tab using VC8 style. """
-
-        pc = pageContainer
-        borderPen = wx.Pen(pc._pParent.GetBorderColour())
-        tabPoints = [wx.Point() for ii in xrange(8)]
-
-        # If we draw the first tab or the active tab, 
-        # we draw a full tab, else we draw a truncated tab
-        #
-        #             X(2)                  X(3)
-        #        X(1)                            X(4)
-        #                                          
-        #                                           X(5)
-        #                                           
-        # X(0),(7)                                  X(6)
-        #
-        #
-
-        tabPoints[0].x = (pc.HasFlag(FNB_BOTTOM) and [posx] or [posx+self._factor])[0]
-        tabPoints[0].y = (pc.HasFlag(FNB_BOTTOM) and [2] or [tabHeight - 3])[0]
-
-        tabPoints[1].x = tabPoints[0].x + tabHeight - VERTICAL_BORDER_PADDING - 3 - self._factor
-        tabPoints[1].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - (VERTICAL_BORDER_PADDING+2)] or [(VERTICAL_BORDER_PADDING+2)])[0]
-
-        tabPoints[2].x = tabPoints[1].x + 4
-        tabPoints[2].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0]
-
-        tabPoints[3].x = tabPoints[2].x + tabWidth - 2
-        tabPoints[3].y = (pc.HasFlag(FNB_BOTTOM) and [tabHeight - VERTICAL_BORDER_PADDING] or [VERTICAL_BORDER_PADDING])[0]
-
-        tabPoints[4].x = tabPoints[3].x + 1
-        tabPoints[4].y = (pc.HasFlag(FNB_BOTTOM) and [tabPoints[3].y - 1] or [tabPoints[3].y + 1])[0]
-
-        tabPoints[5].x = tabPoints[4].x + 1
-        tabPoints[5].y = (pc.HasFlag(FNB_BOTTOM) and [(tabPoints[4].y - 1)] or [tabPoints[4].y + 1])[0]
-
-        tabPoints[6].x = tabPoints[2].x + tabWidth
-        tabPoints[6].y = tabPoints[0].y
-
-        tabPoints[7].x = tabPoints[0].x
-        tabPoints[7].y = tabPoints[0].y
-
-        pc._pagesInfoVec[tabIdx].SetRegion(tabPoints)
-
-        # Draw the polygon
-        br = dc.GetBrush()
-        dc.SetBrush(wx.Brush((tabIdx == pc.GetSelection() and [pc._activeTabColor] or [pc._colorTo])[0]))
-        dc.SetPen(wx.Pen((tabIdx == pc.GetSelection() and [wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)] or [pc._colorBorder])[0]))
-        dc.DrawPolygon(tabPoints)
-
-        # Restore the brush
-        dc.SetBrush(br)
-        rect = pc.GetClientRect()
-
-        if tabIdx != pc.GetSelection() and not pc.HasFlag(FNB_BOTTOM):
-        
-            # Top default tabs
-            dc.SetPen(wx.Pen(pc._pParent.GetBorderColour()))
-            lineY = rect.height
-            curPen = dc.GetPen()
-            curPen.SetWidth(1)
-            dc.SetPen(curPen)
-            dc.DrawLine(posx, lineY, posx+rect.width, lineY)
-        
-        # Incase we are drawing the selected tab, we draw the border of it as well
-        # but without the bottom (upper line incase of wxBOTTOM)
-        if tabIdx == pc.GetSelection():
-        
-            borderPen = wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW))
-            dc.SetPen(borderPen)
-            dc.SetBrush(wx.TRANSPARENT_BRUSH)
-            dc.DrawPolygon(tabPoints)
-
-            # Delete the bottom line (or the upper one, incase we use wxBOTTOM) 
-            dc.SetPen(wx.WHITE_PEN)
-            dc.DrawLine(tabPoints[0].x, tabPoints[0].y, tabPoints[6].x, tabPoints[6].y)
-
-        self.FillVC8GradientColour(pc, dc, tabPoints, tabIdx == pc.GetSelection(), tabIdx)
-
-        # Draw a thin line to the right of the non-selected tab
-        if tabIdx != pc.GetSelection():
-        
-            dc.SetPen(wx.Pen(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE)))
-            dc.DrawLine(tabPoints[4].x-1, tabPoints[4].y, tabPoints[5].x-1, tabPoints[5].y)
-            dc.DrawLine(tabPoints[5].x-1, tabPoints[5].y, tabPoints[6].x-1, tabPoints[6].y)
-        
-        # Text drawing offset from the left border of the 
-        # rectangle
-        
-        # The width of the images are 16 pixels
-        vc8ShapeLen = tabHeight - VERTICAL_BORDER_PADDING - 2
-        if pc.TabHasImage(tabIdx):
-            textOffset = 2*pc._pParent.GetPadding() + 16 + vc8ShapeLen 
-        else:
-            textOffset = pc._pParent.GetPadding() + vc8ShapeLen
-
-        # Draw the image for the tab if any
-        imageYCoord = (pc.HasFlag(FNB_BOTTOM) and [6] or [8])[0]
-
-        if pc.TabHasImage(tabIdx):
-        
-            imageXOffset = textOffset - 16 - pc._pParent.GetPadding()
-            pc._ImageList.Draw(pc._pagesInfoVec[tabIdx].GetImageIndex(), dc,
-                                     posx + imageXOffset, imageYCoord,
-                                     wx.IMAGELIST_DRAW_TRANSPARENT, True)        
-
-        boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
-            
-        # if selected tab, draw text in bold
-        if tabIdx == pc.GetSelection():
-            boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
-        
-        dc.SetFont(boldFont)
-        dc.DrawText(pc.GetPageText(tabIdx), posx + textOffset, imageYCoord)
-
-        # draw 'x' on tab (if enabled)
-        if pc.HasFlag(FNB_X_ON_TAB) and tabIdx == pc.GetSelection():
-
-            textWidth, textHeight = dc.GetTextExtent(pc.GetPageText(tabIdx))
-            tabCloseButtonXCoord = posx + textOffset + textWidth + 1
-
-            # take a bitmap from the position of the 'x' button (the x on tab button)
-            # this bitmap will be used later to delete old buttons
-            tabCloseButtonYCoord = imageYCoord
-            x_rect = wx.Rect(tabCloseButtonXCoord, tabCloseButtonYCoord, 16, 16)
-            # Draw the tab
-            self.DrawTabX(pc, dc, x_rect, tabIdx, btnStatus)
-
-        self.DrawFocusRectangle(dc, pc, pc._pagesInfoVec[tabIdx])
-
-
-    def FillVC8GradientColour(self, pageContainer, dc, tabPoints, bSelectedTab, tabIdx):
-        """ Fills a tab with a gradient shading. """
-
-        # calculate gradient coefficients
-        pc = pageContainer
-
-        if self._first:
-            self._first = False
-            pc._colorTo   = LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE), 0) 
-            pc._colorFrom = LightColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_3DFACE), 60)
-        
-        col2 = pc._pParent.GetGradientColourTo()
-        col1 = pc._pParent.GetGradientColourFrom()
-
-        # If colorful tabs style is set, override the tab color
-        if pc.HasFlag(FNB_COLORFUL_TABS):
-        
-            if not pc._pagesInfoVec[tabIdx].GetColour():
-            
-                # First time, generate color, and keep it in the vector
-                tabColor = RandomColour()
-                pc._pagesInfoVec[tabIdx].SetColour(tabColor)
-            
-            if pc.HasFlag(FNB_BOTTOM):
-            
-                col2 = LightColour(pc._pagesInfoVec[tabIdx].GetColour(), 50)
-                col1 = LightColour(pc._pagesInfoVec[tabIdx].GetColour(), 80)
-            
-            else:
-            
-                col1 = LightColour(pc._pagesInfoVec[tabIdx].GetColour(), 50)
-                col2 = LightColour(pc._pagesInfoVec[tabIdx].GetColour(), 80)
-            
-        size = abs(tabPoints[2].y - tabPoints[0].y) - 1
-
-        rf, gf, bf = 0, 0, 0
-        rstep = float(col2.Red() - col1.Red())/float(size)
-        gstep = float(col2.Green() - col1.Green())/float(size)
-        bstep = float(col2.Blue() - col1.Blue())/float(size)
-        
-        y = tabPoints[0].y 
-
-        # If we are drawing the selected tab, we need also to draw a line 
-        # from 0.tabPoints[0].x and tabPoints[6].x . end, we achieve this
-        # by drawing the rectangle with transparent brush
-        # the line under the selected tab will be deleted by the drwaing loop
-        if bSelectedTab:
-            self.DrawTabsLine(pc, dc)
-
-        while 1:
-        
-            if pc.HasFlag(FNB_BOTTOM):
-            
-                if y > tabPoints[0].y + size:
-                    break
-            
-            else:
-            
-                if y < tabPoints[0].y - size:
-                    break
-            
-            currCol = wx.Colour(col1.Red() + rf, col1.Green() + gf, col1.Blue() + bf)
-
-            dc.SetPen((bSelectedTab and [wx.Pen(pc._activeTabColor)] or [wx.Pen(currCol)])[0])
-            startX = self.GetStartX(tabPoints, y, pc.GetParent().GetWindowStyleFlag()) 
-            endX = self.GetEndX(tabPoints, y, pc.GetParent().GetWindowStyleFlag())
-            dc.DrawLine(startX, y, endX, y)
-
-            # Draw the border using the 'edge' point
-            dc.SetPen(wx.Pen((bSelectedTab and [wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)] or [pc._colorBorder])[0]))
-            
-            dc.DrawPoint(startX, y)
-            dc.DrawPoint(endX, y)
-            
-            # Progress the color 
-            rf += rstep
-            gf += gstep
-            bf += bstep
-
-            if pc.HasFlag(FNB_BOTTOM):
-                y = y + 1
-            else:
-                y = y - 1
-
-
-    def GetStartX(self, tabPoints, y, style):
-        """ Returns the x start position of a tab. """
-
-        x1, x2, y1, y2 = 0.0, 0.0, 0.0, 0.0
-
-        # We check the 3 points to the left
-
-        bBottomStyle = (style & FNB_BOTTOM and [True] or [False])[0]
-        match = False
-
-        if bBottomStyle:
-        
-            for i in xrange(3):
-                
-                if y >= tabPoints[i].y and y < tabPoints[i+1].y:
-                
-                    x1 = tabPoints[i].x
-                    x2 = tabPoints[i+1].x
-                    y1 = tabPoints[i].y
-                    y2 = tabPoints[i+1].y
-                    match = True
-                    break
-                
-        else:
-        
-            for i in xrange(3):
-                
-                if y <= tabPoints[i].y and y > tabPoints[i+1].y:
-                
-                    x1 = tabPoints[i].x
-                    x2 = tabPoints[i+1].x
-                    y1 = tabPoints[i].y
-                    y2 = tabPoints[i+1].y
-                    match = True
-                    break
-                
-        if not match:
-            return tabPoints[2].x
-
-        # According to the equation y = ax + b => x = (y-b)/a
-        # We know the first 2 points
-
-        if x2 == x1:
-            return x2
-        else:
-            a = (y2 - y1)/(x2 - x1)
-
-        b = y1 - ((y2 - y1)/(x2 - x1))*x1
-
-        if a == 0:
-            return int(x1)
-
-        x = (y - b)/a
-        
-        return int(x)
-
-
-    def GetEndX(self, tabPoints, y, style):
-        """ Returns the x end position of a tab. """
-
-        x1, x2, y1, y2 = 0.0, 0.0, 0.0, 0.0
-
-        # We check the 3 points to the left
-        bBottomStyle = (style & FNB_BOTTOM and [True] or [False])[0]
-        match = False
-
-        if bBottomStyle:
-
-            for i in xrange(7, 3, -1):
-                
-                if y >= tabPoints[i].y and y < tabPoints[i-1].y:
-                
-                    x1 = tabPoints[i].x
-                    x2 = tabPoints[i-1].x
-                    y1 = tabPoints[i].y
-                    y2 = tabPoints[i-1].y
-                    match = True
-                    break
-        
-        else:
-        
-            for i in xrange(7, 3, -1):
-                
-                if y <= tabPoints[i].y and y > tabPoints[i-1].y:
-                
-                    x1 = tabPoints[i].x
-                    x2 = tabPoints[i-1].x
-                    y1 = tabPoints[i].y
-                    y2 = tabPoints[i-1].y
-                    match = True
-                    break
-
-        if not match:
-            return tabPoints[3].x
-
-        # According to the equation y = ax + b => x = (y-b)/a
-        # We know the first 2 points
-
-        # Vertical line
-        if x1 == x2:
-            return int(x1)
-        
-        a = (y2 - y1)/(x2 - x1)
-        b = y1 - ((y2 - y1)/(x2 - x1))*x1
-
-        if a == 0:
-            return int(x1)
-
-        x = (y - b)/a
-
-        return int(x)
-
-
-    def NumberTabsCanFit(self, pageContainer, fr=-1):
-        """ Returns the number of tabs that can fit in the visible area. """
-
-        pc = pageContainer
-        
-        rect = pc.GetClientRect()
-        clientWidth = rect.width
-
-        # Empty results
-        vTabInfo = []
-        tabHeight = self.CalcTabHeight(pageContainer)
-
-        # The drawing starts from posx
-        posx = pc._pParent.GetPadding()
-        
-        if fr < 0:
-            fr = pc._nFrom
-
-        for i in xrange(fr, len(pc._pagesInfoVec)):
-        
-            vc8glitch = tabHeight + FNB_HEIGHT_SPACER
-            tabWidth = self.CalcTabWidth(pageContainer, i, tabHeight)
-
-            if posx + tabWidth + vc8glitch + self.GetButtonsAreaLength(pc) >= clientWidth:
-                break
-
-            # Add a result to the returned vector
-            tabRect = wx.Rect(posx, VERTICAL_BORDER_PADDING, tabWidth, tabHeight)
-            vTabInfo.append(tabRect)
-
-            # Advance posx
-            posx += tabWidth + FNB_HEIGHT_SPACER
-        
-        return vTabInfo
-    
-
-# ---------------------------------------------------------------------------- #
-# Class FlatNotebook
-# ---------------------------------------------------------------------------- #
-
-class FlatNotebook(wx.PyPanel):
-    """
-    Display one or more windows in a notebook.
-    
-    B{Events}:
-        - B{EVT_FLATNOTEBOOK_PAGE_CHANGING}: sent when the active 
-            page in the notebook is changing
-        - B{EVT_FLATNOTEBOOK_PAGE_CHANGED}: sent when the active 
-            page in the notebook has changed
-        - B{EVT_FLATNOTEBOOK_PAGE_CLOSING}: sent when a page in the 
-            notebook is closing
-        - B{EVT_FLATNOTEBOOK_PAGE_CLOSED}: sent when a page in the 
-            notebook has been closed
-        - B{EVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU}: sent when the user
-            clicks a tab in the notebook with the right mouse
-            button
-    """
-    
-    def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize,
-                 style=0, name="FlatNotebook"):
-        """
-        Default class constructor.
-
-        All the parameters are as in wxPython class construction, except the
-        'style': this can be assigned to whatever combination of FNB_* styles.
-        
-        """
-
-        self._bForceSelection = False
-        self._nPadding = 6
-        self._nFrom = 0
-        style |= wx.TAB_TRAVERSAL
-        self._pages = None
-        self._windows = []
-        self._popupWin = None
-        self._naviIcon = None
-
-        wx.PyPanel.__init__(self, parent, id, pos, size, style)
-        
-        self._pages = PageContainer(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, style)
-
-        self.Bind(wx.EVT_NAVIGATION_KEY, self.OnNavigationKey)
-
-        self.Init()
-
-
-    def Init(self):
-        """ Initializes all the class attributes. """
-        
-        self._pages._colorBorder = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNSHADOW)
-
-        self._mainSizer = wx.BoxSizer(wx.VERTICAL)
-        self.SetSizer(self._mainSizer)
-
-        # The child panels will inherit this bg color, so leave it at the default value
-        #self.SetBackgroundColour(wx.SystemSettings_GetColour(wx.SYS_COLOUR_APPWORKSPACE))
-
-        # Set default page height
-        dc = wx.ClientDC(self)
-        
-        if "__WXGTK__" in wx.PlatformInfo:
-            # For GTK it seems that we must do this steps in order
-            # for the tabs will get the proper height on initialization
-            # on MSW, preforming these steps yields wierd results
-            boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
-            boldFont.SetWeight(wx.FONTWEIGHT_BOLD)
-            dc.SetFont(boldFont)
-        
-        height = dc.GetCharHeight()
-
-        tabHeight = height + FNB_HEIGHT_SPACER         # We use 8 pixels as padding
-        
-        if "__WXGTK__" in wx.PlatformInfo:
-            tabHeight += 6
-            
-        self._pages.SetSizeHints(-1, tabHeight)
-        # Add the tab container to the sizer
-        self._mainSizer.Insert(0, self._pages, 0, wx.EXPAND)
-        self._mainSizer.Layout()
-
-        self._pages._nFrom = self._nFrom
-        self._pDropTarget = FNBDropTarget(self)
-        self.SetDropTarget(self._pDropTarget)
-
-
-    def DoGetBestSize(self):
-        """ Overrides DoGetBestSize to handle sizers nicely. """
-
-        if not self._windows:
-            # Something is better than nothing... no pages!
-            return wx.Size(20, 20)
-
-        maxWidth = maxHeight = 0
-        tabHeight = self.GetPageBestSize().height
-
-        for win in self._windows:
-            # Loop over all the windows to get their best size
-            width, height = win.GetBestSize()
-            maxWidth, maxHeight = max(maxWidth, width), max(maxHeight, height)
-
-        return wx.Size(maxWidth, maxHeight+tabHeight)
-    
-
-    def SetActiveTabTextColour(self, textColour):
-        """ Sets the text colour for the active tab. """
-
-        self._pages._activeTextColor = textColour
-
-
-    def OnDropTarget(self, x, y, nTabPage, wnd_oldContainer):
-        """ Handles the drop action from a DND operation. """
-
-        return self._pages.OnDropTarget(x, y, nTabPage, wnd_oldContainer)
-
-
-    def GetPreviousSelection(self):
-        """ Returns the previous selection. """
-
-        return self._pages._iPreviousActivePage
-
-
-    def AddPage(self, page, text, select=True, imageId=-1):
-        """
-        Add a page to the L{FlatNotebook}.
-
-        @param page: Specifies the new page.
-        @param text: Specifies the text for the new page.
-        @param select: Specifies whether the page should be selected.
-        @param imageId: Specifies the optional image index for the new page.
-        
-        Return value:
-        True if successful, False otherwise.
-        """
-
-        # sanity check
-        if not page:
-            return False
-
-        # reparent the window to us
-        page.Reparent(self)
-
-        # Add tab
-        bSelected = select or len(self._windows) == 0
-
-        if bSelected:
-            
-            bSelected = False
-            
-            # Check for selection and send events
-            oldSelection = self._pages._iActivePage
-            tabIdx = len(self._windows)
-            
-            event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING, self.GetId())
-            event.SetSelection(tabIdx)
-            event.SetOldSelection(oldSelection)
-            event.SetEventObject(self)
-            
-            if not self.GetEventHandler().ProcessEvent(event) or event.IsAllowed() or len(self._windows) == 0:
-                bSelected = True            
-        
-        curSel = self._pages.GetSelection()
-
-        if not self._pages.IsShown():
-            self._pages.Show()
-
-        self._pages.AddPage(text, bSelected, imageId)
-        self._windows.append(page)
-
-        self.Freeze()
-
-        # Check if a new selection was made
-        if bSelected:
-        
-            if curSel >= 0:
-            
-                # Remove the window from the main sizer
-                self._mainSizer.Detach(self._windows[curSel])
-                self._windows[curSel].Hide()
-            
-            if self.GetWindowStyleFlag() & FNB_BOTTOM:
-            
-                self._mainSizer.Insert(0, page, 1, wx.EXPAND)
-            
-            else:
-            
-                # We leave a space of 1 pixel around the window
-                self._mainSizer.Add(page, 1, wx.EXPAND)
-
-            # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
-            event.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED)
-            event.SetOldSelection(oldSelection)
-            self.GetEventHandler().ProcessEvent(event)
-            
-        else:
-
-            # Hide the page
-            page.Hide()
-
-        self.Thaw()        
-        self._mainSizer.Layout()
-        self.Refresh()
-
-        return True        
-
-
-    def SetImageList(self, imageList):
-        """ Sets the image list for the page control. """
-
-        self._pages.SetImageList(imageList)
-
-
-    def AssignImageList(self, imageList):
-        """ Assigns the image list for the page control. """
-
-        self._pages.AssignImageList(imageList)
-
-
-    def GetImageList(self):
-        """ Returns the associated image list. """
-        
-        return self._pages.GetImageList()
-
-
-    def InsertPage(self, indx, page, text, select=True, imageId=-1):
-        """
-        Inserts a new page at the specified position.
-
-        @param indx: Specifies the position of the new page.
-        @param page: Specifies the new page.
-        @param text: Specifies the text for the new page.
-        @param select: Specifies whether the page should be selected.
-        @param imageId: Specifies the optional image index for the new page.
-        
-        Return value:
-        True if successful, False otherwise.
-        """     
-
-        # sanity check
-        if not page:
-            return False
-
-        # reparent the window to us
-        page.Reparent(self)
-
-        if not self._windows:
-        
-            self.AddPage(page, text, select, imageId)
-            return True
-
-        # Insert tab
-        bSelected = select or not self._windows
-        curSel = self._pages.GetSelection()
-        
-        indx = max(0, min(indx, len(self._windows)))
-
-        if indx <= len(self._windows):
-        
-            self._windows.insert(indx, page)
-        
-        else:
-        
-            self._windows.append(page)
-
-        if bSelected:
-        
-            bSelected = False
-            
-            # Check for selection and send events
-            oldSelection = self._pages._iActivePage
-            
-            event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING, self.GetId())
-            event.SetSelection(indx)
-            event.SetOldSelection(oldSelection)
-            event.SetEventObject(self)
-            
-            if not self.GetEventHandler().ProcessEvent(event) or event.IsAllowed() or len(self._windows) == 0:
-                bSelected = True            
-        
-        self._pages.InsertPage(indx, text, bSelected, imageId)
-        
-        if indx <= curSel:
-            curSel = curSel + 1
-
-        self.Freeze()
-
-        # Check if a new selection was made
-        if bSelected:
-        
-            if curSel >= 0:
-            
-                # Remove the window from the main sizer
-                self._mainSizer.Detach(self._windows[curSel])
-                self._windows[curSel].Hide()
-            
-            self._pages.SetSelection(indx)
-
-            # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
-            event.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED)
-            event.SetOldSelection(oldSelection)
-            self.GetEventHandler().ProcessEvent(event)
-        
-        else:
-        
-            # Hide the page
-            page.Hide()
-
-        self.Thaw()
-        self._mainSizer.Layout()        
-        self.Refresh()
-
-        return True
-
-
-    def SetSelection(self, page):
-        """
-        Sets the selection for the given page.
-        The call to this function generates the page changing events
-        """
-
-        if page >= len(self._windows) or not self._windows:
-            return
-
-        # Support for disabed tabs
-        if not self._pages.GetEnabled(page) and len(self._windows) > 1 and not self._bForceSelection:
-            return
-
-        curSel = self._pages.GetSelection()
-
-        # program allows the page change
-        self.Freeze()
-        if curSel >= 0:
-        
-            # Remove the window from the main sizer
-            self._mainSizer.Detach(self._windows[curSel])
-            self._windows[curSel].Hide()
-        
-        if self.GetWindowStyleFlag() & FNB_BOTTOM:
-        
-            self._mainSizer.Insert(0, self._windows[page], 1, wx.EXPAND)
-        
-        else:
-        
-            # We leave a space of 1 pixel around the window
-            self._mainSizer.Add(self._windows[page], 1, wx.EXPAND)
-        
-        self._windows[page].Show()
-        self.Thaw()
-        
-        self._mainSizer.Layout()
-        
-        if page != self._pages._iActivePage:
-            # there is a real page changing
-            self._pages._iPreviousActivePage = self._pages._iActivePage
-
-        self._pages._iActivePage = page
-        self._pages.DoSetSelection(page)
-
-    def DeletePage(self, page):
-        """
-        Deletes the specified page, and the associated window.
-        The call to this function generates the page changing events.
-        """
-
-        if page >= len(self._windows) or page < 0:
-            return
-
-        # Fire a closing event
-        event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSING, self.GetId())
-        event.SetSelection(page)
-        event.SetEventObject(self)
-        self.GetEventHandler().ProcessEvent(event)
-
-        # The event handler allows it?
-        if not event.IsAllowed():
-            return
-
-        self.Freeze()
-
-        # Delete the requested page
-        pageRemoved = self._windows[page]
-
-        # If the page is the current window, remove it from the sizer
-        # as well
-        if page == self._pages.GetSelection():
-            self._mainSizer.Detach(pageRemoved)
-        
-        # Remove it from the array as well
-        self._windows.pop(page)
-
-        # Now we can destroy it in wxWidgets use Destroy instead of delete
-        pageRemoved.Destroy()
-
-        self.Thaw()
-
-        self._pages.DoDeletePage(page)
-        self.Refresh()
-        self.Update()  
-
-        # Fire a closed event
-        closedEvent = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSED, self.GetId())
-        closedEvent.SetSelection(page)
-        closedEvent.SetEventObject(self)
-        self.GetEventHandler().ProcessEvent(closedEvent)
-
-
-    def DeleteAllPages(self):
-        """ Deletes all the pages. """
-
-        if not self._windows:
-            return False
-
-        self.Freeze()
-        
-        for page in self._windows:
-            page.Destroy()
-        
-        self._windows = []
-        self.Thaw()
-
-        # Clear the container of the tabs as well
-        self._pages.DeleteAllPages()
-        return True
-
-
-    def GetCurrentPage(self):
-        """ Returns the currently selected notebook page or None. """
-        
-        sel = self._pages.GetSelection()
-        if sel < 0:
-            return None
-
-        return self._windows[sel]
-
-
-    def GetPage(self, page):
-        """ Returns the window at the given page position, or None. """
-
-        if page >= len(self._windows):
-            return None
-
-        return self._windows[page]
-
-
-    def GetPageIndex(self, win):
-        """ Returns the index at which the window is found. """
-
-        try:
-            return self._windows.index(win)
-        except:
-            return -1
-
-
-    def GetSelection(self):
-        """ Returns the currently selected page, or -1 if none was selected. """
-        
-        return self._pages.GetSelection()
-
-
-    def AdvanceSelection(self, forward=True):
-        """
-        Cycles through the tabs.
-        The call to this function generates the page changing events.
-        """
-
-        self._pages.AdvanceSelection(forward)
-
-
-    def GetPageCount(self):
-        """ Returns the number of pages in the L{FlatNotebook} control. """
-
-        return self._pages.GetPageCount()
-
-    def SetNavigatorIcon(self, bmp):
-        """ Set the icon used by the L{TabNavigatorWindow} """
-        if isinstance(bmp, wx.Bitmap) and bmp.IsOk():
-            # Make sure image is proper size
-            if bmp.GetSize() != (16, 16):
-                img = bmp.ConvertToImage()
-                img.Rescale(16, 16, wx.IMAGE_QUALITY_HIGH)
-                bmp = wx.BitmapFromImage(img)
-            self._naviIcon = bmp
-        else:
-            raise TypeError, "SetNavigatorIcon requires a valid bitmap"
-
-    def Navigation(self, direction=True):
-        if len(self._windows) >= 1:
-            if not self._popupWin:
-                self._popupWin = TabNavigatorWindow(self, self._naviIcon)
-                self._popupWin.SetReturnCode(wx.ID_OK)
-                self._popupWin.ShowModal()
-                self._popupWin.Destroy()
-                self._popupWin = None
-            else:
-                # a dialog is already opened
-                self._popupWin.Navigation(direction)
-
-    def OnNavigationKey(self, event):
-        """ Handles the wx.EVT_NAVIGATION_KEY event for L{FlatNotebook}. """
-
-        if event.IsWindowChange():
-            if len(self._windows) == 0:
-                return
-            # change pages
-            if self.HasFlag(FNB_SMART_TABS):
-                if not self._popupWin:
-                    self._popupWin = TabNavigatorWindow(self, self._naviIcon)
-                    self._popupWin.SetReturnCode(wx.ID_OK)
-                    self._popupWin.ShowModal()
-                    self._popupWin.Destroy()
-                    self._popupWin = None
-                else:
-                    # a dialog is already opened
-                    self._popupWin.OnNavigationKey(event)
-                    return
-            else:
-                # change pages
-                self.AdvanceSelection(event.GetDirection())
-
-        else:
-            event.Skip()
-            
-
-    def GetPageShapeAngle(self, page_index):
-        """ Returns the angle associated to a tab. """
-
-        if page_index < 0 or page_index >= len(self._pages._pagesInfoVec):
-            return None, False
-        
-        result = self._pages._pagesInfoVec[page_index].GetTabAngle()
-        return result, True
-
-
-    def SetPageShapeAngle(self, page_index, angle):
-        """ Sets the angle associated to a tab. """
-
-        if page_index < 0 or page_index >= len(self._pages._pagesInfoVec):
-            return
-
-        if angle > 15:
-            return
-
-        self._pages._pagesInfoVec[page_index].SetTabAngle(angle)
-
-
-    def SetAllPagesShapeAngle(self, angle):
-        """ Sets the angle associated to all the tab. """
-
-        if angle > 15:
-            return
-
-        for ii in xrange(len(self._pages._pagesInfoVec)):
-            self._pages._pagesInfoVec[ii].SetTabAngle(angle)
-        
-        self.Refresh()
-
-
-    def GetPageBestSize(self):
-        """ Return the page best size. """
-
-        return self._pages.GetClientSize()
-
-
-    def SetPageText(self, page, text):
-        """ Sets the text for the given page. """
-
-        bVal = self._pages.SetPageText(page, text)
-        self._pages.EnsureVisible(page, False)
-        self._pages.Refresh()
-
-        return bVal
-
-
-    def SetPadding(self, padding):
-        """
-        Sets the amount of space around each page's icon and label, in pixels.
-        NB: only the horizontal padding is considered.
-        """
-
-        self._nPadding = padding.GetWidth()
-
-
-    def GetTabArea(self):
-        """ Returns the associated page. """
-
-        return self._pages
-
-
-    def GetPadding(self):
-        """ Returns the amount of space around each page's icon and label, in pixels. """
-        
-        return self._nPadding 
-
-
-    def SetWindowStyleFlag(self, style):
-        """ Sets the L{FlatNotebook} window style flags. """
-            
-        wx.PyPanel.SetWindowStyleFlag(self, style)
-        renderer = self._pages._mgr.GetRenderer(self.GetWindowStyleFlag())
-        renderer._tabHeight = None
-
-        if self._pages:
-        
-            # For changing the tab position (i.e. placing them top/bottom)
-            # refreshing the tab container is not enough
-            self.SetSelection(self._pages._iActivePage)
-
-        if not self._pages.HasFlag(FNB_HIDE_ON_SINGLE_TAB):
-            #For Redrawing the Tabs once you remove the Hide tyle
-            self._pages._ReShow()
-
-
-    def RemovePage(self, page):
-        """ Deletes the specified page, without deleting the associated window. """
-
-        if page >= len(self._windows):
-            return False
-
-        # Fire a closing event
-        event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CLOSING, self.GetId())
-        event.SetSelection(page)
-        event.SetEventObject(self)
-        self.GetEventHandler().ProcessEvent(event)
-
-        # The event handler allows it?
-        if not event.IsAllowed():
-            return False
-
-        self.Freeze()
-
-        # Remove the requested page
-        pageRemoved = self._windows[page]
-
-        # If the page is the current window, remove it from the sizer
-        # as well
-        if page == self._pages.GetSelection():
-            self._mainSizer.Detach(pageRemoved)
-        
-        # Remove it from the array as well
-        self._windows.pop(page)
-        self.Thaw()
-
-        self._pages.DoDeletePage(page)
-
-        return True
-
-
-    def SetRightClickMenu(self, menu):
-        """ Sets the popup menu associated to a right click on a tab. """
-
-        self._pages._pRightClickMenu = menu
-
-
-    def GetPageText(self, nPage):
-        """ Returns the tab caption. """
-
-        return self._pages.GetPageText(nPage)
-
-
-    def SetGradientColours(self, fr, to, border):
-        """ Sets the gradient colours for the tab. """
-
-        self._pages._colorFrom = fr
-        self._pages._colorTo   = to
-        self._pages._colorBorder = border
-
-
-    def SetGradientColourFrom(self, fr):
-        """ Sets the starting colour for the gradient. """
-
-        self._pages._colorFrom = fr
-
-
-    def SetGradientColourTo(self, to):
-        """ Sets the ending colour for the gradient. """
-
-        self._pages._colorTo = to
-
-
-    def SetGradientColourBorder(self, border):
-        """ Sets the tab border colour. """
-
-        self._pages._colorBorder = border
-
-
-    def GetGradientColourFrom(self):
-        """ Gets first gradient colour. """
-
-        return self._pages._colorFrom
-
-
-    def GetGradientColourTo(self):
-        """ Gets second gradient colour. """
-
-        return self._pages._colorTo
-
-
-    def GetGradientColourBorder(self):
-        """ Gets the tab border colour. """
-
-        return self._pages._colorBorder
-
-
-    def GetBorderColour(self):
-        """ Returns the border colour. """
-
-        return self._pages._colorBorder
-    
-
-    def GetActiveTabTextColour(self):
-        """ Get the active tab text colour. """
-
-        return self._pages._activeTextColor
-
-
-    def SetPageImage(self, page, image):
-        """
-        Sets the image index for the given page. Image is an index into the
-        image list which was set with SetImageList.
-        """
-
-        self._pages.SetPageImage(page, image)
-
-
-    def GetPageImage(self, nPage):
-        """
-        Returns the image index for the given page. Image is an index into the
-        image list which was set with SetImageList.
-        """
-
-        return self._pages.GetPageImage(nPage)
-
-
-    def GetEnabled(self, page):
-        """ Returns whether a tab is enabled or not. """
-
-        return self._pages.GetEnabled(page)
-
-
-    def EnableTab(self, page, enabled=True):
-        """ Enables or disables a tab. """
-
-        if page >= len(self._windows):
-            return
-
-        self._windows[page].Enable(enabled)
-        self._pages.EnableTab(page, enabled)
-
-
-    def GetNonActiveTabTextColour(self):
-        """ Returns the non active tabs text colour. """
-
-        return self._pages._nonActiveTextColor
-
-
-    def SetNonActiveTabTextColour(self, color):
-        """ Sets the non active tabs text colour. """
-
-        self._pages._nonActiveTextColor = color
-
-
-    def SetTabAreaColour(self, color):
-        """ Sets the area behind the tabs colour. """
-
-        self._pages._tabAreaColor = color
-
-
-    def GetTabAreaColour(self):
-        """ Returns the area behind the tabs colour. """
-
-        return self._pages._tabAreaColor
-
-
-    def SetActiveTabColour(self, color):
-        """ Sets the active tab colour. """
-
-        self._pages._activeTabColor = color
-
-
-    def GetActiveTabColour(self):
-        """ Returns the active tab colour. """
-
-        return self._pages._activeTabColor
-
-
-    def EnsureVisible(self, page):
-       """ Ensures that a tab is visible. """
-
-       self._pages.DoSetSelection(page)
-
-       
-# ---------------------------------------------------------------------------- #
-# Class PageContainer
-# Acts as a container for the pages you add to FlatNotebook
-# ---------------------------------------------------------------------------- #
-
-class PageContainer(wx.Panel):
-    """
-    This class acts as a container for the pages you add to L{FlatNotebook}.
-    """
-
-    def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
-                 size=wx.DefaultSize, style=0):
-        """ Default class constructor. """
-        
-        self._ImageList = None
-        self._iActivePage = -1
-        self._pDropTarget = None
-        self._nLeftClickZone = FNB_NOWHERE
-        self._iPreviousActivePage = -1
-
-        self._pRightClickMenu = None
-        self._nXButtonStatus = FNB_BTN_NONE
-        self._nArrowDownButtonStatus = FNB_BTN_NONE
-        self._pParent = parent
-        self._nRightButtonStatus = FNB_BTN_NONE
-        self._nLeftButtonStatus = FNB_BTN_NONE
-        self._nTabXButtonStatus = FNB_BTN_NONE
-
-        self._pagesInfoVec = []        
-
-        self._colorTo = wx.SystemSettings_GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
-        self._colorFrom = wx.WHITE
-        self._activeTabColor = wx.WHITE
-        self._activeTextColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNTEXT)
-        self._nonActiveTextColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNTEXT)
-        self._tabAreaColor = wx.SystemSettings_GetColour(wx.SYS_COLOUR_BTNFACE)
-
-        self._nFrom = 0
-        self._isdragging = False
-
-        # Set default page height, this is done according to the system font
-        memDc = wx.MemoryDC()
-        memDc.SelectObject(wx.EmptyBitmap(1,1))
-    
-        if "__WXGTK__" in wx.PlatformInfo:
-            boldFont = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
-            boldFont.SetWeight(wx.BOLD)
-            memDc.SetFont(boldFont)
-
-        height = memDc.GetCharHeight()
-        tabHeight = height + FNB_HEIGHT_SPACER # We use 10 pixels as padding
-
-        wx.Panel.__init__(self, parent, id, pos, wx.Size(size.x, tabHeight),
-                          style|wx.NO_BORDER|wx.NO_FULL_REPAINT_ON_RESIZE|wx.WANTS_CHARS)
-
-        self._pDropTarget = FNBDropTarget(self)
-        self.SetDropTarget(self._pDropTarget)
-        self._mgr = FNBRendererMgr()
-
-        self.Bind(wx.EVT_PAINT, self.OnPaint)
-        self.Bind(wx.EVT_SIZE, self.OnSize)
-        self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
-        self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
-        self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
-        self.Bind(wx.EVT_MIDDLE_DOWN, self.OnMiddleDown)
-        self.Bind(wx.EVT_MOTION, self.OnMouseMove)
-        self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
-        self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave)
-        self.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnterWindow)
-        self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDClick)
-        self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
-        self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
-        self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
-        
-
-    def OnEraseBackground(self, event):
-        """ Handles the wx.EVT_ERASE_BACKGROUND event for L{PageContainer} (does nothing)."""
-
-        pass
-
-    
-    def _ReShow(self):
-        """ Handles the Redraw of the tabs when the FNB_HIDE_ON_SINGLE_TAB has been removed """
-        self.Show()
-        self.GetParent()._mainSizer.Layout()
-        self.Refresh()
-
-
-    def OnPaint(self, event):
-        """ Handles the wx.EVT_PAINT event for L{PageContainer}."""
-
-        dc = wx.BufferedPaintDC(self)
-        renderer = self._mgr.GetRenderer(self.GetParent().GetWindowStyleFlag())
-        renderer.DrawTabs(self, dc)
-
-        if self.HasFlag(FNB_HIDE_ON_SINGLE_TAB) and len(self._pagesInfoVec) <= 1:
-            self.Hide()
-            self.GetParent()._mainSizer.Layout()
-            self.Refresh()
-
-
-    def AddPage(self, caption, selected=True, imgindex=-1):
-        """
-        Add a page to the L{FlatNotebook}.
-
-        @param window: Specifies the new page.
-        @param caption: Specifies the text for the new page.
-        @param selected: Specifies whether the page should be selected.
-        @param imgindex: Specifies the optional image index for the new page.
-        
-        Return value:
-        True if successful, False otherwise.
-        """
-
-        if selected:
-
-            self._iPreviousActivePage = self._iActivePage        
-            self._iActivePage = len(self._pagesInfoVec)
-        
-        # Create page info and add it to the vector
-        pageInfo = PageInfo(caption, imgindex)
-        self._pagesInfoVec.append(pageInfo)
-        self.Refresh()
-
-
-    def InsertPage(self, indx, text, selected=True, imgindex=-1):
-        """
-        Inserts a new page at the specified position.
-
-        @param indx: Specifies the position of the new page.
-        @param page: Specifies the new page.
-        @param text: Specifies the text for the new page.
-        @param select: Specifies whether the page should be selected.
-        @param imgindex: Specifies the optional image index for the new page.
-        
-        Return value:
-        True if successful, False otherwise.
-        """     
-
-        if selected:
-
-            self._iPreviousActivePage = self._iActivePage        
-            self._iActivePage = len(self._pagesInfoVec)
-        
-        self._pagesInfoVec.insert(indx, PageInfo(text, imgindex))
-        
-        self.Refresh()
-        return True
-
-
-    def OnSize(self, event):
-        """ Handles the wx.EVT_SIZE events for L{PageContainer}. """
-
-        # When resizing the control, try to fit to screen as many tabs as we can 
-        style = self.GetParent().GetWindowStyleFlag() 
-        renderer = self._mgr.GetRenderer(style)
-        
-        fr = 0
-        page = self.GetSelection()
-        
-        for fr in xrange(self._nFrom):
-            vTabInfo = renderer.NumberTabsCanFit(self, fr)
-            if page - fr >= len(vTabInfo):
-                continue
-            break
-
-        self._nFrom = fr
-
-        self.EnsureVisible(page, False)
-        self.Refresh() # Call on paint
-        event.Skip()
-
-
-    def OnMiddleDown(self, event):
-        """ Handles the wx.EVT_MIDDLE_DOWN events for L{PageContainer}. """
-
-        # Test if this style is enabled
-        style = self.GetParent().GetWindowStyleFlag()
-        
-        if not style & FNB_MOUSE_MIDDLE_CLOSES_TABS:
-            return
-
-        where, tabIdx = self.HitTest(event.GetPosition())
-        
-        if where == FNB_TAB:
-            self.DeletePage(tabIdx)
-        
-        event.Skip()
-
-
-    def OnRightDown(self, event):
-        """ Handles the wx.EVT_RIGHT_DOWN events for L{PageContainer}. """
-        
-        where, tabIdx = self.HitTest(event.GetPosition())
-
-        if where in [FNB_TAB, FNB_TAB_X]:
-
-            if self._pagesInfoVec[tabIdx].GetEnabled():
-                # Fire events and eventually (if allowed) change selection
-                self.FireEvent(tabIdx)
-
-                # send a message to popup a custom menu
-                event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CONTEXT_MENU, self.GetParent().GetId())
-                event.SetSelection(tabIdx)
-                event.SetOldSelection(self._iActivePage)
-                event.SetEventObject(self.GetParent())
-                self.GetParent().GetEventHandler().ProcessEvent(event)
-
-                if self._pRightClickMenu:
-                    self.PopupMenu(self._pRightClickMenu)
-            
-        event.Skip()
-
-
-    def OnLeftDown(self, event):
-        """ Handles the wx.EVT_LEFT_DOWN events for L{PageContainer}. """
-
-        # Reset buttons status
-        self._nXButtonStatus     = FNB_BTN_NONE
-        self._nLeftButtonStatus  = FNB_BTN_NONE
-        self._nRightButtonStatus = FNB_BTN_NONE
-        self._nTabXButtonStatus  = FNB_BTN_NONE
-        self._nArrowDownButtonStatus = FNB_BTN_NONE
-
-        self._nLeftClickZone, tabIdx = self.HitTest(event.GetPosition())
-
-        if self._nLeftClickZone == FNB_DROP_DOWN_ARROW:
-            self._nArrowDownButtonStatus = FNB_BTN_PRESSED
-            self.Refresh()
-        elif self._nLeftClickZone == FNB_LEFT_ARROW:
-            self._nLeftButtonStatus = FNB_BTN_PRESSED
-            self.Refresh()
-        elif self._nLeftClickZone == FNB_RIGHT_ARROW:
-            self._nRightButtonStatus = FNB_BTN_PRESSED
-            self.Refresh()
-        elif self._nLeftClickZone == FNB_X:
-            self._nXButtonStatus = FNB_BTN_PRESSED
-            self.Refresh()
-        elif self._nLeftClickZone == FNB_TAB_X:
-            self._nTabXButtonStatus = FNB_BTN_PRESSED
-            self.Refresh()
-
-        elif self._nLeftClickZone == FNB_TAB:
-            
-            if self._iActivePage != tabIdx:
-                
-                # In case the tab is disabled, we dont allow to choose it
-                if self._pagesInfoVec[tabIdx].GetEnabled():
-                    self.FireEvent(tabIdx)
-
-
-    def RotateLeft(self):
-
-        if self._nFrom == 0:
-            return
-
-        # Make sure that the button was pressed before
-        if self._nLeftButtonStatus != FNB_BTN_PRESSED:
-            return
-
-        self._nLeftButtonStatus = FNB_BTN_HOVER
-
-        # We scroll left with bulks of 5
-        scrollLeft = self.GetNumTabsCanScrollLeft()
-
-        self._nFrom -= scrollLeft
-        if self._nFrom < 0:
-            self._nFrom = 0
-
-        self.Refresh()
-
-
-    def RotateRight(self):
-
-        if self._nFrom >= len(self._pagesInfoVec) - 1:
-            return
-
-        # Make sure that the button was pressed before
-        if self._nRightButtonStatus != FNB_BTN_PRESSED:
-            return
-
-        self._nRightButtonStatus = FNB_BTN_HOVER
-
-        # Check if the right most tab is visible, if it is
-        # don't rotate right anymore
-        if self._pagesInfoVec[len(self._pagesInfoVec)-1].GetPosition() != wx.Point(-1, -1):
-            return
-
-        self._nFrom += 1
-        self.Refresh()
-
-
-    def OnLeftUp(self, event):
-        """ Handles the wx.EVT_LEFT_UP events for L{PageContainer}. """
-
-        # forget the zone that was initially clicked
-        self._nLeftClickZone = FNB_NOWHERE
-
-        where, tabIdx = self.HitTest(event.GetPosition())
-        
-        # Make sure selected tab has focus
-#        self.SetFocus()
-
-        if where == FNB_LEFT_ARROW:
-            self.RotateLeft()
-            
-        elif where == FNB_RIGHT_ARROW:
-            self.RotateRight()
-            
-        elif where == FNB_X:
-            
-            # Make sure that the button was pressed before
-            if self._nXButtonStatus != FNB_BTN_PRESSED:
-                return
-
-            self._nXButtonStatus = FNB_BTN_HOVER
-
-            self.DeletePage(self._iActivePage)
-            
-        elif where == FNB_TAB_X:
-            
-            # Make sure that the button was pressed before
-            if self._nTabXButtonStatus != FNB_BTN_PRESSED:
-                return 
-
-            self._nTabXButtonStatus = FNB_BTN_HOVER
-
-            self.DeletePage(self._iActivePage)
-
-        elif where == FNB_DROP_DOWN_ARROW:
-
-            # Make sure that the button was pressed before
-            if self._nArrowDownButtonStatus != FNB_BTN_PRESSED:
-                return
-
-            self._nArrowDownButtonStatus = FNB_BTN_NONE
-
-            # Refresh the button status
-            renderer = self._mgr.GetRenderer(self.GetParent().GetWindowStyleFlag())
-            dc = wx.ClientDC(self)
-            renderer.DrawDropDownArrow(self, dc)
-
-            self.PopupTabsMenu()
-
-        event.Skip()
-        
-
-    def HitTest(self, pt):
-        """
-        HitTest method for L{PageContainer}.
-        Returns the flag (if any) and the hit page (if any).
-        """
-
-        style = self.GetParent().GetWindowStyleFlag()
-        render = self._mgr.GetRenderer(style)
-
-        fullrect = self.GetClientRect()
-        btnLeftPos = render.GetLeftButtonPos(self)
-        btnRightPos = render.GetRightButtonPos(self)
-        btnDropdownPos = render.GetDropArrowButtonPos(self)
-        btnXPos = render.GetXPos(self)
-        
-        tabIdx = -1
-        
-        if len(self._pagesInfoVec) == 0:
-            return FNB_NOWHERE, tabIdx
-
-        rect = wx.Rect(btnXPos, 8, 16, 16)
-        if rect.Contains(pt):
-            return (style & FNB_NO_X_BUTTON and [FNB_NOWHERE] or [FNB_X])[0], tabIdx
-
-        rect = wx.Rect(btnDropdownPos, 8, 16, 16)
-        if style & FNB_DROPDOWN_TABS_LIST:
-            rect = wx.Rect(render.GetDropArrowButtonPos(self), 8, 16, 16)
-            if rect.Contains(pt):
-                return FNB_DROP_DOWN_ARROW, tabIdx
-
-        rect = wx.Rect(btnRightPos, 8, 16, 16)
-        if rect.Contains(pt):
-            return (style & FNB_NO_NAV_BUTTONS and [FNB_NOWHERE] or [FNB_RIGHT_ARROW])[0], tabIdx
-
-        rect = wx.Rect(btnLeftPos, 8, 16, 16)
-        if rect.Contains(pt):
-            return (style & FNB_NO_NAV_BUTTONS and [FNB_NOWHERE] or [FNB_LEFT_ARROW])[0], tabIdx
-
-        # Test whether a left click was made on a tab
-        bFoundMatch = False
-        
-        for cur in xrange(self._nFrom, len(self._pagesInfoVec)):
-
-            pgInfo = self._pagesInfoVec[cur]
-
-            if pgInfo.GetPosition() == wx.Point(-1, -1):
-                continue
-
-            if style & FNB_X_ON_TAB and cur == self.GetSelection():
-                # 'x' button exists on a tab
-                if self._pagesInfoVec[cur].GetXRect().Contains(pt):
-                    return FNB_TAB_X, cur
-                    
-            if style & FNB_VC8:
-
-                if self._pagesInfoVec[cur].GetRegion().Contains(pt.x, pt.y):
-                    if bFoundMatch or cur == self.GetSelection():    
-                        return FNB_TAB, cur
-
-                    tabIdx = cur
-                    bFoundMatch = True
-                    
-            else:
-
-                tabRect = wx.Rect(pgInfo.GetPosition().x, pgInfo.GetPosition().y,
-                                  pgInfo.GetSize().x, pgInfo.GetSize().y)
-                
-                if tabRect.Contains(pt):
-                    # We have a match
-                    return FNB_TAB, cur
-
-        if bFoundMatch:
-            return FNB_TAB, tabIdx
-
-        if self._isdragging:
-            # We are doing DND, so check also the region outside the tabs
-            # try before the first tab
-            pgInfo = self._pagesInfoVec[0]
-            tabRect = wx.Rect(0, pgInfo.GetPosition().y, pgInfo.GetPosition().x, self.GetParent().GetSize().y)
-            if tabRect.Contains(pt):
-                return FNB_TAB, 0
-
-            # try after the last tab
-            pgInfo = self._pagesInfoVec[-1]
-            startpos = pgInfo.GetPosition().x+pgInfo.GetSize().x
-            tabRect = wx.Rect(startpos, pgInfo.GetPosition().y, fullrect.width-startpos, self.GetParent().GetSize().y)
-
-            if tabRect.Contains(pt):
-                return FNB_TAB, len(self._pagesInfoVec)        
-
-        # Default
-        return FNB_NOWHERE, -1
-
-
-    def SetSelection(self, page):
-        """ Sets the selected page. """
-
-        book = self.GetParent()
-        book.SetSelection(page)
-        self.DoSetSelection(page)
-
-
-    def DoSetSelection(self, page):
-        """ Does the actual selection of a page. """
-
-        if page < len(self._pagesInfoVec):
-            #! fix for tabfocus
-            da_page = self._pParent.GetPage(page)
-    
-#            if da_page != None:
-#                da_page.SetFocus()
-#        
-        self.EnsureVisible(page)
-
-    def EnsureVisible(self, page, refresh=True):
-        if not self.IsTabVisible(page):
-            # Try to remove one tab from start and try again
-            
-            if not self.CanFitToScreen(page):
-
-                if self._nFrom > page:
-                    self._nFrom = page
-                else:
-                    while self._nFrom < page:
-                        self._nFrom += 1
-                        if self.CanFitToScreen(page):
-                            break
-        if refresh:
-            self.Refresh()
-
-
-    def DeletePage(self, page):
-        """ Delete the specified page from L{FlatNotebook}. """
-
-        book = self.GetParent()
-        book.DeletePage(page)
-        book.Refresh()
-
-
-    def IsTabVisible(self, page):
-        """ Returns whether a tab is visible or not. """
-
-        iLastVisiblePage = self.GetLastVisibleTab()
-        return page <= iLastVisiblePage and page >= self._nFrom
-
-
-    def DoDeletePage(self, page):
-        """ Does the actual page deletion. """
-
-        # Remove the page from the vector
-        book = self.GetParent()
-        self._pagesInfoVec.pop(page)
-
-        # Thanks to Yiaanis AKA Mandrav
-        if self._iActivePage >= page:
-            self._iActivePage = self._iActivePage - 1
-            self._iPreviousActivePage = -1
-
-        # The delete page was the last first on the array,
-        # but the book still has more pages, so we set the
-        # active page to be the first one (0)
-        if self._iActivePage < 0 and len(self._pagesInfoVec) > 0:
-            self._iActivePage = 0
-            self._iPreviousActivePage = -1
-
-        # Refresh the tabs
-        if self._iActivePage >= 0:
-        
-            book._bForceSelection = True
-
-            # Check for selection and send event
-            event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING, self.GetParent().GetId())
-            event.SetSelection(self._iActivePage)
-            event.SetOldSelection(self._iPreviousActivePage)
-            event.SetEventObject(self.GetParent())
-            self.GetParent().GetEventHandler().ProcessEvent(event)            
-
-            book.SetSelection(self._iActivePage)
-            book._bForceSelection = False
-
-            # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
-            event.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED)
-            event.SetOldSelection(self._iPreviousActivePage)
-            self.GetParent().GetEventHandler().ProcessEvent(event)            
-        
-        if not self._pagesInfoVec:        
-            # Erase the page container drawings
-            dc = wx.ClientDC(self)
-            dc.Clear()
-        
-
-    def DeleteAllPages(self):
-        """ Deletes all the pages. """
-
-        self._iActivePage = -1
-        self._iPreviousActivePage = -1
-        self._nFrom = 0
-        self._pagesInfoVec = []
-
-        # Erase the page container drawings
-        dc = wx.ClientDC(self)
-        dc.Clear()
-
-
-    def OnMouseMove(self, event):
-        """ Handles the wx.EVT_MOTION for L{PageContainer}. """
-
-        if self._pagesInfoVec and self.IsShown():
-        
-            xButtonStatus = self._nXButtonStatus
-            xTabButtonStatus = self._nTabXButtonStatus
-            rightButtonStatus = self._nRightButtonStatus
-            leftButtonStatus = self._nLeftButtonStatus
-            dropDownButtonStatus = self._nArrowDownButtonStatus
-            
-            style = self.GetParent().GetWindowStyleFlag()
-
-            self._nXButtonStatus = FNB_BTN_NONE
-            self._nRightButtonStatus = FNB_BTN_NONE
-            self._nLeftButtonStatus = FNB_BTN_NONE
-            self._nTabXButtonStatus = FNB_BTN_NONE
-            self._nArrowDownButtonStatus = FNB_BTN_NONE
-
-            where, tabIdx = self.HitTest(event.GetPosition())
-            
-            if where == FNB_X:
-                if event.LeftIsDown():
-                
-                    self._nXButtonStatus = (self._nLeftClickZone==FNB_X and [FNB_BTN_PRESSED] or [FNB_BTN_NONE])[0]
-                
-                else:
-                
-                    self._nXButtonStatus = FNB_BTN_HOVER
-
-            elif where == FNB_DROP_DOWN_ARROW:
-                if event.LeftIsDown():
-
-                    self._nArrowDownButtonStatus = (self._nLeftClickZone==FNB_DROP_DOWN_ARROW and [FNB_BTN_PRESSED] or [FNB_BTN_NONE])[0]
-
-                else:
-
-                    self._nArrowDownButtonStatus = FNB_BTN_HOVER
-
-            elif where == FNB_TAB_X:
-                if event.LeftIsDown():
-                
-                    self._nTabXButtonStatus = (self._nLeftClickZone==FNB_TAB_X and [FNB_BTN_PRESSED] or [FNB_BTN_NONE])[0]
-                
-                else:
-
-                    self._nTabXButtonStatus = FNB_BTN_HOVER
-                
-            elif where == FNB_RIGHT_ARROW:
-                if event.LeftIsDown():
-                
-                    self._nRightButtonStatus = (self._nLeftClickZone==FNB_RIGHT_ARROW and [FNB_BTN_PRESSED] or [FNB_BTN_NONE])[0]
-                
-                else:
-                
-                    self._nRightButtonStatus = FNB_BTN_HOVER
-                
-            elif where == FNB_LEFT_ARROW:
-                if event.LeftIsDown():
-                
-                    self._nLeftButtonStatus = (self._nLeftClickZone==FNB_LEFT_ARROW and [FNB_BTN_PRESSED] or [FNB_BTN_NONE])[0]
-                
-                else:
-                
-                    self._nLeftButtonStatus = FNB_BTN_HOVER
-                
-            elif where == FNB_TAB:
-                # Call virtual method for showing tooltip
-                self.ShowTabTooltip(tabIdx)
-                
-                if not self.GetEnabled(tabIdx):                
-                    # Set the cursor to be 'No-entry'
-                    wx.SetCursor(wx.StockCursor(wx.CURSOR_NO_ENTRY))
-                
-                # Support for drag and drop
-                if event.Dragging() and not (style & FNB_NODRAG):
-
-                    self._isdragging = True                
-                    draginfo = FNBDragInfo(self, tabIdx)
-                    drginfo = cPickle.dumps(draginfo)
-                    dataobject = wx.CustomDataObject(wx.CustomDataFormat("FlatNotebook"))
-                    dataobject.SetData(drginfo)
-                    dragSource = FNBDropSource(self)
-                    dragSource.SetData(dataobject)
-                    dragSource.DoDragDrop(wx.Drag_DefaultMove)
-                    
-            bRedrawX = self._nXButtonStatus != xButtonStatus
-            bRedrawRight = self._nRightButtonStatus != rightButtonStatus
-            bRedrawLeft = self._nLeftButtonStatus != leftButtonStatus
-            bRedrawTabX = self._nTabXButtonStatus != xTabButtonStatus
-            bRedrawDropArrow = self._nArrowDownButtonStatus != dropDownButtonStatus
-
-            render = self._mgr.GetRenderer(style)
-        
-            if (bRedrawX or bRedrawRight or bRedrawLeft or bRedrawTabX or bRedrawDropArrow):
-
-                dc = wx.ClientDC(self)
-                
-                if bRedrawX:
-                                
-                    render.DrawX(self, dc)
-                
-                if bRedrawLeft:
-                
-                    render.DrawLeftArrow(self, dc)
-                
-                if bRedrawRight:
-                
-                    render.DrawRightArrow(self, dc)
-                
-                if bRedrawTabX:
-                
-                    self.Refresh()
-
-                if bRedrawDropArrow:
-
-                    render.DrawDropDownArrow(self, dc)
-
-        event.Skip()
-
-
-    def GetLastVisibleTab(self):
-        """ Returns the last visible tab. """
-
-        if self._nFrom < 0:
-            return -1
-
-        ii = 0
-        
-        for ii in xrange(self._nFrom, len(self._pagesInfoVec)):
-        
-            if self._pagesInfoVec[ii].GetPosition() == wx.Point(-1, -1):
-                break
-        
-        return ii-1
-
-
-    def GetNumTabsCanScrollLeft(self):
-        """ Returns the number of tabs than can be scrolled left. """
-
-        if self._nFrom - 1 >= 0:
-            return 1
-
-        return 0
-
-
-    def IsDefaultTabs(self):
-        """ Returns whether a tab has a default style. """
-
-        style = self.GetParent().GetWindowStyleFlag()
-        res = (style & FNB_VC71) or (style & FNB_FANCY_TABS) or (style & FNB_VC8)
-        return not res
-
-
-    def AdvanceSelection(self, bForward=True):
-        """
-        Cycles through the tabs.
-        The call to this function generates the page changing events.
-        """
-
-        nSel = self.GetSelection()
-
-        if nSel < 0:
-            return
-
-        nMax = self.GetPageCount() - 1
-        
-        if bForward:
-            newSelection = (nSel == nMax and [0] or [nSel + 1])[0]
-        else:
-            newSelection = (nSel == 0 and [nMax] or [nSel - 1])[0]
-
-        if not self._pagesInfoVec[newSelection].GetEnabled():
-            return
-
-        self.FireEvent(newSelection)
-
-
-    def OnMouseLeave(self, event):
-        """ Handles the wx.EVT_LEAVE_WINDOW event for L{PageContainer}. """
-
-        self._nLeftButtonStatus = FNB_BTN_NONE
-        self._nXButtonStatus = FNB_BTN_NONE
-        self._nRightButtonStatus = FNB_BTN_NONE
-        self._nTabXButtonStatus = FNB_BTN_NONE
-        self._nArrowDownButtonStatus = FNB_BTN_NONE
-
-        style = self.GetParent().GetWindowStyleFlag()        
-        render = self._mgr.GetRenderer(style)
-        
-        dc = wx.ClientDC(self)
-
-        render.DrawX(self, dc)
-        render.DrawLeftArrow(self, dc)
-        render.DrawRightArrow(self, dc)
-
-        selection = self.GetSelection()
-
-        if selection == -1:
-            event.Skip()
-            return
-        
-        if not self.IsTabVisible(selection):
-            if selection == len(self._pagesInfoVec) - 1:
-                if not self.CanFitToScreen(selection):
-                    event.Skip()
-                    return
-            else:
-                event.Skip()
-                return
-                    
-        render.DrawTabX(self, dc, self._pagesInfoVec[selection].GetXRect(), selection, self._nTabXButtonStatus)
-        render.DrawFocusRectangle(dc, self, self._pagesInfoVec[selection])
-
-        event.Skip()
-
-
-    def OnMouseEnterWindow(self, event):
-        """ Handles the wx.EVT_ENTER_WINDOW event for L{PageContainer}. """
-
-        self._nLeftButtonStatus = FNB_BTN_NONE
-        self._nXButtonStatus = FNB_BTN_NONE
-        self._nRightButtonStatus = FNB_BTN_NONE
-        self._nLeftClickZone = FNB_BTN_NONE
-        self._nArrowDownButtonStatus = FNB_BTN_NONE
-
-        event.Skip()
-
-
-    def ShowTabTooltip(self, tabIdx):
-        """ Shows a tab tooltip. """
-
-        pWindow = self._pParent.GetPage(tabIdx)
-        
-        if pWindow:        
-            pToolTip = pWindow.GetToolTip()
-            if pToolTip and pToolTip.GetWindow() == pWindow:
-                self.SetToolTipString(pToolTip.GetTip())
-        
-
-    def SetPageImage(self, page, imgindex):
-        """ Sets the image index associated to a page. """
-
-        if page < len(self._pagesInfoVec):
-        
-            self._pagesInfoVec[page].SetImageIndex(imgindex)
-            self.Refresh()
-
-
-    def GetPageImage(self, page):
-        """ Returns the image index associated to a page. """
-
-        if page < len(self._pagesInfoVec):
-        
-            return self._pagesInfoVec[page].GetImageIndex()
-        
-        return -1
-
-
-    def OnDropTarget(self, x, y, nTabPage, wnd_oldContainer):
-        """ Handles the drop action from a DND operation. """
-
-        # Disable drag'n'drop for disabled tab
-        if not wnd_oldContainer._pagesInfoVec[nTabPage].GetEnabled():
-            return wx.DragCancel
-
-        self._isdragging = True
-        oldContainer = wnd_oldContainer
-        nIndex = -1
-
-        where, nIndex = self.HitTest(wx.Point(x, y))
-
-        oldNotebook = oldContainer.GetParent()
-        newNotebook = self.GetParent()
-
-        if oldNotebook == newNotebook:
-        
-            if nTabPage >= 0:
-            
-                if where == FNB_TAB:
-                    self.MoveTabPage(nTabPage, nIndex)
-                           
-        elif self.GetParent().GetWindowStyleFlag() & FNB_ALLOW_FOREIGN_DND:
-        
-            if wx.Platform in ["__WXMSW__", "__WXGTK__", "__WXMAC__"]:
-                if nTabPage >= 0:
-                
-                    window = oldNotebook.GetPage(nTabPage)
-
-                    if window:
-                        where, nIndex = newNotebook._pages.HitTest(wx.Point(x, y))
-                        caption = oldContainer.GetPageText(nTabPage)
-                        imageindex = oldContainer.GetPageImage(nTabPage)
-                        oldNotebook.RemovePage(nTabPage)
-                        window.Reparent(newNotebook)
-
-                        if imageindex >= 0:
-
-                            bmp = oldNotebook.GetImageList().GetBitmap(imageindex)
-                            newImageList = newNotebook.GetImageList()
-    
-                            if not newImageList:
-                                xbmp, ybmp = bmp.GetWidth(), bmp.GetHeight()
-                                newImageList = wx.ImageList(xbmp, ybmp)                                
-                                imageindex = 0
-                            else:
-                                imageindex = newImageList.GetImageCount()
-
-                            newImageList.Add(bmp)
-                            newNotebook.SetImageList(newImageList)
-                                
-                        newNotebook.InsertPage(nIndex, window, caption, True, imageindex)
-
-        self._isdragging = False
-        
-        return wx.DragMove
-
-
-    def MoveTabPage(self, nMove, nMoveTo):
-        """ Moves a tab inside the same L{FlatNotebook}. """
-
-        if nMove == nMoveTo:
-            return
-
-        elif nMoveTo < len(self._pParent._windows):
-            nMoveTo = nMoveTo + 1
-
-        self._pParent.Freeze()
-        
-        # Remove the window from the main sizer
-        nCurSel = self._pParent._pages.GetSelection()
-        self._pParent._mainSizer.Detach(self._pParent._windows[nCurSel])
-        self._pParent._windows[nCurSel].Hide()
-
-        pWindow = self._pParent._windows[nMove]
-        self._pParent._windows.pop(nMove)
-        self._pParent._windows.insert(nMoveTo-1, pWindow)
-
-        pgInfo = self._pagesInfoVec[nMove]
-
-        self._pagesInfoVec.pop(nMove)
-        self._pagesInfoVec.insert(nMoveTo - 1, pgInfo)
-
-        # Add the page according to the style
-        pSizer = self._pParent._mainSizer
-        style = self.GetParent().GetWindowStyleFlag()
-
-        if style & FNB_BOTTOM:
-        
-            pSizer.Insert(0, pWindow, 1, wx.EXPAND)
-        
-        else:
-        
-            # We leave a space of 1 pixel around the window
-            pSizer.Add(pWindow, 1, wx.EXPAND)
-        
-        pWindow.Show()
-
-        pSizer.Layout()
-        self._iActivePage = nMoveTo - 1
-        self._iPreviousActivePage = -1
-        self.DoSetSelection(self._iActivePage)
-        self.Refresh()
-        self._pParent.Thaw()
-
-
-    def CanFitToScreen(self, page):
-        """ Returns wheter a tab can fit in the left space in the screen or not. """
-
-        # Incase the from is greater than page,
-        # we need to reset the self._nFrom, so in order
-        # to force the caller to do so, we return false
-        if self._nFrom > page:
-            return False
-
-        style = self.GetParent().GetWindowStyleFlag()
-        render = self._mgr.GetRenderer(style)
-
-        vTabInfo = render.NumberTabsCanFit(self)
-
-        if page - self._nFrom >= len(vTabInfo):
-            return False
-        
-        return True
-
-
-    def GetNumOfVisibleTabs(self):
-        """ Returns the number of visible tabs. """
-
-        count = 0
-        for ii in xrange(self._nFrom, len(self._pagesInfoVec)):
-            if self._pagesInfoVec[ii].GetPosition() == wx.Point(-1, -1):
-                break
-            count = count + 1
-
-        return count
-
-
-    def GetEnabled(self, page):
-        """ Returns whether a tab is enabled or not. """
-
-        if page >= len(self._pagesInfoVec):
-            return True # Seems strange, but this is the default
-        
-        return self._pagesInfoVec[page].GetEnabled()
-
-
-    def EnableTab(self, page, enabled=True):
-        """ Enables or disables a tab. """
-
-        if page >= len(self._pagesInfoVec):
-            return
-        
-        self._pagesInfoVec[page].EnableTab(enabled)
-        
-
-    def GetSingleLineBorderColour(self):
-        """ Returns the colour for the single line border. """
-
-        if self.HasFlag(FNB_FANCY_TABS):
-            return self._colorFrom
-        
-        return wx.WHITE
-
-
-    def HasFlag(self, flag):
-        """ Returns whether a flag is present in the L{FlatNotebook} style. """
-
-        style = self.GetParent().GetWindowStyleFlag()
-        res = (style & flag and [True] or [False])[0]
-        return res
-
-
-    def ClearFlag(self, flag):
-        """ Deletes a flag from the L{FlatNotebook} style. """
-
-        style = self.GetParent().GetWindowStyleFlag()
-        style &= ~flag 
-        self.SetWindowStyleFlag(style)
-
-
-    def TabHasImage(self, tabIdx):
-        """ Returns whether a tab has an associated image index or not. """
-
-        if self._ImageList:
-            return self._pagesInfoVec[tabIdx].GetImageIndex() != -1
-        
-        return False
-
-
-    def OnLeftDClick(self, event):
-        """ Handles the wx.EVT_LEFT_DCLICK event for L{PageContainer}. """
-
-        where, tabIdx = self.HitTest(event.GetPosition())
-        
-        if where == FNB_RIGHT_ARROW:
-            self.RotateRight()
-
-        elif where == FNB_LEFT_ARROW:
-            self.RotateLeft()
-
-        elif self.HasFlag(FNB_DCLICK_CLOSES_TABS):
-        
-            if where == FNB_TAB:
-                self.DeletePage(tabIdx)
-        
-        else:
-        
-            event.Skip()
-        
-
-    def OnSetFocus(self, event):
-        """ Handles the wx.EVT_SET_FOCUS event for L{PageContainer}. """
-
-        if self._iActivePage < 0:
-            event.Skip()
-            return
-
-        self.SetFocusedPage(self._iActivePage)
-
-
-    def OnKillFocus(self, event):
-        """ Handles the wx.EVT_KILL_FOCUS event for L{PageContainer}. """
-
-        self.SetFocusedPage()
-
-
-    def OnKeyDown(self, event):
-        """
-        When the PageContainer has the focus tabs can be changed with
-        the left/right arrow keys.
-        """
-        key = event.GetKeyCode()
-        if key == wx.WXK_LEFT:
-            self.GetParent().AdvanceSelection(False)
-        elif key == wx.WXK_RIGHT:
-            self.GetParent().AdvanceSelection(True)
-        elif key == wx.WXK_TAB and not event.ControlDown():
-            flags = 0
-            if not event.ShiftDown(): flags |= wx.NavigationKeyEvent.IsForward
-            if event.CmdDown():       flags |= wx.NavigationKeyEvent.WinChange
-            self.Navigate(flags)
-        else:
-            event.Skip()
-
-            
-    def SetFocusedPage(self, pageIndex=-1):
-        """
-        Sets/Unsets the focus on the appropriate page.
-        If pageIndex is defaulted, we have lost focus and no focus indicator is drawn.
-        """
-
-        for indx, page in enumerate(self._pagesInfoVec):
-            if indx == pageIndex:
-                page._hasFocus = True
-            else:
-                page._hasFocus = False
-            
-        self.Refresh()
-                
-
-    def PopupTabsMenu(self):
-        """ Pops up the menu activated with the drop down arrow in the navigation area. """
-
-        popupMenu = wx.Menu()
-
-        for i in xrange(len(self._pagesInfoVec)):
-            pi = self._pagesInfoVec[i]
-            item = wx.MenuItem(popupMenu, i+1, pi.GetCaption(), pi.GetCaption(), wx.ITEM_NORMAL)
-            self.Bind(wx.EVT_MENU, self.OnTabMenuSelection, item)
-
-            # There is an alignment problem with wx2.6.3 & Menus so only use
-            # images for versions above 2.6.3
-            if wx.VERSION > (2, 6, 3, 0) and self.TabHasImage(i):
-                item.SetBitmap(self.GetImageList().GetBitmap(pi.GetImageIndex()))
-
-            popupMenu.AppendItem(item)
-            item.Enable(pi.GetEnabled())
-            
-        self.PopupMenu(popupMenu)
-
-
-    def OnTabMenuSelection(self, event):
-        """ Handles the wx.EVT_MENU event for L{PageContainer}. """
-
-        selection = event.GetId() - 1
-        self.FireEvent(selection)
-
-
-    def FireEvent(self, selection):
-        """
-        Fires the wxEVT_FLATNOTEBOOK_PAGE_CHANGING and wxEVT_FLATNOTEBOOK_PAGE_CHANGED events
-        called from other methods (from menu selection or Smart Tabbing).
-        Utility function.
-        """
-
-        if selection == self._iActivePage:
-            # No events for the same selection
-            return
-        
-        oldSelection = self._iActivePage
-
-        event = FlatNotebookEvent(wxEVT_FLATNOTEBOOK_PAGE_CHANGING, self.GetParent().GetId())
-        event.SetSelection(selection)
-        event.SetOldSelection(oldSelection)
-        event.SetEventObject(self.GetParent())
-        
-        if not self.GetParent().GetEventHandler().ProcessEvent(event) or event.IsAllowed():
-        
-            self.SetSelection(selection)
-
-            # Fire a wxEVT_FLATNOTEBOOK_PAGE_CHANGED event
-            event.SetEventType(wxEVT_FLATNOTEBOOK_PAGE_CHANGED)
-            event.SetOldSelection(oldSelection)
-            self.GetParent().GetEventHandler().ProcessEvent(event)
-#            self.SetFocus()
-            
-
-    def SetImageList(self, imglist):
-        """ Sets the image list for the page control. """
-
-        self._ImageList = imglist
-
-
-    def AssignImageList(self, imglist):
-        """ Assigns the image list for the page control. """
-
-        self._ImageList = imglist
-
-
-    def GetImageList(self):
-        """ Returns the image list for the page control. """
-
-        return self._ImageList
-
-
-    def GetSelection(self):
-        """ Returns the current selected page. """
-
-        return self._iActivePage 
-
-
-    def GetPageCount(self):
-        """ Returns the number of tabs in the L{FlatNotebook} control. """
-
-        return len(self._pagesInfoVec)
-
-
-    def GetPageText(self, page):
-        """ Returns the tab caption of the page. """
-
-        return self._pagesInfoVec[page].GetCaption() 
-
-
-    def SetPageText(self, page, text):
-        """ Sets the tab caption of the page. """
-
-        self._pagesInfoVec[page].SetCaption(text)
-        return True 
-
-
-    def DrawDragHint(self):
-        """ Draws small arrow at the place that the tab will be placed. """
-
-        # get the index of tab that will be replaced with the dragged tab
-        pt = wx.GetMousePosition()
-        client_pt = self.ScreenToClient(pt)
-        where, tabIdx = self.HitTest(client_pt)
-        self._mgr.GetRenderer(self.GetParent().GetWindowStyleFlag()).DrawDragHint(self, tabIdx)
-
-
diff --git a/utils/PyoDoc.py b/utils/PyoDoc.py
old mode 100644
new mode 100755
index 03e145f..6de22e7
--- a/utils/PyoDoc.py
+++ b/utils/PyoDoc.py
@@ -1,14 +1,23 @@
 #!/usr/bin/env python
 # encoding: utf-8
-from __future__ import with_statement
-import subprocess, threading, os
+from __future__ import print_function
+import subprocess, threading, os, sys, unicodedata, inspect
 import wx
-import wx.stc  as  stc
+import wx.stc as stc
 from wx.lib.embeddedimage import PyEmbeddedImage
 from pyo import *
 
+if sys.version_info[0] < 3:
+    unicode_t = unicode
+else:
+    unicode_t = str
+
 DOC_AS_SINGLE_APP = False
 
+PLATFORM = sys.platform
+DEFAULT_ENCODING = sys.getdefaultencoding()
+ENCODING = sys.getfilesystemencoding()
+
 TEMP_PATH = os.path.join(os.path.expanduser('~'), '.epyo')
 if not os.path.isdir(TEMP_PATH):
     os.mkdir(TEMP_PATH)
@@ -19,14 +28,14 @@ DOC_STYLES = {'Default': {'default': '#000000', 'comment': '#007F7F', 'commentbl
                     'number': '#005000', 'string': '#7F007F', 'triple': '#7F0000', 'keyword': '#00007F', 'keyword2': '#007F9F',
                     'class': '#0000FF', 'function': '#007F7F', 'identifier': '#000000', 'caret': '#00007E',
                     'background': '#EEEEEE', 'linenumber': '#000000', 'marginback': '#B0B0B0', 'markerfg': '#CCCCCC',
-                      'markerbg': '#000000', 'bracelight': '#AABBDD', 'bracebad': '#DD0000', 'lineedge': '#CCCCCC'}}
+                    'markerbg': '#000000', 'bracelight': '#AABBDD', 'bracebad': '#DD0000', 'lineedge': '#CCCCCC'}}
 
 if wx.Platform == '__WXMSW__':
   DOC_FACES = {'face': 'Verdana', 'size' : 8, 'size2': 7}
 elif wx.Platform == '__WXMAC__':
   DOC_FACES = {'face': 'Monaco', 'size' : 12, 'size2': 9}
 else:
-  DOC_FACES = {'face': 'Courier New', 'size' : 8, 'size2': 7}
+  DOC_FACES = {'face': 'Monospace', 'size' : 8, 'size2': 7}
 DOC_FACES['size3'] = DOC_FACES['size2'] + 4
 for key, value in DOC_STYLES['Default'].items():
   DOC_FACES[key] = value
@@ -177,25 +186,25 @@ up_24_png = PyEmbeddedImage(
     "3Aey0QOcASDAAN0xfmdOgZiqAAAAAElFTkSuQmCC")
 catalog['up_24.png'] = up_24_png
 
-_INTRO_TEXT =   """
+_INTRO_TEXT = """
 pyo manual version %s
 
 pyo is a Python module written in C to help digital signal processing script creation.
 
-pyo is a Python module containing classes for a wide variety of audio signal processing types. 
-With pyo, user will be able to include signal processing chains directly in Python scripts or 
-projects, and to manipulate them in real-time through the interpreter. Tools in pyo module 
-offer primitives, like mathematical operations on audio signal, basic signal processing 
-(filters, delays, synthesis generators, etc.) together with complex algorithms to create 
-granulation and others creative sound manipulations. pyo supports OSC protocol (Open Sound 
-Control), to ease communications between softwares, and MIDI protocol, for generating sound 
-events and controlling process parameters. pyo allows creation of sophisticated signal 
-processing chains with all the benefits of a mature, and wild used, general programming 
+pyo is a Python module containing classes for a wide variety of audio signal processing types.
+With pyo, user will be able to include signal processing chains directly in Python scripts or
+projects, and to manipulate them in real-time through the interpreter. Tools in pyo module
+offer primitives, like mathematical operations on audio signal, basic signal processing
+(filters, delays, synthesis generators, etc.) together with complex algorithms to create
+granulation and others creative sound manipulations. pyo supports OSC protocol (Open Sound
+Control), to ease communications between softwares, and MIDI protocol, for generating sound
+events and controlling process parameters. pyo allows creation of sophisticated signal
+processing chains with all the benefits of a mature, and wild used, general programming
 language.
 
 Overview:
 
-Server : Main processing audio loop callback handler. 
+Server : Main processing audio loop callback handler.
 PyoObjectBase : Base class for all pyo objects.
 PyoObject : Base class for all pyo objects that manipulate vectors of samples.
 PyoTableObject : Base class for all pyo table objects.
@@ -205,12 +214,20 @@ functions : Miscellaneous functions.
 
 """ % PYO_VERSION
 
-_DOC_KEYWORDS = ['Attributes', 'Examples', 'Methods', 'Notes', 'Methods details', 
-                 'Parentclass', 'Overview', 'Initline', 'Description']
-_HEADERS = ["Server", "PyoObjectBase", "Map", "Stream", "TableStream", "functions"]
-_KEYWORDS_LIST = ['Parameters']
+PYOGUI_DOC = """
+The classes in this module are based on internal classes that where
+originally designed to help the creation of graphical tools for the
+control and the visualization of audio signals. WxPython must be installed
+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", "MidiDispatcher", "OscListener", "PyoGui"]
+_KEYWORDS_LIST = ['SLMap']
 _KEYWORDS_LIST.extend(_HEADERS)
-_KEYWORDS_LIST.append("SLMap")
 _NUM_PAGES = 1
 _NUM_PAGES += len(_HEADERS)
 for k1 in _HEADERS:
@@ -229,14 +246,22 @@ for k1 in _HEADERS:
     else:
         _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)]
+
+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)
@@ -253,10 +278,10 @@ def _ed_set_style(editor, searchKey=None):
     editor.SetTabWidth(4)
     editor.SetUseTabs(False)
 
-    editor.StyleSetSpec(stc.STC_STYLE_DEFAULT,  "fore:%(default)s,face:%(face)s,size:%(size)d,back:%(background)s" % DOC_FACES)
+    editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, "fore:%(default)s,face:%(face)s,size:%(size)d,back:%(background)s" % DOC_FACES)
     editor.StyleClearAll()
-    editor.StyleSetSpec(stc.STC_STYLE_DEFAULT,     "fore:%(default)s,face:%(face)s,size:%(size)d" % DOC_FACES)
-    editor.StyleSetSpec(stc.STC_STYLE_LINENUMBER,  "fore:%(linenumber)s,back:%(marginback)s,face:%(face)s,size:%(size2)d" % DOC_FACES)
+    editor.StyleSetSpec(stc.STC_STYLE_DEFAULT, "fore:%(default)s,face:%(face)s,size:%(size)d" % DOC_FACES)
+    editor.StyleSetSpec(stc.STC_STYLE_LINENUMBER, "fore:%(linenumber)s,back:%(marginback)s,face:%(face)s,size:%(size2)d" % DOC_FACES)
     editor.StyleSetSpec(stc.STC_STYLE_CONTROLCHAR, "fore:%(default)s,face:%(face)s" % DOC_FACES)
     editor.StyleSetSpec(stc.STC_P_DEFAULT, "fore:%(default)s,face:%(face)s,size:%(size)d" % DOC_FACES)
     editor.StyleSetSpec(stc.STC_P_COMMENTLINE, "fore:%(comment)s,face:%(face)s,size:%(size)d" % DOC_FACES)
@@ -292,20 +317,32 @@ class ManualPanel(wx.Treebook):
         wx.Treebook.__init__(self, parent, -1, style=wx.BK_DEFAULT | wx.SUNKEN_BORDER)
         self.parent = parent
         self.searchKey = None
+        self.needToParse = True
         self.Bind(wx.EVT_TREEBOOK_PAGE_CHANGED, self.OnPageChanged)
         self.parse()
-
+        
     def reset_history(self):
         self.fromToolbar = False
         self.oldPage = ""
         self.sequence = []
         self.seq_index = 0
 
+    def deleteAllPagesButOne(self):
+        c = self.GetPageCount()
+        c-= 1
+        while c != 0:
+            self.DeletePage(c)
+            c -= 1
+
     def parse(self):
         self.searchKey = None
-        self.DeleteAllPages()
         self.reset_history()
 
+        makeIntro = True
+        if self.GetPageCount() > 0:
+            self.deleteAllPagesButOne()
+            makeIntro = False
+
         self.needToParse = False
         if not os.path.isdir(DOC_PATH):
             os.mkdir(DOC_PATH)
@@ -320,8 +357,9 @@ class ManualPanel(wx.Treebook):
                 dlg.SetSize((300, 100))
             keepGoing = True
         count = 1
-        win = self.makePanel("Intro")
-        self.AddPage(win, "Intro")
+        if makeIntro:
+            win = self.makePanel("Intro")
+            self.AddPage(win, "Intro")
         for key in _HEADERS:
             if type(OBJECTS_TREE[key]) == type([]):
                 count += 1
@@ -381,11 +419,11 @@ class ManualPanel(wx.Treebook):
             dlg.Destroy()
         self.setStyle()
         self.getPage("Intro")
-        wx.FutureCall(100, self.AdjustSize)
+        wx.CallLater(100, self.AdjustSize)
 
     def parseOnSearchName(self, keyword):
         self.searchKey = None
-        self.DeleteAllPages()
+        self.deleteAllPagesButOne()
         self.reset_history()
 
         keyword = keyword.lower()
@@ -462,7 +500,7 @@ class ManualPanel(wx.Treebook):
 
     def parseOnSearchPage(self, keyword):
         self.searchKey = keyword
-        self.DeleteAllPages()
+        self.deleteAllPagesButOne()
         self.reset_history()
 
         keyword = keyword.lower()
@@ -547,7 +585,6 @@ class ManualPanel(wx.Treebook):
         wx.CallAfter(self.AdjustSize)
 
     def AdjustSize(self):
-        self.GetTreeCtrl().InvalidateBestSize()
         self.SendSizeEvent()
 
     def copy(self):
@@ -620,13 +657,18 @@ class ManualPanel(wx.Treebook):
                 else:
                     try:
                         text = eval(obj).__doc__
-                        text = text.replace(".. note::", "Notes:").replace(".. seealso::", "See also:").replace(":Args:", "Parameters:")
+                        text = text.replace(".. note::", "Notes:").replace(".. seealso::", "See also:").replace(":Args:", "Parameters:").replace(":Events:", "Events:")
                     except:
                         if obj == "functions":
                             text = "Miscellaneous functions...\n\n"
                             text += "\nOverview:\n"
                             for o in OBJECTS_TREE["functions"]:
                                 text += o + ": " + self.getDocFirstLine(o)
+                        elif obj == "PyoGui":
+                            text = PYOGUI_DOC
+                            text += "\nOverview:\n"
+                            for o in OBJECTS_TREE["PyoGui"]:
+                                text += o + ": " + self.getDocFirstLine(o)
                         else:
                             text = "\nNot documented yet...\n\n"
                     if obj in OBJECTS_TREE["PyoObjectBase"]["PyoObject"].keys():
@@ -708,9 +750,11 @@ class ManualPanel(wx.Treebook):
             filter = MAP_METHODS_FILTER
         elif parentclass == "SLMap":
             filter = SLMAP_METHODS_FILTER
+        elif parentclass == "wx.Panel":
+            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__
@@ -786,7 +830,7 @@ class ManualPanel(wx.Treebook):
                 if not panel.isLoad:
                     panel.isLoad = True
                     panel.win = stc.StyledTextCtrl(panel, -1, size=panel.GetSize(), style=wx.SUNKEN_BORDER)
-                    panel.win.LoadFile(os.path.join(DOC_PATH, word))
+                    panel.win.LoadFile(os.path.join(ensureNFD(DOC_PATH), word))
                     panel.win.SetMarginWidth(1, 0)
                     panel.win.Bind(wx.EVT_LEFT_DOWN, self.MouseDown)
                     if self.searchKey != None:
@@ -804,42 +848,6 @@ class ManualPanel(wx.Treebook):
                 self.fromToolbar = False
                 return
 
-    def getMethodsDoc2(self, text, obj):
-        if obj == "Clean_objects":
-            return "Methods details:\n\nClean_objects.start():\n\n    Starts the thread. The timer begins on this call."
-        lines = text.splitlines(True)
-        flag = False
-        methods = ''
-        for line in lines:
-            if flag:
-                if line.strip() == '': continue
-                else:
-                    l = line.lstrip()
-                    ppos = l.find('(')
-                    if ppos != -1:
-                        meth = l[0:ppos]
-                        args, varargs, varkw, defaults = inspect.getargspec(getattr(eval(obj), meth))
-                        args = inspect.formatargspec(args, varargs, varkw, defaults, formatvalue=removeExtraDecimals)
-                        args = args.replace('self, ', '')
-                        methods += obj + '.' + meth + args + ':\n'
-                        docstr = getattr(eval(obj), meth).__doc__.rstrip()
-                        methods += docstr + '\n\n    '
-
-            if 'Methods:' in line: 
-                flag = True
-                methods += '    Methods details:\n\n    '
-
-            for key in _DOC_KEYWORDS:
-                if key != 'Methods':
-                    if key in line: 
-                        flag = False
-
-        methods_form = ''
-        if methods != '':
-            for line in methods.splitlines():
-                methods_form += line[4:] + '\n'
-        return methods_form
-
     def getExampleScript(self):
         stc = self.GetPage(self.GetSelection()).win
         start = stc.LineFromPosition(stc.FindText(0, stc.GetLength(), "Examples:")) + 1
@@ -850,6 +858,7 @@ class ManualPanel(wx.Treebook):
         return text
 
     def setStyle(self):
+        return # TreeBook has no more a GetTreeCtrl method. Don't know how to retrieve it...
         tree = self.GetTreeCtrl()
         tree.SetBackgroundColour(DOC_STYLES['Default']['background'])
         root = tree.GetRootItem()
@@ -865,7 +874,7 @@ class ManualPanel(wx.Treebook):
             (child, cookie) = tree.GetNextChild(root, cookie)
 
 class ManualFrame(wx.Frame):
-    def __init__(self, parent=None, id=-1, title='Pyo Documentation', size=(940, 700), 
+    def __init__(self, parent=None, id=-1, title='Pyo Documentation', size=(940, 700),
                     osx_app_bundled=False, which_python="python",
                     caller_need_to_invoke_32_bit=False,
                     set_32_bit_arch="export VERSIONER_PYTHON_PREFER_32_BIT=yes;"):
@@ -884,32 +893,44 @@ class ManualFrame(wx.Frame):
         tb_size = 24
 
         self.toolbar = self.CreateToolBar()
-        self.toolbar.SetToolBitmapSize((tb_size, tb_size))  # sets icon size
+        self.toolbar.SetToolBitmapSize((tb_size, tb_size)) # sets icon size
 
         back_ico = catalog["previous_%d.png" % tb_size]
         forward_ico = catalog["next_%d.png" % tb_size]
         home_ico = catalog["up_%d.png" % tb_size]
         exec_ico = catalog["play_%d.png" % tb_size]
 
-        backTool = self.toolbar.AddSimpleTool(wx.ID_BACKWARD, back_ico.GetBitmap(), "Back")
+        if sys.version_info[0] < 3:
+            backTool = self.toolbar.AddSimpleTool(wx.ID_BACKWARD, back_ico.GetBitmap(), "Back")
+        else:
+            backTool = self.toolbar.AddTool(wx.ID_BACKWARD, "", back_ico.GetBitmap(), "Back")
         self.toolbar.EnableTool(wx.ID_BACKWARD, False)
         self.Bind(wx.EVT_MENU, self.onBack, backTool)
 
         self.toolbar.AddSeparator()
 
-        forwardTool = self.toolbar.AddSimpleTool(wx.ID_FORWARD, forward_ico.GetBitmap(), "Forward")
+        if sys.version_info[0] < 3:
+            forwardTool = self.toolbar.AddSimpleTool(wx.ID_FORWARD, forward_ico.GetBitmap(), "Forward")
+        else:
+            forwardTool = self.toolbar.AddTool(wx.ID_FORWARD, "", forward_ico.GetBitmap(), "Forward")
         self.toolbar.EnableTool(wx.ID_FORWARD, False)
         self.Bind(wx.EVT_MENU, self.onForward, forwardTool)
 
         self.toolbar.AddSeparator()
 
-        homeTool = self.toolbar.AddSimpleTool(wx.ID_HOME, home_ico.GetBitmap(), "Go Home")
+        if sys.version_info[0] < 3:
+            homeTool = self.toolbar.AddSimpleTool(wx.ID_HOME, home_ico.GetBitmap(), "Go Home")
+        else:
+            homeTool = self.toolbar.AddTool(wx.ID_HOME, "", home_ico.GetBitmap(), "Go Home")
         self.toolbar.EnableTool(wx.ID_HOME, True)
         self.Bind(wx.EVT_MENU, self.onHome, homeTool)
 
         self.toolbar.AddSeparator()
 
-        execTool = self.toolbar.AddSimpleTool(wx.ID_PREVIEW, exec_ico.GetBitmap(), "Run Example")
+        if sys.version_info[0] < 3:
+            execTool = self.toolbar.AddSimpleTool(wx.ID_PREVIEW, exec_ico.GetBitmap(), "Run Example")
+        else:
+            execTool = self.toolbar.AddTool(wx.ID_PREVIEW, "", exec_ico.GetBitmap(), "Run Example")
         self.toolbar.EnableTool(wx.ID_PREVIEW, True)
         self.Bind(wx.EVT_MENU, self.onRun, execTool)
 
@@ -925,7 +946,8 @@ class ManualFrame(wx.Frame):
             self.searchMenu.Append(id, txt)
             self.Bind(wx.EVT_MENU, self.onSearchScope, id=id)
 
-        self.search = wx.SearchCtrl(self.toolbar, 200, size=(200,-1), style=wx.WANTS_CHARS | wx.TE_PROCESS_ENTER)
+        tw, th = self.GetTextExtent("Q")
+        self.search = wx.SearchCtrl(self.toolbar, 200, size=(200,th+6), style=wx.WANTS_CHARS | wx.TE_PROCESS_ENTER)
         self.search.ShowCancelButton(True)
         self.search.SetMenu(self.searchMenu)
         self.toolbar.AddControl(self.search)
@@ -970,7 +992,7 @@ class ManualFrame(wx.Frame):
         self.search.SetFocus()
 
     def onSearchEnter(self, evt):
-        self.doc_panel.GetTreeCtrl().SetFocus()
+        self.doc_panel.SetFocus()
 
     def onSearch(self, evt):
         if self.searchTimer != None:
@@ -1035,7 +1057,7 @@ class ManualFrame(wx.Frame):
             f.write(text)
         th = RunningThread(DOC_EXAMPLE_PATH, TEMP_PATH, self.which_python, self.osx_app_bundled, self.caller_need_to_invoke_32_bit, self.set_32_bit_arch)
         th.start()
-        wx.FutureCall(8000, self.status.SetStatusText, "", 0)
+        wx.CallLater(8000, self.status.SetStatusText, "", 0)
 
 class RunningThread(threading.Thread):
     def __init__(self, path, cwd, which_python, osx_app_bundled, caller_need_to_invoke_32_bit, set_32_bit_arch):
@@ -1050,39 +1072,83 @@ 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:
             vars_to_remove = "PYTHONHOME PYTHONPATH EXECUTABLEPATH RESOURCEPATH ARGVZERO PYTHONOPTIMIZE"
             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)
+                self.proc = subprocess.Popen(["%s%s%s %s" % (prelude, self.set_32_bit_arch, self.which_python, self.path)],
+                                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)
+                self.proc = subprocess.Popen(["%s%s %s" % (prelude, self.which_python, self.path)], cwd=self.cwd,
+                                    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)
+                self.proc = subprocess.Popen(["%s%s %s" % (self.set_32_bit_arch, self.which_python, self.path)],
+                                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)
+                self.proc = subprocess.Popen(["%s %s" % (self.which_python, self.path)], cwd=self.cwd,
+                                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)
+                self.proc = subprocess.Popen([self.which_python, self.path], cwd=self.cwd,
+                                universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 
 
         while self.proc.poll() == None and not self.terminated:
             time.sleep(.25)
 
+def ensureNFD(unistr):
+    if PLATFORM == 'win32' or PLATFORM.startswith('linux'):
+        encodings = [DEFAULT_ENCODING, ENCODING,
+                     'cp1252', 'iso-8859-1', 'utf-16']
+        format = 'NFC'
+    else:
+        encodings = [DEFAULT_ENCODING, ENCODING,
+                     'macroman', 'iso-8859-1', 'utf-16']
+        format = 'NFC'
+    decstr = unistr
+    if type(decstr) != unicode_t:
+        for encoding in encodings:
+            try:
+                decstr = decstr.decode(encoding)
+                break
+            except UnicodeDecodeError:
+                continue
+            except:
+                decstr = "UnableToDecodeString"
+                print("Unicode encoding not in a recognized format...")
+                break
+    if decstr == "UnableToDecodeString":
+        return unistr
+    else:
+        return unicodedata.normalize(format, decstr)
+
+def toSysEncoding(unistr):
+    try:
+        if PLATFORM == "win32":
+            unistr = unistr.encode(ENCODING)
+        else:
+            unistr = unicode(unistr)
+    except:
+        pass
+    return unistr
+
 if __name__ == "__main__":
     DOC_AS_SINGLE_APP = True
-    app = wx.PySimpleApp()
+    app = wx.App()
     doc_frame = ManualFrame()
     doc_frame.Show()
-    app.MainLoop()
+    app.MainLoop()
\ No newline at end of file
diff --git a/utils/epyo_builder_OSX.sh b/utils/epyo_builder_OSX_py2.sh
similarity index 50%
rename from utils/epyo_builder_OSX.sh
rename to utils/epyo_builder_OSX_py2.sh
index a715ead..5f1b5ab 100755
--- a/utils/epyo_builder_OSX.sh
+++ b/utils/epyo_builder_OSX_py2.sh
@@ -1,25 +1,23 @@
 mkdir Resources
 cp PyoDoc.py Resources/
-cp FlatNoteBook.py Resources/
 cp Tutorial_01_RingMod.py Resources/
 cp Tutorial_02_Flanger.py Resources/
 cp Tutorial_03_TriTable.py Resources/
 cp *.icns Resources/
-svn export ../examples examples/
-cp -R examples Resources/
+cp -R ../examples Resources/
 cp -R snippets Resources/
 cp -R styles Resources/
 
 rm -rf build dist
-py2applet --make-setup E-Pyo.py Resources/*
-python setup.py py2app --plist=info.plist
-rm -f setup.py
+
+python2 setup.py py2app
+
 rm -rf build
-mv dist E-Pyo_OSX
+mv dist E-Pyo_OSX_py2
 
-if cd E-Pyo_OSX;
+if cd E-Pyo_OSX_py2;
 then
-    find . -name .svn -depth -exec rm -rf {} \
+    find . -name .git -depth -exec rm -rf {} \
     find . -name *.pyc -depth -exec rm -f {} \
     find . -name .* -depth -exec rm -f {} \;
 else
@@ -27,20 +25,15 @@ else
     exit;
 fi
 
-ditto --rsrc --arch i386 E-Pyo.app E-Pyo-i386.app
+# keep only 64-bit arch
+ditto --rsrc --arch x86_64 E-Pyo.app E-Pyo-x86_64.app
 rm -rf E-Pyo.app
-mv E-Pyo-i386.app E-Pyo.app
-
-cd ..
-cp -R E-Pyo_OSX/E-Pyo.app .
+mv E-Pyo-x86_64.app E-Pyo.app
 
 # Fixed wrong path in Info.plist
 cd E-Pyo.app/Contents
-awk '{gsub("Library/Frameworks/Python.framework/Versions/2.6/Resources/Python.app/Contents/MacOS/Python", "@executable_path/../Frameworks/Python.framework/Versions/2.6/Python")}1' Info.plist > Info.plist_tmp && mv Info.plist_tmp Info.plist
+awk '{gsub("Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python", "@executable_path/../Frameworks/Python.framework/Versions/2.7/Python")}1' Info.plist > Info.plist_tmp && mv Info.plist_tmp Info.plist
+
+cd ../../..
 
-cd ../..
-#tar -cjvf E-Pyo_OSX-0.6.1.tar.bz2 E-Pyo.app
-#rm -rf E-Pyo.app
-rm -rf E-Pyo_OSX
 rm -rf Resources
-rm -rf examples
diff --git a/utils/epyo_builder_OSX_py3.5.sh b/utils/epyo_builder_OSX_py3.5.sh
new file mode 100755
index 0000000..4eb8c35
--- /dev/null
+++ b/utils/epyo_builder_OSX_py3.5.sh
@@ -0,0 +1,42 @@
+mkdir Resources
+cp PyoDoc.py Resources/
+cp Tutorial_01_RingMod.py Resources/
+cp Tutorial_02_Flanger.py Resources/
+cp Tutorial_03_TriTable.py Resources/
+cp *.icns Resources/
+cp -R ../examples Resources/
+cp -R snippets Resources/
+cp -R styles Resources/
+
+rm -rf build dist
+
+python3.5 setup.py py2app
+
+rm -rf build
+mv dist E-Pyo_OSX_py35
+
+if cd E-Pyo_OSX_py35;
+then
+    find . -name .git -depth -exec rm -rf {} \
+    find . -name *.pyc -depth -exec rm -f {} \
+    find . -name .* -depth -exec rm -f {} \;
+else
+    echo "Something wrong. E-Pyo_OSX not created"
+    exit;
+fi
+
+# keep only 64-bit arch
+ditto --rsrc --arch x86_64 E-Pyo.app E-Pyo-x86_64.app
+rm -rf E-Pyo.app
+mv E-Pyo-x86_64.app E-Pyo.app
+
+# py2app does not handle correctly wxpython phoenix dylib imports, add them manually.
+cp /Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/wx/*.dylib E-Pyo.app/Contents/Resources/lib/python3.5/lib-dynload/wx/
+
+# Fixed wrong path in Info.plist
+cd E-Pyo.app/Contents
+awk '{gsub("/Library/Frameworks/Python.framework/Versions/3.5/bin/python3", "@executable_path/../Frameworks/Python.framework/Versions/3.5/Python")}1' Info.plist > Info.plist_tmp && mv Info.plist_tmp Info.plist
+
+cd ../../..
+
+rm -rf Resources
diff --git a/utils/epyo_builder_OSX_py3.6.sh b/utils/epyo_builder_OSX_py3.6.sh
new file mode 100755
index 0000000..654d2dd
--- /dev/null
+++ b/utils/epyo_builder_OSX_py3.6.sh
@@ -0,0 +1,42 @@
+mkdir Resources
+cp PyoDoc.py Resources/
+cp Tutorial_01_RingMod.py Resources/
+cp Tutorial_02_Flanger.py Resources/
+cp Tutorial_03_TriTable.py Resources/
+cp *.icns Resources/
+cp -R ../examples Resources/
+cp -R snippets Resources/
+cp -R styles Resources/
+
+rm -rf build dist
+
+python3.6 setup.py py2app
+
+rm -rf build
+mv dist E-Pyo_OSX_py36
+
+if cd E-Pyo_OSX_py36;
+then
+    find . -name .git -depth -exec rm -rf {} \
+    find . -name *.pyc -depth -exec rm -f {} \
+    find . -name .* -depth -exec rm -f {} \;
+else
+    echo "Something wrong. E-Pyo_OSX not created"
+    exit;
+fi
+
+# keep only 64-bit arch
+ditto --rsrc --arch x86_64 E-Pyo.app E-Pyo-x86_64.app
+rm -rf E-Pyo.app
+mv E-Pyo-x86_64.app E-Pyo.app
+
+# py2app does not handle correctly wxpython phoenix dylib imports, add them manually.
+cp /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/wx/*.dylib E-Pyo.app/Contents/Resources/lib/python3.6/lib-dynload/wx/
+
+# Fixed wrong path in Info.plist
+cd E-Pyo.app/Contents
+awk '{gsub("/Library/Frameworks/Python.framework/Versions/3.6/bin/python3", "@executable_path/../Frameworks/Python.framework/Versions/3.6/Python")}1' Info.plist > Info.plist_tmp && mv Info.plist_tmp Info.plist
+
+cd ../../..
+
+rm -rf Resources
diff --git a/utils/epyo_builder_win32.py b/utils/epyo_builder_win32.py
index e4265c3..04d620e 100644
--- a/utils/epyo_builder_win32.py
+++ b/utils/epyo_builder_win32.py
@@ -4,20 +4,19 @@ version = sys.version_info[:2]
 
 os.mkdir("Resources")
 shutil.copy("PyoDoc.py", "Resources")
-shutil.copy("FlatNoteBook.py", "Resources")
 shutil.copy("Tutorial_01_RingMod.py", "Resources")
 shutil.copy("Tutorial_02_Flanger.py", "Resources")
 shutil.copy("Tutorial_03_TriTable.py", "Resources")
 shutil.copy("E-PyoIcon.ico", "Resources")
 shutil.copy("E-PyoIconDoc.ico", "Resources")
+shutil.copytree("../examples", "Resources/examples")
+shutil.copytree("snippets", "Resources/snippets")
+shutil.copytree("styles", "Resources/styles")
 
-os.system("svn export ../examples Resources/examples/")
-os.system("svn export snippets Resources/snippets/")
-os.system("svn export styles Resources/styles/")
-
-os.system("C:\Python%d%d\python ..\..\pyinstaller\Configure.py" % version)
-os.system('C:\Python%d%d\python ..\..\pyinstaller\Makespec.py -F -c --icon=Resources\E-PyoIcon.ico "E-Pyo.py"' % version)
-os.system('C:\Python%d%d\python ..\..\pyinstaller\Build.py "E-Pyo.spec"' % version)
+if version[0] < 3:
+    os.system('C:\Python%d%d\Scripts\pyinstaller --clean -F -c --icon=Resources\E-PyoIcon.ico "E-Pyo.py"' % version)
+else:
+    os.system('C:\\Users\olivier\AppData\Local\Programs\Python\Python%d%d-32\Scripts\pyinstaller --clean -F -c --icon=Resources\E-PyoIcon.ico "E-Pyo.py"' % version)
 
 os.mkdir("E-Pyo_py%d%d" % version)
 shutil.copytree("Resources", "E-Pyo_py%d%d/Resources" % version)
diff --git a/utils/info.plist b/utils/info.plist
deleted file mode 100644
index b43497a..0000000
--- a/utils/info.plist
+++ /dev/null
@@ -1,103 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
-<plist version="1.0">
-<dict>
-	<key>CFBundleDevelopmentRegion</key>
-	<string>English</string>
-	<key>CFBundleDisplayName</key>
-	<string>E-Pyo</string>
-	<key>CFBundleDocumentTypes</key>
-	<array>
-		<dict>
-			<key>CFBundleTypeOSTypes</key>
-			<array>
-				<string>TEXT</string>
-			</array>
-			<key>CFBundleTypeExtensions</key>
-			<array>
-				<string>py</string>
-			</array>
-			<key>CFBundleTypeRole</key>
-			<string>Editor</string>
-			<key>CFBundleTypeIconFile</key>
-			<string>E-PyoIconDoc.icns</string>
-			<key>LSIsAppleDefaultForType</key>
-			<false/>
-		</dict>
-	</array>
-	<key>CFBundleExecutable</key>
-	<string>E-Pyo</string>
-	<key>CFBundleIconFile</key>
-	<string>E-PyoIcon.icns</string>
-	<key>CFBundleIdentifier</key>
-	<string>org.pythonmac.unspecified.E-Pyo</string>
-	<key>CFBundleInfoDictionaryVersion</key>
-	<string>0.6.8</string>
-	<key>CFBundleName</key>
-	<string>E-Pyo</string>
-	<key>CFBundlePackageType</key>
-	<string>APPL</string>
-	<key>CFBundleShortVersionString</key>
-	<string>0.6.8</string>
-	<key>CFBundleSignature</key>
-	<string>????</string>
-	<key>CFBundleVersion</key>
-	<string>0.6.8</string>
-	<key>LSHasLocalizedDisplayName</key>
-	<false/>
-	<key>NSAppleScriptEnabled</key>
-	<false/>
-	<key>NSHumanReadableCopyright</key>
-	<string>Copyright not specified</string>
-	<key>NSMainNibFile</key>
-	<string>MainMenu</string>
-	<key>NSPrincipalClass</key>
-	<string>NSApplication</string>
-	<key>PyMainFileNames</key>
-	<array>
-		<string>__boot__</string>
-	</array>
-	<key>PyOptions</key>
-	<dict>
-		<key>alias</key>
-		<false/>
-		<key>argv_emulation</key>
-		<true/>
-		<key>no_chdir</key>
-		<false/>
-		<key>optimize</key>
-		<integer>0</integer>
-		<key>prefer_ppc</key>
-		<false/>
-		<key>site_packages</key>
-		<false/>
-		<key>use_pythonpath</key>
-		<false/>
-	</dict>
-	<key>PyResourcePackages</key>
-	<array/>
-	<key>PyRuntimeLocations</key>
-	<array>
-		<string>@executable_path/../Frameworks/Python.framework/Versions/2.6/Python</string>
-	</array>
-	<key>PythonInfoDict</key>
-	<dict>
-		<key>PythonExecutable</key>
-		<string>@executable_path/../Frameworks/Python.framework/Versions/2.6/Python</string>
-		<key>PythonLongVersion</key>
-		<string>2.6.5 (r265:79359, Mar 24 2010, 01:32:55) 
-[GCC 4.0.1 (Apple Inc. build 5493)]</string>
-		<key>PythonShortVersion</key>
-		<string>2.6</string>
-		<key>py2app</key>
-		<dict>
-			<key>alias</key>
-			<false/>
-			<key>template</key>
-			<string>app</string>
-			<key>version</key>
-			<string>0.4.4</string>
-		</dict>
-	</dict>
-</dict>
-</plist>
diff --git a/utils/setup.py b/utils/setup.py
new file mode 100644
index 0000000..52e4e9e
--- /dev/null
+++ b/utils/setup.py
@@ -0,0 +1,38 @@
+"""
+This is a setup.py script generated by py2applet
+
+Usage:
+    python setup.py py2app
+"""
+from setuptools import setup
+
+APP = ['E-Pyo.py']
+APP_NAME = 'E-Pyo'
+DATA_FILES = ['Resources/']
+OPTIONS = {'argv_emulation': False,
+           'iconfile': 'E-PyoIcon.icns',
+           'plist': {
+               'CFBundleDisplayName': 'E-Pyo',
+               'CFBundleExecutable': 'E-Pyo',
+               'CFBundleIconFile': 'E-PyoIcon.icns',
+               'CFBundleIdentifier': 'com.ajaxsoundstudio.E-Pyo',
+               'CFBundleInfoDictionaryVersion': '0.8.7',
+               'CFBundleName': 'E-Pyo',
+               'CFBundlePackageType': 'APPL',
+               'CFBundleShortVersionString': '0.8.7',
+               'CFBundleVersion': '0.8.7',
+               'CFBundleDocumentTypes': [{'CFBundleTypeOSTypes': ['TEXT'],
+                                          'CFBundleTypeExtensions': ['py'],
+                                          'CFBundleTypeRole': 'Editor',
+                                          'CFBundleTypeIconFile': 'E-PyoIconDoc.icns',
+                                          'LSIsAppleDefaultForType': False}]
+           }
+       }
+
+setup(
+    name=APP_NAME,
+    app=APP,
+    data_files=DATA_FILES,
+    options={'py2app': OPTIONS},
+    setup_requires=['py2app'],
+)
diff --git a/utils/snippets/Utilities/Incrementor b/utils/snippets/Utilities/Incrementor
index 1595907..325608f 100644
--- a/utils/snippets/Utilities/Incrementor
+++ b/utils/snippets/Utilities/Incrementor
@@ -1 +1 @@
-snippet = {'shortcut': u'Shift-Alt-8', 'value': u'count = 0\ndef incrementor():\n    global count\n    count += 1\n    print count\n\npat = Pattern(function=incrementor, time=1).play()\n'}
\ No newline at end of file
+snippet = {'shortcut': u'Shift-Alt-8', 'value': u'count = 0\ndef incrementor():\n    global count\n    count += 1\n    print(count)\n\npat = Pattern(function=incrementor, time=1).play()\n'}
diff --git a/work-in-progress/EventParser.py b/work-in-progress/EventParser.py
new file mode 100644
index 0000000..6d36144
--- /dev/null
+++ b/work-in-progress/EventParser.py
@@ -0,0 +1,63 @@
+"""
+EventParser first draft (very very alpha stage!).
+
+Score format:
+
+Class_name => starttime duration *args **kwargs
+
+Class_name {class reference}: The name of the class which should play the event,
+starttime {float}: Start time of the event, in seconds. 
+duration {float}: Start time of the event, in seconds.
+*args {list of floats}: user-defined arguments (optional).
+**kwargs {dictionary}: user-defined keyword arguments (optional).
+ 
+"""
+# Notes:
+# We should be able to define an event using multiple lines.
+# Actually, the parser uses splitlines() to separate events.
+# How to automatically use globals() from the __main__ module, I don't
+# want to ask the user to pass globals() to have access to instrument classes.
+
+class EventParser:
+    def __init__(self, server, score="", globals=None):
+        self.server = server
+        self.globals = globals
+        self._instruments = {}
+        self.parse(score)
+
+    def extractKwArgs(self, args):
+        kwargs = ""
+        if "{" in args:
+            p1 = args.find("{")
+            args, kwargs = args[:p1], args[p1:]
+        if kwargs:
+            kwargs = eval(kwargs)
+        return args, kwargs
+
+    def parse(self, score):
+        for line in score.splitlines():
+            if line.strip() == "":
+                continue
+            instr, args = line.split("=>")
+            instr = instr.strip()
+            args, kwargs = self.extractKwArgs(args)
+            args = [float(x) for x in args.split()] # should also eval variable
+                                                    # names, not just numbers
+            if instr not in self._instruments:
+                self._instruments[instr] = [{"args": args, "kwargs": kwargs}]
+            else:
+                self._instruments[instr].append({"args": args, "kwargs": kwargs})
+
+    def play(self):
+        self._playing = []
+        for instr in self._instruments:
+            for event in self._instruments[instr]:
+                self.server.setGlobalDel(event["args"][0])
+                self.server.setGlobalDur(event["args"][1] + 0.2)
+                if not event["kwargs"]:
+                    self._playing.append(self.globals[instr](*event["args"][1:]))
+                else:
+                    self._playing.append(self.globals[instr](*event["args"][1:], 
+                                                             **event["kwargs"]))
+        self.server.setGlobalDel(0)
+        self.server.setGlobalDur(0)
diff --git a/work-in-progress/keyboard_widget.py b/work-in-progress/keyboard_widget.py
new file mode 100644
index 0000000..bfa1693
--- /dev/null
+++ b/work-in-progress/keyboard_widget.py
@@ -0,0 +1,292 @@
+import sys
+import wx
+
+KEYBOARD_BACKGROUND_COLOUR = "#CCCCCC"
+
+class Keyboard(wx.Panel):
+    def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
+                 size=wx.DefaultSize, poly=64, style=wx.TAB_TRAVERSAL):
+        wx.Panel.__init__(self, parent, id, pos, size, style)
+        self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)  
+        self.SetBackgroundColour(KEYBOARD_BACKGROUND_COLOUR)
+        self.parent = parent
+
+        self.poly = poly
+        self.gap = 0
+        self.offset = 12
+        self.w1 = 15
+        self.w2 = self.w1 // 2 + 1
+        self.hold = 1
+        self.keyPressed = None
+
+        self.Bind(wx.EVT_LEFT_DOWN, self.MouseDown)
+        self.Bind(wx.EVT_LEFT_UP, self.MouseUp)
+        self.Bind(wx.EVT_PAINT, self.OnPaint)
+        self.Bind(wx.EVT_SIZE, self.OnSize)
+
+        self.white = (0, 2, 4, 5, 7, 9, 11)
+        self.black = (1, 3, 6, 8, 10)
+        self.whiteSelected = []
+        self.blackSelected = []
+        self.whiteVelocities = {}
+        self.blackVelocities = {}
+        self.whiteKeys = []
+        self.blackKeys = []
+
+        wx.CallAfter(self.setRects)
+   
+    def getNotes(self):
+        notes = []
+        for key in self.whiteSelected:
+            notes.append((self.white[key % 7] + key // 7 * 12  + self.offset,
+                          127 - self.whiteVelocities[key]))
+        for key in self.blackSelected:
+            notes.append((self.black[key % 5] + key // 5 * 12  + self.offset,
+                          127 - self.blackVelocities[key]))
+        notes.sort()
+        return notes
+
+    def reset(self):
+        self.whiteSelected = []
+        self.blackSelected = []
+        self.whiteVelocities = {}
+        self.blackVelocities = {}
+        wx.CallAfter(self.Refresh)
+    
+    def setPoly(self, poly):
+        self.poly = poly
+    
+    def setRects(self):
+        w, h = self.GetSize()
+        self.offRec = wx.Rect(w - 55, 0, 21, h)
+        self.holdRec = wx.Rect(w - 34, 0, 21, h)
+        num = w // self.w1
+        self.gap = w - num * self.w1
+        self.whiteKeys = [wx.Rect(i * self.w1, 0, self.w1 - 1, h) for i in range(num)]
+        self.blackKeys = []
+        height2 = h * 4 // 7
+        for i in range(num // 7 + 1):
+            space2 = self.w1 * 7 * i
+            off = self.w1 // 2 + space2 + 3
+            self.blackKeys.append(wx.Rect(off, 0, self.w2, height2))
+            off += self.w1
+            self.blackKeys.append(wx.Rect(off, 0, self.w2, height2))
+            off += self.w1 * 2
+            self.blackKeys.append(wx.Rect(off, 0, self.w2, height2))
+            off += self.w1
+            self.blackKeys.append(wx.Rect(off, 0, self.w2, height2))
+            off += self.w1
+            self.blackKeys.append(wx.Rect(off, 0, self.w2, height2))
+        wx.CallAfter(self.Refresh)
+    
+    def OnSize(self, evt):
+        self.setRects()
+        wx.CallAfter(self.Refresh)
+
+    def MouseUp(self, evt):
+        if not self.hold and self.keyPressed is not None:
+            key = self.keyPressed[0]
+            pit = self.keyPressed[1]
+            if key in self.blackSelected:
+                self.blackSelected.remove(key)
+                del self.blackVelocities[key]
+            if key in self.whiteSelected:
+                self.whiteSelected.remove(key)
+                del self.whiteVelocities[key]
+            note = (pit, 0)
+            self.keyPressed = None
+            wx.CallAfter(self.Refresh)
+
+    def MouseDown(self, evt):
+        w,h = self.GetSize()
+        pos = evt.GetPosition()
+        if self.holdRec.Contains(pos):
+            if self.hold:
+                self.hold = 0
+            else:
+                self.hold = 1
+            wx.CallAfter(self.Refresh)
+            return
+        if self.offUpRec.Contains(pos):
+            self.offset += 12
+            if self.offset > 60:
+                self.offset = 60
+            wx.CallAfter(self.Refresh)
+            return
+        if self.offDownRec.Contains(pos):
+            self.offset -= 12
+            if self.offset < 0:
+                self.offset = 0
+            wx.CallAfter(self.Refresh)
+            return
+
+        total = len(self.blackSelected) + len(self.whiteSelected)
+        scanWhite = True
+        note = None
+        if self.hold:
+            for i, rec in enumerate(self.blackKeys):
+                if rec.Contains(pos):
+                    pit = self.black[i % 5] + i // 5 * 12  + self.offset
+                    if i in self.blackSelected:
+                        self.blackSelected.remove(i)
+                        del self.blackVelocities[i]
+                        vel = 0
+                    else:
+                        hb = h * 4 // 7
+                        vel = (hb - pos[1]) * 127 // hb
+                        if total < self.poly:
+                            self.blackSelected.append(i)
+                            self.blackVelocities[i] = int(127 - vel)
+                    note = (pit, vel)
+                    scanWhite = False
+                    break
+            if scanWhite:
+                for i, rec in enumerate(self.whiteKeys):
+                    if rec.Contains(pos):
+                        pit = self.white[i % 7] + i // 7 * 12  + self.offset
+                        if i in self.whiteSelected:
+                            self.whiteSelected.remove(i)
+                            del self.whiteVelocities[i]
+                            vel = 0
+                        else:
+                            vel = (h - pos[1]) * 127 // h
+                            if total < self.poly:
+                                self.whiteSelected.append(i)
+                                self.whiteVelocities[i] = int(127 - vel)
+                        note = (pit, vel)
+                        break
+            if note:
+                if note[1] == 0:
+                    pass
+                elif total < self.poly:
+                    pass
+        else:
+            self.keyPressed = None
+            for i, rec in enumerate(self.blackKeys):
+                if rec.Contains(pos):
+                    pit = self.black[i % 5] + i // 5 * 12  + self.offset
+                    if i not in self.blackSelected:
+                        hb = h * 4 // 7
+                        vel = (hb - pos[1]) * 127 // hb
+                        if total < self.poly:
+                            self.blackSelected.append(i)
+                            self.blackVelocities[i] = int(127 - vel)
+                    note = (pit, vel)
+                    self.keyPressed = (i, pit)
+                    scanWhite = False
+                    break
+            if scanWhite:
+                for i, rec in enumerate(self.whiteKeys):
+                    if rec.Contains(pos):
+                        pit = self.white[i % 7] + i // 7 * 12 + self.offset
+                        if i not in self.whiteSelected:
+                            vel = (h - pos[1]) * 127 // h
+                            if total < self.poly:
+                                self.whiteSelected.append(i)
+                                self.whiteVelocities[i] = int(127 - vel)
+                        note = (pit, vel)
+                        self.keyPressed = (i, pit)
+                        break
+            if note:
+                if total < self.poly:
+                    pass
+        wx.CallAfter(self.Refresh)
+    
+    def OnPaint(self, evt):
+        w,h = self.GetSize()
+        dc = wx.AutoBufferedPaintDC(self)
+        dc.SetBrush(wx.Brush("#000000", wx.SOLID))
+        dc.Clear()
+        dc.SetPen(wx.Pen("#000000", width=1, style=wx.SOLID))
+        dc.DrawRectangle(0, 0, w, h)
+
+        if sys.platform == "darwin":
+            dc.SetFont(wx.Font(12, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL,
+                               wx.FONTWEIGHT_BOLD))
+        else:
+            dc.SetFont(wx.Font(8, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL,
+                               wx.FONTWEIGHT_BOLD))
+
+        for i, rec in enumerate(self.whiteKeys):
+            if i in self.whiteSelected:
+                amp = int(self.whiteVelocities[i] * 1.5)
+                dc.GradientFillLinear(rec, (250, 250, 250), (amp, amp, amp), wx.SOUTH)
+                dc.SetBrush(wx.Brush("#CCCCCC", wx.SOLID))
+                dc.SetPen(wx.Pen("#CCCCCC", width=1, style=wx.SOLID))
+            else:
+                dc.SetBrush(wx.Brush("#FFFFFF", wx.SOLID))
+                dc.SetPen(wx.Pen("#FFFFFF", width=1, style=wx.SOLID))
+                dc.DrawRectangle(rec)
+            if i == (35 - (7 * (self.offset // 12))):
+                if i in self.whiteSelected:
+                    dc.SetTextForeground("#FFFFFF")
+                else:
+                    dc.SetTextForeground("#000000")
+                dc.DrawText("C", rec[0] + 3, rec[3] - 15)
+    
+        dc.SetPen(wx.Pen("#000000", width=1, style=wx.SOLID))
+        for i, rec in enumerate(self.blackKeys):
+            if i in self.blackSelected:
+                amp = int(self.blackVelocities[i] * 1.5)
+                dc.GradientFillLinear(rec, (250, 250, 250), (amp, amp, amp), wx.SOUTH)
+                dc.DrawLine(rec[0], 0, rec[0], rec[3])
+                dc.DrawLine(rec[0] + rec[2], 0, rec[0] + rec[2], rec[3])
+                dc.DrawLine(rec[0], rec[3], rec[0] + rec[2], rec[3])
+                dc.SetBrush(wx.Brush("#DDDDDD", wx.SOLID))
+            else:
+                dc.SetBrush(wx.Brush("#000000", wx.SOLID))
+                dc.SetPen(wx.Pen("#000000", width=1, style=wx.SOLID))
+                dc.DrawRectangle(rec)
+    
+        dc.SetBrush(wx.Brush(KEYBOARD_BACKGROUND_COLOUR, wx.SOLID))
+        dc.SetPen(wx.Pen("#AAAAAA", width=1, style=wx.SOLID))
+        dc.DrawRectangle(self.offRec)
+        dc.DrawRectangle(self.holdRec)
+        dc.DrawRectangle(wx.Rect(w - 14, 0, 14, h))
+        
+        dc.SetTextForeground("#000000")
+        dc.DrawText("oct", self.offRec[0] + 3, 15)
+        x1, y1 = self.offRec[0], self.offRec[1]
+        dc.SetBrush(wx.Brush("#000000", wx.SOLID))
+        if sys.platform == "darwin":
+            dc.DrawPolygon([wx.Point(x1 + 3, 36), wx.Point(x1 + 10, 29),
+                            wx.Point(x1 + 17, 36)])
+            self.offUpRec = wx.Rect(x1, 28, x1 + 20, 10)
+            dc.DrawPolygon([wx.Point(x1 + 3, 55), wx.Point(x1 + 10, 62),
+                            wx.Point(x1 + 17, 55)])
+            self.offDownRec = wx.Rect(x1, 54, x1 + 20, 10)
+        else:
+            dc.DrawPolygon([wx.Point(x1 + 3, 38), wx.Point(x1 + 10, 31),
+                            wx.Point(x1 + 17, 38)])
+            self.offUpRec = wx.Rect(x1, 30, x1 + 20, 10)
+            dc.DrawPolygon([wx.Point(x1 + 3, 57), wx.Point(x1 + 10, 64),
+                            wx.Point(x1 + 17, 57)])
+            self.offDownRec = wx.Rect(x1, 56, x1 + 20, 10)
+            
+        dc.DrawText("%d" % (self.offset // 12), x1 + 7, 41)
+    
+        if self.hold:
+            dc.SetTextForeground("#0000CC")
+        else:
+            dc.SetTextForeground("#000000")
+        for i, c in enumerate("HOLD"):
+            dc.DrawText(c, self.holdRec[0] + 6, self.holdRec[3] // 6 * i + 15)
+        
+        dc.SetBrush(wx.Brush(KEYBOARD_BACKGROUND_COLOUR, wx.SOLID))
+        dc.SetPen(wx.Pen(KEYBOARD_BACKGROUND_COLOUR, width=1, style=wx.SOLID))
+        dc.DrawRectangle(w - self.gap, 0, self.gap, h)
+        dc.SetPen(wx.Pen("#000000", width=1, style=wx.SOLID))
+        dc.DrawLine(0, 3, w, 3)
+        dc.SetPen(wx.Pen("#444444", width=1, style=wx.SOLID))
+        dc.DrawLine(0, 2, w, 2)
+        dc.SetPen(wx.Pen("#888888", width=1, style=wx.SOLID))
+        dc.DrawLine(0, 1, w, 1)
+        dc.SetPen(wx.Pen("#CCCCCC", width=1, style=wx.SOLID))
+        dc.DrawLine(0, 0, w, 0)
+
+if __name__ == "__main__":
+    app = wx.App()
+    frame = wx.Frame(None, title="Piano keyboard test", size=(650, 110))
+    keyboard = Keyboard(frame)
+    frame.Show()
+    app.MainLoop()
diff --git a/work-in-progress/test_event_parser.py b/work-in-progress/test_event_parser.py
new file mode 100644
index 0000000..81703fa
--- /dev/null
+++ b/work-in-progress/test_event_parser.py
@@ -0,0 +1,69 @@
+import random
+from pyo import *
+from EventParser import EventParser
+
+### Orchestra ###
+class Instr1:
+    def __init__(self, duration, *args):
+        self.f = Fader(0.001, duration-0.005, duration, args[1]).play()
+        self.f.setExp(3)
+        self.osc = SineLoop([args[0], args[0]*1.01], feedback=0.12, mul=self.f)
+        self.filt = ButHP(self.osc, args[0]).out()
+
+class Rhythm:
+    def __init__(self, duration, *args):
+        self.env = CosTable([(0,0), (32,1), (1000,.25), (8191,0)])
+        rhythms = [[2,2,1,1,1,1,4], [1,2,1,2,2,1,2,1,2,1,1],[4,2,1,1,2,2,1.3,1.3,1.4]]
+        self.seq = Seq(.125, random.choice(rhythms), poly=1, onlyonce=True).play()
+        self.amp = TrigEnv(self.seq, self.env, .125, mul=args[1])
+        self.osc = Lorenz([args[0], args[0]*1.01], args[2], True, mul=self.amp)
+        self.disto = Disto(self.osc, drive=0.9, slope=0.9, mul=0.4)
+        self.bp = ButBP(self.disto, freq=1000, q=0.7).out()
+
+class Chord:
+    def __init__(self, duration, *args, **kwargs):
+        self.f = Fader(1, 1, duration, args[0]).play()
+        self.o1 = LFO(kwargs["f1"], sharp=0.95, type=2, mul=self.f).out()
+        self.o2 = LFO(kwargs["f2"], sharp=0.95, type=2, mul=self.f).out(1)
+        self.o3 = LFO(kwargs["f3"], sharp=0.95, type=2, mul=self.f).out()
+        self.o4 = LFO(kwargs["f4"], sharp=0.95, type=2, mul=self.f).out(1)
+
+### Little score generator ###
+sc = ""
+starttime = 8
+for i in range(300):
+    template = "Instr1 => %f %f %f %f\n"
+    dur = random.choice([.25, .75, 1])
+    freq = random.choice(midiToHz([67,70,72,75,79,84,86,87,91]))
+    amp = random.uniform(0.08, 0.15)
+    sc = sc + template % (starttime, dur, freq, amp)
+    starttime += random.choice([.125, .125, .25, .25])
+for i in range(65):
+    template = "Rhythm => %f %f %f %f %f\n"
+    pit = random.uniform(0.9, 1.0)
+    amp = random.uniform(0.1, 0.2)
+    chaos = random.uniform(0.8, 1.0)
+    sc = sc + template % (i, 1, pit, amp, chaos)
+for i in range(17):
+    template = "Chord => %f 5 0.03 %s\n"
+    notes = midiToHz([48.01,55.02,59.99,63.01,67,69.98,72.03,75.04])
+    cdict = {"f1": random.choice(notes), "f2": random.choice(notes),
+             "f3": random.choice(notes), "f4": random.choice(notes)}
+    sc = sc + template % (i * 4, str(cdict))
+
+### Rendering ###
+REALTIME = True
+
+if REALTIME:
+    s = Server().boot()
+else:
+    s = Server(buffersize=8, audio="offline").boot()
+    s.recordOptions(dur=70, filename="rendered_score.wav")
+
+reader = EventParser(s, sc, globals())
+reader.play()
+
+if REALTIME:
+    s.gui(locals())
+else:
+    s.start()
\ No newline at end of file

-- 
python-pyo packaging



More information about the pkg-multimedia-commits mailing list