thinman@netcom.com (Lance Norskog) (04/22/91)
- 50 -
- 51 -
9. _5_D__L_i_b_r_a_r_y
Every deck includes a large library of pre-defined trees
which do a variety of basic operations: 2D bitmaps, text,
sample objects, colors, & textures, etc. The library trees
are assigned a pre-defined block of IDs. 5D program and
tree authors may always assume these classes are available,
as well as the primitive class library. The following trees
are from the core tree library, and are a sample of simple
5D tree composition.
9.0.1 _F_l_o_a_t_i_n_g__P_i_x_m_a_p_
The Floating Pixmap is a 2D pixmap which should not be sub-
or super-sampled, and instead should only be seen at a fixed
size and place. It sets its 2D bounding box to force this
to occur. This might be used for system status messages.
( class
ID='Floating Pixmap'
super=Painted
( method
name=Float
( template
(ID=Pix type=Pixmap)
(ID=Frame type=Drawable)
(ID=Place type=Box)
)
( rewrite
type=Void
/ Set screen box to force placement on screen
( property
name=screenbox
value=Place
)
/ If the sizes of the pixmap and the frame are
/ mis-matched, an exception will be raised,
/ so don't bother checking them here.
Apply(Pix, Frame)
)
)
)
Notes:
+o Obviously, the Floating Pixmap would only be invoked
during a screen refresh. As a defined tree, the
Floating Pixmap inherits the evaluation frequency
property at invocation time. Setting the evaluation
frequency would make no sense.
- 52 -
+o The core library is assumed to be pre-loaded in the
deck, and its members are referred to by standardized
code numbers. However, since Floating Pixmaps can be
described in 5D, they belong in the core library, not
the language specification.
+o A fixed-size pixmap will be legible anywhere on the
screen. Since its placement is a 2D graphics decision,
that is left up to the invoker.
9.0.2 _S_t_e_r_e_o__F_l_o_a_t_i_n_g__P_i_x_m_a_p
The Stereo Floating Pixmap object uses two instances of the
Floating Pixmap object to create a stereo image in a fixed
size and place on the screen. Random sub- or super-sampling
the left and right frames of a stereo image would give your
visual system severe grief, so the Floating Pixmap library
routine is the appropriate choice. The stereo input pixmaps
may be produced with a ray-tracer or stereo video pairs.
( class
ID='Stereo Floating Pixmap'
super='Floating Pixmap'
( method
name=Float
( template
(ID=PixLeft type=Pixmap)
(ID=PixRight type=Pixmap)
(ID=Frame type=Drawable)
(ID=Place type=Box)
)
( rewrite
type=Void
/ Set screen box, which forces placement on screen
( property
name=screenbox
value=Place
)
/ Type of cond is VOID, so can't do cond(left, pix, pix)
cond(LeftEye,
Apply(PixLeft, Frame),
Apply(PixRight, Frame))
)
)
)
Notes:
+o The Stereo Floating Pixmap needs two input bitmaps, and
the size and placement to use for the maps. It uses
- 53 -
the intrinsic boolean variable left_eye to decide
whether to invoke the Floating Pixmap object on the
left or right eye image. Again, the object should only
be invoked during a retrace event.
+o With video-in-a-window, you could do this with live
stereo pairs.
9.0.3 _S_o_u_n_d__s_a_m_p_l_e__a_t_t_a_c_h_e_d__t_o__o_b_j_e_c_t
This class definition plays a continuously cycled sound
sample or synthesizer patch. It adjusts the volume to your
distance from it. This is usually part of a larger object.
( class
ID='Positioned Sound'
super=SoundChannel
( property
name=Volume
(
type=Number
distance((property name=Position type=Point),
EyePoint type=Point)
)
)
( property
name=execute
value=True
)
)
Notes:
+o The actual format of sound samples and instrument
definitions is very deck-dependent. Low-end PC sound
boards have a bunch of oscillators. They allow you to
set a bunch of registers for instrument X out of 10,
and then leave it alone. Higher-end gear requires
generating sound samples on the fly and feeding them to
DMA channels. The very desirable ability to have
high-level definitions of several simultaneous sound
channels making iconic sounds (a FWOOOSH when you grab
something, a TINK when you hit something metal) is thus
much easier on PC's than workstations. On the other
hand, we need to go to more sophisticated hardware to
get stereo or 3D sound placement. There has been work
on doing 2D placement with Midi. [Computer Music
Journal, Feb. 1991, pp. 59] Midi I/O is available for
- 54 -
all desktop PC's; this is an obvious direction for
research.
9.0.4 _F_l_i_p_-_F_l_o_p
The flip-flop uses feedback to create a simple 1-bit memory
of past inputs.
9.0.5 _S_o_f_t_w_a_r_e__P_h_a_s_e_-_L_o_c_k_e_d__L_o_o_p
The phase-locked loop is a key circuit used in interfacing
analog and digital circuitry. The Synthesis operating
system [ref: Columbia University Technical Report] uses a
software implementation of a PLL as its scheduler. Software
PLLs provide a simple, fast system that responds to external
rhythms. A software PLL can interface real-time output to a
user's work rhythm, and gives a powerful tool for making the
user interface controlled by the user's time sense.
It should be possible to interface the MIDI ports with the
software PLL to do interesting drum machine stuff.
9.0.6 _S_a_m_p_l_e__&__H_o_l_d
Sample and hold an input value. Whenever the input switch
is true, sample the value. Whenever the input value
changes, sample the value. Output the held value on demand.
( class
ID='Sample and Hold'
super=Number
super=Boolean
( data
/ secret data sampled & held
ID=$Sample
type=Number
)
- 55 -
( method
/ grab data when boolean is true,
/ and when number changes while boolean is true
( template
name=Sample
type=Number
( name=switch type=Boolean )
( name=input type=Number)
)
( rewrite
(cond
(and
(switch)
(or
(inputChange(switch))
(inputChange(value))
)
)
(set($Sample, input))
() / else do nothing
)
)
)
( method
( template
name=Value
)
( rewrite
type=Number
set(output, $Sample)
)
)
)
The inputChange boolean operation is extremely useful for
asynchronous operations such as Sample&Hold. This class
does not operate continuously, of course, but instead is
driven by its inherited clock.
- 56 -
10. _5_D__S_a_m_p_l_e__P_r_o_g_r_a_m_s
The following program is in severely abridged pidgin 5D for
clarity. It dates back to before the addition of objects to
5D, but does give the flavor of 5D programming.
10.1 _S_o_u_n_d__m_i_x_e_r
This is a sample 5D program which implements a simple
digital sound mixer. It allows the user to record and play
back 2 sound samples.
top of world / visible universe
(
/ built-in boolean switch1 record channel 1
/ built-in boolean switch2 record channel 2
/ built-in boolean switch3 playback channel 1
/ built-in boolean switch4 playback channel 2
/ built-in boolean switch5 playback both channels
call [
property: evaluate when input changes
evaluate [
property: evaluate never
dataset sample1 [
property: sound sample, 10 seconds long.
]
dataset sample2 [
property: sound sample, 10 seconds long.
]
]
evalute [
property: evaluate in order / concurrency control
conditional [
switch1
assign [ / record sample 1
sample1
microphone
]
null
]
conditional [
switch2
assign [ / play sample 1
sound channel 1
sample1
]
null
]
conditional [
switch3
assign [ / record sample 2
- 57 -
sample2
microphone
]
null
]
conditional [
switch4
assign [ / play sample 2
sound channel 2
sample2
]
null
]
conditional [
switch5
evaluate [ / mix both samples
property: evaluate simultaneously
assign [
sound channel 1
sample1
]
assign [
sound channel 2
sample2
]
]
null / empty function
]
]
]
]
This example world has no graphics. Five switches are used,
one for each possible operation. The property of sequenced
evaluation of sub-trees is used to provide concurrency
control; only one operation at a time may be used. A tree
which is never evaluated is used as a data holder for the
two sound samples. The following version uses nested
conditionals:
- 58 -
top of world
[
/ built-in boolean switch1; record channel 1
/ built-in boolean switch2; record channel 2
/ built-in boolean switch3; playback channel 1
/ built-in boolean switch4; playback channel 2
/ built-in boolean switch5; playback both channels
evaluate all [
property: evaluate when input changes
evaluate [
property: evaluate never
dataset sample1 [
property: sound sample, 10 seconds long.
]
dataset sample2 [
property: sound sample, 10 seconds long.
]
]
conditional [
property: evaluate in order/ concurrency control
switch1
assign [ / record sample 1
sample1
microphone
]
conditional [
switch2
assign [ / play sample 1
sound channel 1
sample1
]
conditional [
switch3
assign [ / record sample 2
sample2
microphone
]
conditional [
switch4
assign [ / play sample 2
sound channel 2
sample2
]
conditional [
switch5
evaluate [ / mix both samples
property: evaluate simultaneously
assign [
sound channel 1
sample1
]
- 59 -
assign [
sound channel 2
sample2
]
]
null / empty tree
]
]
]
]
]
]
]
Note that the version with nested conditionals still uses
the sequential evaluation property. Multi-processor systems
can evaluate all 3 branches of a conditional expression
concurrently, being careful that the false leg of the then-
else pair leaves no permanent side effects.