stretch
and
at
can be applied. These functions are the ones that typical users
are expected to use, and most of these functions are written in XLISP.
The "low-level" primitives directly operate on sounds, but know nothing of
environmental variables (such as *warp*
, etc.). The
names of most of these low-level functions start with "snd-
". In
general, programmers should avoid any function with the "snd-
"
prefix. Instead, use the "high-level" functions, which know about the
environment and react appropriately. The names of high-level functions
do not have prefixes like the low-level functions.
There are certain low-level operations that apply directly to sounds (as opposed to behaviors) and are relatively "safe" for ordinary use. These are marked as such.
Nyquist uses both linear frequency and equal-temperament pitch numbers to specify repetition rates. Frequency is always specified in either cycles per second (hz), or pitch numbers, also referred to as "steps," as in steps of the chromatic scale. Steps are floating point numbers such that 60 = Middle C, 61 = C#, 61.23 is C# plus 23 cents, etc. The mapping from pitch number to frequency is the standard exponential conversion, and fractional pitch numbers are allowed:
frequency = 440 * 2^((pitch - 69)/12)There are many predefined pitch names. By default these are tuned in equal temperament, with A4 = 440Hz, but these may be changed. (See Section "Predefined Constants").
Sounds
A sound is a primitive data type in Nyquist. Sounds can be created, passed
as parameters, garbage collected, printed, and set to variables just like
strings, atoms, numbers, and other data types.
What is a Sound?
Sounds have 5 components:
It may seem that there should be srate
- the sample rate of the sound.
samples
- the samples.
signal-start
- the time of the first sample.
signal-stop
- the time of one past the last sample.
logical-stop
- the time at which the sound logically ends, e.g. a
sound may end at the beginning of a decay. This value defaults
to signal-stop
,
but may be set to any value.
logical-start
to indicate the
logical or perceptual beginning of a sound as well as a logical-stop
to indicate the logical ending of a sound. In practice, only
logical-stop
is needed; this attribute tells when the next sound
should begin to form a sequence of sounds. In this respect, Nyquist sounds
are asymmetric: it is possible to compute sequences forward in time by
aligning the logical start of each sound with the logical-stop
of the
previous one, but one cannot compute "backwards", aligning the logical end
of each sound with the logical start of its successor. The root of this
asymmetry is the fact that when we invoke a behavior, we say when to start,
and the result of the behavior tells us its logical duration. There is no
way to invoke a behavior with a direct specification of when to
stop (Footnote 1) .
Note: there is no way to enforce the
intended "perceptual" interpretation of
logical-stop
. As far as Nyquist is concerned, these are just numbers to
guide the alignment of sounds within various control constructs.
Multichannel Sounds
Multichannel sounds are represented by Lisp arrays of sounds. To create an
array of sounds the XLISP vector
function is useful. Most low-level
Nyquist functions (the ones starting with snd-
) do not operate on
multichannel sounds. Most high-level functions do operate on multichannel
sounds.
Accessing and Creating Sound
Several functions display information concerning a sound and can be used to
query the components of a sound. There are functions that access samples in
a sound and functions that construct sounds from samples.
sref(sound, time)
snd-samples
below), or use
snd-srate
and snd-t0
(see below) to find the sample rate
and starting time, and compute a time (t) from the sample number (n):
t = (n / srate) + t0
Thus, the lisp code to access the n^(th) sample of a sound would look like:
(sref sound (global-to-local (+ (/ n (snd-srate sound)) (snd-t0 sound))))
Here is why sref
interprets its time argument as a local time:
> (sref (ramp 1) 0.5) ; evaluate a ramp at time 0.5
0.5
> (at 2.0 (sref (ramp 1) 0.5)) ; ramp is shifted to start at 2.0
; the time, 0.5, is shifted to 2.5
0.5
If you were to use snd-sref
, which treats time as global, instead of sref
, which treats time as local, then the first example above would return the same answer (0.5), but the second example would return 0. Why? Because the (ramp 1)
behavior would be shifted to start at time 2.0, but the resulting sound would be evaluated at global time 0.5. By definition, sounds have a value of zero before their start time.
sref-inverse(sound, value)
snd-from-array(t0, sr,
array)
FLONUM
s into a sound with starting
time t0 and sample rate sr. Safe for ordinary use. Be aware that
arrays of floating-point samples use 14 bytes per sample, and an additional
4 bytes per sample are allocated by this function to create a sound type.
snd-fromarraystream(t0, sr, object)
FLONUM
), and the sample rate is
sr. The object is an XLISP object (see Section "Objects" for
information on objects.) A sound is returned. When the sound needs samples,
they are generated by sending the message :next
to object. If
object returns NIL
, the sound terminates. Otherwise, object
must return an array of FLONUM
s. The values in these arrays are
concatenated to form the samples of the resulting sound.
There is no provision for object to specify the
logical stop time of the sound, so the logical stop time is the termination
time.
snd-fromobject(t0, sr, object)
FLONUM
), and the sample rate is
sr. The object is an XLISP object (see Section "Objects" for
information on objects. A sound is returned. When the sound needs samples,
they are generated by sending the message :next
to object. If
object returns NIL
, the sound terminates. Otherwise, object
must return a FLONUM
. There is no provision for object to specify the
logical stop time of the sound, so the logical stop time is the termination
time.
snd-extent(sound, maxsamples)
snd-fetch(sound)
FLONUM
after each call, or
NIL
when sound terminates. Note: snd-fetch
modifies
sound; it is strongly recommended to copy sound using
snd-copy
and access only the copy with snd-fetch
.
snd-fetch-array(sound, len,
step)
FLONUM
s or NIL
when the sound terminates. The
len parameter, a FIXNUM
, indicates how many samples should be returned
in the result array. After the array is returned, sound is modified by
skipping over step (a FIXNUM
) samples. If step equals len, then
every sample is returned once. If step is less than len, each
returned array will overlap the previous one, so some samples will be
returned more than once. If step is greater than len, then some
samples will be skipped and not returned in any array. The step
and len may change at each call, but in the current implementation, an
internal buffer is allocated for sound on the first call, so subsequent
calls may not specify a greater len than the first. Note:
snd-fetch-array
modifies
sound; it is strongly recommended to copy sound using
snd-copy
and access only the copy with snd-fetch-array
.
snd-flatten(sound, maxlen)
snd-length
. You would use this function to force samples to be computed in memory. Normally, this is not a good thing to do, but here is one appropriate use: In the case of sounds intended for wavetables, the unevaluated
sound may be larger than the evaluated (and typically short) one.
Calling snd-flatten
will compute the samples and allow the unit generators to be freed in the next garbage collection. Note: If a sound is computed from many instances of table-lookup oscillators, calling snd-flatten
will free the oscillators and their tables. Calling (stats)
will print how many total bytes have been allocated to tables.
snd-length(sound, maxlen)
snd-maxsamp(sound)
peak
, a replacement ("Signal Operations").
snd-play(expression)
s-save
(Section "Sound File Input and Output") for saving samples to a file, and
play
(Section "Sound File Input and Output") to play a sound. This function is
safe for ordinary use.
snd-print-tree(sound)
snd-samples(sound, limit)
snd-from-array
, it requires a total of slightly over 18 bytes per
sample.
snd-srate(sound)
snd-time(sound)
snd-t0
instead.
snd-t0(sound)
snd-print(expression, maxlen)
snd-save
, but samples appear in text on the screen instead of in
binary in a file. This function is intended for debugging.
Safe for ordinary use.
snd-set-logical-stop(sound,
time)
set-logical-stop
or set-logical-stop-abs
instead.
snd-sref(sound, time)
sref
instead.
snd-stop-time(sound)
soundp(sound)
stats()
mem
function. Safe for ordinary use. This is the only way to find out how much memory is being used by table-lookup oscillator instances.
Miscellaneous Functions
These are all safe and recommended for ordinary use.
db-to-linear(x)
follow(sound, floor, risetime, falltime, lookahead)
snd-avg
for a function that
can help to generate a low-sample-rate input for follow
.
See snd-chase
in Section "Filters" for a related filter.gate(sound, floor, risetime, falltime, lookahead, threshold)
FLONUM
in seconds). (The signal begins to drop when the signal crosses threshold, not after lookahead.) Decay continues until the value reaches floor (a FLONUM
), at which point the decay stops and the output value is held constant. Either during the decay or after the floor is reached, if the signal goes above threshold, then the ouptut value will rise to unity (1.0) at the point the signal crosses the threshold. Because of internal lookahead, the signal actually begins to rise before the signal crosses threshold. The rise is a constant-rate exponential and set so that a rise from floor to unity occurs in risetime. Similary, the fall is a constant-rate exponential such that a fall from unity to floor takes falltime.hz-to-step(freq)
SOUND
. The result has the same type as the argument. See also step-to-hz
(below).linear-to-db(x)
log(x)
FLONUM
). (See s-log
for a version that operates on signals.)set-control-srate(rate)
*default-control-srate*
and reinitializing the environment. Do not call this within any synthesis function (see the control-srate-abs
transformation, Section "Transformations").set-sound-srate(rate)
*default-sound-srate*
and reinitializing the environment. Do not call this within any synthesis function (see the sound-srate-abs
transformation, Section "Transformations").set-pitch-names()
c0
, cs0
, df0
, d0
, ... b0
, c1
, ... b7
). A440 (the default tuning) is represented by the step 69.0, so the variable a4
(fourth octave A) is set to 69.0. You can change the tuning by setting *A4-Hertz*
to a value (in Hertz) and calling set-pitch-names
to reinitialize the pitch variables. Note that this will result in non-integer step values. It does not alter the mapping from step values to frequency. There is no built-in provision for stretched scales or non-equal temperament, although users can write or compute any desired fractional step values.step-to-hz(pitch)
SOUND
type representing a time-varying step number. The result is a FLONUM
if pitch is a number, and a SOUND
if pitch is a SOUND
. See also hz-to-step
(above).get-duration(dur)
*rslt*
is set to the global time corresponding to local time zero.get-loud()
*loud*
environment variable. If *loud*
is a signal, it is evaluated at local time 0 and a number (FLONUM
) is returned.get-sustain()
*sustain*
environment variable. If *sustain*
is a signal, it is evaluated at local time 0 and a number (FLONUM
) is returned.get-transpose()
*transpose*
environment variable. If *transpose*
is a signal, it is evaluated at local time 0 and a number (FLONUM
) is returned.get-warp()
*warp*
environment variable. For efficiency, *warp*
is stored in three parts representing a shift, a scale factor, and a continuous warp function. Get-warp
is used to retrieve a signal that maps logical time to real time. This signal combines the information of all three components of *warp*
into a single signal. If the continuous warp function component is not present (indicating that the time warp is a simple combination of at
and stretch
transformations), an error is raised. This function is mainly for internal system use. In the future, get-warp
will probably be reimplemented to always return a signal and never raise an error.local-to-global(local-time)
osc-enable(flag)
\slider
with an integer index and a floating point value are accepted. These set internal slider values accessed by the snd-slider
function. Disabling terminates the service (polling for messages) and closes the socket. The previous state of enablement
is returned, e.g. if OSC is enabled and flag is nil, OSC is disabled and T
(true) is returned because OSC was enabled
at the time of the call. This function only exists if Nyquist is compiled with the compiler flag OSC
. Otherwise, the function
exists but always returns the symbol DISABLED
. Consider lowering the audio latency using snd-set-latency
.
Warning: there is the potential for
network-based attacks using OSC. It is tempting to add the ability to evaluate XLISP expressions sent via OSC, but this would create
unlimited and unprotected access to OSC clients. For now, it is unlikely that an attacker could do more than manipulate slider values.snd-set-latency(latency)
FLONUM
. The previous value is returned. The default is 0.3 seconds. To avoid glitches, the latency should be
greater than the time required for garbage collection and message printing and any other system activity external to Nyquist.
Behaviors
Using Previously Created Sounds
These behaviors take a sound and transform that sound according to the
environment. These are useful when writing code to make
a high-level function from a low-level function, or when cuing sounds
which were previously created:
cue(sound)
*loud*
, the starting time from *warp*
, *start*
,
and *stop*
to sound.cue-file(filename)
cue
, except
the sound comes from the named file, samples from which are coerced to the current default *sound-srate*
sample rate.sound(sound)
*loud*
, *warp*
,
*start*
, and *stop*
to sound.control(sound)
sound
, but by convention is used when sound is a control signal
rather than an audio signal.
Sound Synthesis
These functions provide musically interesting creation behaviors that
react to their environment; these are the "unit generators" of Nyquist:
const(value, [duration])
*control-srate*
. Every sample has the given value, and the default duration is 1.0. See also s-rest
, which is equivalent to calling const
with zero, and note that you can pass scalar constants (numbers) to sim
, sum
, and mult
where they are handled more efficiently than constant functions.env(t1, t2, t4, l1, l2, l3,
[dur])
0.0
. If dur is not supplied, then
1.0
is assumed. The envelope duration is the product of dur,
*stretch*
, and *sustain*
. If
t1 + t2 + 2ms + t4 is greater than the envelope
duration, then a two-phase envelope is
substituted that has an attack/release time ratio of t1/t4.
The sample rate of the returned sound is *control-srate*
. (See
pwl
for a more general piece-wise linear function generator.)
The effect of time warping is to warp the starting time and ending time.
The intermediate breakpoints are then computed as described above.exp-dec(hold, halfdec, length)
pwev
(see Section "Piece-wise Approximations"). The envelope starts at 1 and is constant for hold seconds. It then decays with a half life of halfdec seconds until length. (The total duration is length.) In other words, the amplitude falls by half each halfdec seconds. When stretched, this envelope scales linearly, which means the hold time increases and the half decay time increases.force-srate(srate, sound)
resample
.lfo(freq, [duration, table, phase])
osc
(below)
except this computes at the *control-srate*
and frequency
is specified in Hz. Phase is specified in degrees.
The *transpose*
and *sustain*
is not
applied. The effect of time warping is to warp the starting and ending
times. The signal itself will have a constant unwarped frequency.fmlfo(freq, [table, phase])
*control-srate*
using a sound to specify a time-varying
frequency in Hz. Phase is a FLONUM
in degrees. The duration of the result is determined by freq.maketable(sound)
osc
function (see
below). Currently, tables are limited to 1,000,000 samples. This limit is the compile-time constant max_table_len
set in sound.h
.build-harmonic(n, table-size)
control-warp(warp-fn, signal, [wrate])
*control-srate*
. See sound-warp
for an explanation of
wrate and high-quality warping.mult(beh1, beh2, ...)
scale
function is used to scale the sound by the number. When sounds are multiplied, the resulting sample rate is the maximum sample rate of the factors.prod(beh1, beh2, ...)
mult
.pan(sound, where)
(ramp)
or simply a number (e.g. 0.5
). In either case, where should range from 0 to 1, where 0 means pan completely left, and 1 means pan completely right. For intermediate values, the sound to each channel is scaled linearly. Presently, pan
does not check its arguments carefully.prod(beh1, beh2, ...)
mult
.resample(sound, srate)
force-srate
, except
high-quality interpolation is used to prefilter and reconstruct the signal
at the new sample rate. Also, the result is scaled by 0.95 to reduce problems with
clipping. (See also sound-warp
.)scale(scale, sound)
snd-scale
, except that it handles multichannel sounds. Sample rates, start times, etc. are taken from sound.scale-db(db, sound)
scale-srate(sound, scale)
snd-xform
(see Section "Signal Operations").shift-time(sound, shift)
snd-xform
(see Section "Signal Operations").
Figure 5: The shift-time
function shifts a sound in time
according to its shift argument.
sound-warp(warp-fn, signal, [wrate])
*sound-srate*
.
See also control-warp
.
sound-warp
, use scale-srate
to
stretch or shrink the sound, and then resample
to restore the
original sample rate.
Sound-warp
and control-warp
both take the inverse of
warp-fn to get a function from real time to score time. Each sample
of this inverse is thus a score time; signal is evaluated at each of
these score times to yield a value, which is the desired result. The
sample rate of the inverse warp function is somewhat arbitrary. With linear
interpolation, the inverse warp function sample rate is taken to be the
output sample rate. Note, however, that the samples of the inverse warp
function are stored as 32-bit floats, so they have limited precision. Since
these floats represent sample times, rounding can be a problem. Rounding
in this case is equivalent to adding jitter to the sample times. Nyquist
ignores this problem for ordinary warping, but for high-quality warping, the
jitter cannot be ignored.
Sound-warp
can then linearly
interpolate this signal using double-precision floats to minimize jitter
between samples. The sample rate is a compromise: a low sample rate
minimizes jitter, while a high sample rate does a better job of capturing
detail (e.g. rapid fluctuations) in the warp function. A good rule of thumb
is to use at most 1,000 to 10,000 samples for the inverse warp function. For
example, if the result will be 1 minute of sound, use a sample rate of
3000 samples / 60 seconds = 50 samples/second. Because Nyquist has no
advance information about the warp function, the inverse warp function
sample rate must be provided as a parameter. When in doubt, just try
something and let your ears be the judge.integrate(signal)
slope(signal)
osc(pitch, [duration, table, phase])
1.0
(second), table *table*
,
phase 0.0
. The default value of *table*
is a sinusoid. Duration is stretched by *warp*
and
*sustain*
, amplitude is nominally 1, but scaled by *loudness*
, the start time is logical time 0, transformed by *warp*
, and the sample rate is *sound-srate*
.
The effect of time-warping is to warp the starting and ending times only; the
signal has a constant unwarped frequency.
Note 1: table is a list of the form
(sound pitch-number periodic)where the first element is a sound, the second is the pitch of the sound (this is not redundant, because the sound may represent any number of periods), and the third element is
T
if the sound is one period of
a periodic signal, or nil
if the sound is a sample that should not
be looped. The maximum table size is set by max_table_len
in sound.h
, and is currently set to 1,000,000.
Note 2: in the current implementation, it is assumed that the
output should be periodic. See snd-down
and snd-up
for resampling one-shot sounds to a desired sample rate. A future version of osc
will handle both cases.
Note 3: When osc
is called, memory is allocated for the table, and samples are copied from the sound (the first element of the list which is the table parameter) to the memory. Every instance of osc
has a private copy of the table, so the total storage can become large in some cases, for example in granular synthesis with many instances of osc
. In some cases, it may make sense to use snd-flatten
(see Section "Accessing and Creating Sound") to cause the sound to be fully realized, after which the osc
and its table memory can be reclaimed by garbage collection. The partial
function (see below) does not need a private table and does not use much space.partial(pitch, env)
*sound-srate*
. The partial
function is faster than osc
.sine(pitch, [duration])
*sound-srate*
.
This function is like osc
with
respect to transformations. The sine
function is faster than
osc
.hzosc(hz, [table, phase])
*table*
and the default phase is 0.0. The default duration is 1.0
, but this is stretched as in osc
(see above). The hz parameter may be a SOUND
, in which case the duration of the result is the duration of hz. The sample rate is *sound-srate*
.osc-saw(hz)
*sound-srate*
. The hz parameter may be a sound as in hzosc (see above).osc-tri(hz)
*sound-srate*
. The hz parameter may be a sound as in hzosc (see above).osc-pulse(hz, bias, [compare-shape])
-1
and +1
, giving a pulse width from 0% (always at -1
) to 100% (always at +1
). When bias is zero, a square wave is generated. Bias may be a SOUND
to create varying pulse width. If bias changes rapidly, strange effects may occur. The optional compare-shape defaults to a hard step at zero, but other shapes may be used to achieve non-square pulses. The osc-pulse
behavior is written in terms of other behaviors and defined in the file nyquist.lsp
using just a few lines of code. Read the code for the complete story.amosc(pitch, modulation, [table,
phase])
*table*
, and phase is the starting phase (default 0.0 degrees)
within osc-table. The sample rate is *sound-srate*
. fmosc(pitch, modulation, [table,
phase])
*table*
, and phase is the starting phase (default 0.0 degrees)
within osc-table. The modulation
is expressed in hz, e.g. a sinusoid modulation signal with an
amplitude of 1.0 (2.0 peak to peak), will cause a +/- 1.0 hz
frequency deviation in sound. Negative frequencies are correctly
handled. The sample rate is *sound-srate*
. fmfb(pitch, index, [dur])
SOUND
or a FLONUM
. If index is
a FLONUM
, dur must be provided (a FLONUM
) to specify
the duration. Otherwise, dur is ignored if present and the duration is
determined by that of index. The sample rate is *sound-srate*
.
A sinusoid table is used.
If index is below 1.1, this generates a sawtooth-like waveform.buzz(n, pitch, modulation)
*sound-srate*
.pluck(
pitch, [duration,] [final-amplitude])
*sound-srate*
.siosc(pitch,
modulation, tables)
fmosc
. The tables specify a list of
waveforms as follows: (table0 time1 table2 ... timeN
tableN), where each table is a sound representing one period. Each
time is a time interval measured from the starting time. The time is
scaled by the nominal duration (computed using (local-to-global
(get-sustain))
) to get the actual time. Note that this implies linear
stretching rather than continuous timewarping of the interpolation or the
breakpoints. The waveform is table0 at the starting time, table1
after time1 (scaled as described), and so on. The duration and logical
stop time is given by modulation. If modulation is shorter than
timeN, then the full sequence of waveforms is not used. If
modulation is longer than timeN, tableN is used after timeN
without further interpolation.sampler(pitch, modulation, [sample,
npoints])
fmosc
described above. The optional sample (which defaults to the global
variable *table*
is a list of the form
(sound pitch-number loop-start)where the first element is a sound containing the sample, the second is the pitch of the sample, and the third element is the time of the loop point. If the loop point is not in the bounds of the sound, it is set to zero. The optional npoints specifies how many points should be used for sample interpolation. Currently this parameter defaults to 2 and only 2-point (linear) interpolation is implemented. It is an error to modulate such that the frequency is negative. Note also that the loop point may be fractional. The sample rate is
*sound-srate*
.
Piece-wise Exponential Functions:
Cummulative Time:
Default initial point at (0, 1), final value at 1:
pwe
pwe-list
Explicit initial value:
pwev
pwev-list
Relative Time:
Default initial point at (0, 1), final value at 1:
pwer
pwer-list
Explicit initial value:
pwevr
pwevr-list
Piece-wise Approximations
There are a number of related behaviors for piece-wise approximations to functions. The simplest of these, pwl
was mentioned earlier in the manual. It takes a list of breakpoints, assuming an initial point at (0, 0), and a final value of 0. An analogous piece-wise exponential function, pwe
, is provided. Its implicit starting and stopping values are 1 rather than 0. Each of these has variants. You can specify the initial and final values (instead of taking the default). You can specify time in intervals rather than cummulative time. Finally, you can pass a list rather than an argument list. This leads to 16 versions:
Piece-wise Linear Functions:
Cummulative Time:
Default initial point at (0, 0), final value at 0:
pwl
pwl-list
Explicit initial value:
pwlv
pwlv-list
Relative Time:
Default initial point at (0, 0), final value at 0:
pwlr
pwlr-list
Explicit initial value:
pwlvr
pwlvr-list
All of these functions are implemented in terms of pwl
(see nyquist.lsp
for the implementations. There are infinite opportunities for errors in these functions: if you leave off a data point, try to specify points in reverse order, try to create an exponential that goes to zero or negative values, or many other bad things, the behavior is not well-defined. Nyquist should not crash, but Nyquist does not necessarily attempt to report errors at this time.
pwl(t1, l1, t2, l2, ... tn)
*sustain*
(if
*sustain*
is a SOUND
, it is evaluated once at the starting
time of the envelope). Each breakpoint time is then mapped according to
*warp*
. The result is a linear interpolation (unwarped) between
the breakpoints. The sample rate is *control-srate*
. Breakpoint
times are quantized to the nearest sample time. If you specify one or more
breakpoints withing one sample period, pwl
attempts to give a good
approximation to the specified function. In particular, if two breakpoints
are simultaneous, pwl
will move one of them to an adjacent sample,
producing a steepest possible step in the signal. The exact details of this
"breakpoint munging" is subject to change in future versions. Please report
any cases where breakpoint lists give unexpected behaviors. The author will
try to apply the "principle of least surprise" to the design. Note that
the times are relative to 0; they are not durations of each envelope
segment.
pwl-list(breakpoints)
apply
to apply the pwl
function to
the breakpoints, but if the list is very long (hundreds or thousands of
points), you might get a stack overflow because XLISP has a fixed-size
argument stack. Instead, call pwl-list
, passing one argument, the
list of breakpoints.
pwlv(l1, t2, l2, t3, t3, ... tn, ln)
pwl
.
pwlv-list(breakpoints)
pwlv
that takes a single list of breakpoints as its argument. See pwl-list
above for the rationale.
pwlr(i1, l1, i2, l2, ... in)
pwl
.
pwlr-list(breakpoints)
pwlr
that takes a single list of breakpoints as its argument. See pwl-list
above for the rationale.
pwlvr(l1, i2, l2, i3, i3, ... in, ln)
pwlv
.
pwlvr-list(breakpoints)
pwlvr
that takes a single list of breakpoints as its argument. See pwl-list
above for the rationale.
pwe(t1, l1, t2, l2, ...
tn)
pwl
, then exponentiates each resulting sample. A faster implementation is certainly possible!) Breakpoint values (lj) must be greater than zero. Otherwise, this function is similar to pwl
, including stretch by *sustain*
, mapping according to *warp*
, sample rate based on *control-srate*
, and "breakpoint munging" (see pwl
described above). Default initial and final values are of dubious value with exponentials. See pwev
below for the function you are probably looking for.
pwe-list(breakpoints)
pwe
that takes a single list of breakpoints as its argument. See pwl-list
above for the rationale.
pwev(l1, t2, l2, t3, t3, ... tn, ln)
pwe
.
pwev-list(breakpoints)
pwev
that takes a single list of breakpoints as its argument. See pwl-list
above for the rationale.
pwer(i1, l1, i2, l2, ... in)
pwe
. Consider using pwerv
instead of this one.
pwer-list(breakpoints)
pwer
that takes a single list of breakpoints as its argument. See pwl-list
above for the rationale.
pwevr(l1, i2, l2, i3, i3, ... in, ln)
pwev
. Note that this is similar to the csound GEN05 generator. Which is uglier, GEN05 or pwevr?
pwevr-list(breakpoints)
pwevr
that takes a single list of breakpoints as its argument. See pwl-list
above for the rationale.
Filter Behaviors
alpass(sound, decay, hz, [minhz])
SOUND
, the delay may be time-varying. Linear interpolation is then used for fractional sample delay, but it should be noted that linear interpolation implies a low-pass transfer function. Thus, this filter may behave differently with a constant SOUND
than it does with a FLONUM
value for hz. In addition, if hz is of type SOUND
, then minhz is required. The hz parameter will be clipped to be greater than minhz, placing an upper bound on the delay buffer length.comb(sound, decay, hz)
feedback-delay
(see below). The hz parameter must be a number greater than zero. It is used to compute delay, which is then rounded to the nearest integer number of samples (so the frequency is not always exact. Higher sampling rates yield better delay resolution.) The decay may be a sound or a number. In either case, it must also be positive. (Implementation note: an exponentiation is needed to convert decay into the feedback parameter for feedback-delay
, and exponentiation is typically more time-consuming than the filter operation itself. To get high performance, provide decay at a low sample rate.) The resulting sound will have the start time, sample rate, etc. of sound.congen(gate, risetime, falltime)
FLONUM
) seconds. During the decay, the half-time is falltime seconds. The sample rate, start time, logical stop, and terminate time all come from gate. If you want a nice decay, be sure that the gate goes to zero and stays there for awhile before gate terminates, because congen
(and all Nyquist sounds) go immediately to zero at termination time. For example, you can use pwl
to build a pulse followed by some zero time:
(pwl 0 1 duty 1 duty 0 1)Assuming duty is less than 1.0, this will be a pulse of duration duty followed by zero for a total duration of 1.0.
(congen (pwl 0 1 duty 1 duty 0 1) 0.01 0.05)will have a duration of 1.0 because that is the termination time of the
pwl
input. The decaying release of the resulting envelope will be truncated to zero at time 1.0. (Since the decay is theoretically infinite, there is no way to avoid truncation, although you could multiply by another envelope that smoothly truncates to zero in the last millisecond or two to get both an exponential decay and a smooth final transition to zero.)convolve(sound,
response)
feedback-delay(sound, delay, feedback)
lp(sound, cutoff)
tone(sound, cutoff)
lp
instead, or define it by adding (setfn tone lp)
to your program.hp(sound, cutoff)
lp
.atone(sound, cutoff)
hp
instead, or define it by adding (setfn atone hp)
to your program.reson(sound, center, bandwidth, n)
reson
is to simulate resonances in the human vocal tract.
See demos/voice_synthesis.htm
for sample code and documentation.areson(sound, center, bandwidth, n)
areson
filter is an exact
complement of reson
such that if both are applied to the
same signal with the same parameters, the sum of the results yeilds
the original signal.shape(signal, table, origin)
FLONUM
and gives the time which should be considered the origin of table. (This is important because table cannot have values at negative times, but signal will often have negative values. The origin gives an offset so that you can produce suitable tables.) The output at time t is:
table(origin + clip(signal(t))where clip(x) = max(1, min(-1, x)). (E.g. if table is a signal defined over the interval [0, 2], then origin should be 1.0. The value of table at time 1.0 will be output when the input signal is zero.) The output has the same start time, sample rate, etc. as signal. The
shape
function will also accept multichannel signals and tables.demos/distortion.htm
.
The shape
function is also used to map frequency to amplitude to achieve a spectral envelope for
Shepard tones in demos/shepard.lsp
.biquad(signal, b0, b1, b2, a0, a1, a2)
FLONUM
s. See also lowpass2
, highpass2
, bandpass2
, notch2
, allpass2
, eq-lowshelf
, eq-highshelf
, eq-band
, lowpass4
, lowpass6
, highpass4
, and highpass8
in this section for convenient variations based on the same filter. The equations for the filter are: zn = sn + a1 * zn-1 + a2 * zn-2, and yn = zn * b0 + zn-1 * b1 + zn-2 * b2.biquad-m(signal, b0, b1, b2, a0, a1, a2)
FLONUM
s.lowpass2(signal, hz, [q])
snd-biquad
. The cutoff frequency is given by hz (a FLONUM
) and an optional Q factor is given by q (a FLONUM
).highpass2(signal, hz, [q])
snd-biquad
. The cutoff frequency is given by hz (a FLONUM
) and an optional Q factor is given by q (a FLONUM
).bandpass2(signal, hz, [q])
snd-biquad
. The center frequency is given by hz (a FLONUM
) and an optional Q factor is given by q (a FLONUM
).notch2(signal, hz, [q])
snd-biquad
. The center frequency is given by hz (a FLONUM
) and an optional Q factor is given by q (a FLONUM
).allpass2(signal, hz, [q])
snd-biquad
. The frequency is given by hz (a FLONUM
) and an optional Q factor is given by q (a FLONUM
).eq-lowshelf(signal, hz, gain, [slope])
snd-biquad
. The hz parameter (a FLONUM
)is the halfway point in the transition, and gain (a FLONUM
) is the bass boost (or cut) in dB. The optional slope (a FLONUM
) is 1.0 by default, and response becomes peaky at values greater than 1.0.eq-highshelf(signal, hz, gain, [slope])
snd-biquad
. The hz parameter (a FLONUM
)is the halfway point in the transition, and gain (a FLONUM
) is the treble boost (or cut) in dB. The optional slope (a FLONUM
) is 1.0 by default, and response becomes peaky at values greater than 1.0.eq-band(signal, hz, gain, width)
snd-biquad
, snd-eqbandcv
and snd-eqbandvvv
. The hz parameter (a FLONUM
) is the center frequency, gain (a FLONUM
) is the boost (or cut) in dB, and width (a FLONUM
) is the half-gain width in octaves. Alternatively, hz, gain, and width may be SOUND
s, but they must all have the same sample rate, e.g. they should all run at the control rate or at the sample rate.lowpass4(signal, hz)
FLONUM
).lowpass6(signal, hz)
FLONUM
).lowpass8(signal, hz)
FLONUM
).highpass4(signal, hz)
FLONUM
).highpass6(signal, hz)
FLONUM
).highpass8(signal, hz)
FLONUM
).tapv(sound, offset,
vardelay, maxdelay)
snd-tapv
. See it for details ("Signal Operations").nrev(sound, decay, mix)
jcrev(sound, decay, mix)
prcrev(sound, decay, mix)
These reverbs (nrev
, jcrev
, and prcrev
) are implemented
in STK (running within Nyquist). nrev
derives from Common Music's
NRev, which consists of 6 comb filters followed by 3 allpass filters, a
lowpass filter, and another allpass in series followed by two allpass
filters in parallel. jcrev
is the John Chowning
reverberator which is based on the use of networks of simple allpass
and comb delay filters. This reverb implements three series allpass units,
followed by four parallel comb filters, and two decorrelation delay
lines in parallel at the output. prcrev
is a Perry Cook's
reverberator which is based on the Chowning/Moorer/Schroeder
reverberators using networks of simple allpass and comb delay filters.
This one implements two series allpass units and two parallel comb filters.
The sound input may be single or multi-channel. The decay time is
in seconds, and mix sets the mixture of input sound reverb sound,
where 0.0 means input only (dry) and 1.0 means reverb only (wet).stkchorus(sound, depth, freq, mix, [delay])
FLONUM
parameters depth and freq set
the modulation
depth from 0 to 1
and modulation frequency (in Hz), and mix sets the mixture
of input sound and chorused sound, where 0.0 means input sound only (dry)
and 1.0 means chorused sound only (wet). The parameter delay is a
FIXNUM
representing the median desired delay length in samples. pitshift(sound, shift, mix)
SOUND
is pitch-shifted by shift,
a FLONUM
ratio. A value of 1.0 means no shift. The parameter mix
sets the mixture of input and shifted sounds. A value of 0.0
means input only (dry)
and a value of 1.0 means shifted sound only (wet).
clarinet(step, breath-env)
FLONUM
that controls the tube length, and the breath-env (a SOUND
)
controls the air pressure
and also determines the length of the resulting sound. The breath-env signal
should range from zero to one.clarinet-freq(step, breath-env, freq-env)
clarinet
that includes a variable frequency control, freq-env, which specifies
frequency deviation in Hz. The duration of the resulting sound is the minimum
duration of breath-env and freq-env. These parameters may be of type
FLONUM
or SOUND
. FLONUM
s are coerced into SOUND
s
with a nominal duration arbitrarily set to 30.clarinet-all(step, breath-env, freq-env, vibrato-freq, vibrato-gain,
reed-stiffness, noise)
clarinet-freq
that includes controls vibrato-freq (a FLONUM
for vibrato frequency in Hertz),
vibrato-gain (a FLONUM
for the amount of amplitude vibrato),
reed-stiffness (a FLONUM
or SOUND
controlling reed stiffness in the clarinet
model), and noise (a FLONUM
or SOUND
controlling noise amplitude in the input
air pressure). The vibrato-gain is a number from zero to one, where zero
indicates no vibrato, and one indicates a plus/minus 50% change in breath
envelope values. Similarly, the noise parameter ranges from zero to one where
zero means no noise and one means white noise with a peak amplitude of
plus/minus 40% of the breath-env. The reed-stiffness parameter varies
from zero to one.
The duration of the resulting sound is the minimum duration of
breath-env, freq-env, reed-stiffness, and noise. As with
clarinet-freq
, these parameters may be either FLONUM
s or
SOUND
s, and FLONUM
s are coerced to sounds with a nominal
duration of 30.sax(step, breath-env)
FLONUM
that controls the tube length, and the breath-env controls the air pressure
and also determines the length of the resulting sound. The breath-env signal
should range from zero to one.sax-freq(step, breath-env, freq-env)
sax
that includes a variable frequency control, freq-env, which specifies
frequency deviation in Hz. The duration of the resulting sound is the minimum
duration of breath-env and freq-env. These parameters may be of type
FLONUM
or SOUND
. FLONUM
s are coerced into SOUND
s
with a nominal duration arbitrarily set to 30.sax-all(step, breath-env, freq-env, vibrato-freq, vibrato-gain,
reed-stiffness, noise, blow-pos, reed-table-offset)
sax-freq
that includes controls vibrato-freq (a FLONUM
for vibrato frequency in Hertz),
vibrato-gain (a FLONUM
for the amount of amplitude vibrato),
reed-stiffness (a SOUND
controlling reed stiffness in the sax
model), noise (a SOUND
controlling noise amplitude in the input
air pressure), blow-pos (a SOUND
controlling the point of excitation
of the air column), and reed-table-offset (a SOUND
controlling a
parameter of the reed model). The vibrato-gain is a number from zero to one, where zero
indicates no vibrato, and one indicates a plus/minus 50% change in breath
envelope values. Similarly, the noise parameter ranges from zero to one where
zero means no noise and one means white noise with a peak amplitude of
plus/minus 40% of the breath-env. The reed-stiffness, blow-pos, and
reed-table-offset parameters all vary from zero to one.
The duration of the resulting sound is the minimum duration of
breath-env, freq-env, reed-stiffness, noise, breath-env,
blow-pos, and reed-table-offset. As with
sax-freq
, these parameters may be either FLONUM
s or
SOUND
s, and FLONUM
s are coerced to sounds with a nominal
duration of 30.flute(step, breath-env)
FLONUM
that controls the tube
length, and the breath-env
controls the air pressure and also determines the starting time and
length of the resulting sound. The breath-env signal should
range from zero to one.flute-freq(step, breath-env, freq-env)
flute
that includes a variable frequency control, freq-env, which
specifies frequency deviation in Hz. The duration of the
resulting sound is the minimum duration of breath-env and
freq-env. These parameters may be of type FLONUM
or
SOUND
. FLONUM
s are coerced into SOUNDs with a
nominal duration arbitrary set to 30.flute-all(step, breath-env, freq-env, vibrato-freq,
vibrato-gain, jet-delay, noise)
clarinet-freq
that includes controls vibrato-freq (a
FLONUM
for vibrato frequency in Hz), vibrato-gain (a
FLONUM
for the amount of amplitude vibrato), jet-delay
(a FLONUM
or SOUND
controlling jet delay in the
flute model), and
noise (a FLONUM
or SOUND
controlling noise amplitude
in the input air pressure). The vibrato-gain is a number from zero
to one where zero means no vibrato, and one indicates a plus/minus
50% change in breath envelope values. Similarly, the noise parameter
ranges from zero to one, where zero means no noise and one means white
noise with a peak amplitude of
plus/minus 40% of the breath-env. The jet-delay is a ratio
that controls a delay length from the flute model, and therefore it
changes the pitch of the resulting sound. A value of 0.5 will maintain
the pitch indicated by the step parameter. The duration of the
resulting sound is the minimum duration of breath-env, freq-env,
jet-delay, and noise. These parameters may be either
FLONUM
s or SOUND
s, and FLONUM
s are coerced
to sounds with a nominal duration of 30.
bowed(step, bowpress-env)
FLONUM
that controls the string length,
and the bowpress-env controls the bow pressure and also
determines the duration of the resulting sound. The bowpress-env
signal should range from zero to one.bowed-freq(step, bowpress-env, freq-env)
bowed
that includes a variable frequency control, freq-env, which
specifies frequency deviation in Hz. The duration of the resulting
sound is the minimum duration of bowpress-env and freq-env.
These parameters may be of type FLONUM
or SOUND
.
FLONUM
s are coerced into SOUND
s
with a nominal duration arbitrarily set to 30s.mandolin(step, dur, &optional detune)
FLONUM
wich specifies the desired pitch, dur
means the duration of the resulting sound and detune is a
FLONUM
that controls the relative detune of the two strings.
A value of 1.0 means unison. The default value is 4.0.
Note: body-size (see snd-mandolin
does not seem to
work correctly, so a default value is always used
by mandolin
.wg-uniform-bar(step, bowpress-env)
wg-tuned-bar(step, bowpress-env)
wg-glass-harm(step, bowpress-env)
wg-tibetan-bowl(step, bowpress-env)
FLONUM
that controls the resultant pitch, and bowpress-env is a SOUND
ranging
from zero to one that controls a parameter of the model. In addition,
bowpress-env determines the duration of the resulting sound.
(Note: The bowpress-env does not seems influence the timbral
quality of the resulting sound).modalbar(preset, step, dur)
'MARIMBA
, 'VIBRAPHONE
, 'AGOGO
, 'WOOD1
,
'RESO
, 'WOOD2
, 'BEATS
, 'TWO-FIXED
, or
'CLUMP
. The parameter step is a FLONUM
that
sets the pitch, and dur is the duration.sitar(step, dur)
FLONUM
that sets the pitch,
and dur is the duration.
clip(sound, peak)
clip
will return sound limited by peak. If sound is a multichannel sound, clip
returns a multichannel sound where each channel is clipped. The result has the type, sample rate, starting time, etc. of sound.s-abs(sound)
SOUND
, compute the absolute value of each sample. If sound is a number, just compute the absolute value. If sound is a multichannel sound, return a multichannel sound with s-abs
applied to each element. The result has the type, sample rate, starting time, etc. of sound.s-sqrt(sound)
SOUND
, compute the square root of each sample. If sound is a number, just compute the square root. If sound is a multichannel sound, return a multichannel sound with s-sqrt
applied to each element. The result has the type, sample rate, starting time, etc. of sound. In taking square roots, if an input sample is less than zero, the corresponding output sample is zero. This is done because the square root of a negative number is undefined.s-exp(sound)
SOUND
, compute e^(x) for each sample x. If sound is a number x, just compute e^(x). If sound is a multichannel sound, return a multichannel sound with s-exp
applied to each element. The result has the type, sample rate, starting time, etc. of sound.s-log(sound)
SOUND
, compute ln(x) for each sample x. If sound is a number x, just compute ln(x). If sound is a multichannel sound, return a multichannel sound with s-log
applied to each element. The result has the type, sample rate, starting time, etc. of sound. Note that the ln of 0 is undefined (some implementations return negative infinity), so use this function with care.s-max(sound1, sound2)
s-min(sound1, sound2)
osc-note(pitch, [duration, env, loud,
table])
osc
, but osc-note
multiplies the result by env. The env may be a sound,
or a list supplying (t1 t2
t4 l1 l2 l3). The result has a sample rate of *sound-srate*
.quantize(sound, steps)
ramp( [duration])
*Control-srate*
. See Figure 6 for
more detail. Ramp is unaffected by the sustain
transformation. The
effect of time warping is to warp the starting and ending times only. The
ramp itself is unwarped (linear). The sample rate is *control-srate*
.rms(sound, [rate, window-size])
FLONUM
and window-size is a FIXNUM
.
Figure 6: Ramps generated by pwl
and ramp
functions. The
pwl
version ramps toward the breakpoint (1, 1), but in order to ramp
back to zero at breakpoint (1, 0), the function never reaches an amplitude
of 1. If used at the beginning of a seq
construct, the next sound
will begin at time 1. The ramp
version actually reaches breakpoint
(1, 1); notice that it is one sample longer than the pwl
version. If
used in a sequence, the next sound after ramp
would start at time 1 +
P, where P is the sample period.
recip(sound)
SOUND
, compute 1/x for each sample x. If sound is a number x, just compute 1/x. If sound is a multichannel sound, return a multichannel sound with recip
applied to each element. The result has the type, sample rate, starting time, etc. of sound. Note that the reciprocal of 0 is undefined (some implementations return infinity), so use this function with care on sounds. Division of sounds is accomplished by multiplying by the reciprocal. Again, be careful not to divide by zero.s-rest( [duration])
*sound-srate*
.
Default duration is 1.0 sec, and the sound is transformed in time according
to *warp*
. Note: rest
is a Lisp function that is equivalent to cdr
. Be careful to use s-rest
when you need a sound!noise( [duration])
*warp*
. The
sample rate is *sound-srate*
and the amplitude is +/- *loud*
.yin(sound, minstep, maxstep, stepsize)
SOUND
.
The minstep, a FLONUM
, is the minimum frequency considered (in steps),
maxstep, a FLONUM
, is the maximum frequency considered (in steps), and
stepsize, a FIXNUM
, is the desired hop size. The result is
a "stereo" signal,
i.e. an array of two SOUND
s, both at the same sample rate, which is
approximately the sample rate of sound divided by stepsize.
The first SOUND
consists of frequency estimates. The second sound consists
of values that measure the confidence or reliability of the frequency estimate.
A small value (less than 0.1) indicates fairly high confidence. A larger value
indicates lower confidence. This number can also be thought of as a ratio of
non-periodic power to periodic power. When the number is low, it means the signal
is highly periodic at that point in time, so the period estimate will be
reliable.
Hint #1: See
Alain de Cheveigne and Hideki Kawahara's article "YIN, a Fundamental Frequency
Estimator for Speech and Music" in the Journal of the
Acoustic Society of America, April 2002 for details on the yin algorithm.
Hint #2: Typically, the stepsize should be at least the expected number
of samples in one period so that the
fundamental frequency estimates are calculated at a rate far below
the sample rate of the signal. Frequency does not change rapidly and
the yin algorithm is fairly slow. To optimize speed,
you may want to use less than 44.1 kHz sample rates for input sounds. Yin
uses interpolation to achieve potentially fractional-sample-accurate estimates,
so higher sample rates do not necessarily help the algorithm and definitely
slow it down. The computation time is O(n^(2)) per estimate,
where n is the number
of samples in the longest period considered. Therefore, each increase
of minstep by 12 (an octave) gives you a factor of 4 speedup, and
each decrease of the sample rate of sound by a factor of
two gives you another factor of 4 speedup. Finally, the number of estimates is
inversely proportional to stepsize.
Hint #3: Use snd-srate
(see Section "Accessing and Creating Sound") to get
the exact sample rate of the result, which will be the sample rate of
sound divided by stepsize.
E.g. (snd-srate (aref yin-output 0))
,
where yin-output
is a result returned by yin
, will be the
sample rate of the estimates. seq
,
seqrep
, sim
, and simrep
. The
"absolute" versions (starting or ending with "abs") do not look at the
current environment, but rather set an environment variable to a specific value.
In this way, sections of code can be insulated from external
transformations.
abs-env(beh)
(at 10.0 (abs-env (my-beh)))
is equivalent to
(abs-env (my-beh))
because abs-env
forces the default environment.at(time, beh)
*warp*
shifted by time.at-abs(time, beh)
*warp*
shifted so that local time 0 maps to time.continuous-control-warp(beh)
*control-srate*
. Linear interpolation is currently used. Implementation: beh is first evaluated without any shifting, stretching, or warping. The result is functionally composed with the inverse of the environment's warp function.continuous-sound-warp(beh)
*sound-srate*
. Linear interpolation is currently used. See continuous-control-warp
for implementation notes.control-srate-abs(srate,
beh)
*control-srate*
set to sample rate srate. Note: there is no "relative" version of
this function.extract(start, stop, beh)
*warp*
. The result is shifted
to start according to *warp*
, so normally the result will start without a delay of start.extract-abs(start, stop, beh)
*warp*
. The result is shifted
to start according to *warp*
.loud(volume, beh)
*loud*
incremented by volume. (Recall that *loud*
is in decibels, so increment is the proper operation.)loud-abs(volume, beh)
*loud*
set to volume.sound-srate-abs(srate, beh)
*sound-srate*
set to sample rate srate. Note: there is no "relative" version of this function. stretch(factor, beh)
*warp*
scaled by factor. The effect is to "stretch" the result
of beh (under the current environment) by factor. See Chapter
"Continuous Transformations and Time Warps" for more information.stretch-abs(factor, beh)
*warp*
set to a linear time transformation where each unit of logical time maps to factor units of real time. The effect is to stretch the nominal behavior of beh (under the default global environment) by factor. See Chapter "Continuous Transformations and Time Warps" for more information.sustain(factor, beh)
*sustain*
scaled by factor. The effect is to "stretch" the result of beh (under the current environment) by factor; however, the logical stop times are not stretched. Therefore, the overall duration of a sequence is not changed, and sounds will tend to overlap if *sustain*
is greater than one (legato) and be separated by silence if *sustain*
is less than one.sustain-abs(factor, beh)
*sustain*
set to factor. (See sustain
, above.)transpose(amount, beh)
*transpose*
shifted by amount. The effect is relative transposition by amount semitones.transpose-abs(amount, beh)
*transpose*
set to amount. The effect is the transposition of the nominal pitches in beh (under the default global environment) by amount.warp(fn, beh)
*warp*
modified by fn. The idea is that beh and fn are written in the same time system, and fn warps that time system to local time. The current environment already contains a mapping from local time to global (real) time. The value of *warp*
in effect when beh is evaluated is the functional composition of the initial *warp*
with fn.warp-abs(fn, beh)
*warp*
set to fn. In other words, the current *warp*
is ignored and not composed with fn to form the new *warp*
.
Mode
The defaults for format, mode, and bits are as follows:
Combination and Time Structure
These behaviors combine component behaviors into structures, including
sequences (melodies), simultaneous sounds (chords), and structures based
on iteration.
seq(beh1, [beh2, ...])
*time*
and each successive behavior at the
logical-stop
time of the previous one. The results are summed to form a
sound whose logical-stop
is
the logical-stop
of the last behavior in the sequence. Each behavior
can result in a multichannel sound, in which case, the logical stop time is
considered to be the maximum logical stop time of any channel. The number
of channels in the result is the number of channels of the first behavior.
If other behaviors return fewer channels, new channels are created containing
constant zero signals until the required number of channels is obtained. If
other behaviors return a simple sound rather than multichannel sounds, the
sound is automatically assigned to the first channel of a multichannel sound
that is then filled out with zero signals. If another behavior returns more
channels than the first behavior, the error is reported and the computation
is stopped. Sample rates are converted up or down to match the sample rate of the first sound in a sequence.
seqrep( (var, limit) beh)
seq
. The symbol var is
a read-only local variable to beh. Assignments are not restricted
or detected, but may cause a run-time error or crash.
sim( [beh1, beh2, ...])
*warp*
.
If behaviors return multiple channel sounds, the corresponding channels are
added. If the number of channels does not match, the result has the
maximum. For example, if a two-channel sound [L, R] is added to a four-channel
sound [C1, C2, C3, C4], the result is [L + C1, R + C2, C3, C4]. Arguments to sim
may also be numbers. If all arguments are numbers, sim
is equivalent (although slower than) the +
function. If a number is added to a sound, snd-offset
is used to add the number to each sample of the sound. The result of adding a number to two or more sounds with different durations is not defined. Use const
to coerce a number to a sound of a specified duration. An important limitation of sim
is that it cannot handle hundreds of behaviors due to a stack size limitation in XLISP. To compute hundreds of sounds (e.g. notes) at specified times, see timed-seq
, below.
See also sum
below.
simrep( (var, limit) beh)
sim
.
trigger(s, beh)
SOUND
s makes a transition from less than or equal to zero to
greater than zero. (If the first sample of s is greater than zero, an
instance is created immediately.) The sample rate of s and all behaviors
must be the same, and the behaviors must be (monophonic) SOUND
s.
This function is particularly designed to allow behaviors to be invoked
in real time by making s a function of a Nyquist slider, which can be
controlled by a graphical interface or by OSC messages. See snd-slider
in Section "Creating Sounds".
set-logical-stop(beh, time)
sum(a, [b, c, ...])
mult(a, [b, c, ...])
diff(a, b)
(sum a (prod -1 b))
.
timed-seq(score)
`((time1 stretch1 beh1) (time2
stretch2 beh2) ...)
, where timeN is the starting time,
stretchN is the stretch factor, and behN is the behavior. Note
that score is normally a quoted list! The times must be in
increasing order, and each behN is evaluated using lisp's eval
,
so the behN behaviors cannot refer to local parameters or local
variables. The advantage of this form over seq
is that the
behaviors are evaluated one-at-a-time which can take much less stack
space and overall memory. One special "behavior" expression is
interpreted directly by timed-seq
: (SCORE-BEGIN-END)
is ignored, not evaluated as a function. Normally, this special
behavior is placed at time 0 and has two parameters: the score
start time and the score end time. These are used in Xmusic
functions. If the behavior has a :pitch
keyword parameter
which is a list, the list represents a chord, and the expression is
replaced by a set of behaviors, one for each note in the chord.
It follows that if :pitch
is nil
, the behavior
represents a rest and is ignored.
Sound File Input and Output
Format
play(sound)
play
function writes a file and plays it. The details of this
are system-dependent, but play
is defined in the file
system.lsp
. The variable *default-sf-dir*
names a directory into which to save a sound file.
*autonorm-type*
, which is 'lookahead
by default.
The lookahead method precomputes and buffers *autonorm-max-samples*
samples, finds the peak value, and normalizes accordingly. The
'previous
method bases the normalization of the current sound on the peak value of the (entire) previous sound. This might be good if you are working with long sounds that start rather softly. See Section "Memory Space and Normalization" for more details.
(autonorm-off)
Reenable the automatic normalization feature by typing:
(autonorm-on)
(r)
to replay the stored sound. Real-time playback can be disabled by:
(sound-off)
and reenabled by:
(sound-on)
Disabling real-time playback has no effect on (play-file)
or (r)
.
play-file(filename)
s-read
function is used to read the file, and unless
filename specifies an absolute path or starts with ".", it will be read from
*default-sf-dir*
.
autonorm-on()
play
command.
autonorm-off()
play
command.
sound-on()
play
command.
sound-off()
play
command.
s-save(expression, maxlen,
filename, [format: format,] [mode: mode,] [bits: bits,] [swap: flag,] [play: play])
FLONUM
is returned giving the maximum absolute value of all samples
written. (This is useful for normalizing sounds and detecting sample
overflow.) If play is not NIL
, the sound will be output through the computer's audio output system. (:play is not implemented on all systems; if it is implemented, and filename is NIL
, then this will play the file without also writing a file.)
The latency (length of audio buffering) used to play the sound is 0.3s by default, but see snd-set-latency
.
If
a multichannel sound (array) is written, the channels are up-sampled to the
highest rate in any channel so that all channels have the same sample rate.
The maximum number of samples written per channel is given by maxlen,
which allows writing the initial part of a very long or infinite sound. A
header is written according to format, samples are encoded according to
mode, using bits bits/sample, and bytes are swapped if swap is not NIL. Defaults for these are
*default-sf-format*
, *default-sf-mode*
, and
*default-sf-bits*
. The default for swap is NIL.
The bits parameter may be 8, 16, or 32. The values for the format and mode options are described below:
snd-head-none
snd-head-AIFF
snd-head-IRCAM
snd-head-NeXT
snd-head-Wave
snd-head-mode-adpcm
snd-head-mode-pcm
snd-head-mode-ulaw
snd-head-mode-alaw
snd-head-mode-float
snd-head-mode-upcm
snd-head-NeXT
, snd-head-mode-pcm
,
16
snd-head-AIFF
, snd-head-mode-pcm
, 16
s-read(filename, [time-offset: offset,] [srate:
sr,] [dur: dur,] [nchans: chans,] [format: format,] [mode: mode,] [bits: n,] [swap: flag])
:time-offset
and :dur
).
(s-read "mysound.snd" :srate 44100)
specifies a sample rate of 44100 hz, but if the file has a header specifying 22050 hz, the resulting sample rate will be 22050. The parameters are:
If there is an error, for example if :time-offset
- the amount of time (in seconds) to skip from
the beginning of the file. The default is 0.0.
:srate
- the sample rate of the samples in the file. Default is
*default-sf-srate*
, which is normally 44100.
:dur
- the maximum duration in seconds to read. Default is
10000.
:nchans
- the number of channels to read. It is assumed that
samples from each channel are interleaved. Default is 1.
:format
- the header format. See s-save
for details.
Default is *default-sf-format*
, although this parameter is currently
ignored.
:mode
- the sample representation, e.g. PCM or float. See
s-save
for details. Default is *default-sf-format*
.
:bits
- the number of bits per sample. See s-save
for
details. Default is *default-sf-bits*
.
:swap
- (T or NIL) swap byte order of each sample. Default is NIL.
:time-offset
is greater than the length of the file, then NIL
is returned rather than a sound. Information about the sound is also returned by s-read
through *rslt*
(Footnote 2) . The list assigned to *rslt*
is of the form: (format channels mode bits samplerate duration flags byte-offset), which are defined as follows:
s-save
for details.
s-save
for details.
FLONUM
.
s-read
. If a value is actually read from the sound file header, a flag is set. The flags are: snd-head-format
, snd-head-channels
, snd-head-mode
, snd-head-bits
, snd-head-srate
, and snd-head-dur
. For example,
(let ((flags (caddr (cddddr *rslt*))))
(not (zerop (logand flags snd-head-srate))))
tells whether the sample rate was specified in the file. See also sf-info
below.
s-overwrite
and s-add-to
functions).
s-add-to(expression, maxlen,
filename, [offset])
s-add-to
to extend the file with zeros.)
s-overwrite(expression, maxlen, filename, [offset])
FLONUM
is returned, giving the maximum absolute value of all samples written. The
sample rate(s) of expression must match those of the file.
The maximum number of samples written per channel is given by maxlen,
which allows writing the initial part of a very long or infinite sound.
If offset is specified, the new sound is written to the file beginning at
an offset from the beginning (in seconds). The file is extended if
necessary to accommodate the new insert, but if offset falls outside of
the original file, the file is not modified. (If necessary, use
s-add-to
to extend the file with zeros.)
sf-info(filename)
soundfilename
below) unless the filename begins with "." or "/". The source for this function is in the runtime
and provides an example of how to determine sound file parameters.
soundfilename(name)
*default-sf-dir*
is prepended to name. The s-plot
, s-read
, and s-save
functions all use soundfilename
translate filenames.
s-plot(sound, n)
plot
program on a Unix workstation, but now is
primarily used with jNyqIDE
, which has self-contained plotting. Normally,
time/value pairs in ascii are written to points.dat
and system-dependent code
(or the jNyqIDE
program) takes it from there. The data file used is:
*default-plot-file*
s-print-tree(sound)
snd-print-tree
.
Low-level Functions
Nyquist includes many low-level functions that are used to implement the functions and behaviors described in previous sections. For completeness, these functions are described here. Remember that
these are low-level functions that are not intended for normal use. Unless
you are trying to understand the inner workings of Nyquist, you can skip this section.
Creating Sounds
The basic operations that create sounds are described here.
snd-const(value, t0, srate,
duration)
pwl
(see Section "Piece-wise Approximations") instead.snd-read(filename, offset, t0, format,
channels, mode, bits, swap, sr,
dur)
(/ (float N) sr (/ bits 8) channels)If the header is not a multiple of the frame size, either write a header or contact the author (dannenberg@cs.cmu.edu) for assistance. Nyquist will round offset to the nearest sample. The resulting sound will start at time t0. If a header is found, the file will be interpreted according to the header information. If no header was found, channels tells how many channels there are, the samples are encoded according to mode, the sample length is bits, and sr is the sample rate. The swap flag is 0 or 1, where 1 means to swap sample bytes. The duration to be read (in seconds) is given by dur. If dur is longer than the data in the file, then a shorter duration will be returned. If the file contains one channel, a sound is returned. If the file contains 2 or more channels, an array of sounds is returned. Note: you probably want to call
s-read
(see Section "Sound File Input and Output") instead of
snd-read
. Also, see Section "Sound File Input and Output" for information on the
mode and format parameters.snd-save(expression, maxlen,
filename, format, mode, bits, swap, play)
s-save
(see Section "Sound File Input and Output") instead. The format and
mode parameters are described in Section "Sound File Input and Output".snd-overwrite(expression, maxlen, filename, byte-offset, mode, bits, swap, sr, channels)
snd-save
), bits is the number of bits per
sample, swap is 0 or 1, where 1 means to swap sample bytes, sr is the sample rate, and channels is the number of
channels. If these do not match the parameters for filename, it is
likely that filename will be corrupted. Up to a maximum of maxlen
samples will be written per channel. Use s-add-to
(in Section "Sound File Input and Output" or
s-overwrite
(in Section "Sound File Input and Output" instead of this function.snd-coterm(s1, s2)
s-add-to
, we need to read from the
target sound file, add the sounds to a new sound, and overwrite the result
back into the file. We only want to write as many samples into the file as
there are samples in the new sound. However, if we are adding
in samples read from
the file, the result of a snd-add
in Nyquist will have the maximum
duration of either sound. Therefore, we may read to the end of the file.
What we need is a way to truncate the read, but we cannot easily do that,
because we do not know in advance how long the new sound will be. The
solution is to use snd-coterm
, which will allow us to truncate the
sound that is read from the file (s1) according to the duration of the
new sound (s2). When this truncated sound is added to the new sound,
the result will have only the duration of the new sound, and this can be
used to overwrite the file. This function is used in the implementation of
s-add-to
, which is defined in runtime/fileio.lsp
.(snd-from-array ...)
snd-white(t0, sr, d)
noise
(see Section "More Behaviors").snd-zero(t0, srate)
pwl
(see Section "Piece-wise Approximations") instead.get-slider-value(index)
osc-enable
) and by sending character
sequences to Nyquist's standard input. (Normally, these character sequences would
not be typed but generated by the jNyqIDE interactive development environment, which
runs Nyquist as a sub-process, and which present the user with graphical sliders.) snd-slider(index, t0, srate, duration)
get-slider-value
for more information).
The function returns a sound. Since Nyquist sounds are computed in blocks of samples,
and each block is computed at once, each block will contain copies of the current slider
value. To obtain reasonable responsiveness, slider sounds should have high (audio)
sample rates so that the block rate will be reasonably high. Also, consider lowering the audio
latency using snd-set-latency
. To "trigger" a Nyquist behavior using slider input, see the trigger
function in Section "Combination and Time Structure".
snd-abs(sound)
s-abs
instead. (See Section "More Behaviors".)snd-sqrt(sound)
s-sqrt
instead. (See Section "More Behaviors".)snd-add(sound1, sound)
sim
or sum
instead of snd-add
(see Section "Combination and Time Structure").snd-offset(sound, offset)
sum
instead (see Section "Combination and Time Structure").snd-avg(sound, blocksize, stepsize, operation)
snd-gate
or snd-follow
.
To select the operation, operation should be one of OP-AVERAGE
or OP-PEAK
. (These are global lisp variables; the actual
operation parameter is an integer.) For RMS computation, see
rms
in Section "More Behaviors".snd-clip(sound, peak)
clip
instead (see Section "More Behaviors").snd-compose(f, g)
sref
, shape
, and
snd-resample
. snd-compose
for variable pitch shifting,
see demos/pitch_change.htm
.
snd-tapv(sound, offset, vardelay, maxdelay)
FIXNUM
or FLONUM
)
and vardelay (a SOUND
). The specified delay is adjusted to lie in the range
of zero to maxdelay seconds to yield the actual delay, and the delay is
implemented using linear interpolation. This function was designed specifically
for use in a chorus effect: the offset is set to half of maxdelay, and
the vardelay input is a slow sinusoid. The maximum delay is limited to
maxdelay, which determines the length of a fixed-sized buffer.snd-tapf(sound, offset, vardelay, maxdelay)
snd-tapv
except there is no linear interpolation. By
eliminating interpolation, the output is an exact copy of the input with no filtering
or distortion. On the other hand, delays jump by samples causing samples to double or
skip even when the delay is changed smoothly.snd-copy(sound)
snd-down(srate, sound)
force-srate
(see Section "Sound Synthesis").snd-exp(sound)
s-exp
instead (see Section "More Behaviors").snd-follow(sound, floor, risetime, falltime, lookahead)
snd-avg
above for a function that can help to generate a low-sample-rate input for snd-follow
. See snd-chase
in Section "Filters" for a related filter.snd-gate(sound, lookahead, risetime, falltime, floor, threshold)
snd-gate
is not recommended for direct use. Use gate
instead (see Section "Miscellaneous Functions").snd-inverse(signal, start, srate)
snd-inverse
operationally as follows: for each output time point t, scan ahead in signal until the value of signal exceeds t. Interpolate to find an exact time point x from signal and output x at time t. This function is intended for internal system use in implementing time warps.snd-log(sound)
s-log
instead (see Section "More Behaviors").peak(expression, maxlen)
s-save
). Only the first maxlen samples are evaluated. The expression is automatically quoted (peak
is a macro), so do not quote this parameter. If expression is a variable, then the global binding of that variable will be used. Also, since the variable retains a reference to the sound, the sound will be evaluated and left in memory. See Section "Memory Space and Normalization" on "Memory Space and Normalization" for examples.snd-max(expression, maxlen)
snd-save
), which is therefore normally quoted by the caller. At most maxlen samples are computed. The result is the maximum of the absolute values of the samples. Notes: It is recommended to use peak
(see above) instead. If you want to find the maximum of a sound bound to a local variable and it is acceptable to save the samples in memory, then this is probably the function to call. Otherwise, use peak
.snd-maxv(sound1, sound2)
s-max
instead (see Section "More Behaviors").snd-normalize(sound)
snd-oneshot(sound, threshold, ontime)
snd-prod(sound1, sound2)
mult
or
prod
instead (see Section "Sound Synthesis"). Sample rate, start time, etc. are taken from sound.snd-pwl(t0, sr,
lis)
LVAL
) where the
list alternates sample numbers (FIXNUM
s, computed in samples
from the beginning of the pwl function) and values (the value of the pwl
function, given as a FLONUM
). There is an implicit starting
point of (0, 0). The list must contain an odd number of points, the omitted
last
value being implicitly zero (0). The list is assumed to be well-formed. Do
not call this function. Use pwl
instead (see Section "Piece-wise Approximations").snd-quantize(sound, steps)
snd-recip(sound)
recip
instead (see Section "More Behaviors").snd-resample(f,
rate)
resample
instead.snd-resamplev(f, rate, g)
sound-warp
for a detailed discussion. See
snd-compose
for a fast, low-quality alternative to this function.
Normally, you should use sound-warp
instead of this function.snd-scale(scale, sound)
scale
instead (see Section
"Sound Synthesis").snd-shape(signal, table, origin)
shape
is based. The snd-shape
function is like shape
except that signal and table must be (single-channel) sounds. Use shape
instead (see Section "Filter Behaviors").snd-up(srate, sound)
force-srate
(see Section "Sound Synthesis").snd-xform(sound, sr, time, start,
stop, scale)
snd-t0
) of the sound is shifted to
time, (1) the sound is stretched as a result of setting the sample rate
to sr (the start time is unchanged by this), (3) the sound is clipped
from start to stop, (4) if start is greater than time, the sound is shifted
shifted by time - start, so that the start time is time, (5) the
sound is scaled by scale. An empty (zero) sound at time will be
returned if all samples are clipped. Normally, you should accomplish all
this using transformations. A transformation applied to a sound has no
effect, so use cue
to create a transformable sound (see Section
"Using Previously Created Sounds").snd-yin(sound, minstep, maxstep, rate)
yin
. See Section "More Behaviors".Some filters allow time-varying filter parameters. In these functions, filter coefficients are calculated at the sample rate of the filter parameter, and coefficients are not interpolated.
snd-alpass(sound, delay, feedback)
snd-delay
. The feedback should be less than one to avoid exponential amplitude blowup. Delay is rounded to the nearest sample. You should use alpass
instead (see Section "Filter Behaviors").snd-alpasscv(sound, delay,
feedback)
alpass
instead (see Section "Filter Behaviors").snd-alpassvv(sound, delay, feedback, maxdelay)
FLONUM
parameter, maxdelay, that gives an upper bound on the value of delay. Note: delay must remain between zero and maxdelay. If not, results are undefined, and Nyquist may crash. You should use alpass
instead (see Section "Filter Behaviors").snd-areson(sound, hz, bw,
normalization)
areson
unit generator in Csound. The snd-areson
filter is an exact
complement of snd-reson
such that if both are applied to the
same signal with the same parameters, the sum of the results yeilds
the original signal. Note that because of this complementary design,
the power is not normalized as in snd-reson
. See snd-reson
for details on normalization. You should use areson
instead (see
Section "Filter Behaviors").snd-aresoncv(sound, hz, bw,
normalization)
snd-areson
except
the bw (bandwidth) parameter is a sound. Filter coefficients are
updated at the sample rate of bw. The "cv
" suffix stands for Constant,
Variable, indicating that hz and bw are constant (a number) and
variable (a sound), respectively. This naming convention is used throughout.
You should use areson
instead (see
Section "Filter Behaviors").snd-aresonvc(sound, hz, bw,
normalization)
snd-areson
except
the hz (center frequency) parameter is a sound. Filter coefficients are
updated at the sample rate of hz.
You should use areson
instead (see
Section "Filter Behaviors").snd-aresonvv(sound, hz, bw,
normalization)
snd-areson
except
both hz (center frequency) and bw (bandwidth) are sounds. Filter
coefficients are updated at the next sample of either hz or bw.
You should use areson
instead (see
Section "Filter Behaviors").snd-atone(sound, hz)
atone
unit generator in Csound. The snd-atone
filter is an exact
complement of snd-tone
such that if both are applied to the
same signal with the same parameters, the sum of the results yeilds
the original signal. You should use hp
instead (see
Section "Filter Behaviors").snd-atonev(sound, hz)
snd-atone
except that the hz cutoff frequency is a sound. Filter
coefficients are updated at the sample rate of hz. You should use
hp
instead (see Section "Filter Behaviors").snd-biquad(sound, b0, b1, b2, a1, a2, z1init, z2init)
FLONUM
. You should probably use one of lowpass2
, highpass2
, bandpass2
, notch2
, allpass2
, eq-lowshelf
, eq-highshelf
, eq-band
, lowpass4
, lowpass6
, lowpass8
, highpass4
, highpass6
, or highpass8
, which are all based on snd-biquad
and described in Section "Filter Behaviors". For completeness, you will also find biquad
and biquad-m
described in that section.snd-chase(sound, risetime, falltime)
snd-chase
function is safe for ordinary use. See snd-follow
in Section "Signal Operations" for a related function. snd-congen(gate, risetime, falltime)
congen
instead (see Section "Filter Behaviors".snd-convolve(sound, response)
convolve
instead (see Section
"Filter Behaviors").snd-delay(sound, delay, feedback)
feedback-delay
instead (see Section "Filter Behaviors")snd-delaycv(sound, delay,
feedback)
feedback-delay
instead (see Section "Filter Behaviors").snd-reson(sound, hz, bw, normalization)
reson
unit generator in Csound.
The normalization parameter must be an integer and (like in Csound)
specifies a scaling factor. A value of 1 specifies a peak amplitude
response of 1.0; all frequencies other than hz are attenuated. A
value of 2 specifies the overall RMS value of the amplitude response
is 1.0; thus filtered white noise would retain the same power. A value of
zero specifies no scaling. The result sample rate, start time, etc. are takend from sound.
You should use reson
instead (see Section
"Filter Behaviors").snd-resoncv(sound, hz, bw,
normalization)
snd-reson
except
bw (bandwidth) is a sound. Filter coefficients are updated at the
sample rate of bw. You should use reson
instead (see Section
"Filter Behaviors").snd-resonvc(sound, hz, bw,
normalization)
snd-reson
except
hz (center frequency) is a sound. Filter coefficients are updated at the
sample rate of hz. You should use reson
instead (see Section
"Filter Behaviors").snd-resonvv(sound, hz, bw,
normalization)
snd-reson
except
botth hz (center frequency) and bw (bandwidth) are sounds. Filter
coefficients are updated at the next sample from either hz or bw. You should use reson
instead (see Section
"Filter Behaviors").snd-stkchorus(sound, delay, depth, freq, mix,
sr)
FIXNUM
representing the median desired delay length in samples. A typical
value is 6000. The FLONUM
parameters depth and freq set the modulation
depth (from 0 to 1) and modulation frequency (in Hz), mix sets the mixture
of input sound and chorused sound, where a value of 0.0 means input sound
only (dry) and a value of 1.0 means chorused sound only (wet).
The parameter sr is the desired sample rate of the resulting sound (Footnote 3) You should use pitshift
instead
(see Section "Effects").snd-stkpitshift(sound, shift, mix, sr)
FLONUM
representing the shift factor. A value of 1.0 means
no shift. The parameter mix sets the mixture of input and shifted sounds.
A value of 0.0 means input only (dry) and a value of 1.0 means shifted
sound only (wet). The sr is the desired sampling frequency. (Footnote 4) You should use pitshift
instead
(see Section "Effects").snd-stkrev(rev-type, sound, decay, mix, sr)
FIXNUM
ranging from zero to
two and selects the type of reverb. Zero selects NRev type, one selects JCRev,
and two selects PRCRev. The input sound is processed by the reverb with
a decay time in seconds (a FLONUM
). The mix, a FLONUM
,
sets the
mixture of dry input and reverb output. A value of 0.0 means input only (dry)
and a value of 1.0 means reverb only (wet). The sample rate
is sr (Footnote 5) You
should use nrev
, jcrev
or prcrev
instead (see
Section "Effects").snd-tone(sound, hz)
lp
instead (see Section
"Filter Behaviors").snd-tonev(sound, hz)
snd-tone
except hz (cutoff frequency) is a sound.
The filter coefficients are updated at the sample rate of hz. You
should use lp
instead (see Section
"Filter Behaviors").sim
and sine
, then the
physical and logical stop times will be the same and will correspond to the
duration you specified, rounded to the nearest sample.)
fmosc
function is linear, thus calling for a specification in Hertz.
Other parameters common to all of these oscillator functions are:
snd-amosc(sound, step, sr, hz, t0,
am, phase)
amosc
instead (see
Section "Oscillators").snd-fmosc(s, step, sr, hz, t0, fm,
phase)
fmosc
instead (see Section "Oscillators").(snd-fmfb t0 hz sr
index dur)
FLONUM
that
specifies the amount of feedback. You should use fmfb
instead (see
Section "Oscillators").(snd-fmfbv t0 hz sr
index)
SOUND
that
specifies the amount of feedback and determines the duration.
You should use fmfb
instead (see Section "Oscillators").snd-buzz(n, sr, hz, t0, fm)
buzz
instead (see Section "Oscillators").snd-pluck(sr, hz, t0, d,
final-amp)
pluck
instead (see Section
"Oscillators").snd-osc(s, step, sr, hz, t0, d, phase)
osc
instead (see Section
"Oscillators").snd-partial(sr, hz, t0, env)
snd-amosc
that generates a sinusoid starting at phase
0 degrees. The env parameter gives the envelope or any other amplitude
modulation. You should use partial
instead (see Section
"Oscillators").snd-sine(t0, hz, sr, d)
snd-osc
that always generates a sinusoid with initial
phase of 0 degrees. You should use sine
instead (see Section "Oscillators").snd-siosc(tables, sr, hz, t0,
fm)
siosc
instead (see Section "Oscillators").(snd-bandedwg freq bowpress-env preset sr)
FLONUM
in Hz, bowpress-env is
a SOUND
that ranges from zero to one, preset is a FIXNUM
,
and sr is the desired sample rate in Hz. Currently, there are four
presets: uniform-bar (0), tuned-bar (1), glass-harmonica (2), and
tibetan-bowl (3). You should use wg-uniform-bar
, wg-tuned-bar
,
wg-glass-harm
, or wg-tibetan-bowl
instead (see Section
"Physical Models").snd-bowed(freq,
bowpress-env, sr)
FLONUM
in Hertz, bowpress-env is a
SOUND
that ranges from z
ero to one, and sr is the desired sample rate (a FLONUM
).
You should use bowed instead (see Section "Physical Models").snd-bowed-freq(freq, bowpress-env, freq-env, sr)
snd-bowed
but with
an additional parameter for continuous frequency control. You should use
bowed-freq
instead (see Section "Physical Models").snd-clarinet(freq, breath-env, sr)
FLONUM
in Hertz,
breath-env is
a SOUND
that ranges from zero to one, and sr is the
desired sample
rate (a FLONUM
). You should use clarinet
instead
(see Section
"Physical Models").snd-clarinet-freq(freq, breath-env, freq-env, sr)
snd-clarinet
but with
an additional parameter for continuous frequency control. You should use
clarinet-freq
instead (see Section "Physical Models").snd-clarinet-all(freq, vibrato-freq,
vibrato-gain, freq-env, breath-env,
reed-stiffness, noise, sr)
snd-clarinet-freq
but with
additional parameters for vibrato generation and continuous control of
reed stiffness and breath noise. You should use
clarinet-all
instead (see Section "Physical Models").snd-flute(freq,
breath-env, sr)
FLONUM
in Hertz, breath-env is a SOUND
that ranges from zero to one, and sr is
the desired sample rate (a FLONUM
). You should use flute
instead (see Section "Physical Models").snd-flute-freq(freq, breath-env,
freq-env, sr)
snd-flute
but with
an additional parameter for continuous frequency control. You should use
flute-freq
instead (see Section "Physical Models").snd-flute-all(freq, vibrato-freq, vibrato-gain, freq-env, breath-env,
jet-delay, noise, sr)
snd-flute-freq
but with
additional parameters for vibrato generation and continuous control of
breath noise. You should use
flute-all
instead (see Section "Physical Models").snd-mandolin(t0, freq, dur, body-size, detune, sr)
FLONUM
in
Hz, body-size and detune are FLONUM
s, and sr
is the desired sample
rate. You should use mandolin
instead (see Section "Physical Models").snd-modalbar(t0, freq, preset, dur, sr)
FLONUM
in Hz,
preset
is a FIXNUM
ranging from 0 to 8, dur is a
FLONUM
that
sets the duration (in seconds) and sr is the desired sample rate. You
should use modalbar
instead (see Section "Physical Models").snd-sax(freq, breath-env, sr)
FLONUM
in Hertz, breath-env is
a SOUND
that ranges from zero to one, and sr is the desired sample
rate (a FLONUM
). You should use sax
instead (see Section
"Physical Models").snd-sax-freq(freq, freq-env, breath-env,
sr)
snd-sax
but with
an additional parameter for continuous frequency control. You should use
sax-freq
instead (see Section "Physical Models").snd-sax-all(freq, vibrato-freq,
vibrato-gain, freq-env, breath-env,
reed-stiffness, noise, blow-pos, reed-table-offset, sr)
snd-sax-freq
but with
additional parameters for vibrato generation and continuous control of
reed stiffness, breath noise, excitation position, and reed table offset.
You should use
sax-all
instead (see Section "Physical Models").snd-sitar(t0,
freq, dur, sr)
FLONUM
(in Hz), E
dur sets the duration and sr is the sample rate (in Hz)
of the resulting sound. You should use sitar
instead (see Section
"Physical Models").seq
construct.
snd-seq(sound, closure)
seq
in Section
"Combination and Time Structure".snd-multiseq(array, closure)
snd-seq
except the first parameter is a
multichannel sound rather than a single sound. A multichannel sound is
simply an XLISP array of sounds. An array of sounds is returned which is
the sum of array and another array of sounds returned by closure.
The closure is passed the logical stop time of the multichannel sound,
which is the maximum logical stop time of any element of array. Do
not call this function. See seq
in Section "Combination and Time Structure".
snd-trigger(s, closure)
This is one of
the only ways in which a behavior instance can be created by changes in a
signal. When s (a SOUND
) makes a transition from less than or
equal to zero to greater than zero, the closure, which takes a starting
time parameter, is evaluated. The closure must return a SOUND
. The
sum of all these sounds is returned. If there are no sounds, the result will
be zero. The stop time of the result is the maximum stop time of s and
all sounds returned by the closure. The sample rate of the return value is
the sample rate of s, and the sounds returned by the closure must all
have that same sample rate. Do not call this function.
See trigger
in Section "Combination and Time Structure".
An implementation note: There is no way to have snd-trigger
return
a multichannel sound. An alternative implementation would be a built-in
function to scan ahead in a sound to find the time of the next zero crossing.
This could be combined with some LISP code similar to seq
to sum up
instances of the closure. However, this would force arbitrary look-ahead
and therefore would not work with real-time inputs, which was the motivation
for snd-trigger
in the first place.