In most situations, you'll want a more automated way than moving the mouse to specify wavetable read locations; for instance, you might want to be able to play a sample at a steady transposition; you might have several samples playing back at once (or other things requiring attention), you might want to switch quickly between samples or go to prearranged locations. In the next few examples we'll develop an automated looping sample reader, which, although only one of many possible approaches, is a powerful and often-used one.
Patches B05.sampler.loop.pd and B06.sampler.loop.smooth.pd show how to do this; B05.sampler.loop.pd in the simplest possible way and B06.sampler.loop.smooth.pd (pictured in Figure 2.14 part (a)) incorporating a second waveshape to envelope the sound as described in section 2.3. One new object class is introduced here:
![]() |
: Takes the cosine of
times the
input signal (so that 0 to 1 makes a whole cycle.) Unlike the table
reading classes in Pd,
handles wraparound so that
there is no range limitation on its input.
In Figure 2.14 part (a), a
supplies both indices
into the wavetable (at right) and phases for a half-cosine-shaped
envelope function at left. These two are multiplied, and the
product is high-pass filtered and output. Reading the wavetable is
straightforward; the phasor is multiplied by a ``chunk size"
parameter, added to 1, and used as an index to
. The chunk size
parameter is multiplied by 441 to convert it from hundredths of a
second to samples. This corresponds exactly to the block diagram
shown in Figure 2.5, with a
segment location of 1. (The segment location can't be 0 because 1
is the minimum index for which
works.)
The left-hand signal path in 2.14 part (a) corresponds to the
enveloping wavetable lookup shown in Figure 2.7. Here the sawtooth wave is adjusted
to the range (-1/4, 1/4) (by multiplying by 0.5 and then
subtracting 0.25), and then sent to
. This reads the cosine
function in the range (
,
), thus giving only the positive half of the
waveform.
Part (b) of Figure 2.14
introduces a third parameter, the ``read point", which specifies
where in the sample the loop is to start. (In part (a) we always
started at the beginning.) The necessary change is simple enough:
simply add the ``read point" control value, in samples, to the
wavetable index and proceed as before. To avoid discontinuities in
the index we smooth the read point value using
and
objects, just as we did in
the first sampler example (Figure 2.14).
This introduces an important, though subtle, detail. The MOMENTARY TRANSPOSITION formula (section 2.2) predicts that, as long as the chunk size and read point aren't changing in time, the transposition is just the frequency times the chunk size (as always, using appropriate units; Hz. and seconds, for example, so that the product is dimensionless.) However, varying the chunk size and read point in time will affect the momentary transposition, often in very noticeable ways, as can be seen in patch B07.sampler.scratch.pd. Patch B08.sampler.nodoppler.pd (the one shown in the figure), shows one possible way of controlling this effect, while introducing a new object class:
: a sample and hold unit. (This will be familiar
to analog synthesizer users, but with a digital twist.) This stores
a single sample of the left-hand-side input and outputs it
repeatedly, until caused by the right-hand-side input (also a
digital audio signal, called the trigger) to overwrite the
stored sample with a new one--again from the left-hand-side input.
The unit acquires a new sample whenever the trigger's numerical
value falls from one sample to the next. This is designed to be
easy to pair with
objects, to facilitate
triggering on phase wraparounds.
Patch B08.sampler.nodoppler.pd uses two
objects to update the
values of the chunk size and read point, exactly when the
wraps around, at which
moments the cosine envelope is at zero so the effect of the
instantaneous changes can't be heard. In this situation we can
apply the simpler TRANSPOSITION FORMULA for looping wavetables to
relate frequency, chunk size, and transposition. This is shown in
patch B09.sampler.transpose.pd (not shown.)