Hi,
I'm been using PD on and off for about a year now, slowly improving. I wrote a sample player/looper, which works. However, I didn't build in any 'windowing' to avoid clicks when playback loops.
Basically, it works by: 1) loading a sample into an array, 2) doing some calculations based on the sample's length and my loop start/length values, playback speed, etc, and 3) plugging that data into a Phasor~ that reads the array.
So I thought, I just need to insert a Line~ after the Phasor~ to ramp up and down the output each time the sample plays, but I don't know how to tell PD exactly when to trigger those ramps. Can PD rapidly and efficiently 'monitor' Phasor~'s audio data output, that I could then use for the triggers?
Maybe somebody can tell me what the best way to go about this sampler is - I mean, is there a more efficient way to do it? And do you have a solution for my windowing issue that would fit into my patch as it stands?
Thank you
-
Best way to build a sampler
-
Hi,
What exactly do you mean by windowing (I don't know this term)?
As for using [line~] to create some ramp according to [phasor~]'s output, you can do this via signal logic (using objects such as [>~], [==~], [<~], etc.). Here is a patch that will send a single bang every time [phasor~]'s value is larger than 0.8 (if you need some help understanding it, I can explain it in a more detailed way):
In general, I prefer to use [line~] to directly control the playback of an array, since it is easier to control its starting and ending point as well as its speed, but what you want to do is absolutely possible with [phasor~] as well.
I hope this helps, good luck with your project!
Gilberto -
If you want to keep it vanilla (though not lgpl) you can do something like:
[phasor~] [.2( [.9( | | | [expr~ if($v1 > $f2, if($v1 < $f3, 1, 0), 0] | [lop~ 64] <-change this to change the attack and release on the window
The
[expr~]
object should output an audiorate 1 if the input is between .2 and .9 and an audiorate 0 otherwise. The nested ifs are used to simulate something like :if ($v1 > $f2 && $v1 < $f3) { return 1; } else { return 0; }
The
[lop~ 64]
object is for smoothing out the sudden jumps between 0 and 1.Another approach is to drive a windowing function or table lookup using the same
[phasor~]
used to drive sample playback.
One approach would be to do something like this:[phasor~] | [*~ .5] | [+~ .75] | [cos~] | [*~ 100] <-change this to change the attack and release of the window | [clip~ 0 1]
Here we are taking the
[phasor~]
signal and using it to drive the positive half of a cosine function. We then scale this function up to increase the slope of its attack and decay. Finally we use[clip~ 0 1]
to give it a maximum value of 1 instead of 100. Essentially this gives us a square like function with sinusoidal attacks and decays at the ends. -
You can also use the technique described in Kreidler's tutorial, here http://www.pd-tutorial.com/english/ch03s04.html#id426491 (scroll down till you find the loop generator, the second image).
-
It never occurred to me that I could use signal logic to test values of an audio signal. So simple! But I also like the idea of using the same loop playing Phasor~ to run another windowing function in sync with it.
Thanks very much, all three of you who replied.
So I suppose my only remaining question is:
With a variety of methods to achieve the same goal (eg. using Line~ vs Phasor~ to drive sample playback; or the two methods suggested for solving my problem above), is there a most CPU-efficient way to build such a sampler? -
It kind of depends on what you want your sampler to do. If I am playing back one-shot sounds I prefer to use
[line~]
but if I am dealing with loops a would rather use[phasor~]
. I find that it is more intuitive to do all sorts of wacky beat slicing and transformations using[phasor~]
but I don't really think there is a significant difference in CPU usage.