2
Play soundfiles from the disk.
4
SfMarkerXXX objects use markers features (store in the header) from
5
an AIFF file to create more specific reading patterns.
9
Copyright 2010 Olivier Belanger
11
This file is part of pyo, a python module to help digital signal
12
processing script creation.
14
pyo is free software: you can redistribute it and/or modify
15
it under the terms of the GNU General Public License as published by
16
the Free Software Foundation, either version 3 of the License, or
17
(at your option) any later version.
19
pyo is distributed in the hope that it will be useful,
20
but WITHOUT ANY WARRANTY; without even the implied warranty of
21
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
GNU General Public License for more details.
24
You should have received a copy of the GNU General Public License
25
along with pyo. If not, see <http://www.gnu.org/licenses/>.
30
from types import ListType
32
class SfPlayer(PyoObject):
36
Reads audio data from a file using one of several available interpolation
37
types. User can alter its pitch with the `speed` attribute. The object
38
takes care of sampling rate conversion to match the Server sampling
41
Parentclass: PyoObject
46
Full path name of the sound to read.
47
speed : float or PyoObject, optional
48
Transpose the pitch of input sound by this factor. 1 is the
49
original pitch, lower values play sound slower, and higher
50
values play sound faster. Negative values results in playing
51
sound backward. Although the `speed` attribute accepts audio
52
rate signal, its value is updated only once per buffer size.
55
If set to True, sound will play in loop. Defaults to False.
56
offset : float, optional
57
Time in seconds of input sound to be skipped, assuming speed = 1.
59
interp : int, optional
60
Interpolation type. Defaults to 2.
68
setPath(path) : Replace the `path` attribute.
69
setSound(path) : Replace the `path` attribute.
70
setSpeed(x) : Replace the `speed` attribute.
71
setLoop(x) : Replace the `loop` attribute.
72
setOffset(x) : Replace the `offset` attribute.
73
setInterp(x) : Replace the `interp` attribute.
77
path : string, Full path of the sound.
78
sound : alias to the `path` attribute.
79
speed : float or PyoObject, Transposition factor.
80
loop : bool, Looping mode.
81
offset : float, Time, in seconds, of the first sample to read.
82
interp : int {1, 2, 3, 4}, Interpolation method.
86
SfPlayer will sends a trigger signal at the end of the playback if
87
loop is off or any time it wraps around if loop is on. User can
88
retrieve the trigger streams by calling obj['trig']:
90
>>> sf = SfPlayer(SNDS_PATH + "/transparent.aif").out()
91
>>> trig = TrigRand(sf['trig'])
95
>>> s = Server().boot()
97
>>> snd = SNDS_PATH + "/transparent.aif"
98
>>> sf = SfPlayer(snd, speed=[.75,.8], loop=True, mul=.3).out()
101
def __init__(self, path, speed=1, loop=False, offset=0, interp=2, mul=1, add=0):
102
PyoObject.__init__(self)
106
self._offset = offset
107
self._interp = interp
110
path, speed, loop, offset, interp, mul, add, lmax = convertArgsToLists(path, speed, loop, offset, interp, mul, add)
111
self._base_players = []
114
for i in range(lmax):
115
_snd_size, _dur, _snd_sr, _snd_chnls, _format, _type = sndinfo(path[0])
116
self._base_players.append(SfPlayer_base(wrap(path,i), wrap(speed,i), wrap(loop,i), wrap(offset,i), wrap(interp,i)))
117
for j in range(_snd_chnls):
118
self._base_objs.append(SfPlay_base(self._base_players[-1], j, wrap(mul,i), wrap(add,i)))
119
_trig_objs_tmp.append(TriggerDummy_base(self._base_players[-1]))
120
self._trig_objs = Dummy(_trig_objs_tmp)
123
return ['path', 'speed', 'loop', 'offset', 'interp', 'mul', 'add']
127
for obj in self._base_objs:
130
for obj in self._base_players:
134
def play(self, dur=0, delay=0):
135
dur, delay, lmax = convertArgsToLists(dur, delay)
136
self._trig_objs.play(dur, delay)
137
self._base_players = [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_players)]
138
self._base_objs = [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_objs)]
141
def out(self, chnl=0, inc=1, dur=0, delay=0):
142
dur, delay, lmax = convertArgsToLists(dur, delay)
143
self._trig_objs.play(dur, delay)
144
self._base_players = [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_players)]
145
if type(chnl) == ListType:
146
self._base_objs = [obj.out(wrap(chnl,i), wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_objs)]
149
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)))]
151
self._base_objs = [obj.out(chnl+i*inc, wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_objs)]
155
self._trig_objs.stop()
156
[obj.stop() for obj in self._base_players]
157
[obj.stop() for obj in self._base_objs]
160
def setPath(self, path):
162
Sets a new sound to read.
164
The number of channels of the new sound must match those
165
of the sound loaded at initialization time.
170
Full path of the new sound.
173
if type(self._path) == ListType:
174
curNchnls = sndinfo(self._path[0])[3]
176
curNchnls = sndinfo(self._path)[3]
177
if type(path) == ListType:
182
_snd_size, _dur, _snd_sr, _snd_chnls, _format, _type = sndinfo(p)
185
if _snd_chnls != curNchnls:
186
print "Soundfile must contains exactly %d channels." % curNchnls
190
path, lmax = convertArgsToLists(path)
191
[obj.setSound(wrap(path,i)) for i, obj in enumerate(self._base_players)]
193
def setSound(self, path):
195
Sets a new sound to read.
197
The number of channels of the new sound must match those
198
of the sound loaded at initialization time.
203
Full path of the new sound.
208
def setSpeed(self, x):
210
Replace the `speed` attribute.
214
x : float or PyoObject
215
new `speed` attribute.
219
x, lmax = convertArgsToLists(x)
220
[obj.setSpeed(wrap(x,i)) for i, obj in enumerate(self._base_players)]
222
def setLoop(self, x):
224
Replace the `loop` attribute.
228
x : bool {True, False}
229
new `loop` attribute.
233
x, lmax = convertArgsToLists(x)
234
for i, obj in enumerate(self._base_players):
235
if wrap(x,i): obj.setLoop(1)
238
def setOffset(self, x):
240
Replace the `offset` attribute.
245
new `offset` attribute.
249
x, lmax = convertArgsToLists(x)
250
[obj.setOffset(wrap(x,i)) for i, obj in enumerate(self._base_players)]
252
def setInterp(self, x):
254
Replace the `interp` attribute.
259
new `interp` attribute.
263
x, lmax = convertArgsToLists(x)
264
[obj.setInterp(wrap(x,i)) for i, obj in enumerate(self._base_players)]
266
def ctrl(self, map_list=None, title=None, wxnoserver=False):
267
self._map_list = [SLMap(-2., 2., 'lin', 'speed', self._speed), SLMapMul(self._mul)]
268
PyoObject.ctrl(self, map_list, title, wxnoserver)
272
"""string. Full path of the sound."""
275
def path(self, x): self.setPath(x)
279
"""string. Alias to the `path` attribute."""
282
def sound(self, x): self.setPath(x)
286
"""float or PyoObject. Transposition factor."""
289
def speed(self, x): self.setSpeed(x)
293
"""bool. Looping mode."""
296
def loop(self, x): self.setLoop(x)
300
"""float. Time, in seconds, of the first sample to read."""
303
def offset(self, x): self.setOffset(x)
307
"""int {1, 2, 3, 4}. Interpolation method."""
310
def interp(self, x): self.setInterp(x)
312
class SfMarkerShuffler(PyoObject):
314
AIFF with markers soundfile shuffler.
316
Reads audio data from a AIFF file using one of several available
317
interpolation types. User can alter its pitch with the `speed`
318
attribute. The object takes care of sampling rate conversion to
319
match the Server sampling rate setting.
321
The reading pointer randomly choose a marker (from the MARK chunk
322
in the header of the AIFF file) as its starting point and reads
323
the samples until it reaches the following marker. Then, it choose
324
another marker and reads from the new position and so on...
326
Parentclass: PyoObject
331
Full path name of the sound to read. Can't e changed after
333
speed : float or PyoObject, optional
334
Transpose the pitch of input sound by this factor. 1 is the
335
original pitch, lower values play sound slower, and higher
336
values play sound faster. Negative values results in playing
337
sound backward. Although the `speed` attribute accepts audio
338
rate signal, its value is updated only once per buffer size.
340
interp : int, optional
341
Choice of the interpolation method. Defaults to 2.
349
setSpeed(x) : Replace the `speed` attribute.
350
setInterp(x) : Replace the `interp` attribute.
351
getMarkers() : Returns a list of marker time values in samples.
355
speed : float or PyoObject, Transposition factor.
356
interp : int {1, 2, 3, 4}, Interpolation method.
360
>>> s = Server().boot()
362
>>> sf = SfMarkerShuffler(SNDS_PATH + "/transparent.aif", speed=[1,1], mul=.3).out()
365
def __init__(self, path, speed=1, interp=2, mul=1, add=0):
366
PyoObject.__init__(self)
368
self._interp = interp
371
path, speed, interp, mul, add, lmax = convertArgsToLists(path, speed, interp, mul, add)
372
self._base_players = []
374
self._snd_size, self._dur, self._snd_sr, self._snd_chnls, _format, _type = sndinfo(path[0])
375
for i in range(lmax):
377
sf = aifc.open(wrap(path,i))
378
markerstmp = sf.getmarkers()
380
self._markers = [m[1] for m in markerstmp]
383
self._base_players.append(SfMarkerShuffler_base(wrap(path,i), self._markers, wrap(speed,i), wrap(interp,i)))
384
for i in range(lmax * self._snd_chnls):
385
j = i / self._snd_chnls
386
self._base_objs.append(SfMarkerShuffle_base(wrap(self._base_players,j), i % self._snd_chnls, wrap(mul,j), wrap(add,j)))
389
return ['speed', 'interp', 'mul', 'add']
392
for obj in self._base_objs:
395
for obj in self._base_players:
399
def play(self, dur=0, delay=0):
400
dur, delay, lmax = convertArgsToLists(dur, delay)
401
self._base_players = [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_players)]
402
self._base_objs = [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_objs)]
405
def out(self, chnl=0, inc=1, dur=0, delay=0):
406
dur, delay, lmax = convertArgsToLists(dur, delay)
407
self._base_players = [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_players)]
408
if type(chnl) == ListType:
409
self._base_objs = [obj.out(wrap(chnl,i), wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_objs)]
412
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)))]
414
self._base_objs = [obj.out(chnl+i*inc, wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_objs)]
418
[obj.stop() for obj in self._base_players]
419
[obj.stop() for obj in self._base_objs]
422
def setSpeed(self, x):
424
Replace the `speed` attribute.
428
x : float or PyoObject
429
new `speed` attribute.
433
x, lmax = convertArgsToLists(x)
434
[obj.setSpeed(wrap(x,i)) for i, obj in enumerate(self._base_players)]
436
def setInterp(self, x):
438
Replace the `interp` attribute.
443
new `interp` attribute.
447
x, lmax = convertArgsToLists(x)
448
[obj.setInterp(wrap(x,i)) for i, obj in enumerate(self._base_players)]
450
def getMarkers(self):
452
Returns a list of marker time values in samples.
457
def ctrl(self, map_list=None, title=None, wxnoserver=False):
458
self._map_list = [SLMap(0.01, 2., 'lin', 'speed', self._speed), SLMapMul(self._mul)]
459
PyoObject.ctrl(self, map_list, title, wxnoserver)
463
"""float or PyoObject. Transposition factor."""
466
def speed(self, x): self.setSpeed(x)
470
"""int {1, 2, 3, 4}. Interpolation method."""
473
def interp(self, x): self.setInterp(x)
475
class SfMarkerLooper(PyoObject):
477
AIFF with markers soundfile looper.
479
Reads audio data from a AIFF file using one of several available
480
interpolation types. User can alter its pitch with the `speed`
481
attribute. The object takes care of sampling rate conversion to
482
match the Server sampling rate setting.
484
The reading pointer loops a specific marker (from the MARK chunk
485
in the header of the AIFF file) until it received a new integer
486
in the `mark` attribute.
488
Parentclass: PyoObject
493
Full path name of the sound to read.
494
speed : float or PyoObject, optional
495
Transpose the pitch of input sound by this factor. 1 is the
496
original pitch, lower values play sound slower, and higher
497
values play sound faster. Negative values results in playing
498
sound backward. Although the `speed` attribute accepts audio
499
rate signal, its value is updated only once per buffer size.
501
mark : float or PyoObject, optional
502
Integer denoting the marker to loop, in the range
503
0 -> len(getMarkers()). Defaults to 0.
504
interp : int, optional
505
Choice of the interpolation method. Defaults to 2.
513
setSpeed(x) : Replace the `speed` attribute.
514
setInterp(x) : Replace the `interp` attribute.
515
setMark(x) : Replace the `mark` attribute.
516
getMarkers() : Returns a list of marker time values in samples.
520
speed : float or PyoObject, Transposition factor.
521
mark : float or PyoObject, Marker to loop.
522
interp : int {1, 2, 3, 4}, Interpolation method.
526
>>> s = Server().boot()
528
>>> a = SfMarkerLooper(SNDS_PATH + '/transparent.aif', speed=[.999,1], mul=.3).out()
529
>>> rnd = RandInt(len(a.getMarkers()), 2)
533
def __init__(self, path, speed=1, mark=0, interp=2, mul=1, add=0):
534
PyoObject.__init__(self)
537
self._interp = interp
540
path, speed, mark, interp, mul, add, lmax = convertArgsToLists(path, speed, mark, interp, mul, add)
541
self._base_players = []
543
self._snd_size, self._dur, self._snd_sr, self._snd_chnls, _format, _type = sndinfo(path[0])
544
for i in range(lmax):
546
sf = aifc.open(wrap(path,i))
547
markerstmp = sf.getmarkers()
549
self._markers = [m[1] for m in markerstmp]
552
self._base_players.append(SfMarkerLooper_base(wrap(path,i), self._markers, wrap(speed,i), wrap(mark,i), wrap(interp,i)))
553
for i in range(lmax * self._snd_chnls):
554
j = i / self._snd_chnls
555
self._base_objs.append(SfMarkerLoop_base(wrap(self._base_players,j), i % self._snd_chnls, wrap(mul,j), wrap(add,j)))
558
return ['speed', 'mark', 'interp', 'mul', 'add']
561
for obj in self._base_objs:
564
for obj in self._base_players:
568
def play(self, dur=0, delay=0):
569
dur, delay, lmax = convertArgsToLists(dur, delay)
570
self._base_players = [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_players)]
571
self._base_objs = [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_objs)]
574
def out(self, chnl=0, inc=1, dur=0, delay=0):
575
dur, delay, lmax = convertArgsToLists(dur, delay)
576
self._base_players = [obj.play(wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_players)]
577
if type(chnl) == ListType:
578
self._base_objs = [obj.out(wrap(chnl,i), wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_objs)]
581
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)))]
583
self._base_objs = [obj.out(chnl+i*inc, wrap(dur,i), wrap(delay,i)) for i, obj in enumerate(self._base_objs)]
587
[obj.stop() for obj in self._base_players]
588
[obj.stop() for obj in self._base_objs]
591
def setSpeed(self, x):
593
Replace the `speed` attribute.
597
x : float or PyoObject
598
new `speed` attribute.
602
x, lmax = convertArgsToLists(x)
603
[obj.setSpeed(wrap(x,i)) for i, obj in enumerate(self._base_players)]
605
def setMark(self, x):
607
Replace the `mark` attribute.
611
x : float or PyoObject
612
new `mark` attribute.
616
x, lmax = convertArgsToLists(x)
617
[obj.setMark(wrap(x,i)) for i, obj in enumerate(self._base_players)]
619
def setInterp(self, x):
621
Replace the `interp` attribute.
626
new `interp` attribute.
630
x, lmax = convertArgsToLists(x)
631
[obj.setInterp(wrap(x,i)) for i, obj in enumerate(self._base_players)]
633
def getMarkers(self):
635
Returns a list of marker time values in samples.
640
def ctrl(self, map_list=None, title=None, wxnoserver=False):
641
self._map_list = [SLMap(0.01, 2., 'lin', 'speed', self._speed),
642
SLMap(0, len(self._markers)-1, 'lin', 'mark', self._mark, 'int'),
644
PyoObject.ctrl(self, map_list, title, wxnoserver)
648
"""float or PyoObject. Transposition factor."""
651
def speed(self, x): self.setSpeed(x)
655
"""float or PyoObject. Marker to loop."""
658
def mark(self, x): self.setMark(x)
662
"""int {1, 2, 3, 4}. Interpolation method."""
665
def interp(self, x): self.setInterp(x)