Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 54 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
54
Dung lượng
131,08 KB
Nội dung
THE CMU MIDI TOOLKIT ``Charles Ives'' Edition Roger B Dannenberg 14 January 1988 Carnegie Mellon University Pittsburgh, PA 15213, U.S.A The CMU MIDI Toolkit (CMT), consisting of software and documentation, is provided ``as is'' without warranty of any kind, either expressed or implied Should CMT prove defective, you (and not Carnegie-Mellon University) assume the entire cost of all necessary servicing, repair or correction Further, Carnegie-Mellon University does not warrant, guarantee or make any representation regarding your requirements or that CMT is free of errors Neither Carnegie-Mellon University nor anyone else who has been involved in the creation, production, or delivery of CMT program shall be liable for any direct, indirect, consequential or incidental damages arising out of use or inability to use CMT Preface This manual is a guide for users of the Carnegie Mellon University MIDI Toolkit, also known as CMT, a collection of software for experimental computer music using standard Musical Instrument Digital Interface (MIDI) equipment This manual corresponds to CMT Version 2.00 This is the Charles Ives edition, the first CMT manual This manual is updated periodically as new programs are contributed to CMT and as bugs are discovered and fixed I solicit your help in making this manual more accurate and complete PLEASE help us by noting any errors, omissions, or suggestions you may have You can send your suggestions to Dannenberg@A.CS.CMU.EDU (ARPAnet) via computer mail, or by campus mail to Roger B Dannenberg, Center for Art and Technology, CFA, or by ordinary mail to Roger B Dannenberg, Center for Art and Technology, Carnegie Mellon University, Pittsburgh, PA 15213-3890, USA A bug report form can be found at the end of this manual Many people have contributed to CMT which grew out of earlier computer music systems used in the CMU Computer and Electronic Music Studio Dean Rubine wrote the first MPU-401 interface routines with help from Dale Amon Joe Newcomer ported this first version to his IBM-AT and helped clear up many of our interrupt problems Aaron Wohl wrote routines to use the PC timer and made many good suggestions for improvements The Tuning program and the initial tuning software were written by Michael Cressman Most of the development work was done on the IBM-XT in the CMU Computer and Electronic Music Studio This machine was part of a grant from IBM I also wish to acknowledge support from CMU through the Music Department, the Computer Science Department, the Center for the Design of Educational Computing, and especially the Center for Art and Technology Introduction and Overview The CMU MIDI Toolkit (CMT) is a software package designed for experimental computer music education, composition, performance, and research CMT includes a compiler for a simple, text-based music language, and software for recording, playing, and computing MIDI data in real time CMT has three major attractions: the flexibility of an open-ended design, the availability of source code, and low system cost What does CMT do? The major components and their functions are: - Adagio is a language and an associated compiler In Adagio, a note is represented by a line of text that specifies attributes such as pitch, duration, and loudness Adagio is quite flexible and is compatible with several different ways of thinking about scores For example, ``Q'' stands for a quarter note, but duration can also be indicated by ``U87'', which means 0.87 seconds Adagio also supports arbitrary tuning systems - Transcribe reads input from a MIDI keyboard or other MIDI controller and produces an Adagio score The score can be played back using Adagio, or it can be edited with a text editor to make alterations Since Transcribe output is at least somewhat readable by people, it can also be used for performance analysis - Record is a combination of Adagio and Transcribe It plays an existing Adagio score while transcribing a performance Thus, complex compositions can be created one part at a time as if using a multi-track tape recorder - DXGet and DXPut are programs for recording and replaying MIDI system exclusive messages These programs are typically used to save and restore synthesis parameters for a digital synthesizer - Moxc is a real-time programming environment that is ideal for writing interactive music programs Moxc is an extension of the C programming language and is based on Douglas Collinge's Moxie language - Also provided are routines (in C) that allow direct production of MIDI output Other routines are available to read MIDI data from a circular input buffer and to get the current time with 0.01 second resolution Required hardware and software CMT runs on an IBM-XT or IBM-AT with a Roland MPU-401 MIDI interface and IBM-PC interface adapter You should also have a screen-based text editor To use Moxc, you will need a Lattice C compiler Other details CMT is distributed by the CMU Center for Art and Technology, Carnegie-Mellon University, Pittsburgh, PA, 15213 We hope that users will contribute new software to the system and enhance the existing software in various ways We will encourage this by helping to integrate and document new software and by distributing software updates to CMT users 1.1 Installing CMT CMT comes on a set of two floppy disks Disk #1 contains executable programs and some example files Disk #2 contains source code and files you need in order to recompile CMT programs If you have a hard disk, you should copy the contents of the floppy disks that come with CMT onto the hard disk Put Disk #1 in the floppy disk drive and type: c: cd \ mkdir cmt cd cmt copy a:*.* There are some test files in the directory test on Disk #1 as well by typing: You can copy them mkdir test cd test copy a:\test\*.* Some useful non-music programs are included with CMT ls To install these programs, type: They are make, grep, and cd \bin copy a:\bin\*.* If you want to use CMT to write programs, you should copy the contents of Disk #2 into your cmt directory Put Disk #2 into the floppy disk drive and type: cd \cmt copy a:*.* Finally, you add c:\cmt to the path in your autoexec.bat file so that DOS can find CMT programs Assuming you have installed an MPU-401 MIDI interface, you should now connect your synthesizer(s) At Carnegie Mellon, we generally use a Yamaha DX7 as input and a TX816 as output Thus, we connect the DX7 MIDI OUT to the MPU-401 MIDI IN and the MPU-401 MIDI OUT to the TX816 MIDI IN You should not connect the MPU-401 OUT to the DX7 IN Doing so will cause outputs from the DX7 to be returned as inputs This can cause problems in the DX7 If you want to use the same synthesizer for both input and output, a slightly different approach is necessary Here, you should go ahead and connect both MPU-401 IN and OUT to your synthesizer OUT and IN, respectively To avoid the problem of having outputs returned as inputs, you should use the ``-block'' option on all CMT software When the software is not running, it may be necessary to disconnect either of the two MIDI cables because the MPU-401 default is to resend all inputs as outputs In some cases, the DX7 cannot handle having its output data returned to its input DOS Utilities Before describing music software that comes with the CMU MIDI Toolkit, some DOS commands and utility programs are described Three programs are provided with CMT to help make your life easier These are make, ls, and grep A section on backing up files, intended for novice users, is also included in this chapter 2.1 make The make program is based on the Unix (Unix is a trademark of A.T.& T Bell Laboratories) program of the same name, and is documented in the file make.man The purpose of make is to figure out what has to be recompiled when you edit a file A file called makefile contains a list of file dependencies and a command that specifies how to recompile a dependent file The make program figures out what files have changed by examining their ``last modified'' times and dates Therefore, if you use make, you must always tell DOS the time and date when you turn on your machine An example of an entry in makefile describing a dependency is ADOBJ = adagio.obj phase1.obj phase2.obj adaspace.obj noteoff.obj MUSICLIB = cmt.lib adagio.exe : #(ADOBJ) #(MUSICLIB) link #(COBJ) #(ADOBJ),adagio,,#(LIBS) In this example, ADOBJ is a symbol that is defined in the first line to be a list of files The line with the colon (:) says that adagio.exe depends upon everything on the right of the colon, that is, all of the object files represented by ADOBJ and also the file cmt.lib, represented by MUSICLIB If adagio.exe does not exist or is older than one of the files it depends upon, it should be remade by executing the lines after the line stating the dependency In this case, there is only one command (starting with the word link) needed The file makefile, from which this example was taken, is provided with CMT and contains a complete list of CMT file dependencies It is a good reference if you have questions about how to write a makefile To use make, simply give it the file you want to make up-to-date example, For make adagio.exe will make adagio.exe up to date you can type To make sure the entire CMT is up-to-date, make everything Note: the makefile provided with CMT assumes you are in the directory with all the CMT source files when you run make To clean up leftover files, type: make clean This will not remove OBJ files typing: You can get rid of unneeded OBJ files by make cleanobjs 2.2 ls The ls program is like the DOS dir command, except it lists file names only (no size and date information), and the names are formatted into columns in alphabetical order The current version of ls does not work with large directories, although this may be fixed by the time you read this 2.3 grep The grep program searches one or more files for a text string If the string is found, the line containing the string is printed grep is indispensable for reading someone else's code For example, to find out where fileopen is declared (as well as where it is used), type grep fileopen *.c in the CMT source code directory 2.4 Backing up files Note: This section is intended for new users of the CMU Computer Music Studio, but it is worth reading if you are inexperienced with personal computers The IBM XT system has a built-in disk that can store about 10 million characters of information Unfortunately, that may not be enough to meet the demands of all of the studio users Fortunately, there is an alternative way to store information called the floppy disk Floppy disks are also a good way to make copies of your work for safe keeping There is always a small chance that all of your data will be lost from the Studio computer To protect yourself, you should keep a backup copy of any critical files on a floppy disk Floppy disks are thin magnetic disks that come in a protective sleeve and insert into the slot in front of the IBM XT To make a backup copy of your directory, put a floppy disk into the disk drive slot and push down the door if you have not used the disk before, type format a: This will completely erase your disk, so only this if the disk is new or there is nothing on the disk you want to keep type copy *.* a: This will copy all files from your directory to the floppy disk If there is a file on the floppy disk whose name is the same as a file in your directory, then it will be erased and replaced For example, if you copied a file called tune.gio to your floppy disk last week, then edited tune.gio, and now you back up you directory, then you will lose last week's version of tune.gio from your floppy disk It will be replaced by the current version To copy individual files, type copy filename a: where filename is the file you want to save on floppy To recover an individual file from floppy disk to your directory, type copy a:filename The Adagio Language Adagio is an easy-to-use, non-procedural notation for scores In Adagio, text commands are used to specify each note If you are new to Adagio, you may want to glance at the examples in Section 3.3 starting on page before reading any further A note is described in Adagio by a set of attributes, and any attribute not specified is ``inherited'' from the previous line Attributes may appear in any order and must be separated by one or more blanks An attribute may not contain any blanks The attributes are: time, pitch, loudness, voice number, duration, and timbre Adagio has been used to program a variety of hardware and software synthesizers, and the Adagio compiler can be easily adapted to new environments Although not originally intended for MIDI, Adagio works quite well as a representation for MIDI scores The MIDI version of Adagio currently uses the timbre attribute to select a MIDI ``program'' (synthesizer preset) Adagio has been extended to allow MIDI controller data such as modulation wheels, pitch bend, and volume A note command in Adagio must be separated from other notes Usually, notes are distinguished by writing each one on a separate line Notes can also be separated by using a comma or semicolon as will be described below Besides notes, there are several other types of commands: An asterisk (*) in column one (or immediately after a comma or semicolon) indicates that the rest of the line is a comment The line is ignored by Adagio, and is therefore a good way to insert text to be read by people An empty command (a blank line, for example) is ignored as if it were a comment (To be consistent, a blank line ought to generate a note that inherits all of its attributes from the previous one Adagio is intentionally inconsistent in this respect.) An exclamation point (!) in column one (or immediately after a comma or semicolon) indicates a special command A special command does not generate a note, and currently, the only special commands are the Rate and Tempo commands, described below Special commands extend to the end of the line Control change commands are used to control parameters like pitch bend that can change as a note is playing Control change commands can be specified along with notes or by themselves A command that specifies only control changes will not produce a note Adagio is insensitive to case, thus ``A'' is equivalent to ``a'', and you can mix upper and lower case letters freely 3.1 Specifying Attributes 3.1.1 Time The time attribute specifies when to start the note A time is specified by th a ``T'' followed by a number representing 100 's of a second or by a duration (durations are described below) Examples: T150 TQ3 1.5 sec quarter note's duration If no time is specified, the default time is the sum of the time and duration attributes of the previous note (But see Section 3.1.4.) Time is measured relative to the time of the most recent Tempo or Rate command (See the examples in Section 3.3 for some clarification of this point.) 3.1.2 Pitch The pitch attribute specifies what frequency to produce Standard scale pitches are named by name, using "S" for sharp, "F" for flat, and (optionally) "N" for natural For example, "C" and "CN" represent the same pitch, as "FS" and "GF" (F sharp and G flat) Octaves are specified by number C4 is middle C, and B3 is a half step lower F5 is the top line of the treble clef, etc Accidentals can go before or after the octave number, so FS3 and F3S have the same meaning An alternate notation for pitch is Pn, where n is an integer representing the pitch Middle C (C4) is equivalent to P48, CS4 is P49, etc [If you know MIDI codes, you will notice that P48 in Adagio results in a MIDI pitch code of 60 The ``middle C = 48'' convention was borrowed from Gary Nelson's MPL and it is consistent with MUSIC V, cmusic, and many other computer music languages I decided to stick with the convention on the assumption that if you know enough about MIDI to know that middle C is 60, then you know enough not to be confused by Adagio and other CMT software.] If you not specify an octave, Adagio will choose one for you This is done by picking the octave that will make the current pitch as close to the previous pitch as possible In the case of augmented fourths or diminished fifths, there are two equally good choices Adagio chooses the lower octave 3.1.3 Duration Duration is specified by a letter indicating a number of beats, followed by one or several modifiers The basic duration codes are: W (whole, beats), H (half, beats), Q (quarter, beat), I (eighth, 1/2 beat), and S (sixteenth, 1/4 beat) The default tempo is 100 beats per minute (see Section 3.1.9) These codes may be followed by a "T" (triplet), indicting a duration of 2/3 the normal A dot (".") after a duration code extends it by half to 3/2 the normal Finally, an integer after a note multiplies its duration by the indicated value (the result is still just one note) Examples: Q QT W ST6 H5 beat (quarter note) 2/3 beat (quarter triplet) beats(dotted whole note) beat (6 sixteenth triplets) 10 beats(5 half notes) Finally, a duration may be noted by Un, where n is an integer indicating th 100 's of a second For example, U25 is one quarter of one second 3.1.4 Next Time The time of the next command (the next command in the Adagio program text) is normally the time of the current note command plus the duration of the current note This can be overridden by a field consisting of the letter ``N'' followed by a number indicating hundredths of seconds, or followed by a duration as described above The next note will then start at the time of the current note plus the duration specified after ``N'' If the next note has an explicit time attribute (``T''), then the specified time will override the one based on the previous note Examples: N0 N50 NQT start the next note at the same time as the current one start the next note 0.5 seconds after the current one start the next note 2/3 beat after the current one 3.1.5 Rest Rests are obtained by including the field ``R'' in a note command The effect of an ``R'' field is to omit the note that would otherwise occur as the result of the current note command In all other respects, the command is processed just like any other line This means that attributes such as duration, loudness, and pitch can be specified, and anything specified will be inherited by the note in the next command Normally, a rest will include just ``R'' and a duration The fact that a note command specifies a rest is not inherited For example: R H RH a half (two beat) rest illegal, R must be separated from other fields by space(s) Because some synthesizers (e.g a DX7) cannot change programs (presets) rapidly, it may be desirable to change programs at the beginning of a rest so that the synthesizer will be ready to play by the end of the rest See Section 3.1.8 for an example 3.1.6 Loudness Loudness is indicated by an ``L'' followed by a dynamic marking from the following: PPP, PP, P, MP, MF, F, FF, FFF Alternatively, a number from to 127 may be used The loudness attribute is the MIDI note velocity The dynamic markings are translated into numbers as follows: Lppp 20 Lmf 58 Lpp 26 Lf 75 Lp 34 Lff 98 Lmp 44 Lfff 127 3.1.7 Voice The voice attribute tells which of the 16 MIDI channels to use for the note The voice attribute consists of a ``V'' followed by an integer from (the default) to 16 There is a limit to how many notes can be played at the same time on a given voice (MIDI channel) Since the limit depends upon the synthesizer, Adagio cannot tell you when you exceed the limit Similarly, Adagio cannot tell whether your synthesizer is set up to respond to a given channel, so there is no guarantee that what you write will actually be heard 3.1.8 Timbre (MIDI program) A MIDI program (synthesizer preset) can be selected using the attribute ``Zn'', where n is the program number Notice that in MIDI, changing the program on a given channel will effect all notes on that channel Also, for many synthesizers, you will not be able to change programs at the start of a note or during a note Change the program during a rest instead For example: R I Z23 V4 A4 change MIDI channel to program 23 during rest play a note on channel The cartridge programs on a DX7 can be accessed by adding 32 to the cartridge program number For example, cartridge program number 10 is specified by Z42 3.1.9 Tempo The length of a beat may be changed using a Tempo command: !TEMPO n where n indicates beats per minute The exclamation mark tells Adagio that this is a special command line rather than a note definition A special command takes the place of a note specification No other attributes should be written on a line with a special command The new tempo affects all succeeding notes The time attribute of all succeeding notes is now measured relative to the time of the Tempo command Durations specified in hundredths of seconds (for example U58, N15, or T821) are not affected by the Tempo command The Tempo command is fairly clever about default durations If the last duration specified before the Tempo command is symbolic (using one of S, I, Q, H, or W), then the default duration for the node after the Tempo command will be modified according to the tempo change Consider the following tempo change: !TEMPO 60 A4 H !TEMPO 120 G In this example, the first note will last seconds (2 beats at 60 beats per minute) The second note inherits the duration (H) from the first note, but at 120 beats per minute, the second note will last only second If the duration had been specified U200 (also a duration of seconds), the second note would also last seconds because the Tempo command does not affect times or durations specified in hundredths of seconds 3.1.10 Rate The rate command scales all times including those specified in hundredths of seconds A rate of 100 means no change, 200 means twice as fast, and 50 means half as fast For example, to make a piece play 10% faster, you can add the following command at the beginning of the score: !RATE 110 Rate and Tempo commands combine, so !RATE 200 !TEMPO 70 will play 70 beats per minute at double the normal speed, or 140 beats per minute Like Tempo, the time of the Rate command is added to the time attribute of all following notes up to the next Time or Rate command 3.2 Default Attributes If an attribute is omitted, the previous one is used by default (with the exception of the time attribute) The default values for the first note, which are inherited by succeeding notes until something else is specified, are given below in Adagio notation: Time T0 Pitch C4 Duration Q Loudness LFFF Voice V1 Timbre Z1 Tempo Rate Pitch After Porta Porta Bend Y128 Touch O0 Rate J99 Switch K0 !TEMPO 100 !RATE 100 Mod Wheel M0 Foot Pedal X0 3.3 Examples The following plays the first two bars of ``Happy Birthday'' Note that Adagio knows nothing of bar lines, so the fact that the first note occurs on beat or that the meter is three-four is of no consequence: *Example Happy Birthday tune (C major) !TEMPO 120 G4 I LF G4 S A4 Q G4 C5 B4 H The time attribute for the first note is zero (0) The second note will occur a dotted eighth later, etc Notice that no timbre or rate was specified Adagio will provide reasonable default values of and 100, respectively The following example plays the first four bars of an exercise from Bartok's Mikrokosmos (Vol 1, No 12) An extra quarter note is inserted at the beginning of each voice in order to allow time to change MIDI programs The right hand part is played on voice (MIDI channel) and the left hand part on voice Notice the specification of the time attribute to indicate that voice starts at time Also, I have taken advantage of default octaves to reduce typing *Example Bartok *voice 1, right hand R Q Z10 V1 A4 H B Q C D H C D Q C B A B C D R *voice 2, left hand T0 R Q Z15 V2 G3 H F Q E D H E D Q E F G F E D R The next example is the same piece expressed in a different manner, illustrating the interaction between the Tempo command and the time attribute aftertouch data The rec final routine filters the recorded data so that a given control will not change more than once per 0.01 second time period This reduces the size of the output file, reduces the amount of data to be stored by the Adagio program, and has a minimal impact on the accuracy of reproduction 11 What next? A number of improvements remain to be made to the CMU MIDI Toolkit To encourage others to make these improvements, CMT is distributed with source code and documentation In addition, the Center for Art and Technology at Carnegie Mellon University will help coordinate and integrate changes to this software If you develop a new tool or enhance an existing one, you can incorporate it into CMT by sending it to me (Roger B Dannenberg) at the Center for Art and Technology Provided the changes or additions are consistent with the goals of CMT, I will integrate them into the next release and redistribute your code to other users Thus others will benefit from your efforts as I hope you have benefited from mine The following sections outline changes I would like to see in the CMU MIDI Toolkit If you decide to tackle one of these, it might be a good idea to call me at (412) 268-3827 or write to find out if anyone else is working on the same thing 11.1 Microsoft C conversion The current version of CMT uses the Lattice C compiler to make CMT compatible with both Lattice and Microsoft C Work is in progress 11.2 Large memory model conversion The most serious problem with CMT at the moment is that it was designed for use with the ``small memory model'' This means that only 16 bits are used to address code and data, so not all of the available memory can be used This is a problem that limits Adagio to less than thousand notes To use another memory model, one would have to recode some of the assembler routines (particularly aintr.asm) to get the right values into the segment registers 11.3 Multiple Midi Interfaces Another limitation of CMT is that it supports only one MPU-401 There are two reasons for using more than one First, you might want to have more than one MIDI input to the system A keyboard like the KX88 will ``mix'' the data it generates with its MIDI Input to form the MIDI Output Thus, you can get input from a KX88 and at least one other device by connecting them in series However, most MIDI devices cannot ``mix'' MIDI data, so one might want to have several MIDI interfaces to get input from several controllers Notice that input data can be ``mixed'' internally by the IBM PC, and there is no reason to distinguish which physical input is the source of a given piece of data The second reason for multiple interfaces is to overcome the maximum of 16 MIDI channels or to obtain higher speed A reasonable thing to in this case is to implement ``logical'' MIDI channels Logical channels through 16 would correspond to MIDI channels through 16 on the first MPU-401 Logical channels 17 through 32 would correspond to MIDI channels through 16 on the second MPU-401, and so on This presents no problems for Adagio, but there is a lot of CMT software that assumes only bits are needed to store a channel number Implementing logical channels is more work than the mixing idea described in the preceding paragraph 11.4 Improve Adagio compilation (sorting) speed Currently, Adagio keeps a linked list of notes and control changes sorted by start time If scores are roughly in time order, the performance is good However, if a score is constructed by concatenating several files created using transcri or record, then notes are not in order and Adagio can spend several minutes loading a score I believe this can be solved by two transformations First, change the insert routines to insert notes in forward rather than reverse time order and take out the code that reverses the final score Second, keep a pointer to the last point at which a note was inserted When you go to insert a note, try searching forward from the saved pointer Only if this fails should you search from the beginning of the list The resulting program will still perform badly on perverse scores, but the expected performance should be quite good on normal scores 11.5 Multi-track recording Not everyone has enough equipment to play an entire score, and not all scores will fit into the available memory A solution to these problems is to use a multi-track recorder and to record a composition one track at a time To this, one must be able to enable one Adagio voice at a time I suggest adding an option to the Adagio (and Record) command line of the form -v 1,5 which would mean play only voices (MIDI channels) and Notes and control events on other channels would not be saved in memory for playing, so this facility would help get around memory restrictions For long works and pieces where close synchronization of parts is important, it is essential to have some means of synchronizing Adagio output with a tape recorder The MPU-401 has a tape-sync input and output which could be used for this purpose Probably, a command-line switch (``-sync'') should be read by mpu.c When the switch is present, mpu.c should tell the MPU-401 to synchronize to the tape input Notice that CMT has optional code to derive time from the internal IBM-PC timer rather than the MPU-401 If that is the case, then the ``-sync'' switch should either cause mpu.c to revert back to the MPU-401 or there should be some way to cause MPU-401 clock input data to resynchronize the internal IBM-PC timer 11.6 MIDI Continuous Controls Adagio supports the notion of continuous controls through its control change commands, but these are presently very limited Three enhancements should be made First, it should be possible to program how control change commands in Adagio are mapped into MIDI control change commands For example, one might want to use the X command to send breath-controller values This could be implemented by having an optional control specification file, just as there is now an optional tuning specification file The same file format should be used by transcri and record to determine how Adagio scores are produced from MIDI input One could use this same facility to tell record and transcri to ignore certain control information For example, if no command is assigned to control aftertouch, then aftertouch data would be ignored in the recording (transcription) process A second change would be to add new commands to Adagio to allow users to specify smooth, continuous changes without a huge amount of typing This could be done by implementing a new special command For example, !ramp x0 x100 q would mean change the X control smoothly from to 100 in the time of a dotted quarter note This command would be translated into a single Adagio event and the stream of control change data would be computed from the event data in real time Thus, in addition to save typing, the scheme would save on memory space wherever these special commands could be used in place of many control change commands Finally, it would be very interesting to look into using control changes to modify MIDI programs in real-time For example, you can put a DX7 in a mode where the inharmonicity of a tone can be controlled by a slider on the DX7 control panel By using system exclusive messages, one can control the inharmonicity by computer The missing link here is to make the control specification file flexible enough that one can use Adagio to send system exclusive messages as well as conventional control change commands It might be helpful to add yet another command to Adagio to send system exclusive messages directly 11.7 Interacting with Moxc programs Every Moxc program I write has a big asciievent routine that calls different routines and sets values depending upon characters that get typed at run time It should be possible to write a routine that could read the map file produced by the linker and figure out where variables and procedures are located Then, a user interface could be designed such that you could type seti foo 2006 call bar 100 572 in order to set the integer foo to 2006 and then call procedure bar with parameters 100 and 572 11.8 Code to play sequences from Moxc It is hard to write Moxc programs that play sequences of notes, and it would be nice to be able to write sequences in Adagio and trigger them in real time Moxc programs I designed a module for this and wrote most of the code, but I have not tested anything yet The idea is to use a modified Adagio to read scores and transform them into data files that can be input easily without resorting to a full-blown Adagio translator Routines are then provided to read and play these sequences Several parameters including transposition and rate can be changed in real-time to modify the performance of the sequence The interface is as follows: seq read(name, filename); reads the sequence in file filename Sequences are named internally by small integers, and name is the integer to associate with this sequence seq play(name); plays sequence associated with the integer name seq transpose(name, transposition); sets the transposition of the sequence associated with name to transposition seq rate(name, rate); sets the rate of the sequence associated with name to rate A rate of 100 gives the normal rate as specified in the Adagio file that generated the sequence seq cycle(name, flag); sets the cycle flag of the sequence associated with name to flag If the flag is non-zero, then the sequence will repeat (cycle) indefinitely seq pause(name, flag); sets the pause flag of the sequence associated with name to flag If the flag is non-zero, the sequence performance will be suspended until the flag is set to zero seq at end(name, procedure); will cause the routine named by procedure to be called at the end of the performance of the sequence associated with name This implementation of this interface is quite compact A drawback is that there is no provision for recording sequences in real-time within the context of Moxc, so some more thinking and experimentation is probably in order It has also been suggested that one should be able to combine rhythm from one sequence with pitches from another 11.9 A player module Currently, Adagio and Record are very similar The main difference is that in phase 2, in which Adagio plays a score, Record plays a score and calls on record.c to record MIDI input It would be nice to design a module player.c that both Adagio and Record could call on to play a score This would eliminate a lot of redundant code and would insure consistency between Adagio and Record when changes are made For example, one might want to allow users to transpose scores, change the playback speed, and make other changes without editing the score At present these sorts of changes would have to be made in both phase2.c for Adagio and trans2.c for Record 11.10 User-defined note routines for Adagio Not only would it be nice to be able to invoke Adagio-defined sequences from Moxc, it would also be nice to be able to invoke Moxc routines from Adagio scores One way to this would be to separate the Adagio note-playing routines into a separate module Then users could write their own note routines that would get parameters from Adagio scores, but that might have some complex behavior For example, one could write a routine that produced drum rolls consisting of many MIDI notes, but which could be invoked by a single line in Adagio One would have to be careful to smoothly integrate Adagio and Moxc; perhaps Adagio should be modified to use Moxc for its own scheduling 11.11 DX7 Program Librarian In Adagio, one specifies timbre by numbers that correspond to MIDI programs It is up to the user to make sure the proper programs are loaded into the synthesizer in the right locations It would be nice to be able to write a file like Channels 1-8 3-8 ProgramNumber ProgramName marimba harp celeste strings which would specify a correspondence between program numbers and program names One could write a Program Librarian that could read such a file and use it to load up a TX816 or whatever with exactly the right programs for a particular piece The program names would correspond to file names 11.12 An Adagio editor It might be interesting to be able to extract sections of Adagio scores, stretch them, transpose them, copy them, merge them with other files, and so on This can be done with a text editor, but a specialized editor, particularly one that could play the files as it edits them, might be more effective Another idea for an editor is to try to use a combination of typed text and MIDI input to speed up the process of entering scores This is a largely unexplored area that has applications in music typography systems as well as CMT 11.13 Interface to XLISP An interpretive language like LISP can be an excellent teaching and composing tool XLISP is a version of LISP implemented in C and in the public domain It should be fairly simple to provide a LISP interface to mpu.c, allowing XLISP programs to make music 11.14 A Sequencer Everyone else writes sequencers Why not build one for CMT? This would be the first MIDI sequencer for small machines that users could modify to suit their special needs 11.15 Ports There is very little in CMT that is specific to the IBM PC It should not be too difficult to get CMT running on the Macintosh, Amiga, Atari, and other small machines Work is under way at Brown University and Carnegie Mellon to port CMT to an IBM RT as well I The MIDI Interface This appendix contains documentation for calls in the module mpu.c Type boolean is an int that takes on values of true or false, and type byte is an unsigned char exclusive(onflag) boolean onflag; This procedure tells the MPU-401 to read exclusive messages into the buffer provided by a previous call to midi buffer onflag is set to true to receive MIDI exclusive data, otherwise it is set to false boolean getbuf(waitflag, p) boolean waitflag; byte * p; getbuf copies bytes of data from buffer (the MIDI input buffer filled by the interrupt handler in aintr.asm) to *p It will wait for buffer to become nonempty if and only if waitflag is true It returns true if data was written to *p, and false if data was not written to *p int getkey(waitflag) boolean waitflag; getkey tries to read a key It returns the key number of the key which has been depressed, or the key number plus 128 of a key which has been released It returns -1 if waitflag is false and no key has been pressed If waitflag is true this routine will block until a key is pressed Since getkey uses getbuf (see above), non-key events (e.g pitch bend) may be read and discarded by getkey long gettime() Return the time in 100ths of seconds since the last call to musicinit or timereset l rest(time) long time; l rest waits until the amount of time specified by time has elapsed l restuntil(time) long time; l restuntil waits until the specified time has been reached (absolute time as returned by gettime) metronome(onflag) boolean onflag; metronome enables (true) or disables (false) MPU-401 metronome function, as indicated by onflag This procedure must be called before musicinit The metronome is not started until musicinit is called midi bend(channel, value) int channel; int value; Sends a MIDI pitch bend message; channel is the MIDI channel on which to send data, and value is the pitch bend value from to 16383 The value 8192 is the value representing no pitch bend; smaller values bend pitch down, and higher values bend pitch up int xbuffhead, xbufftail; int midi buffer(buffer, size) byte * buffer; int size; midi buffer tells interrupt routine to store system exclusive messages in buffer The largest power of bytes less than size will be used (a power of is used so that masking can be used to cause wrap-around) xbuffhead and xbufftail will be initialized to zero, and xbufftail will be one greater than the index of the last system exclusive byte read from mpu401 midi buffer returns false if size is less than 16 or buffer is NULL, otherwise true midi cont(onflag) boolean onflag; midi cont enables (true) or disables (false) continuous control info from the MPU-401 to the host, depending on the value of onflag midi ctrl(channel, control, value) int channel; int control; int value; Sends a MIDI control change message; channel is the MIDI channel on which to send data, control is the control number, and value is the control value midi exclusive(msg) byte * msg; Sends a MIDI exclusive message; message, terminated by 0xF7 msg is a pointer to a MIDI exclusive midi note(channel, pitch, velocity) int channel; int pitch; int velocity; Sends a MIDI note-on request out; channel is the MIDI channel on which to send data, pitch is the MIDI pitch code, and velocity is the velocity with which to sound it (0 means release) If read tuning has been called to define a tuning and velocity is not zero, then this procedure sends a pitch bend followed by a note-on message The pitch bend and the note-on pitch are found by table lookup, using pitch as the table index For zero velocity, the table lookup is done to get the pitch for a note-on message with zero velocity No pitch bend message is sent since zero velocity means note-off midi program(channel, program) int channel; int program; Sends a program change request; channel is the channel on which to send the MIDI program change request, and program is the program number to send (this number is decremented by before being sent as MIDI data, so values should be in the range of to 128.) midi thru(onflag) boolean onflag; Enables (true) or disables (false) MIDI thru info from MPU-401 to host, depending on the value of onflag The default is enabled, but the command line switch -block will cause it to be disabled initially midi touch(channel, value) int channel; int value; Sends a MIDI after touch message; channel is the MIDI channel on which to send data, and value is the after touch value mpu error check() Reports any errors originating in the interrupt handler by printing them on stdout If you not call this routine, you not find out about the errors mpuexists(flag) boolean flag; If argument is false, this indicates no MPU-401 is on the machine, so simulate the mpu-401 (for debugging only) read tuning(filename) char *filename; Reads tuning information from filename and enables pitch bend to be sent by midi note to effect detuning musicinit() Initializes the MPU-401 device driver and resets the MPU-401 (see gettime) is reset to zero musicterm() Cleans up; disables MPU-401 interrupts; resets MIDI devices upon finishing execution The clock Call this int random(lo, hi) int lo, hi; Returns a pseudo-random number between lo and hi inclusive (lo