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.