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)
(snd-fromarraystream t0sr object)
:next
to object. If
object returns NIL
, the sound terminates. Otherwise, object
must return an array of FLONUMs. 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)
: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)
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)
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)
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)
(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.(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
.)(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.(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*
. (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)
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)
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").(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)
s-abs
applied to each element. The result has the type, sample rate, starting time, etc. of sound.(s-sqrt sound)
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)
s-exp
applied to each element. The result has the type, sample rate, starting time, etc. of sound.(s-log sound)
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)
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)
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.
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)
s-plot
simply writes time/value pairs in ascii to a file named points.dat
. Then, an xterm
is created in Tektronix emulation mode, and the Unix plot
program is used to plot the points. The files used are:
The script for plotting is typically something like:
*default-plot-file*
*plotscript-file*
xterm
, defaults to "sys/unix/rs6k/plotscript".
graph < points.dat | plot -Ttek
This runs the Unix graph program which reads the input, scales it, and adds axes and labels. The output is piped to the plot program which converts the
graphics data into Tektronix commands. It's crude but works well even over
a serial line.
(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)
(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-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-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-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
"Sound Synthesis").(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 "Sound Synthesis").(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 "Sound Synthesis").(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
"Sound Synthesis").(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 "Sound Synthesis").(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 "Sound Synthesis").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.