Annotation of researchv10dc/vol2/music/music.ms, revision 1.1.1.1

1.1       root        1: .so ../ADM/mac
                      2: .XX music 477 "Computer Music Under the 10th Edition UNIX System"
                      3: .nr dP 1
                      4: .nr dV 1.5p
                      5: .de FG
                      6: .ce
                      7: Figure \\$1. \\$2
                      8: .SP .5
                      9: ..
                     10: .TL
                     11: Computer Music under the 10th Edition
                     12: .UX
                     13: System
                     14: .AU
                     15: T. J. Killian
                     16: .AI
                     17: .MH
                     18: .AB
                     19: We describe an evolving computer music system that draws upon many of
                     20: the novel facilities in the Research
                     21: .UX
                     22: system, as well as the standard repertoire of
                     23: familiar tools.
                     24: The Teletype 5620 bitmap display serves both as the user's
                     25: terminal and real-time controller.  The
                     26: .I mux
                     27: window system is used to download a
                     28: .SM MIDI
                     29: interface driver that
                     30: services other windows (by direct code sharing) and
                     31: host processes (which write on the driver's control stream).
                     32: We presently support several
                     33: .SM MIDI
                     34: devices: the Yamaha
                     35: .SM DX7 ,
                     36: .SM TX816 ,
                     37: .SM FB01 ,
                     38: and
                     39: .SM SPX90 .
                     40: .PP
                     41: Window programs include a piano-roll-style score facility and a
                     42: virtual keyboard.  Host programs include a music compiler,
                     43: .I m ,
                     44: that converts an
                     45: .SM ASCII
                     46: score notation into
                     47: .SM MIDI
                     48: events;
                     49: it is based on
                     50: .I lex
                     51: and
                     52: .I yacc,
                     53: making it very easy to modify in response to user needs.
                     54: There are also several filters that perform simple transformations
                     55: (e.g., time and pitch translation) on
                     56: .SM MIDI
                     57: files.  The latter are
                     58: .SM ASCII ,
                     59: so that text filters (especially
                     60: .I awk ,
                     61: .I sed ,
                     62: and
                     63: .I sort)
                     64: can be used for sound manipulation.
                     65: .AE
                     66: .2C
                     67: .NH
                     68: Introduction \- the
                     69: .SM MIDI
                     70: standard.
                     71: .PP
                     72: Computer-music applications have taken off in recent years, largely
                     73: due to the introduction of the
                     74: .SM MIDI
                     75: (Musical Instrument Digital Interface)
                     76: standard |reference(midi standard).
                     77: .SM MIDI
                     78: has made it possible, with very modest hardware,
                     79: to interface a computer to synthesizers and other equipment, with broad
                     80: compatibility among manufacturers.
                     81: A full discussion of the
                     82: .SM MIDI
                     83: standard is out of place here; we will simply
                     84: give some of its essential characteristics.
                     85: .PP
                     86: .SM MIDI
                     87: uses an asynchronous serial protocol at 31.25 Kbaud to transmit \%8-bit
                     88: data bytes over a \%5-mA current loop (thus, to the programmer, it looks like an
                     89: .SM RS232
                     90: line).  Data flow on any given cable is unidirectional.
                     91: .I Status
                     92: and
                     93: .I data
                     94: bytes are distinguished by the high-order bit being set or clear, respectively.
                     95: A status byte encodes a
                     96: .I function,
                     97: and (usually) a
                     98: .SM MIDI
                     99: .I "channel number"
                    100: in the range 1 to 16.
                    101: Bytes are grouped logically into
                    102: .I messages
                    103: that consist of a status byte and (except as noted below) 1 or 2 data bytes.
                    104: For example, the \%3-byte message (\c
                    105: .CW 0x90,\ 0x3c,\ 0x40 )
                    106: says, ``On channel 1,
                    107: turn on note number 60 (middle C) with a volume of 64 (mf).''
                    108: In most cases the size of a message is determined by its status byte, so
                    109: the latter may be omitted if it is the same as the status byte most
                    110: recently transmitted.
                    111: .PP
                    112: The messages most commonly used in performance, such as those that
                    113: select a synthesizer's pre-programmed voices, or
                    114: turn notes on and off, are fixed by the
                    115: .SM MIDI
                    116: standard.  An escape mechanism
                    117: is provided to allow control sequences
                    118: peculiar to the equipment of a given manufacturer.  This
                    119: .I "system exclusive"
                    120: message has the form (\c
                    121: .CW 0xf0,
                    122: .I "ident, data,"
                    123: \&...,
                    124: .CW 0xf7 ");"
                    125: .I ident
                    126: is a manufacturer's code assigned by the standards committee; the
                    127: .I data
                    128: is arbitrary (and can be of any length).
                    129: .PP
                    130: A device typically has three
                    131: .SM MIDI
                    132: sockets, labeled
                    133: .SM IN ,
                    134: .SM OUT ,
                    135: and
                    136: .SM THRU .
                    137: Messages received at the
                    138: .SM IN
                    139: socket are acted upon in real time if the device's
                    140: .SM MIDI
                    141: channel number matches that of the message.
                    142: In any case, the data are buffered directly to the
                    143: .SM THRU
                    144: socket to allow daisy-chaining.
                    145: An instrument such as a
                    146: keyboard may send an independent stream of messages to its
                    147: .SM OUT
                    148: socket.  A typical
                    149: .SM MIDI
                    150: performance consists of (mostly) note-on and note-off messages
                    151: emitted by the ``performer'' with proper timing.
                    152: .PP
                    153: There are several problems with
                    154: .SM MIDI ,
                    155: the most serious of which
                    156: is probably its limited bandwidth.  Chords consisting of, say, ten or twelve
                    157: notes become noticeably arpeggiated, and changes in timbre that might
                    158: require a long system-exclusive message cannot be fitted into fast passages.
                    159: Lack of flow control makes this problem even worse.
                    160: .SM MIDI
                    161: is also tightly bound to the twelve-tone Western scale; it is sometimes possible
                    162: to work around this, again at the expense of bandwidth.
                    163: .NH
                    164: The
                    165: .SM MIDI
                    166: device driver.
                    167: .PP
                    168: Mark Kahrs and I built a
                    169: .SM MIDI
                    170: interface board that plugs into the parallel
                    171: .SM I/O
                    172: port of the Teletype 5620 bitmap terminal |reference(kahrs 5620).
                    173: The 5620 has a \%32-bit
                    174: microprocessor with 1 Mb of memory, and runs the
                    175: .I mux
                    176: window system |reference(blit bstj).
                    177: Using the 5620 as the real-time controller, we are able
                    178: to place a synthesizer under the control of a host computer
                    179: (in this case, a
                    180: .SM VAX
                    181: 750), without a large amount of systems programming.
                    182: .PP
                    183: The
                    184: .SM MIDI
                    185: device driver (\c
                    186: .I midiblt )
                    187: is down-loaded into a
                    188: .I mux
                    189: window, where it takes over interrupt handling on the parallel
                    190: .SM I/O
                    191: port.  Three types of interrupts are handled:
                    192: .SM UART
                    193: transmitter and receiver ready,
                    194: and a \%5-msec clock.
                    195: .SM MIDI
                    196: data are organized into three queues.  Incoming messages are time-stamped
                    197: and placed on the
                    198: .I receiver
                    199: queue, where they are available to other software.  At clock interrupt, the
                    200: .I scheduler
                    201: queue is examined for messages with time less than or equal to the current
                    202: time; such messages are moved from the scheduler queue to the
                    203: .I transmitter
                    204: queue, from which they are sent to the hardware as quickly as possible.
                    205: .PP
                    206: There is a sharp division between routines that control the
                    207: .SM UART
                    208: directly
                    209: (and handle single characters)
                    210: and those that manipulate
                    211: .SM MIDI
                    212: messages.  For example, the
                    213: .SM MIDI
                    214: transmitter is
                    215: a finite-state machine that understands things like elided status bytes; it
                    216: is called by a lower-level routine and produces the next byte to be sent by
                    217: the
                    218: .SM UART .
                    219: .PP
                    220: Routines that empty the receiver queue and fill the scheduler queue are
                    221: available from outside the driver.
                    222: .I Midiblt
                    223: places their entry points in a name table maintained by
                    224: .I mux ;
                    225: since there is no memory mapping in the 5620, they are immediately available
                    226: to other programs down-loaded in the terminal.
                    227: This code-sharing mechanism is used to implement a virtual-keyboard program,
                    228: .I jx7 ,
                    229: which provides the functionality of a one-fingered mouse-pianist, with slide
                    230: controls for volume, vibrato, pitch bend, etc.
                    231: .NH
                    232: Communication with the host.
                    233: .PP
                    234: Host communication takes place via the
                    235: .I streams
                    236: mechanism |reference(latest streams).  Briefly, each
                    237: window is associated with a host control stream managed by
                    238: .I mux ;
                    239: when a program down-loaded in the terminal does a read or write,
                    240: .I mux
                    241: performs the appropriate operation on the stream associated with the window.
                    242: The program at the other end of the stream can be the shell
                    243: (this is how multiple virtual terminals are implemented), or a special-purpose
                    244: program (as in the case of a text editor).
                    245: .I Midiblt
                    246: falls into the second category.  It mounts
                    247: its stream under the name \&\c
                    248: .CW .MIDI
                    249: in the
                    250: user's home directory, in effect
                    251: creating a character-special file for the
                    252: .SM MIDI
                    253: driver.  The terminal side of
                    254: .I midiblt
                    255: reads characters as they appear from the host, assembles them into
                    256: .SM MIDI
                    257: messages, and places the messages on the scheduler queue.  (The host side of
                    258: .I midiblt
                    259: does not look at this data; error correction and flow control are performed by
                    260: .I mux ).
                    261: .PP
                    262: We have followed a time-honored
                    263: .UX
                    264: tradition by formatting the
                    265: .SM MIDI
                    266: file in
                    267: .SM ASCII .
                    268: Such a file consists of a series of lines, one per
                    269: .SM MIDI
                    270: message.
                    271: Each line is a sequence of blank-separated decimal numbers, viz.: event time
                    272: (msec), status byte, and data.  (Backslash-newline can be used
                    273: to break long system-exclusive messages.)
                    274: In this form, the entire panoply of
                    275: .UX
                    276: text-processing tools can be
                    277: brought to bear in rough-and-ready fashion.
                    278: .PP
                    279: On the other hand, this format is not well
                    280: suited for direct transmission to the 5620, since bandwidth is at a premium.
                    281: The program
                    282: .I midi ,
                    283: which compresses the data, is used; it replaces (and has similar semantics to)
                    284: .CW "cat >.MIDI" .
                    285: In addition,
                    286: .I midi
                    287: attaches itself to the
                    288: .I "process group"
                    289: associated with the \&\c
                    290: .CW .MIDI
                    291: stream.  This allows the
                    292: .I midiblt
                    293: window to send signals to the
                    294: .I midi
                    295: process so that, e.g., if the user does a reset from the
                    296: .I midiblt
                    297: menu, there is proper coordination between the host and the driver.
                    298: .PP
                    299: The
                    300: .CW "midi | midiblt"
                    301: pattern is repeated in the programs
                    302: .I score
                    303: and
                    304: .I scoreblt ,
                    305: which produce a pitch vs. time graph.
                    306: .I Scoreblt
                    307: manages a terminal window and draws the display.  Through the code-sharing
                    308: mechanism mentioned earlier, it has access to
                    309: .I thinkblt
                    310: which drives a HP ThinkJet dot-matrix printer.
                    311: .NH
                    312: Synthesizer control.
                    313: .PP
                    314: The system described was first used to run a Yamaha
                    315: .SM DX7
                    316: and, later, a
                    317: .SM TX816 .
                    318: Both produce sound via
                    319: .SM FM
                    320: synthesis |reference(chowning), a voice being described
                    321: by around 100 (digital) parameters, all settable by system-exclusive
                    322: .SM MIDI
                    323: messages.  The
                    324: .SM DX7
                    325: has internal memory for 32 pre-loaded voices that can be
                    326: selected by number (via the
                    327: .SM MIDI
                    328: .I "program change"
                    329: message).  It is a keyboard instrument with additional controls for
                    330: editing voice parameters (the current voice, whether internal or downloaded,
                    331: is always copied into an editing buffer).
                    332: Although the
                    333: .SM DX7
                    334: is limited to playing in one voice at a time,
                    335: up to 16 simultaneous notes can be produced.  The
                    336: .SM TX816
                    337: is a rack-mounted
                    338: unit consisting of eight
                    339: .SM TF1 "'s."
                    340: Each
                    341: .SM TF1
                    342: is essentially a
                    343: .SM DX7
                    344: without keyboard, and
                    345: can be set to a different
                    346: .SM MIDI
                    347: channel, so that
                    348: orchestral and multi-track effects are possible.
                    349: .PP
                    350: A number of C programs are used for synthesizer configuration.
                    351: .I Txchan
                    352: assigns channel numbers to the
                    353: .SM TF1 "'s."
                    354: .I Mecho
                    355: is used to send ``constant'' data (such as to select an internal voice, or
                    356: alter single parameters of a voice).
                    357: .I Dxvoice
                    358: downloads voice data from a library file on the host.  Figure 1 is an example
                    359: of a shell script that sets up the
                    360: .SM TX816
                    361: with five instruments, one of which
                    362: (the harpsichord) uses two
                    363: .SM TF1 "'s"
                    364: in parallel.  The violin voice needs to be
                    365: downloaded; the rest are already stored in the proper
                    366: .SM TF1 "'s"
                    367: (they came from the factory this way).
                    368: Percent signs delimit comments to
                    369: .I mecho .
                    370: .1C
                    371: .KF top
                    372: .P1
                    373: txchan 1 1 3 4 5 6 7 8
                    374: mecho  init \e
                    375:        prog    -c1 28          % harpsichord chan 1    % \e
                    376:                -c4 3           % reeds chan 4          % \e
                    377:                -c6 24          % flute chan 6          % \e
                    378:                -c8 3           % bass pipes chan 8     % \e
                    379:        dx      -c8 p144 24     % move up an octave     % \e
                    380:        parm    -c4 p4 127      % foot control reeds    % \e
                    381:                -c6 p2 127      % breath control flute  % \e
                    382:                -c8 p4 127      % foot control pipes    %
                    383: dxvoice        -c3 -v2 tx816.8         # solo violin chan 3
                    384: .P2
                    385: .FG 1 "Setting up the TX816"
                    386: .KE
                    387: .2C
                    388: .PP
                    389: This scheme is complete in that it allows access to any
                    390: .SM MIDI
                    391: or
                    392: .SM DX
                    393: parameter,
                    394: but it is not altogether satisfactory.  The user must know, for example, that
                    395: voice 3 is ``reeds'' in the fourth unit, but ``bass pipes'' in the eighth.
                    396: Simply assigning names to numbered parameters does not reduce the complexity,
                    397: however.  Ideally, one would like an interactive ``orchestration editor''
                    398: supported by a large database.
                    399: .1C
                    400: .KF bottom
                    401: .P1
                    402: main()
                    403: {
                    404:        int c, x, y, z, magic = 13, size = 64;
                    405:        int mask = 2*size-1;
                    406:        for (c = z = 0; c <= mask; c++, z += magic)
                    407:                for (newfile(), y=0; y < size; y++)
                    408:                        if ((x = (y ^ z) & mask) < size)
                    409:                                play((x+y), (x-y));
                    410: }
                    411: .P2
                    412: .FG 2 "Munching squares"
                    413: .KE
                    414: .2C
                    415: .NH
                    416: Musical examples in C and the shell.
                    417: .PP
                    418: The first piece to be played on our system was written by Cynthia P. Killian
                    419: using a combination of C and the Bourne shell.  The composer took
                    420: raw material produced by the ``munching squares'' algorithm and manipulated
                    421: it by splicing and dubbing techniques.  Figure 2 shows the heart of the algorithm.
                    422: .I X
                    423: and
                    424: .I y
                    425: trace out short diagonal segments, which are rotated by 45 degrees and passed to
                    426: .I play .
                    427: The resulting vertical coordinate is mapped onto a tone row, and the length of
                    428: the segment (as determined by a sequence of points at the same height) determines
                    429: the length of time the tone is held.
                    430: .I Newfile
                    431: breaks the output into separate small files (\c
                    432: .CW smunch.\fI?? )
                    433: for convenience.  The
                    434: latter are then processed by shell scripts like that shown in Figure 3.
                    435: The unfamiliar commands in the script are either shell scripts or trivial C
                    436: programs.
                    437: .I Sed
                    438: and
                    439: .I "sort\ \-n"
                    440: form the basis for cutting and pasting.  Operators that do a lot of arithmetic
                    441: (e.g,
                    442: .I retro ,
                    443: which time-reverses its input) are written in C.  The shell syntax for
                    444: operator precedence and the semantics of the
                    445: .UX
                    446: filter are extremely
                    447: well matched to this application.
                    448: .1C
                    449: .KF
                    450: .P1
                    451: (divider <smunch.06 3 4; divider <smunch.07 1 2
                    452:  divider <smunch.07 1 2 |
                    453:   invert 0 1120 0 | retro) | ttrans 0 280 >tmp$$
                    454: (cat tmp$$
                    455:  divider <smunch.08 7 8) | ttrans `endtime <tmp$$` -1260
                    456: rm tmp$$
                    457: .P2
                    458: .FG 3 "Shell script for processing munching squares"
                    459: .KE
                    460: .KF bottom
                    461: .P1
                    462: /* Inventio 4 (BWV 775) */
                    463: 8 = 120                /* tempo: 120 eighth notes/min  */
                    464: 3 / 8          /* time signature               */
                    465: {
                    466: treble : 1     <      6(16)         | 6(16)         >
                    467:                | F60: d3 e f g a b@ | c# b@ a g f e |
                    468: bass : 1       <      4.            | 4.            >
                    469:                | F60: r             | r             |
                    470: 
                    471: treble < 3(8)          | 3(8)          | 6(16)        >
                    472:        | f    a   d4   | g3    c4# e   | d e f g a b@ |
                    473: bass   < 6(16)         | 6(16)         | 3(8)         >
                    474:        | d2 e f g a b@ | c# b@ a g f e | f   a   d3   |
                    475: \&...
                    476: }
                    477: .P2
                    478: .FG 4 "The beginning of a Bach invention"
                    479: .KE
                    480: .2C
                    481: .NH
                    482: The M language.
                    483: .PP
                    484: The need for a closer tie with standard musical notation led to the development
                    485: of the M language.  We will try to give a feel for the language with a short
                    486: example shown in Figure 4.
                    487: .PP
                    488: An M file consists of ``front matter'' followed by text enclosed
                    489: in matching curly braces.  The comment convention is similar to C's,
                    490: except that comments nest.
                    491: The music is divided into
                    492: .I lines
                    493: formed by a
                    494: .I "voice name" ,
                    495: an optional colon and
                    496: .SM MIDI
                    497: channel number, a
                    498: .I "rhythm list" ,
                    499: and corresponding
                    500: .I "note list" .
                    501: Voice names are arbitrary alphanumeric strings.
                    502: Within rhythm and note lists,
                    503: measures are delimited by barlines.
                    504: A rhythm list consists of
                    505: .I "time values"
                    506: (\c
                    507: .CW \%1 "\&\ =\ whole note,"
                    508: .CW \%2 "\&\ =\ half note,"
                    509: .CW \%4 "\&\ =\ quarter note,"
                    510: .CW \%4. "\&\ =\ dotted quarter note,"
                    511: etc.) and
                    512: .I rests,
                    513: possibly with repeated groups (\c
                    514: .CW "3(16 16r)"
                    515: means
                    516: .\".fp 9 MU Musicpi
                    517: .\"\f(MU\N'140'\fP\ \f(MU\N'24'\fP
                    518: .\"\f(MU\N'140'\fP\ \f(MU\N'24'\fP
                    519: .\"\f(MU\N'140'\fP\ \f(MU\N'24'\fP).
                    520: .fp 8 MU Sonata
                    521: \f(MU\N'120'\fP\ \f(MU\N'197'\fP
                    522: \f(MU\N'120'\fP\ \f(MU\N'197'\fP
                    523: \f(MU\N'120'\fP\ \f(MU\N'197'\fP ).
                    524: A note list consists of
                    525: .I notes ,
                    526: .I rests ,
                    527: and
                    528: .I modifiers .
                    529: Notes specify
                    530: .I "pitch class"
                    531: and, optionally,
                    532: .I "octave number" .
                    533: Pitch class is indicated in standard letter notation, with accidentals
                    534: .CW # ,
                    535: .CW @
                    536: (flat), and
                    537: .CW =
                    538: (natural).  The octave is given by a number appearing
                    539: after the letter name, e.g.,
                    540: .CW c3
                    541: is middle c, and
                    542: .CW c3# ,
                    543: .CW c#3
                    544: are a half-tone above.
                    545: The octave number changes between b and c, so a half-tone below middle c is
                    546: .CW b2 .
                    547: A missing octave number defaults to that of the previous note in the same voice.
                    548: Rests have time value only and are indicated by
                    549: .CW r .
                    550: .PP
                    551: Modifiers are used to set ``environmental'' parameters; in the example,
                    552: the modifier
                    553: .CW F60
                    554: specifies a ``key force'' (volume) of 60 units.
                    555: .PP
                    556: Not shown in the example are notations for ties and more complicated rhythms.
                    557: Ties map particularly easily onto
                    558: .SM MIDI
                    559: events.  Observe that a note usually
                    560: generates two
                    561: .SM MIDI
                    562: events, note-on and note-off.  A note with a tie going out
                    563: (e.g.,
                    564: .CW \%c- "),"
                    565: simply loses its note-off event, and one with a tie coming in
                    566: (e.g.,
                    567: .CW _c ")"
                    568: loses its note-on event.
                    569: Time values may contain multiplicative expressions, e.g.,
                    570: .CW 3(3*4)
                    571: is a triplet to a quarter note.
                    572: Finally, values that are inconvenient to
                    573: generate otherwise can be specified with numerator and denominator, e.g.,
                    574: .CW 9/17 .
                    575: .PP
                    576: Also not shown in the example are possibilities for grouping in the
                    577: note list.  Parentheses group a
                    578: .I sequence ,
                    579: and square brackets group a
                    580: .I chord .
                    581: E.g., all of the notes in
                    582: .CW "[c\ e\ g]"
                    583: are sounded simultaneously, and
                    584: groupings may be nested, so that
                    585: .CW "[(c\ d\ c) (e\ g\ e) (g\ b\ g)]"
                    586: has three
                    587: sequences running in parallel to make a \%I-V-I progression.
                    588: .PP
                    589: To facilitate machine generation of M code, an alternative rhythm
                    590: notation is allowed: the rhythm list can be omitted, and time values prefixed
                    591: to the corresponding notes.  This is readable to humans, but less convenient
                    592: for keyboard input (see below).
                    593: .PP
                    594: M is based on
                    595: .I lex
                    596: and
                    597: .I yacc ,
                    598: and its continuing development depends heavily on them.
                    599: M is intended to be used by musicians who are not computer scientists, and
                    600: who can't always pass on the merits of a feature without testing it.  Hence
                    601: the ability to experiment is most important.
                    602: .I Lex
                    603: in particular has been justly criticized on performance grounds, given that
                    604: lexical analyzers are fairly easy to write by hand.  But this is the case
                    605: only for a static language, and M is still changing rapidly, particularly in
                    606: the area of dynamics control.
                    607: .PP
                    608: M produces a
                    609: .SM MIDI
                    610: file on its standard output, so that
                    611: .CW "m bach\ |\ midi"
                    612: is an example of a common invocation.
                    613: It also has options to restrict the output
                    614: to certain voices or a range of measures, as a debugging aid.
                    615: .NH
                    616: The M keyboard interface.
                    617: .PP
                    618: It is possible to generate the notes of an M program by playing at the
                    619: .SM DX7
                    620: keyboard.  First the note-on and note-off events are collected by
                    621: .I midiblt
                    622: and written into a file on the host.  This file is then converted into a
                    623: list of note names by
                    624: .I unmidi .
                    625: We have used the conventions that the
                    626: .SM DX7 "'s"
                    627: .SM YES
                    628: button generates a newline, and the
                    629: .SM NO
                    630: button produces the comment
                    631: .CW "/*?*/" .
                    632: This gives the user some control over the format and the ability to flag errors.
                    633: We also use the ``portamento'' pedal to generate a barline.
                    634: .I Unmidi
                    635: has an ``output key'' option to direct it towards desired enharmonic spellings.
                    636: The output from
                    637: .I unmidi
                    638: is fed to an
                    639: .I awk
                    640: script which adds voice names.  Now only the rhythm
                    641: is missing.  Since it is separate from the notes, it
                    642: can be typed in quickly by making a second pass over the score.
                    643: .NH
                    644: Conclusions.
                    645: .PP
                    646: Twelve-tone pieces such as the one in section 5, and serialized pieces
                    647: particularly, would be easier and faster to develop with the aid of specialized
                    648: tools.  These could range anywhere from a library of C routines to a
                    649: complete language implementation.  We expect to begin on a modest scale
                    650: with the former and enlist the efforts of interested composers.
                    651: .PP
                    652: It is clear that we have barely scratched the surface of
                    653: an immensely challenging class
                    654: of problems.  The
                    655: .UX
                    656: system, originally crafted as a home for programmers,
                    657: has proven remarkably robust, flexible, and downright hospitable as a base
                    658: for a very different application.
                    659: .NH
                    660: References.
                    661: .LP
                    662: |reference_placement

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.