═══ 1. Introduction ═══ Please read this document in entirety. I took the time to make it explicit, clear, and very useful. It took me longer to write it than it will ever take you to read it. Therefore, you owe it to both of us to read it. OK? MF_DSM is an OS/2 2.X command line application that converts a MIDI (sequencer) file into a text file that can be viewed and edited with a text editor. In other words, it "disassembles" the MIDI file into human readable "source code". In this way, you can visually see the contents of the MIDI file; what notes are being played, when the notes are being played, what other "events" are in the file, etc. The display of this information is very musician friendly, allowing one to easily change/augment/delete the contents simply by editing the text. MF_ASM is an OS/2 2.X command line application that converts a text file such as that produced by MF_DSM back into a MIDI file. In other words, it "assembles" the "source code" into a MIDI file. Furthermore, MF_DSM recognizes certain directives that tell it to further process chunks of the source code, thus allowing one to easily transpose notes in a track, filter events (ie, split apart tracks) by MIDI channels/note numbers/event types, remap note numbers to new note numbers, remap events to new MIDI channels, adjust overall volume of the notes in a track, and replace all note-offs with 0 velocity note-ons. In addition to these "global" adjustments that can be easily applied to an entire track of events, you also can edit each individual event of a track in every possible way. You can change note number (ie, pitch), note velocity (ie, volume), aftertouch amount, program change number, pitch wheel amount, the MIDI channel of an event, controller numbers and amounts, the time upon which the event occurs, and edit/add/delete system exclusive/realtime/system messages. You can also edit/add/delete all of the non-MIDI events that may be found in a MIDI file such as Tempo, Track and Instrument names, Time and Key signatures, Cue Points and Markers, SMPTE time, Lyrics, etc. You could even create a text file from scratch, adding "events" as easily as cutting and pasting text in a text editor, and then create a MIDI file from the result using MF_ASM. The MIDI Disassembler/Assembler offers a relatively straightforward way of creating and editing MIDI files without requiring a sequencer program. It may even offer editing features that aren't found in your sequencer software. You ought to know a little about MIDI before editing any text files. I wrote an OS/2 Online Book called "The MIDI Book" which can give you all of the details about MIDI, as well as the MIDI File Format. The source produced by MF_DSM is formatted using "musical terminology" wherever possible, so you don't have to know about hexadecimal numbering and nitty gritty details like that, but for more involved editing, you may need to reference the MIDI specification. Version 1.1 corrects bugs related to Unknown Chunks and the "Hold Pd" and "Soft Pd" controllers (which are now "HoldPd" and "SoftPd". 1.1 also knows about "Bank Switch" controller. Version 1.2 corrects bugs in interchanging the coarse and fine NRPN controllers, adds the RPN controllers and All Sound Off controller, and uses GENMIDI.DLL. Some of the words in this manual are highlighted in bold text, such as Handshake. These are words that refer to MF_ASM "keywords" or fields that are part of the source code text file. Other words are in colored text such as Channel Pressure. These refer to MIDI messages (ie, data). Underlined words, such as Pitch Wheel, refer to hardware, such as if I was referring to the Pitch Wheel on your MIDI unit. Words that are in colored text such as Read This are meant to be emphasized. Words in italics refer to concepts, such as track. ═══ 2. Copyright ═══ MF_DSM, MF_ASM, MIDIFILE.DLL, GENMIDI.DLL and this manual are all copyright 1995 by Jeff Glatt. These items are freely distributable as long as no internal modifications are made to the items, and copyright messages are left intact. There are no pagan user fees, surreptitious financial charges, or other devious capitalist trickery associated with the use of these files. There are no warranties of any kind with this software. If swallowed, induce vomiting immediately (by contemplating the aesthetics of Windows). I can be contacted at: 6 Sycamore Drive East New Hartford, NY 13413 (315) 735-5350 ═══ 3. Invoking MF_DSM and MF_ASM ═══ MF_DSM and MF_ASM are both used from an OS/2 Command Prompt (window or full-screen). Each takes arguments (ie, additional text after the program name) when run. The syntax for MF_DSM is: MF_DSM midifilename [/I] [/PXXX] [/Otextfilename] midifilename is the name of the MIDI file that you wish to convert into a text source code file. The other 3 args are optional. The /I option produces only a synopsis of the MIDI file contents, rather than creating a text file containing info on every event in the MIDI file. Such a synopsis is only good for reference (ie, gives you a quick overview of what's in the MIDI file) and can't be assembled back into a MIDI file. Omit this option when you want to create "source code" of a MIDI file. The /O option allows the info to be saved to a file on disk so that you can edit it and later assemble it. The filename must immediately follow the /O. Without this option, MF_DSM simply lists the source code to the display, and doesn't save it. The /P option allows you to override the MIDI file's inherent Division (which affects the way that the time-stamps are calculated) where XXX is the desired Division (if negative, then SMPTE times may be forced). If any errors occur in reading the MIDI file, an appropriate message will be displayed. The syntax for MF_ASM is: MF_ASM textfilename [midifilename] textfilename is the name of the text source code file that you wish to convert back into a MIDI file. The other arg is optional. This second arg is the name of the MIDI file to produce. If you don't supply this second arg, it defaults to the textfilename (minus any extension), with the extension .mid added to it. If any errors occur in creating the MIDI file, an appropriate message will be displayed. Both utilities require that the MIDIFILE.DLL and GENMIDI.DLL files be in some directory along the LIBPATH as specified in config.sys file. These are dynamic link libraries I wrote which can be used by C programmers to simplify reading, writing and using MIDI files in their applications. The documentation and examples for such are also available separately. ═══ 4. Disassembly Format ═══ Disassembly is the process of taking a MIDI file (ie, a binary data file) and turning it into a text file (ie, human readable "source code"). MF_DSM does this. A MIDI file is made up of a series of musical events such as a note-on (ie, a musician has started sounding a note on a MIDI controller). The MIDI file time-stamps each event so that a sequencer will know when to play it. Some of the events are actual MIDI events, and others are META events that don't get output of a MIDI jack but which the sequencer uses for control of playback, such as a Tempo event. ═══ 4.1. MThd Header line ═══ Upon the very first line of the source code, MF_DSM displays the overall parameters of the MIDI file. This line begins with the text MThd to indicate that the file is a MIDI file. You should never alter the MThd "ID". The MThd header line must precede all track data (although comment lines may be placed ahead of it), and must start with MThd in order to mark the start of your source code. Next, is the Format of the MIDI file. All MIDI files are either format 0, 1, or 2. Format 0 files have only 1 track. All of the data will be in that 1 track. Think of that track as a complete "song" or "pattern". Sequencers that prefer data to be lumped together into one chunk of memory, in the order that the events will be played, often use this format. Format 1 and 2 can have numerous tracks of data. The tracks of a Format 1 are equivalent to the tracks of a single "pattern" in a sequencer which has multiple tracks. In other words, you might have a track for the drums, and a track for the piano, etc, and all of these tracks can play simultaneously, adding up to a complete song. The very first track in Format 1 usually contains only timing events such as Tempo events. It may also have non-MIDI events such as Time Signature, but it will usually not have any MIDI (ie, note) data. This is often referred to as the tempo map track. Sequencers that prefer to separate the musical performance into multiple tracks (usually so that the musician can better isolate and edit specific musical parts) often use this format. The Format 2 is like a bunch of Format 0 files stuck into one MIDI file. Each track of the Format 2 contains all of the data for one "song" or "pattern", but the MIDI file contains many songs. Devices that can load multiple songs or patterns (such a drum machine) often use this format. The next, overall parameter is the # of tracks in the MIDI file. For Format 0, this is always 1. The last, overall parameter is the Division. This is how the time-stamping is referenced. Normally, this tells you what the clock resolution is of the MIDI file in terms of how many clocks are in a quarter note (ie, PPQN). For example, 96 means that the sequencer ticks off 96 hardware clock pulses for every quarter note. If Division is specified in terms of SMPTE rate, then Division will be two numbers, the first being -24, -25, -29, or -30, corresponding to the 4 SMPTE standards representing frames per second. The second number (a positive number) is the resolution within a frame (ie, subframe resolution). Typical values may be 4 (MIDI Time Code), 8, 10, 80 (SMPTE bit resolution), or 100. The two numbers are separated with a / character. For example, millisecond-based timing would be specified as -25/40 (25 FPS with 40 subframes). The Format, # of Tracks, and Division fields must be separated with a | character (ie, above the ENTER key). This character is used throughout the source code to separate fields on a line. Here's an example of an MThd header line: MThd | Format=1 | # of Tracks=2 | Division=96 Note that there are 4 fields. The | may be optionally omitted after the last field (as it is here for Division). The = sign is most often used to assign a value to the field. The field's name is to the left of the = sign, and the value is on the right. For example, the name of the second field above is Format. (The MThd is the first field even though this isn't a field that can be assigned a value). It has been assigned a value of 1. Generally, you can add or subtract blank spaces wherever you like. For example, this is the same as above: MThd|Format=1|# of Tracks=2|Division=96 You can also add blank spaces at the beginning of the line (but don't put other characters before the MThd). You can even put blank spaces before or after the = sign that assigns a value to the field. The only exception to adding blank spaces is in the field's name (if it has embedded spaces, like # of Tracks does). In other words, don't type #ofTracks. Here's another legal variation on formatting with blank spaces: MThd | Format = 1 |# of Tracks=2 |Division= 96 As you can see, you have some liberty with the use of blank spaces. Furthermore, capitalization is not sensitive in the field names. For example, DIVISION is the same as division. So, you have some liberty with the SHIFT key as well. Finally, for most events, the order of most fields can be rearranged, and some fields can even be omitted. There are some exceptions though. The first field usually has a specific purpose, and for track data events, so does the second field. So, the first and perhaps second can't be rearranged or omitted. But, subsequent fields often can. For the MThd header line, the MThd field must be first, but the Format, # of Tracks, and Division fields can be in any order, as so: MThd | # of Tracks=2 | Division=96 | Format=1 So too, can you omit one or all of those 2 fields, as so: MThd | Division=96 If you omit any field, it automatically is set to a default value, which for Format, # of Tracks, and Division, are the values 0, 1, and 192 respectively. So, the above example defaults to Format 0, 1 track with 96 PPQN. You may change the values for the Format, # of Tracks, and Division fields (but change them to sensible values). You should set # of Tracks to the number of track headers that will be in your source. Otherwise, you'll end up not writing out extra tracks, or create a malformed MIDI file. For Division, you can optionally specify a SMPTE timing as described above. ═══ 4.2. Track Header line ═══ A MIDI file may have numerous tracks of data. MF_DSM first lists all of the events in the first track, in the order that they are to be played. Then, all of the events in the second track are listed, in the order that they are to be played. This repeats for as many tracks as are in the MIDI file. The events for the last track will be at the "bottom" of the text file. Generally, each event of a track is displayed upon its own line to make it easy to distinguish one from the other. So, after the MThd header line, MF_DSM starts listing the first track. The start of a track is always indicated by the words Track # followed by a number telling which track it is (ie, 0 being the first track. Note that there may be a Track Number event also in the track. That will be the track's real number. The number on the track header line is only for your reference). After the track number, MF_DSM fills up the remainder of that line with * characters just to highlight where the data for the track begins. MF_ASM (the assembler) doesn't require that these filler characters be present; but a line must start with Track # in order to mark the start of a track's data. As usual, blank space can precede the Track #, which itself can be typed in lower or upper case. After the Track #, you can optionally place a | character followed by more fields to be described later. Here's an example of the track header line for the first track: Track #0 ****************************************** You can place blank lines between the preceding MThd header line and the Track header line. In fact, you can place blank lines anywhere in the source file for improved readability. ═══ 4.3. An Event line ═══ After the Track header line is the track's first event, on its own line. The first field of an event must be its Time. This describes the point at which the event should be played. The second field (separated from the Time field with a | character) must be a text description of the event's Type, such as a On Note event type. Different event types may have further fields, each separated from the next with the | character. These additional fields are optional, and can usually be in any order. Usually, all of the fields must be on one line. Therefore, the entire event is contained upon one line of text. All events must have the Time and Event Type fields, in that order, and these must be at the start of the line. ═══ 4.3.1. Time Field ═══ The Time field is the first field of an event. This indicates the point at which the event should be played. The Time is expressed in terms of musical bars (measures), beats, and clocks (fractions of a beat) at the current time signature. (Note that MIDI files can have time signature changes, and the Time field display reflects this). The field is displayed as: Measure: Beat: Clock In other words, for any event, you know what measure, beat, and subbeat it gets played upon. The first measure of a track is #1. The first beat in a measure is #1. The first clock within a beat is 0. So, if an event occurs precisely upon the 3rd beat of the 4th measure, then its clock display is: 4: 3: 0 Note: You can use any non-numeric key to separate the measures, beats, and clocks, including blank spaces. For example, if using the numeric keypad, you might separate each field with a dot as so: 5.1.0 You can also add as many blank spaces between the measures, beats, and clocks as desired, in order to line up the measures, beats, and clocks in the same text columns as preceding and subsequent events. The number of beats in a measure depends upon the current time signature. If there is no time signature event in the MIDI file, then 4/4 time is assumed (ie, 4 beats in a measure, and a quarter note is the beat). The number of fractional divisions of a beat depend upon the MThd Division and the current time signature. Division tells you how many subbeats are in a quarter note. For example, if Division is 192, then that means that there are 192 clocks per quarter note. Since there are 2 eighth notes in a quarter note, then there must be 192/2 clock subbeats in an eighth note (ie, 96 clocks). There are 4 sixteenth notes in a quarter note, so each is 192/4 clocks (ie, 48 clocks) in each 16th note. It's best to make a chart based upon the Division, which you can use to determine how many subbeats are in each musical note. Here's the formula used: quarter Division in each note quarter note triplet Division/1.5 in each note eighth Division/2 in each note eighth note triplet Division/3 in each note sixteenth Division/4 in each note sixteenth note triplet Division/6 in each note 32nd note Division/8 in each note 32nd note triplet Division/12 in each note Here's a list of the number of clocks in each type of note for 192 PPQN: quarter 192 quarter note triplet 128 eighth 96 eighth note triplet 64 sixteenth 48 sixteenth note triplet 32 32nd note 24 32nd note triplet 16 For example, assume that a pattern is in 4/4. You want to set an event's Time to the 3rd measure, second beat, on the 3rd sixteenth note of that beat. Because you need to set the time to a fraction of a beat (i.e. the 3rd sixteenth note of the beat), you need to specify a non-zero subbeat when entering the time. The first sixteenth note (or the first of ANY group of fractional beats) occurs right on the downbeat, so it would have a clock offset of 0. The second sixteenth would have a clock offset of 48 (according to the above chart). The third sixteenth would have a clock offset of 48+48. Of course, the fourth sixteenth would have an offset of 48+48+48. So to set the event upon the 3rd measure, second beat, 3rd sixteenth note would be: 3: 2: 96 For SMPTE Divisions, the Time field is not displayed as measure, beats, and subbeats, but rather one number that is simply the clock ticks from the start of the song upon which the event occurs. (The start of the song is at time 0). So, if an event has a Time of 1, then it occurs 1 clock after the start of playback. The Time field is separated from the next field using the | character. So, assuming 4/4, and you wish to place an event on the first measure, fourth beat, second eighth note of that beat (ie, first eighth note is on the beat or at 0 subbeats, and the next is at 0+96): 1: 4: 96 | ═══ 4.3.2. Event Type Field ═══ The Event Type field is the second field of an event. This indicates what type of event it is, for example, a Tempo event. So, a Tempo event would have the text Tempo placed into the second field. The field must be ended with the | character. So, let's specify a Tempo event on the first measure, second beat (ie, right on that beat) of the track. Here are the required Time and Event Type fields, with separators: 1: 2: 0 | tempo | Notice that I used blank space liberally. Also, I specified the Tempo type as all lower caps. These are allowable options. Now, it makes sense that you'd want to specify the tempo. It just so happens that you can add fields to the Tempo event. One field, the BPM field, can be assigned the tempo in quarter notes per minute. Here's how to specify a tempo of 100 BPM at the start of a track (ie, measure 1, beat 1, 0 subbeats): 1: 1: 0 | tempo | BPM=100 The BPM field is optional. If you don't supply it, tempo defaults to 120 BPM. Although the Time and Event Type fields must be specified for an event, and both end with the | character, additional fields are optional. Additional fields should also be separated with the | character, but the | is optional after the last field. These rules of thumb apply to other event types as well. Furthermore, remember that blank space and capitalization are optional. So, you could write the above event as so: 1:1:0| TEMPO| bpm =100 The following sections list the defined Event Types. Each page contains one event type, such as the Tempo event. The text that you type into the Event Type field is listed (for example, Tempo). The additional, optional fields that can be added are also listed. A description of what the event is used for is included. Any particular deviations from the general rules of thumb for specifying an event are described. Finally, an example of the event as it might appear in a source code listing is given. ═══ 4.3.2.1. Off Note ═══ Type Off Note Occurs when You release a note that you previously pressed down on the MIDI unit (ie, cause the note to stop sounding). Other Fields The MIDI channel upon which the note was broadcast is assigned to the chan field. This will be 1 of 16 (ie, a number from 1 to 16). If you don't specify this field, it defaults to the same channel as the preceding event type which can be assigned to a channel (or channel 1 if no preceding event). In other words, if the preceding event is an On Note with channel 2, and you then follow it with an Off Note event omitting the chan field, it defaults to channel 2. The step of the 12 tone scale and octave that the note is (ie, C 3 is middle C) is assigned to the pitch field. Note that the bottom 2 octaves of the allowed MIDI note range are -2 and -1. The displays on some units count MIDI octaves from 0. If you don't specify this field, it defaults to the same pitch as the preceding event type which can be assigned a pitch (or C3 if no such preceding event). In other words, if the preceding event is an On Note of D#3, and you then follow it with an Off Note event omitting the pitch field, it defaults to D#3. Also, note that you use a lower case B (ie, b) to specify a flat. You can use double sharps and flats. The note name, sharp or flat, and octave components can be separated by blank spaces. For example C3 is the same as C 3. The velocity (ie, how quickly you release the key) is assigned to the vol field. This will be from 0 to 127. If you don't specify this field, it defaults to the same volume as the preceding On Note or Off Note (or 64 if no such preceding event). In other words, if the preceding event is an On Note with vol=44, and you then follow it with an Off Note event omitting the vol field, it defaults to 44. Note: Some MIDI units transmit Note On events with 0 velocity in lieu of Note Off events. Such events are represented by the (Off) Note event type (ie, the "Off" is enclosed in parenthesis) Examples 1: 1: 0 | Off Note | chan=1 | pitch=Db2 | vol=76 1: 2: 0 | Off Note | pitch=E 3 | vol=76 <- same chan as preceding event 2: 1: 0 | Off Note | vol=55 | chan=2 <- different order of fields, pitch is E3 ═══ 4.3.2.2. On Note ═══ Type On Note Occurs when You press down (ie, trigger) a note on the MIDI unit (ie, cause the note to sound). Other Fields The MIDI channel upon which the note was broadcast is assigned to the chan field. This will be 1 of 16 (ie, a number from 1 to 16). If you don't specify this field, it defaults to the same channel as the preceding event type which can be assigned to a channel (or channel 1 if no preceding event). In other words, if the preceding event is an On Note with channel 2, and you then follow it with an On Note event omitting the chan field, it defaults to channel 2. The step of the 12 tone scale and octave that the note is (ie, C 3 is middle C) is assigned to the pitch field. Note that the bottom 2 octaves of the allowed MIDI note range are -2 and -1. The displays on some units count MIDI octaves from 0. If you don't specify this field, it defaults to the same pitch as the preceding event type which can be assigned a pitch (or C3 if no such preceding event). In other words, if the preceding event is an Off Note of D#3, and you then follow it with an On Note event omitting the pitch field, it defaults to D#3. Also, note that you use a lower case B (ie, b) to specify a flat. You can use double sharps and flats. The note name, sharp or flat, and octave components can be separated by blank spaces. For example C3 is the same as C 3. The velocity (ie, how quickly you press down the key) is assigned to the vol field. This will be from 1 to 127. Note that 0 for a Note On volume really means that this is a Note off event. If you want that, use the (Off) Note event. A Note on event can't have a zero velocity, and if you specify that, MF_ASM will automatically generate a velocity of 1. If you don't specify this field, it defaults to the same volume as the preceding On Note or Off Note (or 64 if no such preceding event). In other words, if the preceding event is an On Note with vol=44, and you then follow it with a On Note event omitting the vol field, it defaults to 44. Examples 1: 1: 0 | On Note | chan=16 | pitch=A#-1 | vol=127 1: 2: 0 | On Note | pitch=E 1 | vol=76 <- same chan as preceding event 2: 1: 0 | On Note | vol=55 | chan=2 <- different order of fields, pitch is E1 ═══ 4.3.2.3. (Off) Note ═══ Type (Off) Note Occurs when You release a note that you previously pressed down on the MIDI unit (ie, cause the note to stop sounding). Other Fields The MIDI channel upon which the note was broadcast is assigned to the chan field. This will be 1 of 16 (ie, a number from 1 to 16). If you don't specify this field, it defaults to the same channel as the preceding event type which can be assigned to a channel (or channel 1 if no preceding event). In other words, if the preceding event is an On Note with channel 2, and you then follow it with an (Off) Note event omitting the chan field, it defaults to channel 2. The step of the 12 tone scale and octave that the note is (ie, C 3 is middle C) is assigned to the pitch field. Note that the bottom 2 octaves of the allowed MIDI note range are -2 and -1. The displays on some units count MIDI octaves from 0. If you don't specify this field, it defaults to the same pitch as the preceding event type which can be assigned a pitch (or C3 if no such preceding event). In other words, if the preceding event is an On Note of D#3, and you then follow it with an (Off) Note event omitting the pitch field, it defaults to D#3. Also, note that you use a lower case B (ie, b) to specify a flat. You can use double sharps and flats. The note name, sharp or flat, and octave components can be separated by blank spaces. For example C3 is the same as C 3. Note: This is essentially the same thing as an Off Note event, except that it is often more efficient for broadcast over MIDI to use this event in lieu of Off Note. The only advantage of Off Note is that it has a velocity field, which is useful only if your MIDI unit can make use of key release velocity (many units ignore it). Examples 1: 1: 0 | (Off) Note | chan=1 | pitch=Db2 1: 2: 0 | (Off) Note | pitch=E 3 <- same chan as preceding event ═══ 4.3.2.4. Aftertouch ═══ Type Aftertouch Occurs when You apply pressure to (ie, press down harder or softer on) the keys of a MIDI keyboard. Or, aftertouch can be generated in other ways by different controllers, such as a wind controller measuring changes in wind pressure. Other Fields The MIDI channel upon which the message was broadcast is assigned to the chan field. This will be 1 of 16 (ie, a number from 1 to 16). If you don't specify this field, it defaults to the same channel as the preceding event type which can be assigned to a channel (or channel 1 if no preceding event). In other words, if the preceding event is an On Note with channel 2, and you then follow it with an Aftertouch event omitting the chan field, it defaults to channel 2. The step of the 12 tone scale and octave of the note that this message affects is assigned to the pitch field. Note that the bottom 2 octaves of the allowed MIDI note range are -2 and -1. The displays on some units count MIDI octaves from 0. If you don't specify this field, it defaults to the same pitch as the preceding event type which can be assigned a pitch (or C3 if no such preceding event). In other words, if the preceding event is an On Note of D#3, and you then follow it with an Aftertouch event omitting the pitch field, it defaults to D#3. Also, note that you use a lower case B (ie, b) to specify a flat. You can use double sharps and flats. The note name, sharp or flat, and octave components can be separated by blank spaces. For example C3 is the same as C 3. The aftertouch amount is assigned to the press field. This will be from 0 to 127. If omitted, it defaults to the same value as any preceding Aftertouch event (or 0 if no such preceding event). Examples 1: 1: 0 | Aftertouch | chan=16 | pitch=A2 | press=127 1: 2: 0 | Aftertouch | press=76 <- same chan and pitch as preceding event 2: 1: 0 | Aftertouch | press=55 | chan=1 <- different order of fields, pitch is E1 ═══ 4.3.2.5. Controller ═══ Type Controller Occurs when You operate one of 128 different controllers. Other Fields The MIDI channel upon which the message was broadcast is assigned to the chan field. This will be 1 of 16 (ie, a number from 1 to 16). If you don't specify this field, it defaults to the same channel as the preceding event type which can be assigned to a channel (or channel 1 if no preceding event). In other words, if the preceding event is an On Note with channel 2, and you then follow it with a Controller event omitting the chan field, it defaults to channel 2. The controller number; from 0 to 127 is assigned to the contr field. This tells which one of the 128 controllers was operated. There are a number of defined controllers. There are also some undefined controllers. MF_DSM displays the controller number if the controller isn't defined, and if it's defined, a Controller ID is substituted instead. Here are the IDs for defined controllers: BankSw (Bank Switch -- some units have more than 128 patches, and use this to select one of several groups of 128 patches) Mod H (MOD wheel -- coarse) Wind H (Breath controller -- coarse) Foot H (Foot pedal -- coarse) PTme H (Portamento Time -- coarse) SlidrH (Slider -- coarse) Vol H (Volume -- coarse) Bal H (Balance -- coarse) Pan H (Pan -- coarse) Exp H (Expression -- coarse) Genr 1 (General Purpose Slider 1) Genr 2 Genr 3 Genr 4 Mod L (MOD wheel -- fine) Wind L Foot L PTme L SlidrL Vol L Bal L Pan L Exp L HoldPd (Hold pedal On/Off) Porta (Portamento On/Off) Susten (Sustenuto pedal On/Off) SoftPd (Soft pedal On/Off) Hold2 (Hold 2 pedal On/Off) Genr 5 (General Purpose Button 5 On/Off) Genr 6 Genr 7 Genr 8 Effect (Effects On/Off) Tremul (Tremulo On/Off) Chorus (Chorus On/Off) Celest (Celeste On/Off) Phaser (Phaser On/Off) Data + (Data button increment) Data - (Data button decrement) NRPN H (Non-registered parameter - coarse) NRPN L (Non-registered parameter - fine) RPN H (Registered parameter - coarse) RPN L (Registered parameter - fine) CtlOff (All Controllers Off) SndOff (All Sound Off) LocalK (Local keyboard On/Off) NoteOf (All Notes Off) OmniOf (Omni Mode Off) OmniOn (Omni Mode On) MonoOn (Mono Mode On) PolyOn (Poly Mode On) If you prefer, you can specify one of these IDs for the contr field, rather than the actual number. If you don't supply a controller number or ID, it defaults to the same controller as the preceding Controller event (or 1, ie, Mod H, if no preceding Controller event). The controller's value is assigned to the value field. This is a number from 0 to 127. For button types, 64 to 127 values are ON; 0 to 63 values are OFF. If you don't supply the value, it defaults to 0. Examples 1: 1: 0 | Controller | chan=1 | contr=Chorus | value=40 1: 2: 0 | Controller | value=76 <- same chan and cntrl as preceding event 2: 1: 0 | Controller | contr=2 <- controller 2 is set to 0 ═══ 4.3.2.6. Program ═══ Type Program Occurs when You change a patch/preset/instrument/etc. on the MIDI unit. Other Fields The MIDI channel upon which the message was broadcast is assigned to the chan field. This will be 1 of 16 (ie, a number from 1 to 16). If you don't specify this field, it defaults to the same channel as the preceding event type which can be assigned to a channel (or channel 1 if no preceding event). In other words, if the preceding event is an On Note with channel 2, and you then follow it with a Program event omitting the chan field, it defaults to channel 2. The program number; from 1 to 128 is assigned to the pgm # field. This tells which one of the 128 programs (or patches) on your MIDI unit is selected. MF_DSM also displays the patch name as it should be on a MIDI unit with a General MIDI patch set, as a comment at the end of the line. If you don't supply the Program number, it defaults to 1. Examples 1: 1: 0 | Program | chan=1 | pgm #=1 1: 2: 0 | Program | pgm #=128 <- same chan as preceding event ═══ 4.3.2.7. Poly Press ═══ Type Poly Press Occurs when You apply pressure to (ie, press down harder or softer on) the keys of a MIDI keyboard. Or, pressure can be generated in other ways by different controllers, such as a wind controller measuring changes in wind pressure. Note: The difference between Aftertouch and Polyphonic (Channel) Pressure is that the latter affects all notes currently sounding on the MIDI channel whereas the former only affects the one note that a particular Aftertouch event is associated with. Other Fields The MIDI channel upon which the message was broadcast is assigned to the chan field. This will be 1 of 16 (ie, a number from 1 to 16). If you don't specify this field, it defaults to the same channel as the preceding event type which can be assigned to a channel (or channel 1 if no preceding event). In other words, if the preceding event is an On Note with channel 2, and you then follow it with a Poly Press event omitting the chan field, it defaults to channel 2. The pressure amount is assigned to the press field. This will be from 0 to 127. If omitted, it defaults to 0. Examples 2: 1: 0 | Poly Press | chan=16 | press=127 2: 2: 0 | Poly Press | press=76 <- same chan as preceding event 3: 1: 0 | Poly Press | press=55 | chan=1 <- different order of fields ═══ 4.3.2.8. PWhl ═══ Type Pitch Wheel Occurs when You move the pitch wheel. Other Fields The MIDI channel upon which the message was broadcast is assigned to the chan field. This will be 1 of 16 (ie, a number from 1 to 16). If you don't specify this field, it defaults to the same channel as the preceding event type which can be assigned to a channel (or channel 1 if no preceding event). In other words, if the preceding event is an On Note with channel 2, and you then follow it with a Pitch Wheel event omitting the chan field, it defaults to channel 2. The pitch transposition is assigned to the bend field. This will be from -8192 to 8192. Negative numbers indicate that the pitch is being lowered, and positive values indicate that the pitch is being raised. A 0 indicates that the pitch wheel is centered (and therefore not transposing the pitch of the note). If you don't supply the bend amount, it defaults to 0. Examples 1: 1: 0 | Pitch Wheel | chan=4 | bend=-1000 1: 2: 0 | Pitch Wheel | bend=206 <- same chan as preceding event 2: 1: 0 | Pitch Wheel | <- same chan, centered ═══ 4.3.2.9. Sysex ═══ Type Sysex Occurs when The MIDI unit is sending some info that is specific to that unit, such as a dump of its patch memory or waveform data. Other Fields After the Sysex event type field, you must supply a len field, which tells how many data values are to be in this message (including the 0xF0 value that always starts a Sysex message). Sysex messages can be any length. Then, you specify each one of those values on the lines below that event line. In other words, a Sysex event can span any number of lines in the source code. You only need be certain that you supply as many values as the len indicates. You can place as many or as few values as you wish on each line. You can specify either decimal values or hexadecimal values (with an 0x prepended to indicate hex). Examples Assume that we wish to send the following hexadecimal values as a System exclusive message: F0 00 01 50 F7. (Note that all Sysex messages start with F0 and almost always end with F7). We wish to send this message on the 2nd measure, first beat. Note that there are 5 values in this message. 2: 1: 0 | Sysex | len=5 0xF0 0x00 0x01 0x50 0xF7 Note that I indented the values. You can add or remove blank spaces before or after any values. Also, note that I placed all of the values upon one line. I could have placed values on several lines, as so: 2: 1: 0 | Sysex | len=5 0xF0 0x00 0x01 0x50 0xF7 For this event type, it's best to place any comment lines only after all of the data value lines. ═══ 4.3.2.10. First Packet/Packet/Last Packet ═══ Type First Packet/Packet/Last Packet Occurs when The MIDI unit is sending some info that is specific to that unit, such as a dump of its patch memory or waveform data. Other Fields These 3 event types of First Packet, Packet, and Last Packet essentially amount to one Sysex event. It's just that some cheesy MIDI gear (like Casio trash) can't handle a complete Sysex message sent all at one time. It needs the Sysex message to be broken up into several pieces, each sent at specific times. So, the First Packet gets sent. It always starts with a 0xF0, but unlike the Sysex event type, it doesn't end with 0xF7. That's because this isn't the end of the system exclusive message yet. Each one of the Packet event types contains more data values. The Packet doesn't start with 0xF0, because it isn't the start of the system exclusive. (The First Packet was the start). Neither does the Packet end with 0xF7, because it isn't the end of the system exclusive (ie, there is more data to come). Eventually, the Last Packet is the final "chunk" of data. It ends with 0xF7. Confused? Well, so are the Casio engineers who thought up this aberration. Like the Sysex event, you must supply a len with each event type, and then specify the values on the lines below the event line. Examples 1: 1: 0 | First Packet | len=3 0xF0 0x00 0x01 2: 1: 0 | Packet | len=4 0x30 0x01 0x55 0x40 3: 1: 0 | Packet | len=1 0x20 4: 1: 0 | Last Packet | len=2 0x50 0xF7 For these event types, it's best to place any comment lines only after all of the data value lines. ═══ 4.3.2.11. Tempo ═══ Type Tempo Occurs when The tempo changes. Other Fields The tempo in "quarter notes per minute" (ie, BPM) is assigned to the BPM field. The tempo in "microseconds per quarter note" is assigned to the micros field. The micros field allows you to specify the tempo in fractions of a beat. Note: MF_DSM labels this field as micros\quarter which is also acceptable. You can specify both fields, and if you do, the micros field has precedence over the BPM field. (In other words, if you wish to change a tempo event of some source code produced by MF_DSM, and you want to change only the BPM field, then simply delete the micros field altogether). If you omit both fields, the tempo defaults to 120 BPM. If a Format 1 file, this event should only be placed in the first track. Examples 1: 1: 0 | Tempo | BPM=100 2: 1: 0 | Tempo | micros=500000 3: 1: 0 | Tempo | BPM=120 | micros=500000 <- micros has precedence 4: 1: 0 | Tempo | <- 120 BPM default ═══ 4.3.2.12. Time Signature ═══ Type Time Sig Occurs when The time signature changes. Other Fields The time signature is placed into its own field. The time signature is expressed as two numbers separated by a / character, such as 3/4 (ie, Waltz time). If you don't supply the signature, it defaults to 4/4. The number of MIDI clocks in a metronome click is assigned to the click field. This determines how often the metronome clicks. There always 24 MIDI clocks in a quarter note. So, to have the metronome click every quarter note, set click to 24. To click every eighth note, set click to 12 (ie, half of 24). Etc. Note: MF_DSM labels this field as MIDI-clocks\click which is also acceptable. The number of 32nd notes in a quarter note is assigned to the 32nds field. Generally, this will always be 8, but some notation programs allow different settings. Note: MF_DSM labels this field as 32nds\quarter which is also acceptable. If a Format 1 file, this event should only be placed in the first track. Examples 1: 1: 0 | Time Sig | 4/4 | click=24 | 32nds=8 2: 1: 0 | Time Sig | 6/8 | click=12 <- 6/8 time, metronome clicks every eighth You have be careful when changing the Time Signature, since that can invalidate the times of other, subsequent events in the track (or subsequent events in all other tracks in Format 1). For example, assume that you have the following: 1: 1: 0 | Time Signature | 4/4 1: 4: 0 | On Note | chan=1 | pitch=C3 | vol=127 You change the Time signature to 3/4. 1: 1: 0 | Time Sig | 3/4 1: 4: 0 | On Note | chan=1 | pitch=C3 | vol=127 Now you have a problem with the On Note event. It's supposed to be on the fourth beat of the first measure, but a song in 3/4 only has 3 beats in each measure. There is no fourth beat. If you want to maintain the original timing, that On Note would be on the first beat of measure 2. It only makes sense to place a Time Signature on the first beat of a measure. After all, how can you change a Time Signature in the middle of a measure? In other words, the beat and subbeat field of a Time Signature's Time field should always be 1 and 0 respectively. Only the measure number may be different. ═══ 4.3.2.13. Key Signature ═══ Type Key Sig Occurs when The key signature changes. Other Fields The key signature is contained in its own field. You specify the root note, and whether the key is Major or Minor. If you don't supply the key signature, it defaults to C Major. Examples 1: 1: 0 | Key Sig | G Major 2: 1: 0 | Key Sig | <- C Major default 3: 1: 0 | Key Sig | F# minor ═══ 4.3.2.14. SMPTE ═══ Type SMPTE Occurs at The SMPTE time needs to be set to a certain value. Other Fields The SMPTE hour is assigned to the hour field. If you don't supply this, it defaults to the same hour as the preceding SMPTE event (or 0 if no such event). The SMPTE minutes is assigned to the min field. If you don't supply this, it defaults to the same minute as the preceding SMPTE event (or 0 if no such event). The SMPTE second is assigned to the sec field. If you don't supply this, it defaults to the same second as the preceding SMPTE event (or 0 if no such event). The SMPTE frame is assigned to the frame field. If you don't supply this, it defaults to the same frame as the preceding SMPTE event (or 0 if no such event). The SMPTE subframe is assigned to the subs field. If you don't supply this, it defaults to the same subframe as the preceding SMPTE event (or 0 if no such event). Note: The range of the subframe field will depend upon the resolution of your SMPTE rate. Usually, the MThd's Division is expressed as a SMPTE rate, in which case, the subframe resolution is specified there. Examples 1: 1: 0 | SMPTE | hour=1 | min=30 | sec=10 | frame=1 | subs=1 ═══ 4.3.2.15. End of track ═══ Type End of track Occurs when The track is ended. Other Fields None. Every track must end with an End of track event. It must be the last event. The time of this event tells you exactly when the track stops playing. Make certain that you don't forget the | character after the event type. Examples 33: 1: 0 | End of track | ═══ 4.3.2.16. Seq # ═══ Type Seq # Other Fields The sequencer number is contained in its own field. This can be any number from 0 to 65,535. It's used to identify the track, and differentiate it from other tracks. If you don't supply the sequence number, it defaults to which track this happens to be (ie, the first track in your source code is 0). The track's name is assigned to the name field. This can be any amount of text. You should enclose the text between the characters < and > if you wish to place a comment at the end of the line or use numbers in the track name. If you use this event in a track, it must be the very first event in the track. You can only have one such event in the track. Two tracks should not have the same sequence number. Examples 1: 1: 0 | Seq # | 5 | name= ═══ 4.3.2.17. Text event ═══ Type Text event Occurs when At any point. Generally, the sequencer uses this event to display text to the enduser or to somehow "mark" or label something at a certain point in the song. Other Fields After the Text event event type field, you must supply a len field, which tells how many data values (ie, text characters) are to be in this event. Text events can be any length. Then, you specify each one of those values on the lines below that event line. In other words, a Text event can span any number of lines in the source code. You only need be certain that you supply as many values as the len indicates. You can place as many or as few values as you wish on each line. You can specify either decimal values or hexadecimal values (prepended with 0x) that represent the ascii characters. For example, an 'A' character is 0x41. You could specify some values as hexidecimal, and others as decimal. Alternately, you can write the actual text, enclosed between the characters < and >. If the text spans several lines, you must enclose each line's text with < and >. You could supply data values as well as text enclosed between < and > on the same line, but if so, MF_ASM uses one or the other, whichever comes first. In other words, if the data values are placed before the text enclosed within < and >, then the data values are used and the text is ignored. Note: MF_DSM notates Text events with both data values, followed by the equivalent text (ie, ascii characters) enclosed within < and >. If you want to subsequently edit a Text event, and you wish to make changes via the text, then simply delete the preceding data values. Examples 1: 1: 0 | Text event | len=5 0x48 0x65 0x6c 0x6c 0x6f note: data values followed by equivalent text 2: 1: 0 | Text event | len=5 note: only the text 3: 1: 0 | Text event | len=5 0x48 0x65 0x6c 0x6c 0x6f note: only the data values If desired, I could break up the data values and text onto multiple lines, as so: 1: 1: 0 | Text event | len=5 0x48 0x65 0x6c 0x6c 0x6f 3: 1: 0 | Text event | len=34 For this event type, it's best to place any comment lines only after all of the data value or text lines. In addition to the | character, don't use the < or > characters in the comments. Normally, a text event contains data values that are in the ascii range of printable characters (ie, 32 to 126). If MF_DSM disassembles a MIDI file that has a weird text event with a non-printable character in it, that character is replaced by the . (ie, dot) character. Consider the following: 1: 1: 0 | Text event | len=1 0x10 <.> The text indicates a . character, but if that were really meant to be a dot character, the data value would be 0x2E. What you have here is a replacement occurring. If you see a dot character in the text, check that the corresponding data value for it is 0x2E. If so, then that's really meant to be a dot character in the event. Otherwise, you'll have to deal with data values when editing the event, rather than being able to express it entirely as text. It's possible to express some lines starting with data values, and other lines starting with text. For example, assume that you wish to create a text event for the string Hello and null-terminate it (ie, add a zero byte to the end). 1: 1: 0 | Text event | len=1 0x48 0x65 0x6c 0x6c 0x6f note: text before data values so MF_ASM uses text 0x00 <.> note: data values before text so MF_ASM uses data values ═══ 4.3.2.18. Copyright ═══ Type Copyright Occurs when At any point. Generally, the sequencer uses this event to imbed a copyright message in the data file. Other Fields This is just a specialized version of a Text event. See Text event for details of how to supply the data values and/or actual text for the event. Examples 1: 1: 0 | Copyright | len=19 <(C) 1994 Jeff Glatt> ═══ 4.3.2.19. Lyric ═══ Type Lyric Occurs when A syllable of a word in the song's lyrics occurs. Scoring programs use this. Other Fields This is just a specialized version of a Text event. See Text event for details of how to supply the data values and/or actual text for the event. Examples 1: 1: 0 | Lyric | len=3 1: 3: 0 | Lyric | len=2 2: 1: 0 | Lyric | len=4 2: 3: 0 | Lyric | len=3 3: 1: 0 | Lyric | len=6 3: 2: 0 | Lyric | len=5 ═══ 4.3.2.20. Marker ═══ Type Marker Occurs when At any point. Generally, the sequencer uses this event to display text to the enduser or to somehow "mark" or label something at a certain point in the song. Other Fields This is just a specialized version of a Text event. See Text event for details of how to supply the data values and/or actual text for the event. Examples 3: 1: 0 | Marker | len=10 ═══ 4.3.2.21. Cue Point ═══ Type Cue Point Occurs when At any point. Generally, the sequencer uses this event to designate a special, non-MIDI event such as indicating a sampled waveform to load and play, or allowing the user to imbed cueing instructions in the MIDI file. Other Fields This is just a specialized version of a Text event. See Text event for details of how to supply the data values and/or actual text for the event. Examples 1: 1: 0 | Cue Point | len=12 1: 2: 0 | Cue Point | len=12 ═══ 4.3.2.22. Track name ═══ Type Track name Occurs when At the beginning of a track usually. The sequencer uses this event to designate a textual name for the track. Other Fields This is just a specialized version of a Text event. See Text event for details of how to supply the data values and/or actual text for the event. Note: If you specify a Seq # event with a name field, then you don't need to use this event. The Seq # event duplicates the function of this event. Of course, if you have multiple musical parts in one track (ie, a Format 0 file), you might want to specify the names of all parts in the track with numerous Track name events. Examples 1: 1: 0 | Track name | len=11 ═══ 4.3.2.23. Instrument ═══ Type Instrument Occurs when At the beginning of a track usually. The sequencer uses this event to indicate what kind of instrument might be playing the data in the track, such as a Piano. Other Fields This is just a specialized version of a Text event. See Text event for details of how to supply the data values and/or actual text for the event. Examples 1: 1: 0 | Instrument | len=5 ═══ 4.3.2.24. Unknown Meta ═══ Type Unknown Meta Occurs when ??? Other Fields This exists only in case some MetaEvent is added to the MIDI file specification in the future. In that case, you can use this to indicate that. This is just a specialized version of a Text event. See Text event for details of how to supply the data values and/or actual text for the event. But, this has an additional field that must be supplied; the Type field. This should be the type of that yet-to-be-defined MetaEvent. Examples Assume that a MetaEvent known as "Loop Iterations" is defined with a type of 0x0F. Perhaps it needs one data byte that specifies the number of times that a track is looped. Here's our event: 1: 1: 0 | Unknown Meta | type=0x0f | len=1 12 note: I specified decimal instead of hex. That's OK. ═══ 4.3.2.25. Specific ═══ Type Specific Occurs when ??? Other Fields A program would use this to store data that is specific (ie, Proprietary) to that program. For example, maybe a program wants to save a flag that indicates whether its "event list" window is displayed or its "score window". This is just a specialized version of a Text event. See Text event for details of how to supply the data values and/or actual text for the event. Examples Assume that a program wants to store an event that contains 1 data byte which specifies upon what MIDI channel the program recognizes controller messages sent to it (ie, for remote control). 1: 1: 0 | Specific | len=1 2 note: I specified decimal instead of hex. That's OK. ═══ 4.3.2.26. Escape event ═══ Type Escape event Occurs when At any time. This is used to imbed MIDI messages that normally aren't found in a sequencer data file, such as MIDI Common and Realtime messages, like Song Position Pointer. Other Fields This is just a specialized version of a Text event. See Text event for details of how to supply the data values and/or actual text for the event. Examples Assume that you want to imbed a MIDI Song Select message in a MIDI file. That has 2 bytes; the 0xF3 status, and a byte that indicates the song number. Let's make an event for song number 50. 1: 1: 0 | Escape event | len=2 0xF3 50 note: I mixed decimal with hex. That's OK. ═══ 4.3.3. Abbreviating the Event Type field ═══ You don't need to specify the entire Event Type field on an event line. You only need specify enough characters to distinguish the desired type. You can safely use a minimum of the first 3 characters of an event type in order to identify it. For example, instead of typing On Note, you can simply type On. Instead of typing Off Note, you can simply type Off. This saves some time when entering lots of events. ═══ 4.3.4. Omitting Time Components ═══ Let's assume that we have a Tempo event on measure 1, beat 1 (ie, right on the downbeat), followed by a Note off event upon the same measure, but on the third beat. Here are 2 such events, in the order that they must be listed: 1: 1: 0 | tempo | BPM=100 1: 3: 0 | note off | chan=1 | pitch=C3 | vol=100 Notice that both events are on measure 1. When an event is on the same measure as the preceding event, it's measure number can be omitted, as so: 1: 1: 0 | tempo | BPM=100 3: 0 | note off | chan=1 | pitch=C3 | vol=100 This blank space makes it easier to see that the second event is in the same measure as the preceding event. It doesn't matter if the preceding event is the same type or a different type. You can omit the measure field of an event if the preceding event, whatever the type, is on the same measure. Furthermore, if the preceding event is upon the same measure and beat, you can omit both the measure and beat for the second event. Let's assume that we have a third, note on event that occurs upon measure 1, beat 1, the second eighth of that beat (assume 192 Division). 1: 1: 0 | tempo | BPM=100 96 | note on | chan=1 | pitch=C3 | vol=100 3: 0 | note off | chan=1 | pitch=C3 | vol=100 Of course, if an event is upon the same measure, beat, and subbeat, you can omit all 3 fields. 1: 1: 0 | tempo | BPM=100 96 | note on | chan=1 | pitch=C3 | vol=100 3: 0 | note off | chan=1 | pitch=C3 | vol=100 | tempo | BPM=150 The above 150 BPM tempo event gets "played" upon the exact same time as the preceding note off event. When you have large amounts of events occurring upon the same measure, beats, and/or subbeats, omitting time components makes it much easier to see where the measure and beat boundaries occur. That makes editing easier. Furthermore, if you wish to move an entire excerpt of events to a new playback time (ie, maybe move all events in measure 4 over to measure 6), you'll have less time components to edit. You aren't required to omit time components. You can always specify the measure, beat, and subbeat for every event. But, doing otherwise can improve readability and make editing time fields easier. Furthermore, note that in order to omit the beat component, the measure component must also be the same as the preceding event. To omit the subbeat component, both the beat and measure components must be the same as the preceding components. ═══ 4.4. Unknown Chunk Header line ═══ A MIDI file may contain a chunk that is defined by the application that created the file. Obviously, the purpose and contents of that chunk would be unknown to any other application. An Unknown Chunk can occur anyplace that you might put a Track Header. (ie, It must come after the MThd Header line, and of course, you can't put an Unknown Chunk in the middle of a track's data). Every chunk must have an ID. This is 4, ascii characters that uniquely identify the chunk. For example, Xtra is a legal ID for a chunk. The only 2 ID's you can't use are MThd and MTrk, as these are already used for defined chunks in a MIDI file. Every chunk must also have a len which is how many data values (ie, bytes) are contained in the chunk. When MF_DSM encounters such a chunk, it displays an Unknown Chunk Header line with 3 fields. The first field contains the text Unknown Chunk. The second field contains the chunk's ID, enclosed with the characters < and >. The last field is the len. The data values are then displayed upon subsequent lines, with the equivalent ascii characters to the left, enclosed with the characters < and >. (ie, This is much the same layout as with text type of events). ═══ 5. Assembly Format ═══ Assembly is the process of taking a text file (ie, human readable "source code") describing events and headers in a MIDI file and converting it back into a MIDI (binary) file. MF_ASM does this. MF_ASM requires that you follow the guidelines used by MF_DSM in formatting your source code. In addition, MF_ASM also supports a few additional features that you can add to the source code which allows further processing. ═══ 5.1. Track Header fields ═══ As mentioned, the start of a track is indicated with a Track Header line. This is a line that must start with the text Track # usually followed by the number of the track. After this mandatory initial field, there are several other fields that can be added to the Track Header line. These fields apply to all events within that track, and offer numerous ways of easily processing the entire track as a whole. Just as with the Event lines and MThd Header line, a | character is used to separate the fields on the Track Header line. An = sign is used to assign values to fields. The | can optionally be omitted after the last field. For example, here's how you might specify a Track Header line with two of its possible, additional fields: Track #0 | transpose = -2 | chan=3 Note how the fields are separated by a | character. Optional fields (ie, after the Track # field) can appear in any order, and you may include any or all of the possible fields. Note: If editing a Track Header line created by MF_DSM, it's OK to leave the * filler characters at the end of the line. Note that whatever fields you include on a Track Header line only affect the events in those tracks, and not events in other tracks. So, you can have separate map and filter files, and various settings for each track. If you wanted a specific setting for all tracks in the source code, you'd have to add the appropriate field to every Track Header line. The following sections list each possible field that can be added to the Track Header line. Each page tells what the field's name is, what its purpose is, what values can be assigned to it, and gives an example of its use. ═══ 5.1.1. Chan ═══ Field Chan Purpose This is a global MIDI channel setting which will override the channel assignments of individual events in a track. In other words, it forces all MIDI events in the track to be on this one MIDI channel. If all of the events in a track happen to be for a single musical part (which is common in Format 1 files), it would make sense that all of the events would be on the same MIDI channel. In this case, the global chan can quickly reassign that musical part to a different channel. Values The desired MIDI channel is assigned to this field. This will be 1 of 16 (ie, a number from 1 to 16). Examples Track #0 | chan=12 <- Forces all events to MIDI channel 12 ═══ 5.1.2. Transpose ═══ Field Transpose Purpose Tranposes all of the On Note, Off Note, (Off) Note, and Aftertouch events in the track up or down by half steps. Values The transpose amount, in +/- half steps is assigned to this field. This will be a number from -127 to 127. Note: If you specify a transpose amount that happens to transpose a note out of the MIDI note range, MF_ASM will abort with an error. You'll have to locate that Event Line and change the note's pitch so that it remains in the legal note range after transposition (or delete the event if it isn't needed). Examples Track #0 | transpose=-1 <- transposes down a half step Track #0 | transpose=2 <- transposes up a whole step Track #0 | transpose = 12 <- transposes up an octave ═══ 5.1.3. Vol ═══ Field Vol Purpose Scales the volume (ie, note velocity) of all On Note and Off Note events in the track by a specified percentage. Since note velocity is most often tied to the VCA on most MIDI units, this effects an overall master volume control for the track. Values The volume percentage is assigned to this field. This can be any number from 1 to several thousand (although every note will be clipped using percentages > 12800). Percentages less than 100% lower the volume of a track. Percentages > 100% raise the volume of a track. A percentage of 100% is a special case. This signifies that you want MF_ASM to set all the volumes of all On Note and Off Note events in the track to the same volume as the first such event in the track. Thus, you can force all notes to a particular volume. Note: If a Vol > 100% causes some event's volume to be clipped (ie, MIDI velocity only goes up to 127), then MF_ASM will display a warning message but not abort. Clipping a MIDI note's volume doesn't cause "distortion" the way that an overloading amp might, but rather is more like a limiter. Examples Track #0 | vol=200% <- double the volume Track #0 | vol=50% <- halve the volume Track #0 | vol=100% 1: 1: 0 | On Note | pitch=C3 | vol=64 <- all volumes are forced to 64 ═══ 5.1.4. Exclude ═══ Field Exclude Purpose Allows you to specify a list of MIDI channels to filter. In other words, all events on those MIDI channels will be filtered out of the track when MF_ASM assembles the source code. This is useful for extracting particular musical parts from a track since most musical parts are entirely contained upon one MIDI channel. This also allows converting a Format 0 file (ie, one track which likely contains numerous MIDI channels) into Format 1 by assembling several versions of the original source listing, each with a different Exclude assignment, disassembling the resulting MIDI files into source listings, and combining those into a source listing with multiple tracks and Format=1. Values The MIDI channels that are to be excluded are assigned to this field. Each channel should be separated by a space or non-numeric character other than | or =. If you wish to place a comment after this field, it's best to end the field with the | character. Examples Track #0 | exclude= 1, 14, 15 | <-filters out events on channels 1, 14, and 15 Track # | exclude = 1 14 15 | <- same thing, with spaces instead of , ═══ 5.1.5. Options ═══ Field Options Purpose Specifies various options. Values The specific options that you desire are assigned to this field. Each option should be separated by a space. This field should always be ended with a | character. The allowable options are: 0vel -- This converts all Off Note events in the track to (Off) Note events which may reduce the size of the MIDI file or make it more efficient for playback over MIDI (assuming that the file has Off Note events in it). If your MIDI unit can't make use of key release velocity, you may as well use this option. off -- Causes MF_ASM to add (Off) Note events at the end of a track if any On Note events within it haven't been turned off. In other words, it turns off notes that might otherwise be "stuck" if you played back the track. If you're editing deleting or editing the note pitches of On Note events, remember that you also have to make the respective change to the subsequent Off Note or (Off) Note event that goes with that On Note. The opposite is also true. Furthermore, if you're changing around the order of events, make sure that you don't reverse the order of On Note and its respective Off or (Off). The Off or (Off) must come after the On. Finally, if you're inserting new On Note events, you have to make Off or (Off) events for them. This option will at least help account for sloppy editing that violates the preceding rules, and result in a MIDI file that doesn't have inherent stuck notes. (But, a note may end up held all of the way to the end of the track, which could be musically unpleasant). Note that MF_ASM also deletes Off or (Off) events that don't have a preceding On event. (In that case, a WARNING message is displayed). So, with this option, you're at least safe from stuck notes upon playing a MIDI file in which you've performed some of the described edits. Examples Track #0 | options = off | Just "off" option Track #0 | options = 0vel | <- Just 0vel option Track #0 | options = 0vel off | <- both options ═══ 5.1.6. Filter ═══ Field Filter Purpose Allows you to specify which Event Types are to be filtered from the track. You can filter any of the event types listed in the Disassembly Format's Event Type Field sections. For example, you can filter all Tempo event types from a track, making it possible to easily extract a "tempo map" from a Format 0's track. Or you can do other processing such as removing Aftertouch events, etc. Values You must create another text file (in addition to your source code) that contains a list of all the Event Types that you wish to filter out of the track. Each Event Type should be on its own line. You can use Event Type abbreviations if desired to save typing. Then, you assign the name of that text file to the Filter field. You should enclose the filename in double quotes and end the field with a | character. You may fully qualify the filename (ie, prepend the complete path as you would on a command line). Examples Assume that you wish to filter all note events (ie, On Note, Off Note, and (Off) Note) in a track. We'll create a text file called DataFile on the C: drive. This text file should contain those 3 Event Types, each on its own line, as so: On Note Off Note (Off) Note Now, we specify the Filter field as so: Track #0 | filter="c:\datafile" ═══ 5.1.7. Map ═══ Field Map Purpose Allows you to specify which note (and aftertouch) pitches get mapped to other note pitches, and also can specify which specific note (and aftertouch) pitches are to be filtered from the track. For example, you can filter all note and aftertouch pitches from C3 to C4, and remap any D5 note and aftertouch to F1. This is very useful for remapping drum note assignments, or filtering out musical parts that are all on the same MIDI channel (in different note ranges, such as a split-keyboard might produce). Values You must create another text file (in addition to your source code) that contains a list of all the pitches that you wish to remap, as well as any pitches that you wish to filter out of the track. Each pitch remapping or filtering should be on its own line. For remapping, you specify the pitch that you want to be remapped, followed by the pitch that you want it to be mapped to. Separate the two with an = sign. For pitch filtering, start with an = sign, and follow it with the pitch that you want filtered from the track. Examples For the following example, we'll always create a text file called DataFile on the C: drive. So, our Track Header would always look like: Track #0 | map = "c:\datafile" | Assume that you wish to remap all C4 pitches to D#5 and all B3 to F#-1. Here's what the data file should look like: C4 = D#5 B3 = F#-1 Note: Blank spaces can be added anywhere to improve readability, just like when you specify the pitch in your source code. Also, capitalization is optional. Assume that you wish to filter all D#5 and B3 pitches from the track. Here's what the data file should look like: = D#5 = B3 Assume that you wish to remap C4 to D#5 and filter F#-1. Here's what the data file should look like: C4 = D#5 = F#-1 It doesn't matter which order you specify pitches in the file (ie, low pitches before higher, etc). But, if you normally specify lower pitches first, then you can save typing on the pitch after the = sign (ie, destination pitch). If you omit the destination pitch, it defaults to one higher than the previous destination pitch. For example: C3 = C4 C#3 = ;C#3 is remapped to C#4 because the preceding destination pitch is C4 D3 = ;D3 is remapped to D4 because the preceding destination pitch is C#4 This also works on filtering. For example, here's how to filter all notes and aftertouch in the range C3 to B3 inclusive. = C3 ;filter C3 = ;filter C#3 because the preceding destination pitch is C3 = ;filter D3 because the preceding destination pitch is C#3 = ;filter D#3 because the preceding destination pitch is D3 = ;filter E3 because the preceding destination pitch is D#3 = ;filter F3 because the preceding destination pitch is E3 = ;filter F#3 because the preceding destination pitch is F3 = ;filter G3 because the preceding destination pitch is F#3 = ;filter G#3 because the preceding destination pitch is G3 = ;filter A3 because the preceding destination pitch is G#3 = ;filter A#3 because the preceding destination pitch is A3 = ;filter B3 because the preceding destination pitch is A#3 Note: If you wish to put comments in a map file, it would be best to preface them with a ; or /* character, or some other non alphabetic character (other than =). ═══ 5.2. Commenting the source ═══ Often, it's convenient to add comments to your source code which MF_ASM should ignore when assembling the code. Generally, comments are placed at the end of a line, or on a separate line. An important point is that you should never use the | character anywhere in a comment since this is used by MF_ASM to find the end of fields. Furthermore, if the comment is to appear at the end of an MThd Header, Track Header, or event line, you should not use the = character anywhere in a comment. There may be other exceptions for individual Event Types. For example, avoid using the / character in a comment at the end of a Time Signature event line. Avoid using the < or > characters in a comment at the end of any Text type of event (ie, Marker, Cue Point, Lyric, Instrument, etc). Generally, it's always safe to put a comment on its own line, begin the comment with some non alphabetic character (such as ;), and don't use the | character. Follow this policy, and your comments should be transparent to the assembler. ═══ 6. Error Messages ═══ Here are the possible error messages that you may see. Following each message is a description of likely causes for that error and possible remedies. ═══ 6.1. Memory Commitment Fail/Memory Allocation ═══ Synopsis The assembler and disassembler need to allocate some memory to do their work. Either of these 2 errors means that OS/2 did not grant that memory, and therefore the program can't continue. Cause Not enough free RAM in your system, and your swap file is full. Cure Terminate other programs that you don't need running. Buy more RAM. ═══ 6.2. Can't open input file ═══ Synopsis A file, that you asked MF_ASM to convert to MIDI, or that you asked MF_DSM to convert to text, didn't open. Cause The filename that you specified is incorrect. Cure Check the filename that you entered. Does it exist? Did you specify the path if it was needed? Cause Some other program has this filename currently in use, and is preventing SHARED access. Cure Make that other program close this filename. ═══ 6.3. Can't open the MIDI file to save ═══ Synopsis A file, that you asked MF_ASM or MF_DSM to create, didn't open. Cause The filename that you specified is incorrect. Cure Check the filename that you entered. Did you specify some directory that doesn't exist? The utilities only creates files; not new directories. Cause Some other program has this filename currently in use, and is preventing SHARED access. Cure Make that other program close this filename. Cause You chose to save data upon some media that is write-protected. Cure Remove the write-protection. ═══ 6.4. Format 0 can only have 1 Track ═══ Synopsis You've asked MF_ASM to assemble a source listing where you set the MThd's Format=0 but the # of Tracks is greater than 1. A Format 0 file can only have 1 track. Cure Either change the Format to 1 or 2 if you want more than one track in the file, or change # of Tracks to 1. ═══ 6.5. No MThd! Must not be a MIDI text file ═══ Synopsis MF_ASM can't find your MThd Header line in your source code. Cause You placed characters (other than spaces) before the MThd field of the MThd Header line. Cure Delete those characters. Cause You forgot to put an MThd Header line in your source code. Cure Put it in, dummy. Cause You didn't spell MThd properly. Capitalization isn't important, but you do need the correct letters. Cure Learn to spell. ═══ 6.6. Line XXX: Event time out of order ═══ Synopsis An event's time is out of order with respect to its placement in the source code. The XXX in the message will be the line number within the source code where the error occurred. Cause The event has a measure:beat:clock that puts it ahead of the event that is on the line above it. Cure You must place the events in the source code with respect to their time-stamps. The earliest events in a track are first after their Track Header line. Check the event before the erroneous event. Is the preceding event on a later measure number than the erroneous event? If the measures are the same, is the preceding event on a later beat number than the erroneous event? If the measures and beats are both the same, is the preceding event on a later clock number than the erroneous event? If so, reverse the order of the events. Cause That erroneous line was supposed to be a comment, but MF_ASM thought it was an event line, which it didn't make sense as. Cure Make sure that you didn't use the | character in your comment. Also make sure that you didn't forget the End of track event at the end of any track prior to where the error occurred. ═══ 6.7. Line XXX: Event time exceeds current time signature ═══ Synopsis An event's time is out of order with respect to the current time signature. The XXX in the message will be the line number within the source code where the error occurred. Cause You changed a Time Signature such that it invalidated some event time in a track, but neglected to resolve that invalidation. In other words, if an event supposedly occurs on beat 4 of some measure, and you change the time signature to 3/4 (ie, there is no fourth beat), then you invalidate the event's time. This could cause problems with MF_ASM calculating an event's time, and result in this error message. Furthermore, it's possible to also have problems with the subbeat component if you've changed the denominator of the time signature. For example, in going from 4/4 to 4/8, the beat changes from a quarter note to an eighth note. Therefore, at 192 PPQN, the beat goes from spanning 192 subbeats to spanning only 192/2 subbeats. If you have a subsequent event supposedly on the 97th subbeat of a beat, then you've got an invalid time. Cure Check the Time Signature event that comes before the erroneous event. (In a Format 1, all of the Time Signatures should be in the first track, and these determine time references for all tracks). That's the current time signature. Does the beat of the erroneous event jive with the Time Signature's "numerator"? Does the subbeat of the erroneous event jive with the Time Signature's "denominator"? ═══ 6.8. Line XXX: Number of bytes supplied is less than specified length ═══ Synopsis You didn't supply as many bytes as the len field indicates for some text event (ie, Text event, Marker, Lyric, Cue Point, Track name, etc) or an Unknown Chunk. The XXX indicates the line number in the source code where the erroneous event began (ie, on the first line of the event, before all of the subsequent data values or text). Cause The len field specifies more values than you intended, or you forgot to specify all of those values. Cure Check the len field of the event. Then, count how many values or text characters you've supplied. Make sure that the two match. Cause You specified text instead of data values, but forget to enclose the text inbetween < and > characters. Cure Make sure that the text is enclosed within < and >. If your text spans multiple lines, make sure that each line of text is separately enclosed with < and >. ═══ 6.9. Line XXX: Can't open map file ═══ Synopsis The filename that you supplied for a Track Header's map field can't be opened. The XXX indicates the line number where the erroneous Track Header occurs in the source code. Cause The filename that you specified is incorrect. Cure Check the filename that you entered. Does it exist? Did you specify the path if it was needed? Cause Some other program has this filename currently in use, and is preventing SHARED access. Cure Make that other program close this filename. ═══ 6.10. Line XXX: Can't open filter file ═══ Synopsis The filename that you supplied for a Track Header's filter field can't be opened. The XXX indicates the line number where the erroneous Track Header occurs in the source code. Cause The filename that you specified is incorrect. Cure Check the filename that you entered. Does it exist? Did you specify the path if it was needed? Cause Some other program has this filename currently in use, and is preventing SHARED access. Cure Make that other program close this filename. ═══ 6.11. map file line XXX: Note out of range ═══ Synopsis Some pitch listed in the map file is beyond the legal MIDI note range. For example G#33 is way out of range. The XXX indicates the line number upon which the bad pitch occurs in the map file. Cure Check the pitches specified on that line. If you have comments at the end of the line, try putting a ; character at the start of the comment to ensure that no numbers or letters in the comment are being misinterpreted as a pitch. ═══ 6.12. Line XXX: Bad channel for 'exclude' ═══ Synopsis One of the MIDI channels that you supplied for a Track Header's exclude field is not a legal MIDI channel number. The XXX indicates the line number where the erroneous Track Header occurs in the source code. Cause You specified a channel of 0 or a channel > 16. Cure MIDI channels are 1 to 16. Cause If the Exclude field is the last field on the Track Header line, a | character hasn't closed the field, and what follows is a comment, MF_DSM may be regarding numbers in the comment as MIDI channels. Cure End the Exclude field with the | character. Cause You separated the channels with more than one, non-space character (ie, exclude = 3 /// 14 /// 4). Cure Only use blank space to separate channels, or one non-space character. ═══ 6.13. Line XXX: Unknown 'option' SSS ═══ Synopsis One of the options that you supplied for a Track Header's options field is not a defined option. There are only 2; 0vel and off. The XXX indicates the line number where the erroneous Track Header occurs in the source code. Cause If the Options field is the last field on the Track Header line, a | character hasn't closed the field, and what follows is a comment, MF_DSM may be regarding text in the comment as options. Cure Always end the Options field with the | character. Cause You separated the options with a non-space character(s). Cure Only use blank space to separate options. ═══ 6.14. Line XXX: There are less Tracks defined than the '# of Tracks' indicates ═══ Synopsis There are less Track Header lines in your source code than your MThd Header's # of Tracks field indicates. The XXX indicates the line number where MF_ASM started searching for another Track Header which it expected to find but never did. Cause If your source does indeed have some Track Header line after the line number displayed in the error message, then you've probably made a mistake specifying the Track Header. Cure Make sure that the Track Header line begins with Track #, and that it is the first text on that line. Cause The MThd # of Tracks indicates more tracks than you intended, or you forgot to add that many Track Header lines to the source code. Cure Make sure that these conditions match. ═══ 6.15. Line XXX: Undefined Event Type ═══ Synopsis The second field of an event line (ie, the Event Type field) has some text that isn't recognized as one of the defined event types (as listed in the Disassembly Format's Event Type Field sections). The XXX indicates the line number where MF_ASM found an event type that it didn't understand. Cause That erroneous line was supposed to be a comment, but MF_ASM thought it was an event line, which it didn't make sense as. Cure Make sure that you didn't use the | character in your comment. Also make sure that you didn't forget the End of track event at the end of any track prior to where the error occurred. Cause You misspelled the Event Type. Cure Learn to spell. Cause You forgot the Event Type field entirely, or didn't place it as the second field. Cure Read this entire book again, dummy, this time with your eyes open. ═══ 6.16. Line XXX: Missing Event Type ═══ Synopsis MF_ASM encounters what appears to be an event line with only a Time field (ie, missing all other fields). The XXX indicates the line number where MF_ASM found the erroneous line. Cause That erroneous line was supposed to be a comment, but MF_ASM thought it was an event line, which it didn't make sense as. Cure Make sure that you didn't use the | character in your comment. Also make sure that you didn't forget the End of track event at the end of any track prior to where the error occurred. Cause You forgot the Event Type field entirely, or didn't place it as the second field. Cure Read this entire book again, dummy, this time with your eyes open. ═══ 6.17. Line XXX: No 'End of Track' event for Track ═══ Synopsis MF_ASM nevers found the required End of track event line at the end of a track. The XXX indicates the line number where MF_ASM might have expected such an event. Cure Make sure that the Track Header line before where the error occurred has a subsequent End of track event. ═══ 6.18. Line XXX: Sysex data byte has value > 127 (ie, 0x7F) ═══ Synopsis While processing a Sysex, First Packet, Packet, or Last Packet event, MF_ASM encountered a data value greater than 0x7F. This is not a legal value for a data byte in a sysex message (with the exception of the first and last bytes). The XXX indicates the line number where MF_ASM encountered the illegal value. Cause The len field of that event specifies more values than you intended, or you forgot to specify all of those values. Cure Check the len field of the event. Then, count how many values you've supplied. Make sure that the two match. Cause You have a comment at the end of the line which contains numeric characters (ie, 1 ,2, 3, etc). Cure For these Sysex events, it's best to place comments only after all of the data values. ═══ 6.19. Line XXX: Note transposed out of range ═══ Synopsis The pitch ended up being transposed above or below the legal MIDI note range. For example, transposing a C-1 more than 12 half steps down will cause it to be transposed out of range. The XXX indicates the line number upon which the out of range transposition occurred. Cure Change the pitch specified on that line so that it doesn't transpose out of range. Or, delete that event if it isn't needed. Or, change the Transpose amount for that track so that it doesn't force the event out of range. ═══ 6.20. Line XXX: Note out of range ═══ Synopsis The specified pitch for this event is beyond the legal MIDI note range. For example G#33 is way out of range. The XXX indicates the line number in the source code upon which the bad pitch occurs. Cure Check the pitch specified on that line. If you have a comment at the end of the line, make sure that the pitch field is ended with a | character, and that the comment doesn't contain | or = characters. ═══ 6.21. Line XXX: Unknown contr ID SSS ═══ Synopsis The controller ID text specified for the contrl # field isn't one of the defined ID's. The XXX indicates the line number in the source code upon which the erroneous event occurs. Cure Make sure that the ID you specified is one of the ID's specified on the Controller Event Type page. ═══ 6.22. Line XXX: N/D Time signature doesn't make sense ═══ Synopsis The time signature field of a Time Signature event is illegal. The XXX is the line number in the source code upon which the erroneous event occurs. N is the "numerator" that MF_ASM found, and D is the "denominator". Cure Make sure that you only specify 2, 4, 8, 16, 32 for the denominator. Don't specify a 0 numerator. ═══ 6.23. Line XXX: Bad KKK key signature ═══ Synopsis The key signature field of a Key Signature event is incorrectly specified. The XXX is the line number in the source code upon which the erroneous event occurs. KKK is the key that MF_ASM found. Cure Make sure that you only specify one of the following keys (in major or minor): Cb Gb Db Ab Eb Bb F C G D A E B F# C# ═══ 6.24. Had an error while saving the MIDI file ═══ Synopsis MF_ASM encountered an error trying to write data to the MIDI file that it is creating. Cause There is no more free space upon the media to which MF_ASM is writing. Cure Save to a drive or floppy with more free space. ═══ 6.25. Line XXX: Unknown field for event ═══ Synopsis While processing an event line, MF_ASM encountered some field containing a field name that it doesn't recognize for that event type. The XXX is the line number in the source code upon which the extraneous field occurs. Cause You misspelled a field name (ie, transpoze). Cure Learn to spell. Cause You used a | or = character in a comment at the end of the event line. Cure Do not use either of these characters in a comment at the end of any event line. Cause You used a field name that doesn't belong to this event. For example, a Poly Press event does not have a Pitch field even though an On Note event does. Cure Consult the appropriate section in the Event Types to determine what field names a particular event allows. ═══ 6.26. Line XXX: Deleting a note-off without a matching note-on before it ═══ Synopsis While processing an Off Note or (Off) Note event line, MF_ASM recognizes that this event does not have a respective On Note event preceding it. MF_ASM therefore deletes this Off or (Off) Note since it has no purpose in the track. The XXX is the line number in the source code upon which the extraneous event occurs. Cause You deleted the preceding On Note for this (Off) or Off. Cure Remember to always delete On Note and Off or (Off) events in pairs. Every On Note must have a subsequent Off or (Off) on the same channel and with the same pitch. Cause You edited the Chan and/or Pitch fields of the preceding On Note for this (Off) or Off without making the same changes to the Off or (Off). Cure Make sure that each On Note is paired with a subsequent Off or (Off) event on the same channel and with the same pitch. ═══ 6.27. Line XXX: Unknown field for MThd Header ═══ Synopsis While processing an MThd Header line, MF_ASM encountered some field containing a field name that it doesn't recognize for the MThd. The XXX is the line number in the source code upon which the extraneous field occurs. Cause You misspelled a field name (ie, # of traks). Cure Learn to spell. Cause You used a | or = character in a comment at the end of the MThd Header line. Cure Do not use either of these characters in a comment at the end of any event line. Cause You used a field name that doesn't belong to the MThd. For example, the MThd Header does not have a Chan field. Cure Consult the MThd Header line section to determine what field names an MThd Header allows. ═══ 6.28. Line XXX: Unknown field for Track Header ═══ Synopsis While processing a Track Header line, MF_ASM encountered some field containing a field name that it doesn't recognize for the Track Header. The XXX is the line number in the source code upon which the extraneous field occurs. Cause You misspelled a field name (ie, transpoze). Cure Learn to spell. Cause You used a | or = character in a comment at the end of the Track Header line. Cure Do not use either of these characters in a comment at the end of any event line. Cause You used a field name that doesn't belong to the Track Header. For example, the Track Header does not have a Format field. Cure Consult the Track Header Fields section to determine what field names a Track Header allows. Cause You forget the | character at end of a field that requires it (ie, the fields that require filenames such as map or filter need to be terminated with a |, even if at the end of the Track Header line). Cure Make sure that there's a | character at the end of each field. ═══ 6.29. Line XXX: Unknown field for Unknown Chunk ═══ Synopsis While processing an Unknown Chunk, MF_ASM encountered some field containing a field name that it doesn't recognize. The XXX is the line number in the source code upon which the extraneous field occurs. Cause You misspelled a field name (ie, length instead of len). Cure Use the abbreviation. Cause You used a | or = character in a comment at the end of the line after the Unknown Chunk Header. Cure Do not use either of these characters in a comment at the end of any event line. Cause You used a field name that doesn't belong to the Unknown Chunk. The Unknown Chunk only has 2 fields; the ID and len fields. Cure Consult the Unknown Chunk Fields section to determine what field names an Unknown Chunk allows. ═══ 6.30. Line XXX: Unwritten Track Header ═══ Synopsis MF_ASM encountered more Track Header lines than the MThd # of Tracks indicates. The XXX is the line number in the source code upon which the extraneous Track Header line occurs. Cause The MThd # of Tracks indicates less tracks than you intended, or you forgot to remove extra Track Header lines (and their events) from the source code. Cure Make sure that these conditions are resolved. ═══ 6.31. Line XXX: Volume Clipped ═══ Synopsis The volume supplied for an On Note or Off Note was beyond 127. It was therefore clipped to 127. The XXX is the line number in the source code of the event whose volume was clipped. Cause You set the Track Header's Vol to a very high percentage such that clipping occurred. Cure Lower the percentage, or lower the individual vol field of the event that clipped. Cause You specified a vol greater than 127. Cure Observe that upper limit. ═══ 6.32. Line XXX: The following notes haven't been turned off for Track XXX ═══ Synopsis The end of a track was reached and there were On Note events in the track which didn't have subsequent, matching Off or (Off) events (ie, with the same Chan and Pitch). MF_ASM simply displays this warning message. If you invoke the off Option field in the Track Header line, then MF_ASM will automatically generate the missing Off Note events. The XXX is the Track # which has "stuck notes" in it. MF_ASM then also displays which notes on each of the 16 possible MIDI channels in a track are "stuck on". Cause You deleted the respective Off Note for an On Note without also deleting that On Note. Cure Remember to always delete On Note and Off or (Off) events in pairs. Every On Note must have a subsequent Off or (Off) on the same channel and with the same pitch. Cause You edited the Chan and/or Pitch fields of an Off Note without making the same changes to its preceding, respective On Note. Cure Make sure that each On Note is paired with a subsequent Off or (Off) event on the same channel and with the same pitch. ═══ 6.33. Doesn't contain a MThd. Not a MIDI file ═══ Synopsis You tried to disassemble a binary file that isn't a MIDI file. All MIDI files must begin with an MThd header. This one doesn't and so it isn't a MIDI file. ═══ 6.34. Found misplaced running status. ═══ Synopsis While disassembling a MIDI file, MF_DSM discovered an aberration in the format of some event in a track. This may be a corrupt file. ═══ 6.35. Found an undefined status in the MIDI file ═══ Synopsis While disassembling a MIDI file, MF_DSM discovered an aberration in the format of some track. This may be a corrupt file. ═══ 6.36. This is a mal-formed MIDI file ═══ Synopsis While disassembling a MIDI file, MF_DSM discovered an aberration in the format. This may be a corrupt file. ═══ 6.37. Line XXX: Possibly less data values than len indicates ═══ Synopsis While processing a Sysex, First Packet, Packet, or Last Packet event, MF_ASM encountered what appears to be less data values specified than the event's len indicates. The XXX indicates the line number where MF_ASM expected more data values, but instead found a line that looks like the next event line. Cause The len field of that event specifies more values than you intended, or you forgot to specify all of those values. Cure Check the len field of the event. Then, count how many values you've supplied. Make sure that the two match. Cause You have a comment which contains a | character. Cure For these Sysex events, it's best to place comments only after all of the data values, and don't use the | character. ═══ 6.38. Line XXX: Possibly less data values or text than len indicates ═══ Synopsis While processing a text type of event (ie, Track name, Instrument, Marker, Cue Point, etc), MF_ASM encountered what appears to be less data values or text specified than the event's len indicates. The XXX indicates the line number where MF_ASM expected more data values or text, but instead found a line that looks like the next event line. Cause The len field of that event specifies more values or text characters than you intended, or you forgot to specify all of those values. Cure Check the len field of the event. Then, count how many values or text characters you've supplied. Make sure that the two match. Cause You have a comment which contains a | character. Cure For these text events, it's best to place comments only after all of the data values or text, and don't use the | character. Cause You omitted the closing > character at the end of a line's text. Cure Make sure that each line upon which you specify the actual text (as opposed to data values representing those ascii characters) has < and > characters enclosing the text.