"""
Set of objects that call Python functions from triggers or number counts.
Useful for event sequencing.
"""
"""
Copyright 2009-2015 Olivier Belanger
This file is part of pyo, a python module to help digital signal
processing script creation.
pyo is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
pyo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with pyo. If not, see <http://www.gnu.org/licenses/>.
"""
from ._core import *
from ._maps import *
[docs]class Pattern(PyoObject):
"""
Periodically calls a Python function.
The play() method starts the pattern timer and is not called
at the object creation time.
:Parent: :py:class:`PyoObject`
:Args:
function: Python callable (function or method)
Python function to be called periodically.
time: float or PyoObject, optional
Time, in seconds, between each call. Default to 1.
arg: anything, optional
Argument sent to the function's call. If None, the function
will be called without argument. Defaults to None.
.. note::
The out() method is bypassed. Pattern doesn't return signal.
Pattern has no `mul` and `add` attributes.
If `arg` is None, the function must be defined without argument:
>>> def tocall():
>>> pass # function's body
If `arg` is not None, the function must be defined with one argument:
>>> def tocall(arg):
>>> print(arg)
>>> s = Server().boot()
>>> s.start()
>>> t = HarmTable([1,0,.33,0,.2,0,.143,0,.111])
>>> a = Osc(table=t, freq=[250,251], mul=.2).out()
>>> def pat():
... f = random.randrange(200, 401, 25)
... a.freq = [f, f+1]
>>> p = Pattern(pat, .125)
>>> p.play()
"""
def __init__(self, function, time=1, arg=None):
pyoArgsAssert(self, "cO", function, time)
PyoObject.__init__(self)
self._function = getWeakMethodRef(function)
self._time = time
self._arg = arg
function, time, arg, lmax = convertArgsToLists(function, time, arg)
self._base_objs = [
Pattern_base(WeakMethod(wrap(function, i)), wrap(time, i), wrap(arg, i)) for i in range(lmax)
]
[docs] def setFunction(self, x):
"""
Replace the `function` attribute.
:Args:
x: Python callable (function or method)
new `function` attribute.
"""
pyoArgsAssert(self, "c", x)
self._function = getWeakMethodRef(x)
x, lmax = convertArgsToLists(x)
[obj.setFunction(WeakMethod(wrap(x, i))) for i, obj in enumerate(self._base_objs)]
[docs] def setTime(self, x):
"""
Replace the `time` attribute.
:Args:
x: float or PyoObject
New `time` attribute.
"""
pyoArgsAssert(self, "O", x)
self._time = x
x, lmax = convertArgsToLists(x)
[obj.setTime(wrap(x, i)) for i, obj in enumerate(self._base_objs)]
[docs] def setArg(self, x):
"""
Replace the `arg` attribute.
:Args:
x: Anything
new `arg` attribute.
"""
self._arg = x
x, lmax = convertArgsToLists(x)
[obj.setArg(wrap(x, i)) for i, obj in enumerate(self._base_objs)]
[docs] def out(self, x=0, inc=1, dur=0, delay=0):
return self.play(dur, delay)
[docs] def setMul(self, x):
pass
[docs] def setAdd(self, x):
pass
[docs] def setSub(self, x):
pass
[docs] def setDiv(self, x):
pass
[docs] def ctrl(self, map_list=None, title=None, wxnoserver=False):
self._map_list = [SLMap(0.125, 4.0, "lin", "time", self._time)]
PyoObject.ctrl(self, map_list, title, wxnoserver)
@property
def function(self):
"""Python callable. Function to be called."""
return self._function
@function.setter
def function(self, x):
self.setFunction(x)
@property
def time(self):
"""float or PyoObject. Time, in seconds, between each call."""
return self._time
@time.setter
def time(self, x):
self.setTime(x)
@property
def arg(self):
"""Anything. Callable's argument."""
return self._arg
@arg.setter
def arg(self, x):
self.setArg(x)
[docs]class Score(PyoObject):
"""
Calls functions by incrementation of a preformatted name.
Score takes audio stream containning integers in input and calls
a function whose name is the concatenation of `fname` and the changing
integer.
Can be used to sequence events, first by creating functions p0, p1,
p2, etc. and then, by passing a counter to a Score object with "p"
as `fname` argument. Functions are called without parameters.
:Parent: :py:class:`PyoObject`
:Args:
input: PyoObject
Audio signal. Must contains integer numbers. Integer must change
before calling its function again.
fname: string, optional
Name of the functions to be called. Defaults to 'event_', meaning
that the object will call the function 'event_0', 'event_1', 'event_2',
and so on... Available at initialization time only.
.. note::
The out() method is bypassed. Score's signal can not be sent
to audio outs.
Score has no `mul` and `add` attributes.
.. seealso:: :py:class:`Pattern`, :py:class:`TrigFunc`
>>> s = Server().boot()
>>> s.start()
>>> a = SineLoop(freq=[200,300,400,500], feedback=0.05, mul=.1).out()
>>> def event_0():
... a.freq=[200,300,400,500]
>>> def event_1():
... a.freq=[300,400,450,600]
>>> def event_2():
... a.freq=[150,375,450,525]
>>> m = Metro(1).play()
>>> c = Counter(m, min=0, max=3)
>>> sc = Score(c)
"""
def __init__(self, input, fname="event_"):
pyoArgsAssert(self, "os", input, fname)
PyoObject.__init__(self)
self._input = input
self._fname = fname
self._in_fader = InputFader(input)
in_fader, fname, lmax = convertArgsToLists(self._in_fader, fname)
self._base_objs = [Score_base(wrap(in_fader, i), wrap(fname, i)) for i in range(lmax)]
self._init_play()
[docs] def out(self, chnl=0, inc=1, dur=0, delay=0):
return self.play(dur, delay)
[docs] def setMul(self, x):
pass
[docs] def setAdd(self, x):
pass
@property
def input(self):
"""PyoObject. Audio signal sending integer numbers."""
return self._input
@input.setter
def input(self, x):
self.setInput(x)
[docs]class CallAfter(PyoObject):
"""
Calls a Python function after a given time.
:Parent: :py:class:`PyoObject`
:Args:
function: Python callable (function or method)
Python callable execute after `time` seconds.
time: float, optional
Time, in seconds, before the call. Default to 1.
arg: any Python object, optional
Argument sent to the called function. Default to None.
.. note::
The out() method is bypassed. CallAfter doesn't return signal.
CallAfter has no `mul` and `add` attributes.
If `arg` is None, the function must be defined without argument:
>>> def tocall():
>>> pass # function's body
If `arg` is not None, the function must be defined with one argument:
>>> def tocall(arg):
>>> print(arg)
The object is not deleted after the call. The user must delete it himself.
>>> s = Server().boot()
>>> s.start()
>>> # Start an oscillator with a frequency of 250 Hz.
>>> syn = SineLoop(freq=[250,251], feedback=.07, mul=.2).out()
>>> def callback(arg):
... # Change the oscillator's frequency to 300 Hz after 2 seconds.
... # Convert the tuple back to a list.
... syn.freq = list(arg)
>>> # Use a tuple for the argument to avoid multi-channel expansion.
>>> a = CallAfter(callback, 2, (300,301))
"""
def __init__(self, function, time=1, arg=None):
pyoArgsAssert(self, "cn", function, time)
PyoObject.__init__(self)
self._function = getWeakMethodRef(function)
self._time = time
self._arg = arg
function, time, arg, lmax = convertArgsToLists(function, time, arg)
self._base_objs = [
CallAfter_base(WeakMethod(wrap(function, i)), wrap(time, i), wrap(arg, i)) for i in range(lmax)
]
self._init_play()
[docs] def out(self, x=0, inc=1, dur=0, delay=0):
return self.play(dur, delay)
[docs] def setMul(self, x):
pass
[docs] def setAdd(self, x):
pass
[docs] def setSub(self, x):
pass
[docs] def setDiv(self, x):
pass
[docs] def setTime(self, x):
"""
Replace the `time` attribute.
:Args:
x: float
New `time` attribute.
"""
pyoArgsAssert(self, "n", x)
self._time = x
x, lmax = convertArgsToLists(x)
[obj.setTime(wrap(x, i)) for i, obj in enumerate(self._base_objs)]
[docs] def setArg(self, x):
"""
Replace the `arg` attribute.
:Args:
x: Anything
new `arg` attribute.
"""
self._arg = x
x, lmax = convertArgsToLists(x)
[obj.setArg(wrap(x, i)) for i, obj in enumerate(self._base_objs)]
@property
def time(self):
"""float. Time, in seconds, before the function call."""
return self._time
@time.setter
def time(self, x):
self.setTime(x)
@property
def arg(self):
"""Anything. Callable's argument."""
return self._arg
@arg.setter
def arg(self, x):
self.setArg(x)