[SCM] python-pyo/master: Imported Upstream version 0.6.9
tiago at users.alioth.debian.org
tiago at users.alioth.debian.org
Sun Apr 13 04:14:14 UTC 2014
The following commit has been merged in the master branch:
commit da14e9b15dca57a5131d683f8cbfb975354dece8
Author: Tiago Bortoletto Vaz <tiago at debian.org>
Date: Sun Apr 13 00:12:46 2014 -0400
Imported Upstream version 0.6.9
diff --git a/ChangeLog b/ChangeLog
index ef1d32f..e792be3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,48 @@
2013-10-16 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>
+
* Release tag: 0.6.8.
- rev 1142
diff --git a/doc-sphinx/source/api/alphabetical.rst b/doc-sphinx/source/api/alphabetical.rst
index 3b2862b..3ad686f 100644
--- a/doc-sphinx/source/api/alphabetical.rst
+++ b/doc-sphinx/source/api/alphabetical.rst
@@ -39,6 +39,7 @@ Alphabetical class reference
- :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.
@@ -153,11 +154,13 @@ Alphabetical class reference
- :py:class:`PVVerb` : Spectral domain reverberation.
- :py:class:`Pan` : Cosinus panner with control on the spread factor.
- :py:class:`ParaTable` : Generates parabola window function.
+- :py:class:`PartialTable` : Inharmonic waveform generator.
- :py:class:`Pattern` : Periodically calls a Python function.
- :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:`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.
@@ -183,6 +186,7 @@ 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:`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.
@@ -219,6 +223,7 @@ Alphabetical class reference
- :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:`TrigChoice` : Random generator from user's defined values.
- :py:class:`TrigEnv` : Envelope reader generator.
diff --git a/doc-sphinx/source/api/classes/effects.rst b/doc-sphinx/source/api/classes/effects.rst
index be32c61..4a3ce41 100644
--- a/doc-sphinx/source/api/classes/effects.rst
+++ b/doc-sphinx/source/api/classes/effects.rst
@@ -78,3 +78,9 @@ as distortions, delays, chorus and reverbs.
.. autoclass:: FreqShift
:members:
+*STRev*
+------------
+
+.. autoclass:: STRev
+ :members:
+
diff --git a/doc-sphinx/source/api/classes/filters.rst b/doc-sphinx/source/api/classes/filters.rst
index 865fb9a..358744b 100644
--- a/doc-sphinx/source/api/classes/filters.rst
+++ b/doc-sphinx/source/api/classes/filters.rst
@@ -180,4 +180,9 @@ sinusoidal component according to its frequency.
.. autoclass:: ButBR
:members:
+*ComplexRes*
+------------
+
+.. autoclass:: ComplexRes
+ :members:
diff --git a/doc-sphinx/source/api/classes/tableprocess.rst b/doc-sphinx/source/api/classes/tableprocess.rst
index 3ad98e6..bbb09d2 100644
--- a/doc-sphinx/source/api/classes/tableprocess.rst
+++ b/doc-sphinx/source/api/classes/tableprocess.rst
@@ -62,6 +62,12 @@ store audio samples or algorithmic sequences for future uses.
.. autoclass:: Pointer
:members:
+*Pointer2*
+-----------------------------------
+
+.. autoclass:: Pointer2
+ :members:
+
*Pulsar*
-----------------------------------
diff --git a/doc-sphinx/source/api/classes/utils.rst b/doc-sphinx/source/api/classes/utils.rst
index 58ebb12..c84bbab 100644
--- a/doc-sphinx/source/api/classes/utils.rst
+++ b/doc-sphinx/source/api/classes/utils.rst
@@ -125,3 +125,9 @@ Miscellaneous objects.
.. autoclass:: TranspoToCents
:members:
+*TrackHold*
+-----------------------------------
+
+.. autoclass:: TrackHold
+ :members:
+
diff --git a/doc-sphinx/source/api/functions/audio.rst b/doc-sphinx/source/api/functions/audio.rst
index d9b36ec..eeff482 100644
--- a/doc-sphinx/source/api/functions/audio.rst
+++ b/doc-sphinx/source/api/functions/audio.rst
@@ -3,6 +3,16 @@ Audio Setup
.. module:: pyo
+*pa_get_version*
+---------------------------------
+
+.. autofunction:: pa_get_version
+
+*pa_get_version_text*
+---------------------------------
+
+.. autofunction:: pa_get_version_text
+
*pa_count_host_apis*
---------------------------------
diff --git a/doc-sphinx/source/conf.py b/doc-sphinx/source/conf.py
index 55ad51d..413f581 100644
--- a/doc-sphinx/source/conf.py
+++ b/doc-sphinx/source/conf.py
@@ -49,9 +49,9 @@ copyright = u'2013, Olivier Bélanger'
# built documents.
#
# The short X.Y version.
-version = '0.6.8'
+version = '0.6.9'
# The full version, including alpha/beta/rc tags.
-release = '0.6.8'
+release = '0.6.9'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/doc-sphinx/source/index.rst b/doc-sphinx/source/index.rst
index abf1888..0698ad1 100644
--- a/doc-sphinx/source/index.rst
+++ b/doc-sphinx/source/index.rst
@@ -3,7 +3,7 @@
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
-Welcome to the Pyo 0.6.8 documentation
+Welcome to the Pyo 0.6.9 documentation
===================================================
.. toctree::
diff --git a/embedded/m_pyo.h b/embedded/m_pyo.h
new file mode 100644
index 0000000..c0a5235
--- /dev/null
+++ b/embedded/m_pyo.h
@@ -0,0 +1,312 @@
+#include <stdlib.h>
+#include "Python.h"
+
+#ifndef __m_pyo_h_
+
+#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
+extern "C" {
+#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:
+** chnls : int, number of in/out channels of the pyo server.
+**
+** returns the new python thread's interpreter state.
+*/
+inline PyThreadState * pyo_new_interpreter(int chnls) {
+ char msg[64];
+ PyThreadState *interp;
+ if(!Py_IsInitialized()) {
+ Py_Initialize();
+ 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(44100, %d, 256, 1, 'embedded')", chnls);
+ 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 = PyString_AsString(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 = PyString_AsString(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 = PyString_AsString(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 = PyString_AsString(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);
+ Py_EndInterpreter(interp);
+ PyEval_ReleaseLock();
+}
+
+/*
+** 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);
+}
+
+/*
+** 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 execfile('./%s')\nexcept:\n execfile('%s')",
+ 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, PyString_AsString(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..972541c
--- /dev/null
+++ b/embedded/openframeworks/PyoClass.cpp
@@ -0,0 +1,204 @@
+#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(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. 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
+** shutdown and reboot 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 assign.
+**
+** 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 point.
+** value : float, value to be assign.
+**
+** 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 point.
+** 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/PyoTemplate/Makefile b/embedded/openframeworks/PyoTemplate/Makefile
new file mode 100644
index 0000000..7a7fe8b
--- /dev/null
+++ b/embedded/openframeworks/PyoTemplate/Makefile
@@ -0,0 +1,13 @@
+# Attempt to load a config.make file.
+# If none is found, project defaults in config.project.make will be used.
+ifneq ($(wildcard config.make),)
+ include config.make
+endif
+
+# make sure the the OF_ROOT location is defined
+ifndef OF_ROOT
+ OF_ROOT=../../..
+endif
+
+# call the project makefile!
+include $(OF_ROOT)/libs/openFrameworksCompiled/project/makefileCommon/compile.project.mk
diff --git a/embedded/openframeworks/PyoTemplate/config.make b/embedded/openframeworks/PyoTemplate/config.make
new file mode 100644
index 0000000..2a5b520
--- /dev/null
+++ b/embedded/openframeworks/PyoTemplate/config.make
@@ -0,0 +1,141 @@
+################################################################################
+# CONFIGURE PROJECT MAKEFILE (optional)
+# This file is where we make project specific configurations.
+################################################################################
+
+################################################################################
+# OF ROOT
+# The location of your root openFrameworks installation
+# (default) OF_ROOT = ../../..
+################################################################################
+# OF_ROOT = ../../..
+
+################################################################################
+# PROJECT ROOT
+# The location of the project - a starting place for searching for files
+# (default) PROJECT_ROOT = . (this directory)
+#
+################################################################################
+# PROJECT_ROOT = .
+
+################################################################################
+# PROJECT SPECIFIC CHECKS
+# This is a project defined section to create internal makefile flags to
+# conditionally enable or disable the addition of various features within
+# this makefile. For instance, if you want to make changes based on whether
+# GTK is installed, one might test that here and create a variable to check.
+################################################################################
+# None
+
+################################################################################
+# PROJECT EXTERNAL SOURCE PATHS
+# These are fully qualified paths that are not within the PROJECT_ROOT folder.
+# Like source folders in the PROJECT_ROOT, these paths are subject to
+# exlclusion via the PROJECT_EXLCUSIONS list.
+#
+# (default) PROJECT_EXTERNAL_SOURCE_PATHS = (blank)
+#
+# Note: Leave a leading space when adding list items with the += operator
+################################################################################
+# PROJECT_EXTERNAL_SOURCE_PATHS =
+
+################################################################################
+# PROJECT EXCLUSIONS
+# These makefiles assume that all folders in your current project directory
+# and any listed in the PROJECT_EXTERNAL_SOURCH_PATHS are are valid locations
+# to look for source code. The any folders or files that match any of the
+# items in the PROJECT_EXCLUSIONS list below will be ignored.
+#
+# Each item in the PROJECT_EXCLUSIONS list will be treated as a complete
+# string unless teh user adds a wildcard (%) operator to match subdirectories.
+# GNU make only allows one wildcard for matching. The second wildcard (%) is
+# treated literally.
+#
+# (default) PROJECT_EXCLUSIONS = (blank)
+#
+# Will automatically exclude the following:
+#
+# $(PROJECT_ROOT)/bin%
+# $(PROJECT_ROOT)/obj%
+# $(PROJECT_ROOT)/%.xcodeproj
+#
+# Note: Leave a leading space when adding list items with the += operator
+################################################################################
+# PROJECT_EXCLUSIONS =
+
+################################################################################
+# PROJECT LINKER FLAGS
+# These flags will be sent to the linker when compiling the executable.
+#
+# (default) PROJECT_LDFLAGS = -Wl,-rpath=./libs
+#
+# Note: Leave a leading space when adding list items with the += operator
+#
+# Currently, shared libraries that are needed are copied to the
+# $(PROJECT_ROOT)/bin/libs directory. The following LDFLAGS tell the linker to
+# add a runtime path to search for those shared libraries, since they aren't
+# incorporated directly into the final executable application binary.
+################################################################################
+PROJECT_LDFLAGS = `python-config --ldflags`
+
+################################################################################
+# PROJECT DEFINES
+# Create a space-delimited list of DEFINES. The list will be converted into
+# CFLAGS with the "-D" flag later in the makefile.
+#
+# (default) PROJECT_DEFINES = (blank)
+#
+# Note: Leave a leading space when adding list items with the += operator
+################################################################################
+# PROJECT_DEFINES =
+
+################################################################################
+# PROJECT CFLAGS
+# This is a list of fully qualified CFLAGS required when compiling for this
+# project. These CFLAGS will be used IN ADDITION TO the PLATFORM_CFLAGS
+# defined in your platform specific core configuration files. These flags are
+# presented to the compiler BEFORE the PROJECT_OPTIMIZATION_CFLAGS below.
+#
+# (default) PROJECT_CFLAGS = (blank)
+#
+# Note: Before adding PROJECT_CFLAGS, note that the PLATFORM_CFLAGS defined in
+# your platform specific configuration file will be applied by default and
+# further flags here may not be needed.
+#
+# Note: Leave a leading space when adding list items with the += operator
+################################################################################
+PROJECT_CFLAGS = `python-config --cflags`
+
+################################################################################
+# PROJECT OPTIMIZATION CFLAGS
+# These are lists of CFLAGS that are target-specific. While any flags could
+# be conditionally added, they are usually limited to optimization flags.
+# These flags are added BEFORE the PROJECT_CFLAGS.
+#
+# PROJECT_OPTIMIZATION_CFLAGS_RELEASE flags are only applied to RELEASE targets.
+#
+# (default) PROJECT_OPTIMIZATION_CFLAGS_RELEASE = (blank)
+#
+# PROJECT_OPTIMIZATION_CFLAGS_DEBUG flags are only applied to DEBUG targets.
+#
+# (default) PROJECT_OPTIMIZATION_CFLAGS_DEBUG = (blank)
+#
+# Note: Before adding PROJECT_OPTIMIZATION_CFLAGS, please note that the
+# PLATFORM_OPTIMIZATION_CFLAGS defined in your platform specific configuration
+# file will be applied by default and further optimization flags here may not
+# be needed.
+#
+# Note: Leave a leading space when adding list items with the += operator
+################################################################################
+# PROJECT_OPTIMIZATION_CFLAGS_RELEASE =
+# PROJECT_OPTIMIZATION_CFLAGS_DEBUG =
+
+################################################################################
+# PROJECT COMPILERS
+# Custom compilers can be set for CC and CXX
+# (default) PROJECT_CXX = (blank)
+# (default) PROJECT_CC = (blank)
+# Note: Leave a leading space when adding list items with the += operator
+################################################################################
+# PROJECT_CXX =
+# PROJECT_CC =
diff --git a/embedded/openframeworks/PyoTemplate/scripts/stereoDelay.py b/embedded/openframeworks/PyoTemplate/scripts/stereoDelay.py
new file mode 100644
index 0000000..0d98f4e
--- /dev/null
+++ b/embedded/openframeworks/PyoTemplate/scripts/stereoDelay.py
@@ -0,0 +1,5 @@
+# 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()
+
diff --git a/embedded/openframeworks/PyoTemplate/src/PyoClass.cpp b/embedded/openframeworks/PyoTemplate/src/PyoClass.cpp
new file mode 100644
index 0000000..972541c
--- /dev/null
+++ b/embedded/openframeworks/PyoTemplate/src/PyoClass.cpp
@@ -0,0 +1,204 @@
+#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(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. 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
+** shutdown and reboot 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 assign.
+**
+** 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 point.
+** value : float, value to be assign.
+**
+** 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 point.
+** 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/PyoTemplate/src/PyoClass.h b/embedded/openframeworks/PyoTemplate/src/PyoClass.h
new file mode 100644
index 0000000..2ca65b4
--- /dev/null
+++ b/embedded/openframeworks/PyoTemplate/src/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/PyoTemplate/src/m_pyo.h b/embedded/openframeworks/PyoTemplate/src/m_pyo.h
new file mode 100644
index 0000000..c0a5235
--- /dev/null
+++ b/embedded/openframeworks/PyoTemplate/src/m_pyo.h
@@ -0,0 +1,312 @@
+#include <stdlib.h>
+#include "Python.h"
+
+#ifndef __m_pyo_h_
+
+#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
+extern "C" {
+#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:
+** chnls : int, number of in/out channels of the pyo server.
+**
+** returns the new python thread's interpreter state.
+*/
+inline PyThreadState * pyo_new_interpreter(int chnls) {
+ char msg[64];
+ PyThreadState *interp;
+ if(!Py_IsInitialized()) {
+ Py_Initialize();
+ 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(44100, %d, 256, 1, 'embedded')", chnls);
+ 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 = PyString_AsString(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 = PyString_AsString(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 = PyString_AsString(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 = PyString_AsString(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);
+ Py_EndInterpreter(interp);
+ PyEval_ReleaseLock();
+}
+
+/*
+** 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);
+}
+
+/*
+** 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 execfile('./%s')\nexcept:\n execfile('%s')",
+ 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, PyString_AsString(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/PyoTemplate/src/main.cpp b/embedded/openframeworks/PyoTemplate/src/main.cpp
new file mode 100644
index 0000000..a7d241d
--- /dev/null
+++ b/embedded/openframeworks/PyoTemplate/src/main.cpp
@@ -0,0 +1,13 @@
+#include "ofMain.h"
+#include "testApp.h"
+
+//========================================================================
+int main( ){
+ ofSetupOpenGL(1024,768,OF_WINDOW); // <-------- setup the GL context
+
+ // this kicks off the running of my app
+ // can be OF_WINDOW or OF_FULLSCREEN
+ // pass in width and height too:
+ ofRunApp(new testApp());
+
+}
diff --git a/embedded/openframeworks/PyoTemplate/src/testApp.cpp b/embedded/openframeworks/PyoTemplate/src/testApp.cpp
new file mode 100644
index 0000000..882cec7
--- /dev/null
+++ b/embedded/openframeworks/PyoTemplate/src/testApp.cpp
@@ -0,0 +1,80 @@
+#include "testApp.h"
+
+//--------------------------------------------------------------
+void testApp::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.setup(this, nChannels, nChannels, sampleRate, bufferSize, 4);
+}
+
+void testApp::audioIn(float * input, int bufferSize, int nChannels){
+ // send audio samples to pyo
+ pyo.fillin(input);
+}
+
+void testApp::audioOut(float * output, int bufferSize, int nChannels){
+ // process and get new audio samples from pyo
+ pyo.process(output);
+}
+
+//--------------------------------------------------------------
+void testApp::update(){
+
+}
+
+//--------------------------------------------------------------
+void testApp::draw(){
+
+}
+
+//--------------------------------------------------------------
+void testApp::keyPressed(int key){
+
+}
+
+//--------------------------------------------------------------
+void testApp::keyReleased(int key){
+
+}
+
+//--------------------------------------------------------------
+void testApp::mouseMoved(int x, int y ){
+
+}
+
+//--------------------------------------------------------------
+void testApp::mouseDragged(int x, int y, int button){
+
+}
+
+//--------------------------------------------------------------
+void testApp::mousePressed(int x, int y, int button){
+
+}
+
+//--------------------------------------------------------------
+void testApp::mouseReleased(int x, int y, int button){
+
+}
+
+//--------------------------------------------------------------
+void testApp::windowResized(int w, int h){
+
+}
+
+//--------------------------------------------------------------
+void testApp::gotMessage(ofMessage msg){
+
+}
+
+//--------------------------------------------------------------
+void testApp::dragEvent(ofDragInfo dragInfo){
+
+}
diff --git a/embedded/openframeworks/PyoTemplate/src/testApp.h b/embedded/openframeworks/PyoTemplate/src/testApp.h
new file mode 100644
index 0000000..4a98213
--- /dev/null
+++ b/embedded/openframeworks/PyoTemplate/src/testApp.h
@@ -0,0 +1,26 @@
+#pragma once
+
+#include "ofMain.h"
+#include "PyoClass.h"
+
+class testApp : public ofBaseApp{
+ public:
+ void setup();
+ void update();
+ void draw();
+
+ void keyPressed(int key);
+ void keyReleased(int key);
+ void mouseMoved(int x, int y );
+ void mouseDragged(int x, int y, int button);
+ void mousePressed(int x, int y, int button);
+ void mouseReleased(int x, int y, int button);
+ void windowResized(int w, int h);
+ void dragEvent(ofDragInfo dragInfo);
+ void gotMessage(ofMessage msg);
+
+ void audioIn(float * input, int bufferSize, int nChannels);
+ void audioOut(float * input, int bufferSize, int nChannels);
+ ofSoundStream soundStream;
+ Pyo pyo;
+};
diff --git a/embedded/openframeworks/README b/embedded/openframeworks/README
new file mode 100644
index 0000000..7879578
--- /dev/null
+++ b/embedded/openframeworks/README
@@ -0,0 +1,101 @@
+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 go and create an OpenFrameworks project.
+
+------------------------------------------------------------------------
+Step 1 - Create a default project with project generator.
+
+------------------------------------------------------------------------
+Step 2 - Add pyo files to your project. You only need to copy
+these files in your project's src 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. 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/testApp.h.
+
+- Include PyoClass definition:
+
+#include "PyoClass.h"
+
+- Add audio in/out callbacks to the public attributes of the testApp 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 testApp class:
+
+ofSoundStream soundStream;
+
+- Add a Pyo object to the public attributes of the testApp class:
+
+Pyo pyo;
+
+------------------------------------------------------------------------
+Step 6 - Edit src/testApp.cpp.
+
+- Creates the setup() function:
+
+void testApp::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.setup(this, nChannels, nChannels, sampleRate, bufferSize, 4);
+}
+
+- Creates audio in/out functions:
+
+void testApp::audioIn(float * input, int bufferSize, int nChannels){
+ // send audio samples to pyo
+ pyo.fillin(input);
+}
+
+void testApp::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.
+
+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/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/m_pd.h b/embedded/puredata/m_pd.h
new file mode 100755
index 0000000..71bd28e
--- /dev/null
+++ b/embedded/puredata/m_pd.h
@@ -0,0 +1,665 @@
+/* Copyright (c) 1997-1999 Miller Puckette.
+* For information on usage and redistribution, and for a DISCLAIMER OF ALL
+* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+
+#ifndef __m_pd_h_
+
+#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
+extern "C" {
+#endif
+
+#define PD_MAJOR_VERSION 0
+#define PD_MINOR_VERSION 41
+#define PD_BUGFIX_VERSION 4
+#define PD_TEST_VERSION "extended"
+
+/* old name for "MSW" flag -- we have to take it for the sake of many old
+"nmakefiles" for externs, which will define NT and not MSW */
+#if defined(NT) && !defined(MSW)
+#define MSW
+#endif
+
+/* These pragmas are only used for MSVC, not MinGW or Cygwin <hans at at.or.at> */
+#ifdef _MSC_VER
+/* #pragma warning( disable : 4091 ) */
+#pragma warning( disable : 4305 ) /* uncast const double to float */
+#pragma warning( disable : 4244 ) /* uncast float/int conversion etc. */
+#pragma warning( disable : 4101 ) /* unused automatic variables */
+#endif /* _MSC_VER */
+
+ /* the external storage class is "extern" in UNIX; in MSW it's ugly. */
+#ifdef MSW
+#ifdef PD_INTERNAL
+#define EXTERN __declspec(dllexport) extern
+#else
+#define EXTERN __declspec(dllimport) extern
+#endif /* PD_INTERNAL */
+#else
+#define EXTERN extern
+#endif /* MSW */
+
+ /* and depending on the compiler, hidden data structures are
+ declared differently: */
+#if defined( __GNUC__) || defined( __BORLANDC__ ) || defined( __MWERKS__ )
+#define EXTERN_STRUCT struct
+#else
+#define EXTERN_STRUCT extern struct
+#endif
+
+
+#if !defined(_SIZE_T) && !defined(_SIZE_T_)
+#include <stddef.h> /* just for size_t -- how lame! */
+#endif
+
+#define MAXPDSTRING 1000 /* must be >= FILENAME_MAX */
+#define MAXPDARG 5 /* max number of args we can typecheck today */
+
+/* signed and unsigned integer types the size of a pointer: */
+/* GG: long is the size of a pointer */
+typedef long t_int;
+
+typedef float t_float; /* a floating-point number at most the same size */
+typedef float t_floatarg; /* floating-point type for function calls */
+
+typedef struct _symbol
+{
+ char *s_name;
+ struct _class **s_thing;
+ struct _symbol *s_next;
+} t_symbol;
+
+EXTERN_STRUCT _array;
+#define t_array struct _array /* g_canvas.h */
+
+/* pointers to glist and array elements go through a "stub" which sticks
+around after the glist or array is freed. The stub itself is deleted when
+both the glist/array is gone and the refcount is zero, ensuring that no
+gpointers are pointing here. */
+
+#define GP_NONE 0 /* the stub points nowhere (has been cut off) */
+#define GP_GLIST 1 /* the stub points to a glist element */
+#define GP_ARRAY 2 /* ... or array */
+
+typedef struct _gstub
+{
+ union
+ {
+ struct _glist *gs_glist; /* glist we're in */
+ struct _array *gs_array; /* array we're in */
+ } gs_un;
+ int gs_which; /* GP_GLIST/GP_ARRAY */
+ int gs_refcount; /* number of gpointers pointing here */
+} t_gstub;
+
+typedef struct _gpointer /* pointer to a gobj in a glist */
+{
+ union
+ {
+ struct _scalar *gp_scalar; /* scalar we're in (if glist) */
+ union word *gp_w; /* raw data (if array) */
+ } gp_un;
+ int gp_valid; /* number which must match gpointee */
+ t_gstub *gp_stub; /* stub which points to glist/array */
+} t_gpointer;
+
+#define PD_BLOBS 1 /* MP20070211 Use this to test for blob capability */
+/* MP20061223 blob type: */
+typedef struct _blob /* pointer to a blob */
+{
+ unsigned long s_length; /* length of blob in bytes */
+ unsigned char *s_data; /* pointer to 1st byte of blob */
+} t_blob;
+/* ...MP20061223 blob type */
+
+
+typedef union word
+{
+ t_float w_float;
+ t_symbol *w_symbol;
+ t_gpointer *w_gpointer;
+ t_array *w_array;
+ struct _glist *w_list;
+ int w_index;
+ t_blob *w_blob; /* MP20061223 blob type */
+} t_word;
+
+typedef enum
+{
+ A_NULL,
+ A_FLOAT,
+ A_SYMBOL,
+ A_POINTER,
+ A_SEMI,
+ A_COMMA,
+ A_DEFFLOAT,
+ A_DEFSYM,
+ A_DOLLAR,
+ A_DOLLSYM,
+ A_GIMME,
+ A_CANT,
+ A_BLOB /* MP20061223 blob type */
+} t_atomtype;
+
+#define A_DEFSYMBOL A_DEFSYM /* better name for this */
+
+typedef struct _atom
+{
+ t_atomtype a_type;
+ union word a_w;
+} t_atom;
+
+EXTERN_STRUCT _class;
+#define t_class struct _class
+
+EXTERN_STRUCT _outlet;
+#define t_outlet struct _outlet
+
+EXTERN_STRUCT _inlet;
+#define t_inlet struct _inlet
+
+EXTERN_STRUCT _binbuf;
+#define t_binbuf struct _binbuf
+
+EXTERN_STRUCT _clock;
+#define t_clock struct _clock
+
+EXTERN_STRUCT _outconnect;
+#define t_outconnect struct _outconnect
+
+EXTERN_STRUCT _glist;
+#define t_glist struct _glist
+#define t_canvas struct _glist /* LATER lose this */
+
+typedef t_class *t_pd; /* pure datum: nothing but a class pointer */
+
+typedef struct _gobj /* a graphical object */
+{
+ t_pd g_pd; /* pure datum header (class) */
+ struct _gobj *g_next; /* next in list */
+} t_gobj;
+
+typedef struct _scalar /* a graphical object holding data */
+{
+ t_gobj sc_gobj; /* header for graphical object */
+ t_symbol *sc_template; /* template name (LATER replace with pointer) */
+ t_word sc_vec[1]; /* indeterminate-length array of words */
+} t_scalar;
+
+typedef struct _text /* patchable object - graphical, with text */
+{
+ t_gobj te_g; /* header for graphical object */
+ t_binbuf *te_binbuf; /* holder for the text */
+ t_outlet *te_outlet; /* linked list of outlets */
+ t_inlet *te_inlet; /* linked list of inlets */
+ short te_xpix; /* x&y location (within the toplevel) */
+ short te_ypix;
+ short te_width; /* requested width in chars, 0 if auto */
+ unsigned int te_type:2; /* from defs below */
+} t_text;
+
+#define T_TEXT 0 /* just a textual comment */
+#define T_OBJECT 1 /* a MAX style patchable object */
+#define T_MESSAGE 2 /* a MAX stype message */
+#define T_ATOM 3 /* a cell to display a number or symbol */
+
+#define te_pd te_g.g_pd
+
+ /* t_object is synonym for t_text (LATER unify them) */
+
+typedef struct _text t_object;
+
+#define ob_outlet te_outlet
+#define ob_inlet te_inlet
+#define ob_binbuf te_binbuf
+#define ob_pd te_g.g_pd
+#define ob_g te_g
+
+typedef void (*t_method)(void);
+typedef void *(*t_newmethod)( void);
+typedef void (*t_gotfn)(void *x, ...);
+
+/* ---------------- pre-defined objects and symbols --------------*/
+EXTERN t_pd pd_objectmaker; /* factory for creating "object" boxes */
+EXTERN t_pd pd_canvasmaker; /* factory for creating canvases */
+EXTERN t_symbol s_pointer;
+EXTERN t_symbol s_float;
+EXTERN t_symbol s_symbol;
+EXTERN t_symbol s_blob;
+EXTERN t_symbol s_bang;
+EXTERN t_symbol s_list;
+EXTERN t_symbol s_anything;
+EXTERN t_symbol s_signal;
+EXTERN t_symbol s__N;
+EXTERN t_symbol s__X;
+EXTERN t_symbol s_x;
+EXTERN t_symbol s_y;
+EXTERN t_symbol s_;
+
+/* --------- prototypes from the central message system ----------- */
+EXTERN void pd_typedmess(t_pd *x, t_symbol *s, int argc, t_atom *argv);
+EXTERN void pd_forwardmess(t_pd *x, int argc, t_atom *argv);
+EXTERN t_symbol *gensym(const char *s);
+EXTERN t_gotfn getfn(t_pd *x, t_symbol *s);
+EXTERN t_gotfn zgetfn(t_pd *x, t_symbol *s);
+EXTERN void nullfn(void);
+EXTERN void pd_vmess(t_pd *x, t_symbol *s, char *fmt, ...);
+#define mess0(x, s) ((*getfn((x), (s)))((x)))
+#define mess1(x, s, a) ((*getfn((x), (s)))((x), (a)))
+#define mess2(x, s, a,b) ((*getfn((x), (s)))((x), (a),(b)))
+#define mess3(x, s, a,b,c) ((*getfn((x), (s)))((x), (a),(b),(c)))
+#define mess4(x, s, a,b,c,d) ((*getfn((x), (s)))((x), (a),(b),(c),(d)))
+#define mess5(x, s, a,b,c,d,e) ((*getfn((x), (s)))((x), (a),(b),(c),(d),(e)))
+EXTERN void obj_list(t_object *x, t_symbol *s, int argc, t_atom *argv);
+EXTERN t_pd *pd_newest(void);
+
+/* --------------- memory management -------------------- */
+EXTERN void *getbytes(size_t nbytes);
+EXTERN void *getzbytes(size_t nbytes);
+EXTERN void *copybytes(void *src, size_t nbytes);
+EXTERN void freebytes(void *x, size_t nbytes);
+EXTERN void *resizebytes(void *x, size_t oldsize, size_t newsize);
+
+/* -------------------- atoms ----------------------------- */
+
+#define SETSEMI(atom) ((atom)->a_type = A_SEMI, (atom)->a_w.w_index = 0)
+#define SETCOMMA(atom) ((atom)->a_type = A_COMMA, (atom)->a_w.w_index = 0)
+#define SETPOINTER(atom, gp) ((atom)->a_type = A_POINTER, \
+ (atom)->a_w.w_gpointer = (gp))
+#define SETFLOAT(atom, f) ((atom)->a_type = A_FLOAT, (atom)->a_w.w_float = (f))
+#define SETSYMBOL(atom, s) ((atom)->a_type = A_SYMBOL, \
+ (atom)->a_w.w_symbol = (s))
+#define SETBLOB(atom, st) ((atom)->a_type = A_BLOB, (atom)->a_w.w_blob = (st)) /* MP 20061226 blob type */
+#define SETDOLLAR(atom, n) ((atom)->a_type = A_DOLLAR, \
+ (atom)->a_w.w_index = (n))
+#define SETDOLLSYM(atom, s) ((atom)->a_type = A_DOLLSYM, \
+ (atom)->a_w.w_symbol= (s))
+
+EXTERN t_float atom_getfloat(t_atom *a);
+EXTERN t_int atom_getint(t_atom *a);
+EXTERN t_symbol *atom_getsymbol(t_atom *a);
+EXTERN t_blob *atom_getblob(t_atom *a);/* MP 20070108 blob type */
+EXTERN t_symbol *atom_gensym(t_atom *a);
+EXTERN t_float atom_getfloatarg(int which, int argc, t_atom *argv);
+EXTERN t_int atom_getintarg(int which, int argc, t_atom *argv);
+EXTERN t_symbol *atom_getsymbolarg(int which, int argc, t_atom *argv);
+
+EXTERN void atom_string(t_atom *a, char *buf, unsigned int bufsize);
+
+/* ------------------ binbufs --------------- */
+
+EXTERN t_binbuf *binbuf_new(void);
+EXTERN void binbuf_free(t_binbuf *x);
+EXTERN t_binbuf *binbuf_duplicate(t_binbuf *y);
+
+EXTERN void binbuf_text(t_binbuf *x, char *text, size_t size);
+EXTERN void binbuf_gettext(t_binbuf *x, char **bufp, int *lengthp);
+EXTERN void binbuf_clear(t_binbuf *x);
+EXTERN void binbuf_add(t_binbuf *x, int argc, t_atom *argv);
+EXTERN void binbuf_addv(t_binbuf *x, char *fmt, ...);
+EXTERN void binbuf_addbinbuf(t_binbuf *x, t_binbuf *y);
+EXTERN void binbuf_addsemi(t_binbuf *x);
+EXTERN void binbuf_restore(t_binbuf *x, int argc, t_atom *argv);
+EXTERN void binbuf_print(t_binbuf *x);
+EXTERN int binbuf_getnatom(t_binbuf *x);
+EXTERN t_atom *binbuf_getvec(t_binbuf *x);
+EXTERN void binbuf_eval(t_binbuf *x, t_pd *target, int argc, t_atom *argv);
+EXTERN int binbuf_read(t_binbuf *b, char *filename, char *dirname,
+ int crflag);
+EXTERN int binbuf_read_via_canvas(t_binbuf *b, char *filename, t_canvas *canvas,
+ int crflag);
+EXTERN int binbuf_read_via_path(t_binbuf *b, char *filename, char *dirname,
+ int crflag);
+EXTERN int binbuf_write(t_binbuf *x, char *filename, char *dir,
+ int crflag);
+EXTERN void binbuf_evalfile(t_symbol *name, t_symbol *dir);
+EXTERN t_symbol *binbuf_realizedollsym(t_symbol *s, int ac, t_atom *av,
+ int tonew);
+
+/* ------------------ clocks --------------- */
+
+EXTERN t_clock *clock_new(void *owner, t_method fn);
+EXTERN void clock_set(t_clock *x, double systime);
+EXTERN void clock_delay(t_clock *x, double delaytime);
+EXTERN void clock_unset(t_clock *x);
+EXTERN double clock_getlogicaltime(void);
+EXTERN double clock_getsystime(void); /* OBSOLETE; use clock_getlogicaltime() */
+EXTERN double clock_gettimesince(double prevsystime);
+EXTERN double clock_getsystimeafter(double delaytime);
+EXTERN void clock_free(t_clock *x);
+
+/* ----------------- pure data ---------------- */
+EXTERN t_pd *pd_new(t_class *cls);
+EXTERN void pd_free(t_pd *x);
+EXTERN void pd_bind(t_pd *x, t_symbol *s);
+EXTERN void pd_unbind(t_pd *x, t_symbol *s);
+EXTERN t_pd *pd_findbyclass(t_symbol *s, t_class *c);
+EXTERN void pd_pushsym(t_pd *x);
+EXTERN void pd_popsym(t_pd *x);
+EXTERN t_symbol *pd_getfilename(void);
+EXTERN t_symbol *pd_getdirname(void);
+EXTERN void pd_bang(t_pd *x);
+EXTERN void pd_pointer(t_pd *x, t_gpointer *gp);
+EXTERN void pd_float(t_pd *x, t_float f);
+EXTERN void pd_symbol(t_pd *x, t_symbol *s);
+EXTERN void pd_blob(t_pd *x, t_blob *st); /* MP 20061226 blob type */
+EXTERN void pd_list(t_pd *x, t_symbol *s, int argc, t_atom *argv);
+EXTERN void pd_anything(t_pd *x, t_symbol *s, int argc, t_atom *argv);
+#define pd_class(x) (*(x))
+
+/* ----------------- pointers ---------------- */
+EXTERN void gpointer_init(t_gpointer *gp);
+EXTERN void gpointer_copy(const t_gpointer *gpfrom, t_gpointer *gpto);
+EXTERN void gpointer_unset(t_gpointer *gp);
+EXTERN int gpointer_check(const t_gpointer *gp, int headok);
+
+/* ----------------- patchable "objects" -------------- */
+EXTERN t_inlet *inlet_new(t_object *owner, t_pd *dest, t_symbol *s1,
+ t_symbol *s2);
+EXTERN t_inlet *pointerinlet_new(t_object *owner, t_gpointer *gp);
+EXTERN t_inlet *floatinlet_new(t_object *owner, t_float *fp);
+EXTERN t_inlet *symbolinlet_new(t_object *owner, t_symbol **sp);
+EXTERN t_inlet *signalinlet_new(t_object *owner, t_float f);
+EXTERN void inlet_free(t_inlet *x);
+
+EXTERN t_outlet *outlet_new(t_object *owner, t_symbol *s);
+EXTERN void outlet_bang(t_outlet *x);
+EXTERN void outlet_pointer(t_outlet *x, t_gpointer *gp);
+EXTERN void outlet_float(t_outlet *x, t_float f);
+EXTERN void outlet_symbol(t_outlet *x, t_symbol *s);
+EXTERN void outlet_blob(t_outlet *x, t_blob *st); /* MP 20061226 blob type */
+EXTERN void outlet_list(t_outlet *x, t_symbol *s, int argc, t_atom *argv);
+EXTERN void outlet_anything(t_outlet *x, t_symbol *s, int argc, t_atom *argv);
+EXTERN t_symbol *outlet_getsymbol(t_outlet *x);
+EXTERN void outlet_free(t_outlet *x);
+EXTERN t_object *pd_checkobject(t_pd *x);
+
+
+/* -------------------- canvases -------------- */
+
+EXTERN void glob_setfilename(void *dummy, t_symbol *name, t_symbol *dir);
+
+EXTERN void canvas_setargs(int argc, t_atom *argv);
+EXTERN void canvas_getargs(int *argcp, t_atom **argvp);
+EXTERN t_symbol *canvas_getcurrentdir(void);
+EXTERN t_glist *canvas_getcurrent(void);
+EXTERN void canvas_makefilename(t_glist *c, char *file,
+ char *result,int resultsize);
+EXTERN t_symbol *canvas_getdir(t_glist *x);
+EXTERN char sys_font[]; /* default typeface set in s_main.c */
+EXTERN char sys_fontweight[]; /* default font weight set in s_main.c */
+EXTERN int sys_fontwidth(int fontsize);
+EXTERN int sys_fontheight(int fontsize);
+EXTERN void canvas_dataproperties(t_glist *x, t_scalar *sc, t_binbuf *b);
+EXTERN int canvas_open(t_canvas *x, const char *name, const char *ext,
+ char *dirresult, char **nameresult, unsigned int size, int bin);
+
+/* ---------------- widget behaviors ---------------------- */
+
+EXTERN_STRUCT _widgetbehavior;
+#define t_widgetbehavior struct _widgetbehavior
+
+EXTERN_STRUCT _parentwidgetbehavior;
+#define t_parentwidgetbehavior struct _parentwidgetbehavior
+EXTERN t_parentwidgetbehavior *pd_getparentwidget(t_pd *x);
+
+/* -------------------- classes -------------- */
+
+#define CLASS_DEFAULT 0 /* flags for new classes below */
+#define CLASS_PD 1
+#define CLASS_GOBJ 2
+#define CLASS_PATCHABLE 3
+#define CLASS_NOINLET 8
+
+#define CLASS_TYPEMASK 3
+
+
+EXTERN t_class *class_new(t_symbol *name, t_newmethod newmethod,
+ t_method freemethod, size_t size, int flags, t_atomtype arg1, ...);
+EXTERN void class_addcreator(t_newmethod newmethod, t_symbol *s,
+ t_atomtype type1, ...);
+EXTERN void class_addmethod(t_class *c, t_method fn, t_symbol *sel,
+ t_atomtype arg1, ...);
+EXTERN void class_addbang(t_class *c, t_method fn);
+EXTERN void class_addpointer(t_class *c, t_method fn);
+EXTERN void class_doaddfloat(t_class *c, t_method fn);
+EXTERN void class_addsymbol(t_class *c, t_method fn);
+EXTERN void class_addblob(t_class *c, t_method fn);/* MP 20061226 blob type */
+EXTERN void class_addlist(t_class *c, t_method fn);
+EXTERN void class_addanything(t_class *c, t_method fn);
+EXTERN void class_sethelpsymbol(t_class *c, t_symbol *s);
+EXTERN void class_setwidget(t_class *c, t_widgetbehavior *w);
+EXTERN void class_setparentwidget(t_class *c, t_parentwidgetbehavior *w);
+EXTERN t_parentwidgetbehavior *class_parentwidget(t_class *c);
+EXTERN char *class_getname(t_class *c);
+EXTERN char *class_gethelpname(t_class *c);
+EXTERN void class_setdrawcommand(t_class *c);
+EXTERN int class_isdrawcommand(t_class *c);
+EXTERN void class_domainsignalin(t_class *c, int onset);
+EXTERN void class_set_extern_dir(t_symbol *s);
+#define CLASS_MAINSIGNALIN(c, type, field) \
+ class_domainsignalin(c, (char *)(&((type *)0)->field) - (char *)0)
+
+ /* prototype for functions to save Pd's to a binbuf */
+typedef void (*t_savefn)(t_gobj *x, t_binbuf *b);
+EXTERN void class_setsavefn(t_class *c, t_savefn f);
+EXTERN t_savefn class_getsavefn(t_class *c);
+ /* prototype for functions to open properties dialogs */
+typedef void (*t_propertiesfn)(t_gobj *x, struct _glist *glist);
+EXTERN void class_setpropertiesfn(t_class *c, t_propertiesfn f);
+EXTERN t_propertiesfn class_getpropertiesfn(t_class *c);
+
+#ifndef PD_CLASS_DEF
+#define class_addbang(x, y) class_addbang((x), (t_method)(y))
+#define class_addpointer(x, y) class_addpointer((x), (t_method)(y))
+#define class_addfloat(x, y) class_doaddfloat((x), (t_method)(y))
+#define class_addsymbol(x, y) class_addsymbol((x), (t_method)(y))
+#define class_addblob(x, y) class_addblob((x), (t_method)(y)) /* MP20061226 blob type */
+#define class_addlist(x, y) class_addlist((x), (t_method)(y))
+#define class_addanything(x, y) class_addanything((x), (t_method)(y))
+#endif
+
+/* ------------ printing --------------------------------- */
+EXTERN void post(const char *fmt, ...);
+EXTERN void startpost(const char *fmt, ...);
+EXTERN void poststring(const char *s);
+EXTERN void postfloat(float f);
+EXTERN void postatom(int argc, t_atom *argv);
+EXTERN void endpost(void);
+EXTERN void error(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
+EXTERN void verbose(int level, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
+EXTERN void bug(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
+EXTERN void pd_error(void *object, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
+EXTERN void sys_logerror(const char *object, const char *s);
+EXTERN void sys_unixerror(const char *object);
+EXTERN void sys_ouch(void);
+
+
+/* ------------ system interface routines ------------------- */
+EXTERN int sys_isreadablefile(const char *name);
+EXTERN int sys_isabsolutepath(const char *dir);
+EXTERN void sys_bashfilename(const char *from, char *to);
+EXTERN void sys_unbashfilename(const char *from, char *to);
+EXTERN int open_via_path(const char *name, const char *ext, const char *dir,
+ char *dirresult, char **nameresult, unsigned int size, int bin);
+EXTERN int sched_geteventno(void);
+EXTERN double sys_getrealtime(void);
+EXTERN int (*sys_idlehook)(void); /* hook to add idle time computation */
+
+
+/* ------------ threading ------------------- */
+EXTERN void sys_lock(void);
+EXTERN void sys_unlock(void);
+EXTERN int sys_trylock(void);
+
+
+/* --------------- signals ----------------------------------- */
+
+typedef float t_sample;
+#define MAXLOGSIG 32
+#define MAXSIGSIZE (1 << MAXLOGSIG)
+
+typedef struct _signal
+{
+ int s_n; /* number of points in the array */
+ t_sample *s_vec; /* the array */
+ t_float s_sr; /* sample rate */
+ int s_refcount; /* number of times used */
+ int s_isborrowed; /* whether we're going to borrow our array */
+ struct _signal *s_borrowedfrom; /* signal to borrow it from */
+ struct _signal *s_nextfree; /* next in freelist */
+ struct _signal *s_nextused; /* next in used list */
+ int s_vecsize; /* allocated size of array in points */
+} t_signal;
+
+typedef t_int *(*t_perfroutine)(t_int *args);
+
+EXTERN t_int *plus_perform(t_int *args);
+EXTERN t_int *zero_perform(t_int *args);
+EXTERN t_int *copy_perform(t_int *args);
+
+EXTERN void dsp_add_plus(t_sample *in1, t_sample *in2, t_sample *out, int n);
+EXTERN void dsp_add_copy(t_sample *in, t_sample *out, int n);
+EXTERN void dsp_add_scalarcopy(t_float *in, t_sample *out, int n);
+EXTERN void dsp_add_zero(t_sample *out, int n);
+
+EXTERN int sys_getblksize(void);
+EXTERN t_float sys_getsr(void);
+EXTERN int sys_get_inchannels(void);
+EXTERN int sys_get_outchannels(void);
+
+EXTERN void dsp_add(t_perfroutine f, int n, ...);
+EXTERN void dsp_addv(t_perfroutine f, int n, t_int *vec);
+EXTERN void pd_fft(t_float *buf, int npoints, int inverse);
+EXTERN int ilog2(int n);
+
+EXTERN void mayer_fht(t_sample *fz, int n);
+EXTERN void mayer_fft(int n, t_sample *real, t_sample *imag);
+EXTERN void mayer_ifft(int n, t_sample *real, t_sample *imag);
+EXTERN void mayer_realfft(int n, t_sample *real);
+EXTERN void mayer_realifft(int n, t_sample *real);
+
+EXTERN float *cos_table;
+#define LOGCOSTABSIZE 9
+#define COSTABSIZE (1<<LOGCOSTABSIZE)
+
+EXTERN int canvas_suspend_dsp(void);
+EXTERN void canvas_resume_dsp(int oldstate);
+EXTERN void canvas_update_dsp(void);
+EXTERN int canvas_dspstate;
+
+/* up/downsampling */
+typedef struct _resample
+{
+ int method; /* up/downsampling method ID */
+
+ t_int downsample; /* downsampling factor */
+ t_int upsample; /* upsampling factor */
+
+ t_sample *s_vec; /* here we hold the resampled data */
+ int s_n;
+
+ t_sample *coeffs; /* coefficients for filtering... */
+ int coefsize;
+
+ t_sample *buffer; /* buffer for filtering */
+ int bufsize;
+} t_resample;
+
+EXTERN void resample_init(t_resample *x);
+EXTERN void resample_free(t_resample *x);
+
+EXTERN void resample_dsp(t_resample *x, t_sample *in, int insize, t_sample *out, int outsize, int method);
+EXTERN void resamplefrom_dsp(t_resample *x, t_sample *in, int insize, int outsize, int method);
+EXTERN void resampleto_dsp(t_resample *x, t_sample *out, int insize, int outsize, int method);
+
+/* ----------------------- utility functions for signals -------------- */
+EXTERN t_float mtof(t_float);
+EXTERN t_float ftom(t_float);
+EXTERN t_float rmstodb(t_float);
+EXTERN t_float powtodb(t_float);
+EXTERN t_float dbtorms(t_float);
+EXTERN t_float dbtopow(t_float);
+
+EXTERN t_float q8_sqrt(t_float);
+EXTERN t_float q8_rsqrt(t_float);
+#ifndef N32
+EXTERN t_float qsqrt(t_float); /* old names kept for extern compatibility */
+EXTERN t_float qrsqrt(t_float);
+#endif
+/* --------------------- data --------------------------------- */
+
+ /* graphical arrays */
+EXTERN_STRUCT _garray;
+#define t_garray struct _garray
+
+EXTERN t_class *garray_class;
+EXTERN int garray_getfloatarray(t_garray *x, int *size, t_float **vec);
+EXTERN int garray_getfloatwords(t_garray *x, int *size, t_word **vec);
+EXTERN t_float garray_get(t_garray *x, t_symbol *s, t_int indx);
+EXTERN void garray_redraw(t_garray *x);
+EXTERN int garray_npoints(t_garray *x);
+EXTERN char *garray_vec(t_garray *x);
+EXTERN void garray_resize(t_garray *x, t_floatarg f);
+EXTERN void garray_usedindsp(t_garray *x);
+EXTERN void garray_setsaveit(t_garray *x, int saveit);
+EXTERN t_class *scalar_class;
+
+EXTERN t_float *value_get(t_symbol *s);
+EXTERN void value_release(t_symbol *s);
+EXTERN int value_getfloat(t_symbol *s, t_float *f);
+EXTERN int value_setfloat(t_symbol *s, t_float f);
+
+/* ------- GUI interface - functions to send strings to TK --------- */
+typedef void (*t_guicallbackfn)(t_gobj *client, t_glist *glist);
+
+EXTERN void sys_vgui(char *fmt, ...);
+EXTERN void sys_gui(char *s);
+EXTERN void sys_pretendguibytes(int n);
+EXTERN void sys_queuegui(void *client, t_glist *glist, t_guicallbackfn f);
+EXTERN void sys_unqueuegui(void *client);
+ /* dialog window creation and destruction */
+EXTERN void gfxstub_new(t_pd *owner, void *key, const char *cmd);
+EXTERN void gfxstub_deleteforkey(void *key);
+
+extern t_class *glob_pdobject; /* object to send "pd" messages */
+
+/*------------- Max 0.26 compatibility --------------------*/
+
+/* the following reflects the new way classes are laid out, with the class
+ pointing to the messlist and not vice versa. Externs shouldn't feel it. */
+typedef t_class *t_externclass;
+
+EXTERN void c_extern(t_externclass *cls, t_newmethod newroutine,
+ t_method freeroutine, t_symbol *name, size_t size, int tiny, \
+ t_atomtype arg1, ...);
+EXTERN void c_addmess(t_method fn, t_symbol *sel, t_atomtype arg1, ...);
+
+#define t_getbytes getbytes
+#define t_freebytes freebytes
+#define t_resizebytes resizebytes
+#define typedmess pd_typedmess
+#define vmess pd_vmess
+
+/* A definition to help gui objects straddle 0.34-0.35 changes. If this is
+defined, there is a "te_xpix" field in objects, not a "te_xpos" as before: */
+
+#define PD_USE_TE_XPIX
+
+#if defined(__i386__) || defined(__x86_64__)
+/* a test for NANs and denormals. Should only be necessary on i386. */
+#define PD_BADFLOAT(f) ((((*(unsigned int*)&(f))&0x7f800000)==0) || \
+ (((*(unsigned int*)&(f))&0x7f800000)==0x7f800000))
+/* more stringent test: anything not between 1e-19 and 1e19 in absolute val */
+#define PD_BIGORSMALL(f) ((((*(unsigned int*)&(f))&0x60000000)==0) || \
+ (((*(unsigned int*)&(f))&0x60000000)==0x60000000))
+#else
+#define PD_BADFLOAT(f) 0
+#define PD_BIGORSMALL(f) 0
+#endif
+
+#if defined(_LANGUAGE_C_PLUS_PLUS) || defined(__cplusplus)
+}
+#endif
+
+#define __m_pd_h_
+#endif /* __m_pd_h_ */
diff --git a/embedded/puredata/pyo~-help.pd b/embedded/puredata/pyo~-help.pd
new file mode 100644
index 0000000..e8c9c8a
--- /dev/null
+++ b/embedded/puredata/pyo~-help.pd
@@ -0,0 +1,311 @@
+#N canvas 296 140 952 365 10;
+#X obj 28 108 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X obj 144 108 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1
+1;
+#X obj 13 234 *~;
+#X obj 51 234 *~;
+#X obj 13 256 dac~;
+#X obj 72 213 hsl 128 15 0 1 0 1 empty empty master_gain -2 -8 0 10
+-262144 -1 -1 6200 1;
+#X obj 274 223 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 1
+1;
+#X msg 274 243 \; pd dsp \$1;
+#X obj 13 59 r msg_to_pyo;
+#X text 161 107 play;
+#X obj 13 166 pyo~ 2;
+#X text 66 168 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 11200 0;
+#X floatatom 32 120 5 0 0 0 - - -;
+#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 1300 0;
+#X floatatom 95 403 5 0 0 0 - - -;
+#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 10800 0;
+#X floatatom 108 470 5 0 0 0 - - -;
+#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 4700 0;
+#X obj 71 177 vsl 15 80 50 500 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 3200 0;
+#X obj 91 177 vsl 15 80 50 500 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 5800 0;
+#X obj 110 177 vsl 15 80 50 500 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 7100 0;
+#X obj 130 177 vsl 15 80 50 500 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 5500 0;
+#X obj 149 177 vsl 15 80 50 500 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 7100 0;
+#X obj 169 177 vsl 15 80 50 500 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 4400 0;
+#X obj 189 177 vsl 15 80 50 500 0 0 empty empty empty 0 -9 0 10 -262144
+-1 -1 1800 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 60 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 - - -;
+#X floatatom 124 160 5 0 0 0 - - -;
+#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 - - -;
+#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 - - -;
+#X floatatom 222 186 5 0 0 0 - - -;
+#X msg 222 216 set amp.fadeout \$1;
+#X msg 281 184 set amp.dur \$1;
+#X floatatom 281 165 5 0 0 0 - - -;
+#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 84 pd synthesis_example;
+#N canvas 1 75 629 295 loop_soundfile 0;
+#X obj 43 42 openpanel;
+#X obj 43 64 t a b;
+#X obj 43 170 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 392 16 inlet start;
+#X obj 236 52 sel 1;
+#X obj 236 205 outlet~;
+#X obj 347 163 spigot 1;
+#X obj 43 126 pack s s s;
+#X obj 71 86 symbol \$0-table_l;
+#X obj 100 105 symbol \$0-table_r;
+#X msg 43 148 read -resize \$1 \$2 \$3;
+#X obj 44 200 table \$0-table_l;
+#X obj 44 223 table \$0-table_r;
+#X obj 423 206 outlet~;
+#X obj 236 140 tabplay~ \$0-table_l;
+#X obj 424 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 126 pd loop_soundfile;
+#X text 44 108 load file;
+#N canvas 1 75 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 - - -;
+#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 36 pd conv_reverb_example;
+#X text 26 86 play a soundfile to send audio signals to pyo;
+#N canvas 114 140 450 300 README 0;
+#X restore 406 227 pd README;
+#N canvas 198 75 1001 402 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 499 43 call function [arg1 arg2 ...];
+#X text 499 229 clear;
+#X text 516 250 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 516 63 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 515 103 call varname.method [arg1 arg2 ...];
+#X text 36 351 set frequencies 100 200 300 400 500 600;
+#X text 499 130 create varname object [\$1 \$2 ...];
+#X text -16 3 Here are the messages that can be used to control the
+internal processing of the pyo~ object.;
+#X text 513 149 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 499 291 debug \$1;
+#X text 516 312 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 restore 406 248 pd MESSAGES;
+#X msg 553 297 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 518 323 s msg_to_pyo;
+#X msg 553 234 set pits 0.001 0.002 0.003 0.004;
+#X msg 553 255 create fr Rossler pitch=pits chaos=0.9 mul=250 add=500
+;
+#X msg 553 276 create b SumOsc freq=fr ratio=0.499 index=0.4 mul=0.2
+;
+#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..1e675b1
--- /dev/null
+++ b/embedded/puredata/pyo~.c
@@ -0,0 +1,250 @@
+#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 = -1;
+ x->sr = -1.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->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_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_debug, gensym("debug"),
+ A_DEFFLOAT, 0); /* set the debug (verbose) mode */
+ CLASS_MAINSIGNALIN(pyo_tilde_class, t_pyo_tilde, f);
+}
diff --git a/examples/utilities/02_osc_scan.py b/examples/utilities/02_osc_scan.py
new file mode 100644
index 0000000..442247e
--- /dev/null
+++ b/examples/utilities/02_osc_scan.py
@@ -0,0 +1,37 @@
+#!/usr/bin/env python
+# encoding: utf-8
+"""
+Scan Open Sound Control inputs. Launch this script from a terminal.
+
+"""
+from pyo import *
+import time
+
+port = 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 = raw_input("Do you want to continue ? (y/n) : ")
+ if again == "y":
+ print "Continue..."
+ go = True
+
+s.stop()
+time.sleep(1)
+exit()
+
\ No newline at end of file
diff --git a/examples/utilities/04_batch_processing.py b/examples/utilities/04_batch_processing.py
index fa7b094..fa1f6b6 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)) != 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..8b32246
--- /dev/null
+++ b/examples/utilities/04_batch_synthesis.py
@@ -0,0 +1,39 @@
+#!/usr/bin/env python
+# encoding: utf-8
+"""
+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/07_scope.py b/examples/utilities/07_scope.py
new file mode 100644
index 0000000..4af4ec3
--- /dev/null
+++ b/examples/utilities/07_scope.py
@@ -0,0 +1,33 @@
+#!/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=range(CHNLS))
+scope = Scope(inp, LENGTH)
+
+s.gui(locals())
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/include/pyomodule.h b/include/pyomodule.h
index ce4ba6c..d83f8f7 100644
--- a/include/pyomodule.h
+++ b/include/pyomodule.h
@@ -21,7 +21,7 @@
#include "Python.h"
#include <math.h>
-#define PYO_VERSION "0.6.8"
+#define PYO_VERSION "0.6.9"
#ifndef __MYFLT_DEF
#define __MYFLT_DEF
@@ -73,6 +73,7 @@
#define TYPE__OFII "|Ofii"
#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"
@@ -153,6 +154,7 @@
#define TYPE__OFII "|Odii"
#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"
@@ -455,6 +457,11 @@ 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;
/* Constants */
#define E M_E
@@ -492,6 +499,7 @@ extern PyTypeObject TableScaleType;
#define FREEVERB_ID 24
#define XNOISEDUR_ID 25
#define URN_ID 26
+/* Do not forget to modify Server_generateSeed function */
/* object headers */
#define pyo_audio_HEAD \
@@ -776,6 +784,128 @@ 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 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; \
diff --git a/installers/osx/PkgResources_i386/ReadMe.rtf b/installers/osx/PkgResources_i386/ReadMe.rtf
index da986d8..ab49df1 100755
--- a/installers/osx/PkgResources_i386/ReadMe.rtf
+++ b/installers/osx/PkgResources_i386/ReadMe.rtf
@@ -1,71 +1,92 @@
-{\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
+{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360
+{\fonttbl\f0\fnil\fcharset0 LucidaGrande;\f1\froman\fcharset0 Times-Roman;}
+{\colortbl;\red255\green255\blue255;}
+\margl1440\margr1440\vieww14120\viewh11700\viewkind0
+\deftab720
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720
+
+\f0\fs26 \cf0 pyo (version 0.6.6)
+\f1\fs24 \
+
+\f0\fs26 \
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720\ql\qnatural
+\cf0 System requirements : OS X 10.5 or higher
+\f1\fs24 \
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720
+
+\f0\fs26 \cf0 \
+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.
+\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):
+\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.0.dylib
+\f1\fs24 \
+
+\f0\fs26 libportaudio.2.dylib
+\f1\fs24 \
+
+\f0\fs26 libportmidi.dylib
+\f1\fs24 \
+
+\f0\fs26 libsndfile.1.dylib
+\f1\fs24 \
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720\ql\qnatural
+
+\f0\fs26 \cf0 libFLAC.8.dylib\
+libvorbisenc.2.dylib\
+libvorbis.0.dylib\
+libogg.0.dylib\
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720
+\cf0 \
+\pard\pardeftab720\ql\qnatural
+\cf0 Olivier B\'e9langer, 2013
+\f1\fs24 \
+}
\ No newline at end of file
diff --git a/installers/osx/PkgResources_x86_64/ReadMe.rtf b/installers/osx/PkgResources_x86_64/ReadMe.rtf
index d6db53b..511c18c 100755
--- a/installers/osx/PkgResources_x86_64/ReadMe.rtf
+++ b/installers/osx/PkgResources_x86_64/ReadMe.rtf
@@ -1,75 +1,88 @@
-{\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
+{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360
+{\fonttbl\f0\fnil\fcharset0 LucidaGrande;\f1\froman\fcharset0 Times-Roman;}
+{\colortbl;\red255\green255\blue255;}
+\margl1440\margr1440\vieww13160\viewh13300\viewkind0
+\deftab720
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720\ql\qnatural
+
+\f0\fs26 \cf0 pyo (version 0.6.6)
+\f1\fs24 \
+
+\f0\fs26 \
+System requirements : OS X 10.6 to 10.8
+\f1\fs24 \
+
+\f0\fs26 \
+This package installs all the required components to run pyo inside your current Python installation. Python 2.6 or 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\ql\qnatural
+
+\b \cf0 1. pyo extension:
+\f1\b0\fs24 \
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardeftab720\ql\qnatural
+
+\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\ql\qnatural
+
+\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\ql\qnatural
+
+\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\ql\qnatural
+
+\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\ql\qnatural
+
+\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\
+libvorbisenc.2.dylib\
+libvorbis.0.dylib\
+libogg.0.dylib\
+\
+\pard\pardeftab720\ql\qnatural
+\cf0 Olivier B\'e9langer, 2013
+\f1\fs24 \
+}
\ No newline at end of file
diff --git a/installers/osx/release_i386.sh b/installers/osx/release_i386.sh
index 7fc5e31..3838604 100644
--- a/installers/osx/release_i386.sh
+++ b/installers/osx/release_i386.sh
@@ -7,9 +7,9 @@
# 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 PACKAGE_NAME=pyo_0.6.9_i386.pkg
+export DMG_DIR="pyo 0.6.9 Intel"
+export DMG_NAME="pyo_0.6.9_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
@@ -37,6 +37,11 @@ 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
+sudo install_name_tool -change libportmidi.dylib /usr/local/lib/libportmidi.dylib $PYO_MODULE_DIR/python26/_pyo.so
+sudo install_name_tool -change libportmidi.dylib /usr/local/lib/libportmidi.dylib $PYO_MODULE_DIR/python26/_pyo64.so
+sudo install_name_tool -change libportmidi.dylib /usr/local/lib/libportmidi.dylib $PYO_MODULE_DIR/python27/_pyo.so
+sudo install_name_tool -change libportmidi.dylib /usr/local/lib/libportmidi.dylib $PYO_MODULE_DIR/python27/_pyo64.so
+
cd ..
echo "copying support libs..."
@@ -45,9 +50,9 @@ sudo cp /usr/local/lib/libportaudio.2.dylib $SUPPORT_LIBS_DIR/libportaudio.2.dyl
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
+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
echo "setting permissions..."
diff --git a/installers/osx/release_x86_64.sh b/installers/osx/release_x86_64.sh
index 4c21d67..317badf 100644
--- a/installers/osx/release_x86_64.sh
+++ b/installers/osx/release_x86_64.sh
@@ -1,8 +1,8 @@
#!/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 PACKAGE_NAME=pyo_0.6.9_x86_64.pkg
+export DMG_DIR="pyo 0.6.9 Universal"
+export DMG_NAME="pyo_0.6.9_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
@@ -33,6 +33,11 @@ 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 libportmidi.dylib /usr/local/lib/libportmidi.dylib $PYO_MODULE_DIR/python26/_pyo.so
+sudo install_name_tool -change libportmidi.dylib /usr/local/lib/libportmidi.dylib $PYO_MODULE_DIR/python26/_pyo64.so
+sudo install_name_tool -change libportmidi.dylib /usr/local/lib/libportmidi.dylib $PYO_MODULE_DIR/python27/_pyo.so
+sudo install_name_tool -change libportmidi.dylib /usr/local/lib/libportmidi.dylib $PYO_MODULE_DIR/python27/_pyo64.so
+
cd ..
echo "copying support libs..."
@@ -41,12 +46,11 @@ sudo cp /usr/local/lib/libportaudio.2.dylib $SUPPORT_LIBS_DIR/libportaudio.2.dyl
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
+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
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
diff --git a/installers/win/win_installer_py26.iss b/installers/win/win_installer_py26.iss
index 1d24ca6..759d3d1 100644
--- a/installers/win/win_installer_py26.iss
+++ b/installers/win/win_installer_py26.iss
@@ -7,7 +7,7 @@
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{4F72B6EF-CFA0-434F-A2B4-B130F94F54EB}
AppName=Pyo
-AppVersion=0.6.8
+AppVersion=0.6.9
AppPublisher=iACT.umontreal.ca
AppPublisherURL=http://code.google.com/p/pyo
AppSupportURL=http://code.google.com/p/pyo
@@ -17,7 +17,7 @@ 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
+OutputBaseFilename=pyo_0.6.9_py2.6_setup
Compression=lzma
SolidCompression=yes
ChangesAssociations=yes
@@ -42,7 +42,7 @@ Source: "C:\Python26\Lib\site-packages\pthreadVC2.dll"; DestDir: "{sd}\Python26\
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:\Python26\Lib\site-packages\pyo-0.6.9-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
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
diff --git a/installers/win/win_installer_py27.iss b/installers/win/win_installer_py27.iss
index 6b0cf86..e879227 100644
--- a/installers/win/win_installer_py27.iss
+++ b/installers/win/win_installer_py27.iss
@@ -7,7 +7,7 @@
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{244D309A-C251-481A-AD24-0602D392A634}
AppName=Pyo
-AppVersion=0.6.8
+AppVersion=0.6.9
AppPublisher=iACT.umontreal.ca
AppPublisherURL=http://code.google.com/p/pyo
AppSupportURL=http://code.google.com/p/pyo
@@ -17,7 +17,7 @@ DisableDirPage=yes
DefaultGroupName=pyo
AllowNoIcons=yes
InfoBeforeFile=C:\Documents and Settings\user\svn\pyo\installers\win\\README-win32-py27.txt
-OutputBaseFilename=pyo_0.6.8_py2.7_setup
+OutputBaseFilename=pyo_0.6.9_py2.7_setup
Compression=lzma
SolidCompression=yes
ChangesAssociations=yes
@@ -26,8 +26,11 @@ ChangesEnvironment=yes
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
+; One installer for both python version
+; functions to set which python directory in Setup section
+; Check: DirExists(ExpandConstant('{sd}\Python27'))
[Files]
-Source: "C:\Python27\Lib\site-packages\pyo.py"; DestDir: "{sd}\Python27\Lib\site-packages"; Flags: ignoreversion
+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
@@ -41,7 +44,7 @@ Source: "C:\Python27\Lib\site-packages\pthreadVC2.dll"; DestDir: "{sd}\Python27\
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:\Python27\Lib\site-packages\pyo-0.6.9-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
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
diff --git a/pyo.py b/pyo.py
index f7a865f..081056d 100644
--- a/pyo.py
+++ b/pyo.py
@@ -99,7 +99,6 @@ if WITH_EXTERNALS:
import pyolib.external as external
from pyolib.external import *
-# Temporary objects, need to be coded in C
class FreqShift(PyoObject):
"""
Frequency shifting using single sideband amplitude modulation.
@@ -110,26 +109,14 @@ class FreqShift(PyoObject):
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
+ :Parent: :py:class:`PyoObject`
- Parameters:
+ :Args:
- 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:
+ input : PyoObject
+ Input signal to process.
+ shift : float or PyoObject, optional
+ Amount of shifting in Hertz. Defaults to 100.
>>> s = Server().boot()
>>> s.start()
@@ -141,11 +128,9 @@ class FreqShift(PyoObject):
"""
def __init__(self, input, shift=100, mul=1, add=0):
- PyoObject.__init__(self)
+ PyoObject.__init__(self, mul, add)
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)
@@ -162,25 +147,20 @@ class FreqShift(PyoObject):
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
+ 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]
- [obj.stop() for obj in self._base_objs]
- return self
+ return PyoObject.stop(self)
def out(self, chnl=0, inc=1, dur=0, delay=0):
dur, delay, lmax = convertArgsToLists(dur, delay)
@@ -188,14 +168,7 @@ class FreqShift(PyoObject):
[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)]
- 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
+ return PyoObject.out(self, chnl, inc, dur, delay)
def setInput(self, x, fadetime=0.05):
"""
@@ -245,6 +218,98 @@ class FreqShift(PyoObject):
@shift.setter
def shift(self, x): self.setShift(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):
+ 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.
+
+ """
+ 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)
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',
@@ -253,11 +318,12 @@ OBJECTS_TREE = {'functions': sorted(['pa_count_devices', 'pa_get_default_input',
'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_input_max_channels', 'pa_get_output_max_channels', 'pa_get_devices_infos', 'pa_get_version',
+ 'pa_get_version_text']),
'PyoObjectBase': {
'PyoMatrixObject': sorted(['NewMatrix']),
'PyoTableObject': sorted(['LinTable', 'NewTable', 'SndTable', 'HannTable', 'HarmTable', 'SawTable', 'ParaTable', 'LogTable', 'CosLogTable',
- 'SquareTable', 'ChebyTable', 'CosTable', 'CurveTable', 'ExpTable', 'DataTable', 'WinTable', 'SincTable']),
+ 'SquareTable', 'ChebyTable', 'CosTable', 'CurveTable', 'ExpTable', 'DataTable', 'WinTable', 'SincTable', 'PartialTable']),
'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',
@@ -265,10 +331,10 @@ OBJECTS_TREE = {'functions': sorted(['pa_count_devices', 'pa_get_default_input',
'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']),
+ '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']),
+ 'Biquada', 'Atone', 'SVF', 'Average', 'Reson', 'Resonx', 'ButLP', 'ButHP', 'ButBP', 'ButBR', 'ComplexRes']),
'generators': sorted(['Noise', 'Phasor', 'Sine', 'Input', 'FM', 'SineLoop', 'Blit', 'PinkNoise', 'CrossFM',
'BrownNoise', 'Rossler', 'Lorenz', 'LFO', 'SumOsc', 'SuperSaw', 'RCOsc']),
'internals': sorted(['Dummy', 'InputFader', 'Mix', 'VarPort']),
@@ -278,7 +344,7 @@ OBJECTS_TREE = {'functions': sorted(['pa_count_devices', 'pa_get_default_input',
'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',
+ 'tableprocess': sorted(['TableRec', 'Osc', 'Pointer', 'Pointer2', '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',
@@ -287,7 +353,7 @@ OBJECTS_TREE = {'functions': sorted(['pa_count_devices', 'pa_get_default_input',
'TrigVal']),
'utils': sorted(['Clean_objects', 'Print', 'Snap', 'Interp', 'SampHold', 'Compare', 'Record', 'Between', 'Denorm',
'ControlRec', 'ControlRead', 'NoteinRec', 'NoteinRead', 'DBToA', 'AToDB', 'Scale', 'CentsToTranspo',
- 'TranspoToCents', 'MToF', 'MToT']),
+ 'TranspoToCents', 'MToF', 'MToT', 'TrackHold']),
'fourier': sorted(['FFT', 'IFFT', 'CarToPol', 'PolToCar', 'FrameDelta', 'FrameAccum', 'Vectral', 'CvlVerb', 'Spectrum'])}},
'Map': {'SLMap': sorted(['SLMapFreq', 'SLMapMul', 'SLMapPhase', 'SLMapQ', 'SLMapDur', 'SLMapPan'])},
'Server': [],
@@ -295,5 +361,4 @@ OBJECTS_TREE = {'functions': sorted(['pa_count_devices', 'pa_get_default_input',
'TableStream': []}
DOC_KEYWORDS = ['Attributes', 'Examples', 'Parameters', 'Methods', 'Notes', 'Methods details', 'See also', 'Parentclass']
-
DEMOS_PATH = SNDS_PATH
diff --git a/pyolib/_core.py b/pyolib/_core.py
index 0a643c6..aea4c02 100644
--- a/pyolib/_core.py
+++ b/pyolib/_core.py
@@ -46,6 +46,7 @@ FILE_FORMATS = {'wav': 0, 'wave': 0, 'aif': 1, 'aiff': 1, 'au': 2, '': 3, 'sd2':
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_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)",
@@ -223,6 +224,9 @@ def getVersion():
major, minor, rev = PYO_VERSION.split('.')
return (int(major), int(minor), int(rev))
+def dumpref():
+ pass
+
class PyoError(Exception):
"""Base class for all pyo exceptions."""
@@ -286,6 +290,20 @@ class PyoObjectBase(object):
"""
return self._base_objs
+ def cleanFuncRefs(self):
+ """
+ Method used to remove internal references to callback functions.
+
+ An internal reference to a callback function (ex. the function
+ called by the TrigFunc object) may prevent the object to be
+ properly deleted when its reference count drop to zero. Calling
+ this function just before deleting the last reference will replace
+ the callback reference by a dump ref.
+
+ """
+ if hasattr(self, "_function"):
+ self.setFunction(dumpref)
+
def __getitem__(self, i):
if i == 'trig':
return self._trig_objs
@@ -1123,13 +1141,103 @@ 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.
+
+ """
+ [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.
+
+ """
+ [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.
+
+ """
+ [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.
+
+ """
+ [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.
+
+ """
+ [obj.fadeout(dur) for obj in self._base_objs]
+ self.refreshView()
+ return self
+
def copy(self):
"""
Returns a deep copy of the object.
@@ -1779,6 +1887,7 @@ class VarPort(PyoObject):
PyoObject.__init__(self, mul, add)
self._value = value
self._time = time
+ self._function = 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), wrap(function,i), wrap(arg,i), wrap(mul,i), wrap(add,i)) for i in range(lmax)]
@@ -1810,6 +1919,20 @@ class VarPort(PyoObject):
x, lmax = 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.
+
+ """
+ self._function = x
+ x, lmax = convertArgsToLists(x)
+ [obj.setFunction(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
+
@property
def value(self):
"""float. Numerical value to convert."""
@@ -1824,6 +1947,13 @@ class VarPort(PyoObject):
@time.setter
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):
"""
Performs a power function on audio signal.
diff --git a/pyolib/_maps.py b/pyolib/_maps.py
index 9845c77..7005918 100644
--- a/pyolib/_maps.py
+++ b/pyolib/_maps.py
@@ -158,17 +158,22 @@ class SLMap(Map):
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)]
>>> 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, self._init, self._res, self._ramp, self._dataOnly = name, init, res, ramp, dataOnly
@property
def name(self):
@@ -186,6 +191,10 @@ class SLMap(Map):
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):
"""
diff --git a/pyolib/_widgets.py b/pyolib/_widgets.py
index 518299c..1eb1db9 100644
--- a/pyolib/_widgets.py
+++ b/pyolib/_widgets.py
@@ -151,8 +151,7 @@ def wxCreateDelayedTableWindows():
def wxCreateDelayedSndTableWindows():
global CURRENT_X, MAX_X, NEXT_Y
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])
@@ -227,8 +226,8 @@ def createViewTableWindow(samples, title="Table waveform", wxnoserver=False, tab
else:
if wxnoserver or wx.GetApp() != None:
root = createRootWindow()
- if WITH_PIL: f = ViewTable_withPIL(None, samples, tableclass)
- else: f = ViewTable_withoutPIL(None, samples, tableclass)
+ if WITH_PIL: f = ViewTable_withPIL(None, samples, tableclass, object)
+ else: f = ViewTable_withoutPIL(None, samples, tableclass, object)
wxShowWindow(f, title, root)
if object != None:
object._setViewFrame(f)
@@ -246,8 +245,7 @@ def createSndViewTableWindow(obj, title="Table waveform", wxnoserver=False, tabl
else:
if wxnoserver or wx.GetApp() != None:
root = createRootWindow()
- if WITH_PIL: f = SndViewTable_withPIL(None, obj, tableclass, mouse_callback)
- else: f = SndViewTable_withoutPIL(None, obj, tableclass, mouse_callback)
+ f = SndViewTable(None, obj, tableclass, mouse_callback)
if title == None: title = obj.__class__.__name__
wxShowWindow(f, title, root)
obj._setViewFrame(f)
@@ -267,8 +265,8 @@ It helps a lot to speed up matrix drawing!"""
else:
if wxnoserver or wx.GetApp() != None:
root = createRootWindow()
- if WITH_PIL: f = ViewMatrix_withPIL(None, samples, size)
- else: f = ViewMatrix_withoutPIL(None, samples, size)
+ if WITH_PIL: f = ViewMatrix_withPIL(None, samples, size, object)
+ else: f = ViewMatrix_withoutPIL(None, samples, size, object)
wxShowWindow(f, title, root)
if object != None:
object._setViewFrame(f)
diff --git a/pyolib/_wxwidgets.py b/pyolib/_wxwidgets.py
index 4e85080..5651072 100644
--- a/pyolib/_wxwidgets.py
+++ b/pyolib/_wxwidgets.py
@@ -887,14 +887,17 @@ class PyoObjectControl(wx.Frame):
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]:
self._excluded.append(key)
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 scl == 'log': scl = True
@@ -907,15 +910,16 @@ class PyoObjectControl(wx.Frame):
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])
+ # 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)
@@ -927,14 +931,17 @@ class PyoObjectControl(wx.Frame):
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()
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)
######################################################################
### View window for PyoTableObject
@@ -1021,7 +1028,7 @@ class ViewTable_withoutPIL(ViewTable):
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.SetMinSize((300, 150))
self.menubar = wx.MenuBar()
self.fileMenu = wx.Menu()
closeItem = self.fileMenu.Append(-1, 'Close\tCtrl+W', kind=wx.ITEM_NORMAL)
@@ -1029,24 +1036,59 @@ class SndViewTable(wx.Frame):
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)
+ wx.CallAfter(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, mouse_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_MOTION, self.OnMotion)
+ self.Bind(wx.EVT_SIZE, self.OnSize)
+ self.obj = obj
+ self.chnls = len(self.obj)
+ self.begin = 0
+ self.end = self.obj.getDur(False)
+ self.mouse_callback = mouse_callback
+ if sys.platform == "win32":
+ self.dcref = wx.BufferedPaintDC
+ else:
+ self.dcref = wx.PaintDC
self.setImage()
+
+ def setBegin(self, x):
+ self.begin = x
+
+ def setEnd(self, x):
+ self.end = x
+
+ def setImage(self):
+ self.img = self.obj.getViewTable(self.GetSize(), self.begin, self.end)
self.Refresh()
def clipPos(self, pos):
@@ -1056,6 +1098,7 @@ class SndViewTable(wx.Frame):
if pos[1] < 0.0: y = 0.0
elif pos[1] > 1.0: y = 1.0
else: y = pos[1]
+ x = x * ((self.end - self.begin) / self.obj.getDur(False)) + (self.begin / self.obj.getDur(False))
return (x, y)
def OnMouseDown(self, evt):
@@ -1086,77 +1129,50 @@ class SndViewTable(wx.Frame):
if self.HasCapture():
self.ReleaseMouse()
-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 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)
- dc.DrawLine(0, y+off, w, y+off)
-
-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()
-
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
+ 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)
+ 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):
- 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)
- else:
- dc.DrawLineList(samples)
- dc.SetPen(wx.Pen('#444444', width=1, style=wx.SHORT_DASH))
+ 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)
+
+ def OnSize(self, evt):
+ wx.CallAfter(self.setImage)
######################################################################
## View window for PyoMatrixObject
@@ -2281,13 +2297,13 @@ class ServerGUI(wx.Frame):
if not justSet:
self.startf()
self._started = True
- self.startButton.SetLabel('Stop')
- self.quitButton.Disable()
+ wx.CallAfter(self.startButton.SetLabel, 'Stop')
+ wx.CallAfter(self.quitButton.Disable)
else:
self.stopf()
self._started = False
- self.startButton.SetLabel('Start')
- self.quitButton.Enable()
+ wx.CallAfter(self.startButton.SetLabel, 'Start')
+ wx.CallAfter(self.quitButton.Enable)
def record(self, evt):
if self._recstarted == False:
diff --git a/pyolib/analysis.py b/pyolib/analysis.py
index ffcdc53..7ba6fd8 100644
--- a/pyolib/analysis.py
+++ b/pyolib/analysis.py
@@ -246,7 +246,7 @@ class ZCross(PyoObject):
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)
@@ -292,6 +292,10 @@ class ZCross(PyoObject):
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):
@@ -440,6 +444,13 @@ class Yin(PyoObject):
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):
diff --git a/pyolib/controls.py b/pyolib/controls.py
index d993bbc..28dca81 100644
--- a/pyolib/controls.py
+++ b/pyolib/controls.py
@@ -129,6 +129,12 @@ class Fader(PyoObject):
x, lmax = convertArgsToLists(x)
[obj.setDur(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."""
@@ -281,6 +287,14 @@ class Adsr(PyoObject):
x, lmax = convertArgsToLists(x)
[obj.setDur(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."""
@@ -749,6 +763,10 @@ class SigTo(PyoObject):
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, dataOnly=True)]
+ PyoObject.ctrl(self, map_list, title, wxnoserver)
+
@property
def value(self):
"""float or PyoObject. Numerical value to convert."""
diff --git a/pyolib/dynamics.py b/pyolib/dynamics.py
index 9e6abd8..f4d6a88 100644
--- a/pyolib/dynamics.py
+++ b/pyolib/dynamics.py
@@ -511,6 +511,8 @@ class Compress(PyoObject):
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)
@@ -690,6 +692,7 @@ class Gate(PyoObject):
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)
diff --git a/pyolib/effects.py b/pyolib/effects.py
index 09024ed..068206c 100644
--- a/pyolib/effects.py
+++ b/pyolib/effects.py
@@ -150,6 +150,17 @@ class Delay(PyoObject):
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()
@@ -259,6 +270,10 @@ class SDelay(PyoObject):
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()
@@ -313,7 +328,7 @@ class SDelay(PyoObject):
[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)
@@ -1166,6 +1181,7 @@ class Harmonizer(PyoObject):
def ctrl(self, map_list=None, title=None, wxnoserver=False):
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)
@@ -1247,3 +1263,220 @@ class Delay1(PyoObject):
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):
+ 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)]
+
+ 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.
+
+ """
+ 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.
+
+ """
+ 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.
+
+ """
+ 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.
+
+ """
+ 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.
+
+ """
+ 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.
+
+ """
+ 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.
+
+ """
+ self._firstRefGain = x
+ x, lmax = convertArgsToLists(x)
+ [obj.setFirstRefGain(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(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)
diff --git a/pyolib/filters.py b/pyolib/filters.py
index 1feb485..89d60cb 100644
--- a/pyolib/filters.py
+++ b/pyolib/filters.py
@@ -141,7 +141,9 @@ class Biquad(PyoObject):
[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
@@ -297,7 +299,9 @@ class Biquadx(PyoObject):
[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
@@ -684,6 +688,7 @@ class EQ(PyoObject):
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),
+ SLMap(0, 2, 'lin', 'type', self._type, res="int", dataOnly=True),
SLMapMul(self._mul)]
PyoObject.ctrl(self, map_list, title, wxnoserver)
@@ -1946,6 +1951,7 @@ class Vocoder(PyoObject):
SLMap(0.25, 2, "lin", "spread", self._spread),
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)
@@ -2125,7 +2131,8 @@ class IRWinSinc(PyoObject):
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
@@ -2352,7 +2359,8 @@ class IRPulse(PyoObject):
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
@@ -2738,7 +2746,8 @@ class Average(PyoObject):
[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
@@ -3361,3 +3370,109 @@ class ButBR(PyoObject):
return self._q
@q.setter
def q(self, x): self.setQ(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):
+ 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)]
+
+ 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.
+
+ """
+ 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.
+
+ """
+ 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.
+
+ """
+ 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/generators.py b/pyolib/generators.py
index a24bb1e..d4731ca 100644
--- a/pyolib/generators.py
+++ b/pyolib/generators.py
@@ -1033,7 +1033,10 @@ class LFO(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)]
+ self._map_list = [SLMapFreq(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
diff --git a/pyolib/pan.py b/pyolib/pan.py
index 54b16d7..f66eb18 100644
--- a/pyolib/pan.py
+++ b/pyolib/pan.py
@@ -39,7 +39,8 @@ class Pan(PyoObject):
input : PyoObject
Input signal to process.
outs : int, optional
- Number of channels on the panning circle. Defaults to 2.
+ 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.
@@ -149,7 +150,8 @@ class SPan(PyoObject):
input : PyoObject
Input signal to process.
outs : int, optional
- Number of channels on the panning circle. Defaults to 2.
+ 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.
@@ -238,7 +240,8 @@ class Switch(PyoObject):
input : PyoObject
Input signal to process.
outs : int, optional
- Number of outputs. Defaults to 2.
+ 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.
@@ -684,7 +687,8 @@ class Mixer(PyoObject):
return 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
diff --git a/pyolib/phasevoc.py b/pyolib/phasevoc.py
index bb4f5e5..379b934 100644
--- a/pyolib/phasevoc.py
+++ b/pyolib/phasevoc.py
@@ -295,8 +295,8 @@ class PVAddSynth(PyoObject):
>>> 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):
diff --git a/pyolib/players.py b/pyolib/players.py
index 98992ad..3a1f7a4 100644
--- a/pyolib/players.py
+++ b/pyolib/players.py
@@ -208,7 +208,9 @@ class SfPlayer(PyoObject):
[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
@@ -354,7 +356,9 @@ class SfMarkerShuffler(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), 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
@@ -492,6 +496,7 @@ class SfMarkerLooper(PyoObject):
def ctrl(self, map_list=None, title=None, wxnoserver=False):
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)
diff --git a/pyolib/randoms.py b/pyolib/randoms.py
index 695ee21..737a0e6 100644
--- a/pyolib/randoms.py
+++ b/pyolib/randoms.py
@@ -627,7 +627,7 @@ class Xnoise(PyoObject):
new `x2` attribute.
"""
- self._x2= x
+ self._x2 = x
x, lmax = convertArgsToLists(x)
[obj.setX2(wrap(x,i)) for i, obj in enumerate(self._base_objs)]
@@ -645,6 +645,15 @@ class Xnoise(PyoObject):
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):
"""string or int. Distribution type."""
@@ -880,6 +889,14 @@ class XnoiseMidi(PyoObject):
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):
"""string or int. Distribution type."""
@@ -1097,6 +1114,14 @@ class XnoiseDur(PyoObject):
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):
"""string or int. Distribution type."""
@@ -1208,7 +1233,7 @@ class Urn(PyoObject):
[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)
diff --git a/pyolib/server.py b/pyolib/server.py
index b7729a0..73af2ba 100644
--- a/pyolib/server.py
+++ b/pyolib/server.py
@@ -98,7 +98,7 @@ class Server(object):
"""
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:
+ if os.environ.has_key("PYO_SERVER_AUDIO") and "offline" not in audio and "embedded" not in audio:
audio = os.environ["PYO_SERVER_AUDIO"]
self._time = time
self._nchnls = nchnls
@@ -637,13 +637,6 @@ class Server(object):
"""
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):
"""
diff --git a/pyolib/tableprocess.py b/pyolib/tableprocess.py
index 2b4fb7c..042d01e 100644
--- a/pyolib/tableprocess.py
+++ b/pyolib/tableprocess.py
@@ -136,6 +136,7 @@ class Osc(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)
@@ -403,6 +404,7 @@ 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)
@@ -854,7 +856,10 @@ class TableRead(PyoObject):
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
@@ -1019,7 +1024,11 @@ class Pulsar(PyoObject):
:Args:
x : int {1, 2, 3, 4}
- new `interp` attribute.
+ Choice of the interpolation method.
+ 1. no interpolation
+ 2. linear
+ 3. cosinus
+ 4. cubic
"""
self._interp = x
@@ -1030,6 +1039,7 @@ 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)
@@ -1149,6 +1159,144 @@ class Pointer(PyoObject):
@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):
+ 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)]
+
+ def setTable(self, x):
+ """
+ Replace the `table` attribute.
+
+ :Args:
+
+ x : PyoTableObject
+ new `table` attribute.
+
+ """
+ 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.
+
+ """
+ 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)
+
+ """
+ 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.
+
+ """
+ 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."""
+ 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)
+
+ @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.
@@ -1710,6 +1858,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)
@@ -2128,7 +2278,9 @@ class Looper(PyoObject):
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(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)
diff --git a/pyolib/tables.py b/pyolib/tables.py
index f3a4a3f..4fc552a 100644
--- a/pyolib/tables.py
+++ b/pyolib/tables.py
@@ -1588,6 +1588,33 @@ class SndTable(PyoTableObject):
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.
@@ -1759,10 +1786,13 @@ class NewTable(PyoTableObject):
"""
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()
@@ -1774,6 +1804,33 @@ class NewTable(PyoTableObject):
"""
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.
diff --git a/pyolib/triggers.py b/pyolib/triggers.py
index dac00f0..e653171 100644
--- a/pyolib/triggers.py
+++ b/pyolib/triggers.py
@@ -676,7 +676,11 @@ 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
@@ -2261,6 +2265,14 @@ class Counter(PyoObject):
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):
"""PyoObject. Audio trigger signal."""
@@ -2367,6 +2379,10 @@ class Select(PyoObject):
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):
"""PyoObject. Audio signal."""
@@ -2923,6 +2939,12 @@ class Count(PyoObject):
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):
"""PyoObject. Trigger signal. Start/Restart the count."""
diff --git a/pyolib/utils.py b/pyolib/utils.py
index f1de462..ab68c0a 100644
--- a/pyolib/utils.py
+++ b/pyolib/utils.py
@@ -430,7 +430,7 @@ class SampHold(PyoObject):
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.
+ is sampled and held until next sampling.
:Parent: :py:class:`PyoObject`
@@ -441,7 +441,7 @@ class SampHold(PyoObject):
controlsig : PyoObject
Controls when to sample the signal.
value : float or PyoObject, optional
- Sampling targeted value. Default to 0.0.
+ Sampling target value. Default to 0.0.
>>> s = Server().boot()
>>> s.start()
@@ -521,7 +521,7 @@ class SampHold(PyoObject):
@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)
@@ -1736,3 +1736,105 @@ class Between(PyoObject):
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):
+ 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)]
+
+ 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 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.
+
+ """
+ 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.
+
+ """
+ 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)
diff --git a/scripts/release_doc_src.sh b/scripts/release_doc_src.sh
index 9b8c344..2c2f029 100644
--- 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.6.9
replace=XXX
doc_rep=pyo_XXX-doc
diff --git a/setup.py b/setup.py
index 92bcd39..1777d95 100644
--- a/setup.py
+++ b/setup.py
@@ -23,7 +23,7 @@ from distutils.core import setup, Extension
import os, sys, getopt
import time
-pyo_version = "0.6.8"
+pyo_version = "0.6.9"
build_osx_with_jack_support = False
compile_externals = False
@@ -68,13 +68,14 @@ files = ['pyomodule.c', 'servermodule.c', 'pvstreammodule.c', 'streammodule.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',
+files = ['tablemodule.c', 'wgverbmodule.c', 'freeverbmodule.c', 'phasevocmodule.c', 'fftmodule.c',
+ 'oscilmodule.c', 'randommodule.c', 'oscmodule.c','analysismodule.c',
+ 'sfplayermodule.c', 'oscbankmodule.c', 'lfomodule.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',
+ 'selectmodule.c', 'compressmodule.c', 'utilsmodule.c',
+ 'convolvemodule.c', 'arithmeticmodule.c', 'sigmodule.c',
'matrixprocessmodule.c', 'harmonizermodule.c', 'chorusmodule.c']
if compile_externals:
@@ -93,6 +94,8 @@ 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:
diff --git a/src/engine/interpolation.c b/src/engine/interpolation.c
index a9ee2b5..00ee8c2 100644
--- a/src/engine/interpolation.c
+++ b/src/engine/interpolation.c
@@ -38,7 +38,7 @@ MYFLT cosine(MYFLT *buf, int index, MYFLT frac, int size) {
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) {
diff --git a/src/engine/pyomodule.c b/src/engine/pyomodule.c
index 208eff1..6de20d9 100644
--- a/src/engine/pyomodule.c
+++ b/src/engine/pyomodule.c
@@ -52,6 +52,28 @@ static void portaudio_assert(PaError ecode, const char* cmdName) {
>>> print c\n\
1\n\n"
+#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"
+
+static PyObject *
+portaudio_get_version() {
+ return PyInt_FromLong(Pa_GetVersion());
+}
+
+#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"
+
+static PyObject *
+portaudio_get_version_text() {
+ return PyString_FromString(Pa_GetVersionText());
+}
+
static PyObject *
portaudio_count_host_apis(){
PaError err;
@@ -1296,7 +1318,7 @@ 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;
@@ -2077,6 +2099,8 @@ serverBooted(PyObject *self) {
}
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},
@@ -2408,6 +2432,11 @@ 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);
PyModule_AddStringConstant(m, "PYO_VERSION", PYO_VERSION);
#ifdef COMPILE_EXTERNALS
diff --git a/src/engine/servermodule.c b/src/engine/servermodule.c
index 9148323..e7418c8 100644
--- a/src/engine/servermodule.c
+++ b/src/engine/servermodule.c
@@ -2136,85 +2136,6 @@ Server_boot(Server *self, PyObject *arg)
return Py_None;
}
-/* Like the Server_boot() but without reinitializing the buffers */
-static PyObject *
-Server_flush(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;
- }
- self->server_started = 0;
- self->stream_count = 0;
- self->elapsedSamples = 0;
-
- 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
- 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
- break;
- case PyoOffline:
- audioerr = Server_offline_init(self);
- if (audioerr < 0) {
- Server_offline_deinit(self);
- }
- break;
- case PyoOfflineNB:
- audioerr = Server_offline_init(self);
- if (audioerr < 0) {
- Server_offline_deinit(self);
- }
- break;
- case PyoEmbedded:
- audioerr = Server_embedded_init(self);
- if (audioerr < 0) {
- Server_embedded_deinit(self);
- }
- break;
- }
-
- 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;
-}
-
static PyObject *
Server_start(Server *self)
{
@@ -2240,7 +2161,7 @@ Server_start(Server *self)
self->server_started = 1;
self->timeStep = (int)(0.01 * self->samplingRate);
- if (self->audio_be_type != PyoOffline && self->audio_be_type != PyoOfflineNB) {
+ if (self->audio_be_type != PyoOffline && self->audio_be_type != PyoOfflineNB && self->audio_be_type != PyoEmbedded) {
midierr = Server_pm_init(self);
Server_debug(self, "PortMidi initialization return code : %d.\n", midierr);
}
@@ -2742,7 +2663,6 @@ static PyMethodDef Server_methods[] = {
{"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"},
diff --git a/src/objects/delaymodule.c b/src/objects/delaymodule.c
index f4a0302..4114833 100644
--- a/src/objects/delaymodule.c
+++ b/src/objects/delaymodule.c
@@ -35,6 +35,7 @@ typedef struct {
PyObject *feedback;
Stream *feedback_stream;
MYFLT maxdelay;
+ MYFLT oneOverSr;
long size;
long in_count;
int modebuffer[4];
@@ -50,8 +51,8 @@ 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;
@@ -99,8 +100,8 @@ Delay_process_ai(Delay *self) {
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;
@@ -130,8 +131,8 @@ Delay_process_ia(Delay *self) {
MYFLT del = PyFloat_AS_DOUBLE(self->delay);
MYFLT *fdb = Stream_getData((Stream *)self->feedback_stream);
- 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;
@@ -175,8 +176,8 @@ Delay_process_aa(Delay *self) {
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;
@@ -325,6 +326,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;
@@ -615,7 +619,7 @@ SDelay_process_i(SDelay *self) {
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];
@@ -648,7 +652,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];
diff --git a/src/objects/fadermodule.c b/src/objects/fadermodule.c
index 906d3c8..98cf25b 100644
--- a/src/objects/fadermodule.c
+++ b/src/objects/fadermodule.c
@@ -55,8 +55,10 @@ Fader_generate_auto(Fader *self) {
for (i=0; i<self->bufsize; i++) {
if (self->currentTime <= self->attack)
val = self->currentTime / self->attack;
- else if (self->currentTime > self->duration)
+ else if (self->currentTime > self->duration) {
val = 0.;
+ Fader_internal_stop((Fader *)self);
+ }
else if (self->currentTime >= (self->duration - self->release))
val = (self->duration - self->currentTime) / self->release;
else
@@ -427,8 +429,10 @@ Adsr_generate_auto(Adsr *self) {
val = self->currentTime * invatt;
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)
+ else if (self->currentTime > self->duration) {
val = 0.;
+ Adsr_internal_stop((Adsr *)self);
+ }
else if (self->currentTime >= (self->duration - self->release))
val = (self->duration - self->currentTime) * invrel * self->sustain;
else
diff --git a/src/objects/filtremodule.c b/src/objects/filtremodule.c
index d848581..de7c575 100644
--- a/src/objects/filtremodule.c
+++ b/src/objects/filtremodule.c
@@ -5792,6 +5792,7 @@ 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
@@ -5829,9 +5830,9 @@ 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
@@ -5887,11 +5888,12 @@ 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);
}
@@ -5971,11 +5973,12 @@ Vocoder_filters_aii(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;
@@ -6053,11 +6056,12 @@ Vocoder_filters_iai(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;
@@ -6138,11 +6142,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;
@@ -6220,11 +6225,12 @@ Vocoder_filters_iia(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;
@@ -6304,11 +6310,12 @@ Vocoder_filters_aia(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;
@@ -6388,11 +6395,12 @@ Vocoder_filters_iaa(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;
@@ -6474,11 +6482,12 @@ Vocoder_filters_aaa(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;
@@ -6674,6 +6683,7 @@ 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;
@@ -11024,3 +11034,510 @@ 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);
+ self->ob_type->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;
+
+ 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;
+}
+
+static PyObject *
+ComplexRes_setDecay(ComplexRes *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->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*/
+(binaryfunc)ComplexRes_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)ComplexRes_inplace_add, /*inplace_add*/
+(binaryfunc)ComplexRes_inplace_sub, /*inplace_subtract*/
+(binaryfunc)ComplexRes_inplace_multiply, /*inplace_multiply*/
+(binaryfunc)ComplexRes_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 ComplexResType = {
+PyObject_HEAD_INIT(NULL)
+0, /*ob_size*/
+"_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_compare*/
+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 */
+};
diff --git a/src/objects/freeverbmodule.c b/src/objects/freeverbmodule.c
index 8ba510b..9f98523 100644
--- a/src/objects/freeverbmodule.c
+++ b/src/objects/freeverbmodule.c
@@ -50,7 +50,7 @@ static const MYFLT allpass_delays[NUM_ALLPASS] = {
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;
@@ -929,4 +929,3 @@ PyTypeObject FreeverbType = {
0, /* tp_alloc */
Freeverb_new, /* tp_new */
};
-
diff --git a/src/objects/matrixmodule.c b/src/objects/matrixmodule.c
index dc1a8d6..9178518 100644
--- a/src/objects/matrixmodule.c
+++ b/src/objects/matrixmodule.c
@@ -595,6 +595,7 @@ MatrixRec_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
INIT_INPUT_STREAM
Py_XDECREF(self->matrix);
+ Py_INCREF(matrixtmp);
self->matrix = (NewMatrix *)matrixtmp;
PyObject_CallMethod(self->server, "addStream", "O", self->stream);
@@ -801,6 +802,7 @@ MatrixRecLoop_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
INIT_INPUT_STREAM
Py_XDECREF(self->matrix);
+ Py_INCREF(matrixtmp);
self->matrix = (NewMatrix *)matrixtmp;
PyObject_CallMethod(self->server, "addStream", "O", self->stream);
@@ -1013,6 +1015,7 @@ MatrixMorph_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
INIT_INPUT_STREAM
Py_XDECREF(self->matrix);
+ Py_INCREF(matrixtmp);
self->matrix = (PyObject *)matrixtmp;
width = NewMatrix_getWidth((NewMatrix *)self->matrix);
@@ -1021,6 +1024,7 @@ 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);
diff --git a/src/objects/oscilmodule.c b/src/objects/oscilmodule.c
index 5c7f1e0..ca15b18 100644
--- a/src/objects/oscilmodule.c
+++ b/src/objects/oscilmodule.c
@@ -3084,13 +3084,12 @@ Pointer_readframes_a(Pointer *self) {
int size = TableStream_getSize(self->table);
MYFLT *pha = Stream_getData((Stream *)self->index_stream);
-
+
for (i=0; i<self->bufsize; i++) {
- ph = Osc_clip(pha[i] * size, size);
-
+ 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;
+ self->data[i] = tablelist[ipart] + (tablelist[ipart+1] - tablelist[ipart]) * fpart;
}
}
@@ -3221,7 +3220,7 @@ Pointer_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
PyObject_CallMethod(self->server, "addStream", "O", self->stream);
(*self->mode_func_ptr)(self);
-
+
return (PyObject *)self;
}
@@ -3414,6 +3413,428 @@ Pointer_new, /* tp_new */
};
/**************/
+/* Pointer2 object */
+/**************/
+typedef struct {
+ pyo_audio_HEAD
+ PyObject *table;
+ PyObject *index;
+ Stream *index_stream;
+ int modebuffer[2];
+ 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
+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);
+
+ 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 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
+Pointer2_setProcMode(Pointer2 *self)
+{
+ int muladdmode;
+ muladdmode = self->modebuffer[0] + self->modebuffer[1] * 10;
+
+ self->proc_func_ptr = Pointer2_readframes_a;
+
+ switch (muladdmode) {
+ case 0:
+ self->muladd_func_ptr = Pointer2_postprocessing_ii;
+ break;
+ case 1:
+ self->muladd_func_ptr = Pointer2_postprocessing_ai;
+ break;
+ case 2:
+ self->muladd_func_ptr = Pointer2_postprocessing_revai;
+ break;
+ case 10:
+ self->muladd_func_ptr = Pointer2_postprocessing_ia;
+ break;
+ case 11:
+ self->muladd_func_ptr = Pointer2_postprocessing_aa;
+ break;
+ case 12:
+ self->muladd_func_ptr = Pointer2_postprocessing_revaa;
+ break;
+ case 20:
+ self->muladd_func_ptr = Pointer2_postprocessing_ireva;
+ break;
+ case 21:
+ self->muladd_func_ptr = Pointer2_postprocessing_areva;
+ break;
+ case 22:
+ self->muladd_func_ptr = Pointer2_postprocessing_revareva;
+ break;
+ }
+}
+
+static void
+Pointer2_compute_next_data_frame(Pointer2 *self)
+{
+ (*self->proc_func_ptr)(self);
+ (*self->muladd_func_ptr)(self);
+}
+
+static int
+Pointer2_traverse(Pointer2 *self, visitproc visit, void *arg)
+{
+ pyo_VISIT
+ Py_VISIT(self->table);
+ Py_VISIT(self->index);
+ Py_VISIT(self->index_stream);
+ return 0;
+}
+
+static int
+Pointer2_clear(Pointer2 *self)
+{
+ pyo_CLEAR
+ Py_CLEAR(self->table);
+ Py_CLEAR(self->index);
+ Py_CLEAR(self->index_stream);
+ return 0;
+}
+
+static void
+Pointer2_dealloc(Pointer2* self)
+{
+ pyo_DEALLOC
+ Pointer2_clear(self);
+ self->ob_type->tp_free((PyObject*)self);
+}
+
+static PyObject *
+Pointer2_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ int i;
+ PyObject *tabletmp, *indextmp, *multmp=NULL, *addtmp=NULL;
+ 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, Pointer2_compute_next_data_frame);
+ self->mode_func_ptr = Pointer2_setProcMode;
+
+ 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 Pointer2 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 (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 * 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 * 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 * 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 *
+Pointer2_getTable(Pointer2* self)
+{
+ Py_INCREF(self->table);
+ return self->table;
+};
+
+static PyObject *
+Pointer2_setTable(Pointer2 *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(Py_None);
+ return Py_None;
+}
+
+static PyObject *
+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 Pointer2 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);
+
+ 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 PyObject *
+Pointer2_setInterp(Pointer2 *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 *
+Pointer2_setAutoSmooth(Pointer2 *self, PyObject *arg)
+{
+ if (arg == NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ 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 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 Pointer2_as_number = {
+(binaryfunc)Pointer2_add, /*nb_add*/
+(binaryfunc)Pointer2_sub, /*nb_subtract*/
+(binaryfunc)Pointer2_multiply, /*nb_multiply*/
+(binaryfunc)Pointer2_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)Pointer2_inplace_add, /*inplace_add*/
+(binaryfunc)Pointer2_inplace_sub, /*inplace_subtract*/
+(binaryfunc)Pointer2_inplace_multiply, /*inplace_multiply*/
+(binaryfunc)Pointer2_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 Pointer2Type = {
+PyObject_HEAD_INIT(NULL)
+0, /*ob_size*/
+"_pyo.Pointer2_base", /*tp_name*/
+sizeof(Pointer2), /*tp_basicsize*/
+0, /*tp_itemsize*/
+(destructor)Pointer2_dealloc, /*tp_dealloc*/
+0, /*tp_print*/
+0, /*tp_getattr*/
+0, /*tp_setattr*/
+0, /*tp_compare*/
+0, /*tp_repr*/
+&Pointer2_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*/
+"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 */
+Pointer2_methods, /* tp_methods */
+Pointer2_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 */
+Pointer2_new, /* tp_new */
+};
+
+/**************/
/* TableIndex object */
/**************/
typedef struct {
diff --git a/src/objects/oscmodule.c b/src/objects/oscmodule.c
index a8e8f05..51fb4ef 100644
--- a/src/objects/oscmodule.c
+++ b/src/objects/oscmodule.c
@@ -1054,6 +1054,8 @@ OscDataReceive_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
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) {
@@ -1094,6 +1096,8 @@ 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 */
diff --git a/src/objects/sigmodule.c b/src/objects/sigmodule.c
index 93e295e..7cd4cf0 100644
--- a/src/objects/sigmodule.c
+++ b/src/objects/sigmodule.c
@@ -333,9 +333,9 @@ typedef struct {
pyo_audio_HEAD
PyObject *value;
Stream *value_stream;
- MYFLT time;
MYFLT lastValue;
MYFLT currentValue;
+ MYFLT time;
long timeStep;
MYFLT stepVal;
long timeCount;
@@ -346,20 +346,19 @@ static void
SigTo_generates_i(SigTo *self) {
int i;
MYFLT value;
-
if (self->modebuffer[2] == 0) {
value = PyFloat_AS_DOUBLE(self->value);
+ if (value != self->lastValue) {
+ self->timeCount = 0;
+ self->timeStep = (long)(self->time * self->sr);
+ self->stepVal = (value - self->currentValue) / self->timeStep;
+ self->lastValue = value;
+ }
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;
- }
-
+ else {
for (i=0; i<self->bufsize; i++) {
if (self->timeCount == (self->timeStep - 1)) {
self->currentValue = value;
@@ -386,6 +385,7 @@ SigTo_generates_i(SigTo *self) {
value = vals[i];
if (value != self->lastValue) {
self->timeCount = 0;
+ self->timeStep = (long)(self->time * self->sr);
self->stepVal = (value - self->currentValue) / self->timeStep;
self->lastValue = value;
}
@@ -497,7 +497,6 @@ SigTo_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
self->value = PyFloat_FromDouble(0.0);
self->time = 0.025;
- self->timeStep = (long)(self->time * self->sr);
self->timeCount = 0;
self->stepVal = 0.0;
self->modebuffer[0] = 0;
@@ -532,6 +531,7 @@ SigTo_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
PyObject_CallMethod(self->server, "addStream", "O", self->stream);
self->lastValue = self->currentValue = inittmp;
+ self->timeStep = (long)(self->time * self->sr);
(*self->mode_func_ptr)(self);
@@ -590,7 +590,6 @@ SigTo_setTime(SigTo *self, PyObject *arg)
Py_INCREF(tmp);
if (isNumber == 1) {
self->time = PyFloat_AS_DOUBLE(PyNumber_Float(tmp));
- self->timeStep = (long)(self->time * self->sr);
}
Py_INCREF(Py_None);
@@ -992,6 +991,26 @@ VarPort_setTime(VarPort *self, PyObject *arg)
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 };
@@ -1026,6 +1045,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."},
diff --git a/src/objects/tablemodule.c b/src/objects/tablemodule.c
index 0be9ea5..285deb9 100644
--- a/src/objects/tablemodule.c
+++ b/src/objects/tablemodule.c
@@ -231,6 +231,13 @@ 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_setTable(HarmTable *self, PyObject *arg) { SET_TABLE };
static PyObject * HarmTable_getTable(HarmTable *self) { GET_TABLE };
@@ -307,7 +314,14 @@ static PyMethodDef HarmTable_methods[] = {
{"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."},
{"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"},
@@ -505,6 +519,13 @@ 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_setTable(ChebyTable *self, PyObject *arg) { SET_TABLE };
static PyObject * ChebyTable_getTable(ChebyTable *self) { GET_TABLE };
@@ -657,6 +678,13 @@ static PyMethodDef ChebyTable_methods[] = {
{"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."},
@@ -787,6 +815,13 @@ 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_setTable(HannTable *self, PyObject *arg) { SET_TABLE };
static PyObject * HannTable_getTable(HannTable *self) { GET_TABLE };
@@ -842,6 +877,13 @@ static PyMethodDef HannTable_methods[] = {
{"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."},
@@ -991,6 +1033,13 @@ 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_setTable(SincTable *self, PyObject *arg) { SET_TABLE };
static PyObject * SincTable_getTable(SincTable *self) { GET_TABLE };
@@ -1080,6 +1129,13 @@ static PyMethodDef SincTable_methods[] = {
{"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."},
@@ -1203,6 +1259,13 @@ 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_setTable(WinTable *self, PyObject *arg) { SET_TABLE };
static PyObject * WinTable_getTable(WinTable *self) { GET_TABLE };
@@ -1279,6 +1342,13 @@ static PyMethodDef WinTable_methods[] = {
{"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."},
@@ -1415,6 +1485,13 @@ 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_setTable(ParaTable *self, PyObject *arg) { SET_TABLE };
static PyObject * ParaTable_getTable(ParaTable *self) { GET_TABLE };
@@ -1470,6 +1547,13 @@ static PyMethodDef ParaTable_methods[] = {
{"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."},
@@ -1639,6 +1723,13 @@ 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_setTable(LinTable *self, PyObject *arg) { SET_TABLE };
static PyObject * LinTable_getTable(LinTable *self) { GET_TABLE };
@@ -1748,6 +1839,13 @@ static PyMethodDef LinTable_methods[] = {
{"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."},
@@ -1943,6 +2041,13 @@ 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_setTable(LogTable *self, PyObject *arg) { SET_TABLE };
static PyObject * LogTable_getTable(LogTable *self) { GET_TABLE };
@@ -2052,6 +2157,13 @@ static PyMethodDef LogTable_methods[] = {
{"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."},
@@ -2225,6 +2337,13 @@ 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_setTable(CosTable *self, PyObject *arg) { SET_TABLE };
static PyObject * CosTable_getTable(CosTable *self) { GET_TABLE };
@@ -2334,6 +2453,13 @@ static PyMethodDef CosTable_methods[] = {
{"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."},
@@ -2531,6 +2657,13 @@ 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_setTable(CosLogTable *self, PyObject *arg) { SET_TABLE };
static PyObject * CosLogTable_getTable(CosLogTable *self) { GET_TABLE };
@@ -2640,6 +2773,13 @@ static PyMethodDef CosLogTable_methods[] = {
{"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."},
@@ -2840,6 +2980,13 @@ 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_setTable(CurveTable *self, PyObject *arg) { SET_TABLE };
static PyObject * CurveTable_getTable(CurveTable *self) { GET_TABLE };
@@ -2999,6 +3146,13 @@ 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."},
{NULL} /* Sentinel */
};
@@ -3190,6 +3344,13 @@ 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_setTable(ExpTable *self, PyObject *arg) { SET_TABLE };
static PyObject * ExpTable_getTable(ExpTable *self) { GET_TABLE };
@@ -3348,6 +3509,13 @@ 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."},
{NULL} /* Sentinel */
};
@@ -3856,6 +4024,13 @@ 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_setTable(SndTable *self, PyObject *arg) { SET_TABLE };
static PyObject * SndTable_getTable(SndTable *self) { GET_TABLE };
@@ -3864,17 +4039,37 @@ static PyObject * SndTable_get(SndTable *self, PyObject *args, PyObject *kwds) {
static PyObject *
SndTable_getViewTable(SndTable *self, PyObject *args, PyObject *kwds) {
- int i, j, y, w, h, h2, step;
+ 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};
+ static char *kwlist[] = {"size", "begin", "end", "yOffset", NULL};
- if (! PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &sizetmp))
+ 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,20 +4089,52 @@ 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;
};
@@ -4080,6 +4307,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."},
@@ -4148,6 +4382,7 @@ typedef struct {
pyo_table_HEAD
MYFLT length;
MYFLT feedback;
+ MYFLT sr;
int pointer;
} NewTable;
@@ -4222,8 +4457,8 @@ NewTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
if (! PyArg_ParseTupleAndKeywords(args, kwds, TYPE_F_OF, kwlist, &self->length, &inittmp, &self->feedback))
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++) {
@@ -4237,7 +4472,7 @@ NewTable_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
}
TableStream_setData(self->tablestream, self->data);
- TableStream_setSamplingRate(self->tablestream, sr);
+ TableStream_setSamplingRate(self->tablestream, self->sr);
return (PyObject *)self;
}
@@ -4249,6 +4484,13 @@ 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_setTable(NewTable *self, PyObject *arg) { SET_TABLE };
static PyObject * NewTable_getTable(NewTable *self) { GET_TABLE };
@@ -4257,17 +4499,37 @@ static PyObject * NewTable_get(NewTable *self, PyObject *args, PyObject *kwds) {
static PyObject *
NewTable_getViewTable(NewTable *self, PyObject *args, PyObject *kwds) {
- int i, j, y, w, h, h2, step;
+ 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", "begin", "end", "yOffset", NULL};
- static char *kwlist[] = {"size", NULL};
-
- if (! PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &sizetmp))
+ 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 +4549,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;
};
@@ -4360,6 +4654,13 @@ static PyMethodDef NewTable_methods[] = {
{"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."},
@@ -4492,6 +4793,13 @@ 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_setTable(DataTable *self, PyObject *arg) { SET_TABLE };
static PyObject * DataTable_getTable(DataTable *self) { GET_TABLE };
@@ -4530,6 +4838,13 @@ static PyMethodDef DataTable_methods[] = {
{"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."},
@@ -4727,6 +5042,7 @@ TableRec_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Py_Exit(1);
}
Py_XDECREF(self->table);
+ Py_INCREF(tabletmp);
self->table = (NewTable *)tabletmp;
PyObject_CallMethod(self->server, "addStream", "O", self->stream);
@@ -5217,9 +5533,11 @@ TableMorph_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Py_Exit(1);
}
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);
@@ -5521,6 +5839,7 @@ TrigTableRec_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
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);
@@ -5535,6 +5854,7 @@ TrigTableRec_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Py_Exit(1);
}
Py_XDECREF(self->table);
+ Py_INCREF(tabletmp);
self->table = (NewTable *)tabletmp;
PyObject_CallMethod(self->server, "addStream", "O", self->stream);
@@ -5996,6 +6316,7 @@ TablePut_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
Py_Exit(1);
}
Py_XDECREF(self->table);
+ Py_INCREF(tabletmp);
self->table = (DataTable *)tabletmp;
PyObject_CallMethod(self->server, "addStream", "O", self->stream);
diff --git a/src/objects/trigmodule.c b/src/objects/trigmodule.c
index cdbcf85..29176d2 100644
--- a/src/objects/trigmodule.c
+++ b/src/objects/trigmodule.c
@@ -1394,7 +1394,7 @@ TrigFunc_setArg(TrigFunc *self, PyObject *arg)
PyObject *tmp;
tmp = arg;
- Py_DECREF(self->arg);
+ Py_XDECREF(self->arg);
Py_INCREF(tmp);
self->arg = tmp;
diff --git a/src/objects/utilsmodule.c b/src/objects/utilsmodule.c
index a82cec9..fe0bf39 100644
--- a/src/objects/utilsmodule.c
+++ b/src/objects/utilsmodule.c
@@ -1203,11 +1203,11 @@ SampHold_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
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) {
@@ -1393,6 +1393,383 @@ SampHold_new, /* tp_new */
};
/************/
+/* TrackHold */
+/************/
+typedef struct {
+ pyo_audio_HEAD
+ PyObject *input;
+ Stream *input_stream;
+ 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
+TrackHold_filters_i(TrackHold *self) {
+ MYFLT ctrl;
+ int i;
+ MYFLT *in = Stream_getData((Stream *)self->input_stream);
+ MYFLT *ctrlsig = Stream_getData((Stream *)self->controlsig_stream);
+ MYFLT val = PyFloat_AS_DOUBLE(self->value);
+
+ 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);
+ self->ob_type->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;
+
+ if (arg == NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ 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*/
+(binaryfunc)TrackHold_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)TrackHold_inplace_add, /*inplace_add*/
+(binaryfunc)TrackHold_inplace_sub, /*inplace_subtract*/
+(binaryfunc)TrackHold_inplace_multiply, /*inplace_multiply*/
+(binaryfunc)TrackHold_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 TrackHoldType = {
+PyObject_HEAD_INIT(NULL)
+0, /*ob_size*/
+"_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_compare*/
+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 {
diff --git a/src/objects/wgverbmodule.c b/src/objects/wgverbmodule.c
index 79970ce..1fa6d06 100644
--- a/src/objects/wgverbmodule.c
+++ b/src/objects/wgverbmodule.c
@@ -26,18 +26,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
@@ -486,12 +488,6 @@ WGVerb_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
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;
@@ -770,7 +766,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 +785,1327 @@ 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] * (rand()/((MYFLT)(RAND_MAX)+1)) - 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] * (rand()/((MYFLT)(RAND_MAX)+1)) - 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] * (rand()/((MYFLT)(RAND_MAX)+1)) - 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] * (rand()/((MYFLT)(RAND_MAX)+1)) - 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);
+ self->ob_type->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_setInpos(STReverb *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->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;
+
+ if (arg == NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ 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;
+
+ if (arg == NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ 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;
+
+ if (arg == NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ 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;
+
+ if (arg == NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ int isNumber = PyNumber_Check(arg);
+
+ if (isNumber == 1) {
+ roomSize = PyFloat_AS_DOUBLE(PyNumber_Float(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;
+
+ if (arg == NULL) {
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ int isNumber = PyNumber_Check(arg);
+
+ if (isNumber == 1) {
+ tmp = PyFloat_AS_DOUBLE(PyNumber_Float(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."},
+{"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 = {
+PyObject_HEAD_INIT(NULL)
+0, /*ob_size*/
+"_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_compare*/
+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);
+ self->ob_type->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*/
+(binaryfunc)STRev_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)STRev_inplace_add, /*inplace_add*/
+(binaryfunc)STRev_inplace_sub, /*inplace_subtract*/
+(binaryfunc)STRev_inplace_multiply, /*inplace_multiply*/
+(binaryfunc)STRev_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 STRevType = {
+PyObject_HEAD_INIT(NULL)
+0, /*ob_size*/
+"_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_compare*/
+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 */
+};
diff --git a/utils/E-Pyo.py b/utils/E-Pyo.py
index e0b42f5..87656d1 100755
--- a/utils/E-Pyo.py
+++ b/utils/E-Pyo.py
@@ -40,6 +40,70 @@ 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.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', '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) != 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))
+
TEMP_PATH = os.path.join(os.path.expanduser('~'), '.epyo')
if not os.path.isdir(TEMP_PATH):
os.mkdir(TEMP_PATH)
@@ -201,7 +265,7 @@ 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"])
+ PREF_STYLE = os.path.join(ensureNFD(STYLES_PATH), PREFERENCES["pref_style"])
else:
PREF_STYLE = DEFAULT_STYLE
@@ -216,70 +280,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
@@ -685,7 +685,7 @@ 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']
@@ -702,7 +702,31 @@ STYLES_LABELS = {'default': 'Foreground', 'background': 'Background', 'selback':
with open(PREF_STYLE) as f:
text = f.read()
exec text in locals()
-STYLES = copy.deepcopy(style)
+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 not STYLES.has_key('face'):
STYLES['face'] = DEFAULT_FONT_FACE
if not STYLES.has_key('size'):
@@ -1189,7 +1213,7 @@ 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()
STYLES = copy.deepcopy(style)
@@ -1550,10 +1574,10 @@ 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:
@@ -2444,9 +2468,13 @@ class MainFrame(wx.Frame):
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()
@@ -2457,7 +2485,7 @@ class MainFrame(wx.Frame):
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()
self.panel.editor.insertSnippet(snippet["value"])
@@ -2474,7 +2502,7 @@ class MainFrame(wx.Frame):
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()
STYLES = copy.deepcopy(style)
@@ -2654,7 +2682,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):
@@ -4901,7 +4929,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
@@ -5381,7 +5409,7 @@ if __name__ == '__main__':
else:
pass
- app = wx.PySimpleApp()
+ app = wx.App(False)
X,Y = wx.SystemSettings.GetMetric(wx.SYS_SCREEN_X), wx.SystemSettings.GetMetric(wx.SYS_SCREEN_Y)
if X < 850: X -= 50
else: X = 850
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/PyoDoc.py b/utils/PyoDoc.py
index 03e145f..737c317 100644
--- a/utils/PyoDoc.py
+++ b/utils/PyoDoc.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# encoding: utf-8
from __future__ import with_statement
-import subprocess, threading, os
+import subprocess, threading, os, sys, unicodedata
import wx
import wx.stc as stc
from wx.lib.embeddedimage import PyEmbeddedImage
@@ -9,6 +9,10 @@ from pyo import *
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)
@@ -26,7 +30,7 @@ if wx.Platform == '__WXMSW__':
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
@@ -206,11 +210,10 @@ functions : Miscellaneous functions.
""" % PYO_VERSION
_DOC_KEYWORDS = ['Attributes', 'Examples', 'Methods', 'Notes', 'Methods details',
- 'Parentclass', 'Overview', 'Initline', 'Description']
+ 'Parentclass', 'Overview', 'Initline', 'Description', 'Parameters']
_HEADERS = ["Server", "PyoObjectBase", "Map", "Stream", "TableStream", "functions"]
-_KEYWORDS_LIST = ['Parameters']
+_KEYWORDS_LIST = ['SLMap']
_KEYWORDS_LIST.extend(_HEADERS)
-_KEYWORDS_LIST.append("SLMap")
_NUM_PAGES = 1
_NUM_PAGES += len(_HEADERS)
for k1 in _HEADERS:
@@ -786,7 +789,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:
@@ -1080,6 +1083,42 @@ class RunningThread(threading.Thread):
while self.proc.poll() == None and not self.terminated:
time.sleep(.25)
+def ensureNFD(unistr):
+ if PLATFORM in ['linux2', 'win32']:
+ 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) != 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
+
if __name__ == "__main__":
DOC_AS_SINGLE_APP = True
app = wx.PySimpleApp()
diff --git a/utils/info.plist b/utils/info.plist
index b43497a..cc6108e 100644
--- a/utils/info.plist
+++ b/utils/info.plist
@@ -32,17 +32,17 @@
<key>CFBundleIdentifier</key>
<string>org.pythonmac.unspecified.E-Pyo</string>
<key>CFBundleInfoDictionaryVersion</key>
- <string>0.6.8</string>
+ <string>0.6.9</string>
<key>CFBundleName</key>
<string>E-Pyo</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
- <string>0.6.8</string>
+ <string>0.6.9</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
- <string>0.6.8</string>
+ <string>0.6.9</string>
<key>LSHasLocalizedDisplayName</key>
<false/>
<key>NSAppleScriptEnabled</key>
--
python-pyo packaging
More information about the pkg-multimedia-commits
mailing list