File: part10.html

package info (click to toggle)
nyquist 3.23%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 58,064 kB
  • sloc: ansic: 74,758; lisp: 18,104; java: 10,719; cpp: 6,688; sh: 171; xml: 58; makefile: 40; python: 15
file content (479 lines) | stat: -rw-r--r-- 25,057 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
<!DOCTYPE html>
<html><head><title>Interactive Nyquist</title>
<link rel="stylesheet" type="text/css" href="nyquiststyle.css">
<link rel="icon" href="nyquist-icon.png" />
<link rel="shortcut icon" href="nyquist-icon.png" />
</head>
<body bgcolor="ffffff">
<a href = "part9.html">Previous Section</a> | <a href = "part11.html">Next Section</a> | <a href = "title.html#toc">Table of Contents</a> | <a href = "indx.html">Index</a> | <a href = "title.html">Title Page</a>
<hr>
<a name = "110"><h2>Interactive Nyquist</h2></a><a name="index903"></a>
<p>Nyquist is not intended for real-time performance, but it has some
features that allow you to adjust parameters interactively. The basic
idea is that there is an array of 1000 floating point values, called
sliders, that can be accessed while synthesizing sounds in
Nyquist. The <code>slider</code> unit generator returns a signal that copies
the current value of a slider value. You can change the slider value
while playing sounds using either Open Sound Control or the NyquistIDE.
<small></p>

<p>Sounds are normally computed on demand. So the result returned by
<code>slider</code> does not immediately compute any samples. Samples
are only computed when something tries to use this signal. At that
time, the slider value is read. Normally, if the slider is used to
control a sound, you will hear changes in the sound pretty soon after
the slider value changes. However, one thing that can interfere with
this is that <code>SOUND</code> samples are computed in blocks of about 1000
samples. When the slider value is read, the same value is used to fill
a block of 1000 samples, so even if the sample rate is 44,100 Hz, the
effective slider sample rate is 44,100/1000, or 44.1 Hz. If you give
the slider a very low sample rate, say 1000, then slider value changes
will only be noticed by Nyquist approximately once per second. For
this reason, you should normally use the audio sample rate (typically
44,100 Hz) for the rate of the <code>snd-slider</code> output
<code>SOUND</code>. (Yes, this is terribly wasteful to represent each slider
value with 1000 samples, but Nyquist was not designed for low-latency
computation, and this is an expedient work-around.) </p>

<p>When you load
<code>sliders.lsp</code>, which defines a number of slider functions, two
important settings may be changed. First <code>autonorm-off</code> is
called. The problem with auto-normalization is that it works by
computing 1 million samples ahead of real time to determine a
normalization factor. If Nyquist computes ahead, it will be unable to
respond to control changes until the million samples (about 20
seconds) have been played. Secondly, <code>snd-set-latency</code> is used to
set the audio latency to 0.02s (20 milliseconds). Normally, Nyquist
uses a generous 0.3s latency which allows Nyquist to stop computing
audio and run garbage collection without breaks in the audio
output. At 20ms, interactivity is greatly enhanced because changes do
not sit in audio buffers for 300ms, but you may notices some break-up
in the audio, especially when garbage collection takes place. The
latency can be changed to any value you like after you load
<code>sliders.lsp</code>.
</p>
</small>

<p>In addition to reading sliders as continually changing <code>SOUND</code>s,
you can get the slider value as a Lisp <code>FLONUM</code> (a floating point
number) using <code>get-slider-value</code>. This might be
useful if you are computing 
a sequence of many notes (or other sound events) and want to apply the
current slider value to the whole note or sound event.</p>

<p>Other unit generators exist to instantiate behaviors and to stop
sounds according to slider values. These will be described below.</p>
<a name = "111"><h3>Interactive Control with the NyquistIDE</h3></a>
<p>To control sounds interactively using the NyquistIDE, you first create
a control panel, then populate the panel with sliders and buttons.
These will send values into the sliders array in the Nyquist
process. To control a sound, you use built-in functions to retrieve
real-time values from the sliders array as sound is being played.
Further discussion and examples can be found in 
<code>nyquist/lib/sliders/slider-demos.sal</code><a name="index904"></a><a name="index905"></a>. </p>
<a name = "112"><h4>Creating a Control Panel</h4></a>
<p>A control panel is created with <code>make-slider-panel</code>, which takes
a panel name and color as parameters. Control panels <i>can only be
created by executing code in Nyquist.</i> There is no way to configure
control panels directly using the NyquistIDE. Control panels can be
deleted interactively using the close button on the panel or through
code by calling <code>close-slider-panel</code>.</p>
<dl>
<dt>
<code>make-slider-panel(<a name="index906"></a><a name="index907"></a><a name="index908"></a><i>name</i>, <i>color</i>)</code> [SAL]<br>

<code>(make-slider-panel <i>name</i> <i>color</i>)</code> [LISP]</dt>
<dd>Create
a control panel in the IDE. The title of the control panel window is
given by <i>name</i>, a STRING. The color of the panel is given by
<i>color</i>, a FIXNUM from 0 through 12. The color 0 is gray. Other
colors are implementation-dependent, but different numbers give
distinguishable colors. You must load <code>sliders.lsp</code> to access
this function.<br><br>
<dt><code>close-slider-panel(<a name="index909"></a><i>name</i>)</code> [SAL]<br>

<code>(close-slider-panel <i>name</i>)</code>
[LISP]</dt>
<dd>Close 
a control panel in the NyquistIDE named by <i>name</i>, a STRING. Any
embedded controls (sliders or buttons) are also destroyed. You must
load <code>sliders.lsp</code> to access this function.
</dd></dl><a name = "113"><h4>Creating Controls</h4></a>
<p>You can create slider and button controls. A slider control adjusts a
floating point value in the sliders array and accessible as a
time-varying signal (a <code>SOUND</code>) or as a <code>FLONUM</code>. A button control sets a
floating point value in the sliders array to zero (0.0) or one (1.0).
The value changes when the left mouse button is pressed over the button control
and changes back when the mouse button is released.</p>
<dl>
<dt>
<code>make-slider(<a name="index910"></a><a name="index911"></a><i>name</i>,
<i>init</i>, <i>low</i>, <i>high</i>)</code> [SAL]<br>

<code>(make-slider <i>name</i> <i>init</i> <i>low</i> <i>high</i>)</code> [LISP]</dt>
<dd>Create
a slider in the most recently created control panel. (Thus, you should
populate a control panel with sliders and buttons before creating
another control panel.) Sliders have a label specified by <i>name</i>, a
STRING, an initial value specified by <i>init</i>, a FLONUM, a minimum
value specified by <i>low</i>, a FLONUM, and a maximum value specified by
<i>high</i>, a FLONUM. Sliders are added to the current panel in order from top
to bottom. You must
load <code>sliders.lsp</code> to access this function.<br><br>
<dt><code>make-button(<a name="index912"></a><a name="index913"></a><i>name</i>
[, <i>normal</i>])</code> [SAL]<br>

<code>(make-button <i>name</i> [<i>normal</i>])</code> 
[LISP]</dt>
<dd>Create a button in the most
recently created control panel. Buttons have a label specified by
<i>name</i>, a STRING, and a "normal value" specified by 0 or 1 (a
FIXNUM). If 0 is specified, the value controlled by the button is 0
when the button is released and 1 when the button is pressed. If 1 is
specified, the normal value is 1 changing to 0 when the button is
pressed. Buttons are added to the control panel in order from top to
bottom. You must
load <code>sliders.lsp</code> to access this function.
</dd></dl><a name = "114"><h4>Accessing Control Values</h4></a>
<p>Each control created by <code>make-slider</code> or <code>make-button</code> is
assigned a slider index from 10 to 999. Control changes are passed via
hidden text input from the NyquistIDE to the nyquist process, where
the values are converted to floats and stored in the slider array. You
can then access these values with either <code>slider</code>,
<code>lpslider</code>, or <code>get-slider-value</code>.</p>
<dl>
<dt>
<code>slider(<a name="index914"></a><i>number</i> [, <i>dur</i>])</code> [SAL]<br>

<code>slider(<i>name</i> [, <i>dur</i>])</code> [SAL]<br>

<code>slider(<i>panel</i>, <i>name</i> [, <i>dur</i>])</code> [SAL]<br>

<code>(slider <i>number</i> [<i>dur</i>])</code> [LISP]<br>

<code>(slider <i>name</i> [<i>dur</i>])</code> [LISP]<br>

<code>(slider <i>panel</i> <i>name</i> [<i>dur</i>])</code>
[LISP]</dt>
<dd>Create a <code>SOUND</code> that reads signal values
from the slider array. In the first form, the first parameter is the
index (a FIXNUM) of the value in the slider array. In the second form,
the slider value will be controlled by the NyquistIDE control created
by <code>make-slider</code> or <code>make-button</code> using the same <i>name</i>, a
STRING. The control must be in the most recently created panel. In the
third form, the panel named <i>panel</i> is searched for the control
named <i>name</i> to determine the value. In all cases, the optional
<i>dur</i>, a FLONUM, is used to determine the duration of the
sound. This duration is scaled by the environment in the usual way. You must
load <code>sliders.lsp</code> to access this function.<br><br>
<dt><code>lpslider(<a name="index915"></a><i>number</i> [, <i>dur</i>])</code> [SAL]<br>

<code>lpslider(<i>name</i> [, <i>dur</i>])</code> [SAL]<br>

<code>lpslider(<i>panel</i>, <i>name</i> [, <i>dur</i>])</code> [SAL] <br>

<code>(lpslider <i>number</i> [<i>dur</i>])</code> [LISP]<br>

<code>(lpslider <i>name</i> [<i>dur</i>])</code> [LISP]<br>

<code>(lpslider <i>panel</i> <i>name</i> [<i>dur</i>])</code>
[LISP]</dt>
<dd>Create a <code>SOUND</code> based on the value of
an interactive control. This function is exactly like <code>slider</code>,
except the sound is low-pass filtered to avoid sudden jumps when the
control value is adjusted. The low-pass filter cutoff is determined by
<code>*lpslider-cutoff*</code>, which is initialized to 20Hz when
<code>slider.lsp</code> is loaded. You must
load <code>sliders.lsp</code> to access this function.<br><br>
<dt><code>get-slider-value(<a name="index916"></a><i>number</i>)</code> [SAL]<br>

<code>get-slider-value(<i>name</i>)</code> [SAL]<br>

<code>get-slider-value(<i>panel</i>, <i>name</i>)</code> [SAL]<br>

<code>(get-slider-value <i>number</i>)</code> [LISP]<br>

<code>(get-slider-value <i>name</i>)</code> [LISP]<br>

<code>(get-slider-value <i>panel</i> <i>name</i>)</code>
[LISP]</dt>
<dd>Get a value (a FLONUM) stored in the 
slider array. The array is accessed directly if the parameter is
<i>number</i>, a FIXNUM. The index can be determined by searching the
most recently created control panel by <i>name</i>, a STRING, if only
<i>name</i> is given. If both <i>panel</i> and <i>name</i> are given (STRINGS),
the named panel is searched for the named control. The result is a FLONUM.
You must
load <code>sliders.lsp</code> to access this function.<br><br>
<dt><code>snd-slider(<a name="index917"></a><i>index</i>, <i>t0</i>, <i>srate</i>, <i>duration</i>)</code> [SAL]<br>

<code>(snd-slider <i>index</i> <i>t0</i> <i>srate</i> <i>duration</i>)</code> [LISP]</dt>
<dd>Create
a sound controlled by the slider named by <i>index</i> (an integer 
index into the array of sliders).
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. Normally, you would call <code>slider</code> (see above) rather than
this low-level function.
</dd></dl><a name = "115"><h4>Starting and Stopping Sounds</h4></a>
<p>All Nyquist sounds have a duration. Even the <code>slider</code> unit
generator has a duration and terminates at the end of that
duration. In most cases, you will instead want interactive functions to run
until you interactively ask them to stop. The <code>stop-on-zero</code>
function terminates when an input signal (typically a slider) goes to
zero. This can be used to terminate a complex
interatively controlled sound. For example, here is a tone that
terminates when the Stop button is pressed:
</p>
<pre>
exec make-button("Stop", 1)

function can-stop()
  play (hzosc(1000) * stop-on-zero(slider("Stop"))) ~ 100
</pre>

<p>
The stretch factor of 100 will cause this tone to play for 100
seconds. However, if the button named "Stop" is pressed, it will
change value from the "normal" value 1 to 0. When the signal goes to
zero, <code>stop-on-zero</code> will terminate. The multiplication then
immediately terminates (because anything multiplied by zero will be
zero; termination is just an efficient way to return zeros from now
on). Since the multiplication is the top-level sound being played, the
play stops.</p>

<p>Another thing you might want to do with interactive control is start
some sound. The <code>trigger</code> function computes an instance of a
behavior each time an input <code>SOUND</code> goes from zero to
greater-than-zero. This can be used, for example, to create a
sequence of sound events interactively. For example:
</p>
<pre>
exec make-button("Trigger", 0)

function trigger-me()
  play trigger(slider("Trigger", 100), pluck(c3))
</pre>

<p>
Here, a button control changes value from 0 to 1 when the button is
  pressed. This value is retrieved by the <code>slider</code> function,
  which runs for 100 seconds. When the button and hence the
  <code>slider</code> goes from 0 to 1, the behavior, <code>pluck(c3)</code> is
  instantiated. Many instances can be triggered by the button.</p>
<dl>
<dt>
<code>stop-on-zero(<a name="index918"></a><i>s</i>)</code> [SAL]<br>

<code>(stop-on-zero <i>s</i>)</code>
[LISP]</dt>
<dd>Return a <code>SOUND</code> that is identical
to <i>s</i>, a <code>SOUND</code>, except the returned sound terminates when <i>s</i>
first goes to zero. When a sound terminates, it remains at zero. A
<code>SOUND</code> multiplication terminates when either parameter terminates, so
multiplying by <code>stop-on-zero</code> is a way to terminate a sound
interactively. (See the example above.)
You must
load <code>sliders.lsp</code> to access this function.<br><br>
<dt>
<code>trigger(<a name="index919"></a><i>s</i>, <i>beh</i>)</code> [SAL]<br>

<code>(trigger <i>s</i> <i>beh</i>)</code> [LISP]</dt>
<dd>Returns a sound which is the
sum of zero or more possibly overlapping instances of the behavior <i>beh</i>.
One instance is created each time
<code>SOUND</code> <i>s</i> makes a transition from less than or equal to zero to
greater than zero. (If the first sample of <i>s</i> is greater than zero, an
instance is created immediately.) The start time of the result is the
start time of <i>s</i>, and zero samples will be generated until the
first instance of <i>beh</i>. The sample rate of the result is
<code>*sound-srate*</code>, and all instances of <i>beh</i> must have the same
<code>*sound-srate*</code> sample rate.  The behaviors (instances of <i>beh</i>)
must be (monophonic)
<code>SOUND</code>s.  The stop time of the result is the maximum stop time of
<i>s</i> and all sounds returned by instances of the behavior.  This
function is particularly designed to allow behaviors to be invoked in
real time. See the <code>trigger-me</code> function definition shown above.

<small>
An implementation note: There is no way to have <code>trigger</code> 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 <code>seq</code> 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 <code>trigger</code> in the first place.
</small>


<small>
Warning: The <i>beh</i> argument of <code>trigger</code> is converted to a
closure that captures the current environment, including any variables
in scope. The following example illustrates a problem where <i>s</i> is a local variable:

<p></p>
<pre>
(defun example (snd) (trigger snd (pluck c4)))
</pre>

<p>
or in SAL:
</p>
<pre>
function example(snd) return trigger(snd, pluck(c4))
</pre>

<p>
The problem here is that <i>snd</i> will be captured by the closure built from <code>pluck(c4)</code>. As <code>trigger</code> begins to evaluate <i>snd</i> looking for zero crossings, the samples from <i>snd</i> will be retained in memory because <i>snd</i> is retained in the closure. A solution is the following:
</p>
<pre>
(defmacro unbind (sym) `(let ((x ,sym)) (setf ,sym nil) x))
(defun example (snd) (trigger (unbind snd) (pluck c4)))
</pre>

<p>
or in SAL:
</p>
<pre>
;; unbind must be defined as above and loaded from a .lsp file
function example(snd) return trigger(unbind(snd), pluck(c4))
</pre>

<p>
In this code, <i>snd</i> is still retained by the constructed closure,
but it is set to <code>nil</code> by <code>unbind</code>, which returns the
<i>value</i> of <i>snd</i>. Thus, the only surviving reference to the
original value of <i>snd</i> is held by <code>trigger</code>, which frees
samples immediately after computing them. No samples are retained
in memory.
</p>
</small>
<br><br>
<dt><code>snd-stoponzero(<a name="index920"></a><i>s</i>)</code> [SAL]<br>

<code>(snd-stoponzero <i>s</i>)</code>
[LISP]</dt>
<dd>This function is identical to
<code>stop-on-zero</code>. You should use <code>stop-on-zero</code> instead.<br><br>
<dt><code>snd-trigger(<a name="index921"></a><i>s</i>, <i>closure</i>)</code> [SAL]<br>

<code>(snd-trigger <i>s</i> <i>closure</i>)</code> [LISP]</dt>
<dd>This is a
low-level support function for <code>trigger</code>. The <i>closure</i> takes a
starting time and returns a <code>SOUND</code>. See <code>trigger</code> above for more
details. Use <code>trigger</code> as described above and do not call this function
directly.
</dd></dl><a name = "116"><h3>Using Open Sound Control</h3></a><a name="index922"></a>
<p>Open Sound Control (OSC) is a simple protocol for communicating music
control parameters between software applications and across
networks. For more information, see <a
href="http://wwww.cnmat.berkeley.edu/OpenSoundControl"><code>http://www.cnmat.berkeley.edu/OpenSoundControl/</code></a>. The
Nyquist implementation of Open Sound Control is simple: an array of
floats can be set by OSC messages and read by Nyquist functions. That
is about all there is to it. </p>

<p>The <code>slider</code> and
<code>get-slider-value</code> functions, described above, can be used to
access these values within Nyquist. Each of these functions can take a
slider array index to specify which value to use. Since
<code>make-slider</code> allocates slider indices starting at 10, it is
recommended that you control sliders 0 through 9 via OSC. If you
change a slider array value via OSC that is already controlled by a
graphical slider in the NyquistIDE, the graphical slider will not be
updated or synchronized to the OSC value. (And there is no current way
to send OSC command to the NyquistIDE.)</p>

<p>Note: Open Sound Control must be enabled by calling
<code>osc-enable(t)</code>. If this fails under Windows, see the
installation instructions in <code>sys/win/README.txt</code> regarding
<code>SystemRoot</code>.</p>
<dl>
<dt>
<code>osc-enable(<a name="index923"></a><a name="index924"></a><a name="index925"></a><i>flag</i>)</code> [SAL]<br>

<code>(osc-enable <i>flag</i>)</code> [LISP]</dt>
<dd>Enable or disable Open Sound Control.
(See Section <a href = "#116">Using Open Sound Control</a>.)
Enabling creates a socket and a service that listens for UDP 
packets on port 7770. Currently, only two messages are accepted 
by Nyquist. The first is of the form <code>/slider</code>
with an integer index and a floating point value. These set internal 
slider values accessed by the <code>slider</code> and
<code>get-slider-value</code> functions. The second is of the form
<code>/wii/orientation</code> with 
two floating point values. This message is a special case to 
support the DarwiinRemoteOsc<a name="index926"></a> program
 which can relay data from
a Nintendo<a name="index927"></a> WiiMote<a name="index928"></a>
 device to Nyquist via OSC. The two orientation
values control sliders 0 and 1.
Disabling terminates the service (polling for messages) 
and closes the socket. The <i>previous</i> state of enablement
is returned, e.g. if OSC is enabled and <i>flag</i> is <i>nil</i>, 
OSC is disabled and <code>T</code> (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 <code>OSC</code>. 
Otherwise, the function 
exists but always returns the symbol <code>DISABLED</code>. 
<i>Warning:</i> 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.
</dd></dl><a name = "117"><h4>Sending Open Sound Control Messages</h4></a>
<p>A variety of programs support OSC. The only OSC message interpreted by
Nyquist has an address of <code>/slider</code>, and two parameters: an
integer slider number and a float value, nominally from 0.0 to 1.0.</p>
<a name = "118"><h4>Python3 OSC Interface Demo</h4></a>
<p>In <code>nyquist/demos/osc</code> are two programs that demonstrate
controlling Nyquist sounds with Python in real time. Open
<code>nyquist/demos/osc/getosc.sal</code> in the NyquistIDE and read the
comments. There are several functions you can run or play while
executing the Python program <code>nyquist/demos/osc/nyquistosc.py</code>
from a command line (terminal) window.</p>
<a name = "119"><h4>Test Programs in C</h4></a> 
<p>Two small programs are included in the Nyquist distribution for
sending OSC messages. (Both can be found in the same directory as the
nyquist executable.) The first one, <code>osc-test-client</code> sends a
sequence of messages that just cause slider 0 to ramp slowly up and
down. If you run this on a command line, you can use "?" or "h" to get
help information. There is an interactive mode that lets you send each
OSC message by typing RETURN.</p>
<a name = "120"><h4>The ser-to-osc Program</h4></a>
<p>The second program is <code>ser-to-osc</code>, a program that reads serial input (for example from a PIC-based microcontroller) and sends OSC messages. Run this command-line program from a shell (a terminal window under OS X or Linux; use the CMD program under Windows). You must name the serial input device on the command line, e.g. under OS X, you might run:
</p>
<pre>
./ser-to-osc /dev/tty.usbserial-0000103D
</pre>

<p>
(Note that the program name is preceded by &ldquo;<code>./</code>". This tells the shell exactly where to find the executable program in case the current directory is not on the search path for executable programs.)
Under Windows, you might run:
</p>
<pre>
ser-to-osc com4
</pre>

<p>
(Note that you do not type &ldquo;<code>./</code>&rdquo; in front of a windows program.)</p>

<p>To use <code>ser-to-osc</code>, you will have to find the serial device. On the Macintosh and Linux, try the following:
</p>
<pre>
ls /dev/*usb*
</pre>

<p>
This will list all serial devices with &ldquo;usb&rdquo; in their names. Probably, one will be a name similar to <code>/dev/tty.usbserial-0000103D</code>. The <code>ser-to-osc</code> program will echo data that it receives, so you should know if things are working correctly.</p>

<p>Under Windows, open Control Panel from the Start menu, and open the System control panel. Select the Hardware tab and click the Device Manager button. Look in the device list under Ports (COM &amp; LPT). When you plug in your serial or USB device, you should see a new entry appear, e.g. <code>COM4</code>. This is the device name you need.</p>

<p>The format for the serial input is: any non-whitespace character(s), a slider number, a slider value, and a newline (control-j or ASCII 0x0A). These fields need to be separated by tabs or spaces. An optional carriage return (control-m or ASCII 0x0D) preceding the ASCII 0x0A is ignored. The slider number should be in decimal, and theh slider value is a decimal number from 0 to 255. This is scaled to the range 0.0 to 1.0 (so an input of 255 translates to 1.0).</p>

<p>There is a simple test program in <code>nyquist/lib/osc/osc-test.lsp</code> you can run to try out control with Open Sound Control. There are two examples in that file. One uses <code>snd-slider</code> to control the frequency of an oscillator. The other uses <code>get-slider-value</code> to control the pitch of grains in a granular synthesis process.</p>
<hr>
<a href = "part9.html">Previous Section</a> | <a href = "part11.html">Next Section</a> | <a href = "title.html#toc">Table of Contents</a> | <a href = "indx.html">Index</a> | <a href = "title.html">Title Page</a>
</body></html>