|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
News |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
1. Introduction |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Mscore is a MIDI scoring tool for Linux. Its capabilities include
The Mscore suite of scripts was designed with the idea of creating MIDI tools for Linux compatible with Csound and compatible with the Ascore utility. A third consideration was to create low level components that do as little as possible (functionality broken up into many separate modules) and do not have built-in graphical interfaces. The components may then be used in different combinations and easily interfaced to other components. Consider how the unix operating system was designed; consider how the ALSA sound system was designed, and you will understand what I had in mind. My thinking for these tools is to have (eventually) a GUI as a separate component which helps to visually consolidate the configuration of the low level components. You use the GUI to automate similar, repeated configurations but don't let it get in the way of batch processing. Above and beyond the preceding considerations, this tool was intended to provide the MIDI musician with a way to see, and work with, the MIDI notes aligned in a time-synchonized fashion. The notes in each MIDI track are listed in parallel columns down the page, and any notes on the same line start at the same time. I looked around for other Linux MIDI tools before I started on this one. I think Midge is especially impressive. You may find Midge easier to use than Mscore. But I needed the parallel tracking arrangement of the notes, so I embarked on writing my own tool. This afforded me the opportunity to make Ascore a front end for Mscore. As you will see, Mscore can be a stand-alone scoring tool. But any some ways it might be viewed as an intermediate file type. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
2. Why Mscore? |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
An Mscore MIDI score is an ASCII text file with a specially defined MIDI language that arranges notes in parallel "tracks" so that note synchronization can be seen visually. The following example shows a typical representation. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0.587647* @3{55__0.587647*}70 @8{36__0.587647*}100 | 0.587663* @3{60__0.587647*}70 | @10{42__0.587647*}100 0.587633* @3{62__0.587647*}70 @8{36__0.587647*}95 | 0.587633* @3{55__0.587647*}70 | @10{42__0.587647*}90 0.587667* @3{60__0.587647*}70 | @10{38__0.587647*}85 0.587633* @3{64__0.587647*}70 | @10{42__0.587647*}80 0.587667* @3{62__0.587647*}70 @8{36__0.587647*}90 | 0.587633* @3{55__0.587647*}70 | @10{42__0.587647*}85 0.587667* @3{60__0.587647*}70 @8{36__0.587647*}90 | 0.587633* @3{62__0.587647*}70 | @10{42__0.587647*}100 0.587633* @3{55__0.587647*}70 @8{36__0.587647*}95 | 0.587667* @3{64__0.587647*}70 | @10{42__0.587647*}90 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The above piece of score contains three MIDI tracks and a timing column at the far left. Every line contains notes that start at the same time. The * symbol represents an eighth note. On the first line, 0.587647* is a 0.587647 fraction of an eighth note and is the amount of time that will elapse before the following line is played. The note representation contains four non-whitespace delimited, order-dependent parameters that represent the MIDI channel, the MIDI note number, the note duration and the MIDI velocity number. Consider the note in column 2 (track 1) on the first line: |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@3{55__0.587647*}70 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The symbols in this note specification have the following meaning:
Notice the separators
There is no whitespace (spaces or tabs) in the note specification. The "|" symbol in the above code block means that the note in the preceding line is still playing, or that there is a rest. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
3. Score Layout |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There is a rough correspondence between the structure of a MIDI file and the layout of the Mscore score file. The exception to that similarity is that tracks in a MIDI file are contained in separate blocks, or chunks. The notes in each track are not interlaced according to start times as they are in the Mscore score. Aside from that, the parameters and their positions in the score follow the MIDI sequence of events. There are basically two sections: the header and the list of notes. The header starts with 3 global parameters followed by setup parameters for each track:
The follow header example might be used for the above notes section: |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
MIDI_FORMAT multi_track TRACKS 3 TICS_PER_BEAT 220 0 META TK1 MIDIPORT 0 0 META TK1 TEMPO 100 0 META TK1 TIME_SIGNATURE 04 02 36 08 0 MIDI TK1 CH3 CT7 VL80 0 META TK1 TEXT Dummy Note 0 META TK2 MIDIPORT 0 0 META TK2 TEMPO 100 0 META TK2 TIME_SIGNATURE 04 02 36 08 0 MIDI TK2 CH8 CT7 VL80 0 META TK3 MIDIPORT 0 0 META TK3 TEMPO 100 0 META TK3 TIME_SIGNATURE 04 02 36 08 0 MIDI TK3 CH10 CT7 VL80 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The lines following the the three global parameters are MIDI events. While these should be included as headings to each track, they are not necessarily required. Also, these MIDI events may be interspersed with the MIDI notes. Combining the header and notes block, the following example represents the Mscore score layout: |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# # A complete Mscore score # # Header Block # # MIDI_FORMAT multi_track TRACKS 3 TICS_PER_BEAT 220 0 META TK1 MIDIPORT 0 0 META TK1 TEMPO 100 0 META TK1 TIME_SIGNATURE 04 02 36 08 0 MIDI TK1 CH3 CT7 VL80 0 META TK1 TEXT Dummy Note 0 META TK2 MIDIPORT 0 0 META TK2 TEMPO 100 0 META TK2 TIME_SIGNATURE 04 02 36 08 0 MIDI TK2 CH8 CT7 VL80 0 META TK3 MIDIPORT 0 0 META TK3 TEMPO 100 0 META TK3 TIME_SIGNATURE 04 02 36 08 0 MIDI TK3 CH10 CT7 VL80 # # # Notes Block # # 0.587647* @3{55__0.587647*}70 @8{36__0.587647*}100 | 0.587663* @3{60__0.587647*}70 | @10{42__0.587647*}100 0.587633* @3{62__0.587647*}70 @8{36__0.587647*}95 | 0.587633* @3{55__0.587647*}70 | @10{42__0.587647*}90 0.587667* @3{60__0.587647*}70 | @10{38__0.587647*}85 0.587633* @3{64__0.587647*}70 | @10{42__0.587647*}80 0.587667* @3{62__0.587647*}70 @8{36__0.587647*}90 | 0.587633* @3{55__0.587647*}70 | @10{42__0.587647*}85 0.587667* @3{60__0.587647*}70 @8{36__0.587647*}90 | 0.587633* @3{62__0.587647*}70 | @10{42__0.587647*}100 0.587633* @3{55__0.587647*}70 @8{36__0.587647*}95 | 0.587667* @3{64__0.587647*}70 | @10{42__0.587647*}90 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
4. MIDI Events |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Notice that after the three global parameters the setup parameters for each track follow with a start time at the far left column. The track 1 parameters are given with the keyword TK1. Likewise, the track parameters for tracks 2 and 3 are given by TK2 and TK3. These track parameters all translate into MIDI events in the MIDI file. I am using the term MIDI event broadly. In the General Midi file specification, events are subclassed as MIDI, META and SYETEM EXCLUSIVE. As such, "MIDI events" are a specific group of events that include note on, note off, program change, control change, and others. The "META events" are things like tempo, time signature, track name and text information. The "SYSTEM EXCLUSIVE events" are manufacturer-specific messages for controlling a synthesizer. With the exception of the MIDI notes, all events in the Mscore score are given with the same general syntax:
In the case of META events, the 4th argument is the name of the event, such as TEMPO, and the parameters are hexidecimal byte sequences (this is low-level MIDI). In the case of MIDI events, the 4th argument is the channel (1-16), and the parameters are 2 keyword-number fields that specify the type of MIDI event and its value. For example, |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0 MIDI TK3 CH10 CT7 VL80 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Is a controller 7 change (volume) with value 80 (range 0-127) on MIDI channel 10 in track 3 The controller numbers as given in the range 0 to 127. A program change event (changing the synthesizer preset number) does not include the VLnn (e.g., VL80) field. The program numbers are numbered 0 to 127. For example, |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0 MIDI TK3 CH10 PG22 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
will change the channel 10 preset number to 22, where the first preset would be numbered 0. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
5. Event Types |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
You should consult your low-level General MIDI specification. Events are divided into subcatagories.
The MIDI events are the most commonly use events for controlling a synthesizer. They include the following list:
Mscore combines the NOTE ON and NOTE OFF messages into a single note representation as shown above. The special MIDI events, that is, the non-note events are coded in Mscore using the following two-character keywords:
As shown above these keywords given by combining these two-character codes with a 7-bit number into a single token. For example, control change 7 (volume change) is CT7, and program change to 22 is PG22. These codes can be followed by a data value, depending on which code is being used. The data value is given in Mscore by combining the two-character code VL with a 7-bit number to create a single token. KP, CT and PB events require a data value, whereas PG and CP do not. The numbers combined with these character codes are decimal numbers. The number combined with CT, for example, ranges from 0 to 127, and the number combined with VL ranges from 0 to 127. The META events are also given a start time and track number. Here is the list of META events.
Some of these META events have string arguments, such as TEXT. Others have arguments that are raw byte values from the file. For example, the SEQUENCER_SPECIFIC values are a hexidecimal byte dump. There are several META events for which I saw no useful purpose, and so they are included but represented as raw data. Of these, TIME_SIGNATURE and KEY_SIGNATURE use a sequence of decimal bytes. SMPTE_OFFSET and SEQUENCER_SPECIFIC are followed by a sequence of hexidecimal bytes. As of the current build of Mscore you will have to translate these yourself if you use them. The exception is TEMPO, which is given as the decimal beats per minute.
The SYSEX (system exclusive) events are obviously handled as raw hexidecimal byte sequences. As of the current version, the SYSEX, SYSCM (system common) and SYSRT (system real-time) events are ignored, because these are usually found only in real-time MIDI keyboard control. I have yet to encounter a MIDI file with these codes. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
6. Creating a MIDI File |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
To create a MIDI file you must first create an ascii text score with the above syntax and format--an Mscore score. You then convert this score file, say "scorefile", into a hex dump with the mscore.awk script as follows: |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Or, another way to run it would be |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The result, tempfile.hex, will be an ascii text file that is a single column of hexidecimal 8-bit numbers. When this file is converted into a binary file you have a MIDI file. You can use your own program if you like, or perhaps the GNU hexdump program does that? If not, a hex to binary converter is provided in the Mscore package called hexxer.c. Compile this simple C program, then run it as follows: |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Note that the argument "b" is necessary for using hexxer to convert ascii to binary. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
7. MIDI Dumps |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
To start with an existing MIDI binary file, that is, a "standard midi file" (SMF) and create an ascii text dump of the file you can use the utility mid2score.awk included in the Mscore package. However, you must first convert the binary file into a hex dump file. The hexxer.c utility in the Mscore package can be used for that according to the following syntax: |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Then convert the ascii hex dump into an equivalent Mscore score file with the following command: |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The following example listing was produced with the mid2score.awk tool from a MIDI file downloaded from the Yamaha ES6 keyboard synthesizer's sequencer. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# ----------------- # MIDI SCORE FILE # generated by mid2score.awk (Alfred Steffens Jr. 2007) # mid2score ver. 1.03 # ----------------- # # Unix Text MIDI_FORMAT single_track (0) TRACKS 1 TICS_PER_BEAT 480 # sequencer specific event # total events 149 0 META TK1 SEQUENCER_SPECIFIC 43 7b 0 58 46 30 32 0 2 0 META TK1 TRACKNAME 0 META TK1 TEMPO 120 o META TK1 TIME_SIGNATURE 04 02 24 08 # ----------------- q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 q @1{38__0.9!}100 q @1{36__0.9!}100 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
You can get a dump that shows the hex bytes as they are translated into Mscore statements by giving the debug_messages argument to mid2score.awk as follows: |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
An example of re-running the above MIDI dump using the debug_messages=1 argument can be found here. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
8. Csound to MIDI |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Converting a Csound score into a MIDI file can be done with the Mscore package using a tool called cs2mtx.awk (CSound 2 Midi TeXt). A Bash shell script, cs2mtx.sh, is provided that illustrates how this is done. Csound scores are simple (to a programmer) structures that just contain rows of notes in ascii text format. The first three columns in the score are assumed to have standard meaning: the instrument, the start time, and the duration. Any columns after that have an arbitrary meaning depending on your particular score. The first thing that must be done to the Csound score is to sort the lines according to start time. There is an AWK script included in the Mscore package to help do this: cs2sort.awk. The output from the sorter is then given as input to cs2mtx.awk. There are some command-line arguments that need to be passed to cs2mtx.awk in order to resolve ambiguities: you need to specify how instruments are assigned to MIDI channels. The following example shows the command-line arguments to cs2mtx.awk for a particular Csound orchestra. You would change this to meet your own needs: |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The tempo is given with the bpm argument. The argument with "tracks" is saying that the first track will be assigned to MIDI channel 1, the second track to MIDI channel 10 and the third track to MIDI channel 2. This argument is obviously order-dependent. The argument specifying "drums" says assign instruments 50, 51, 52, 53, 54, 55, 56, 57 to MIDI channel 10 (drums). The argument that starts with "alias2" say that MIDI channel 2 will be assigned to instruments 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42. The list of instruments in these arguments is independent of order. The "nshift" argument will shift the pitch of track 1 up by 12 half tones, track 2 by 0 half tones and track 3 by 12 half tones. This argument is obviously order-dependent. Care must be taken that no whitespace should appear in these comma-separated arguments. The columns of the resulting Mscore body may be aligned with the supplied utility, malign.awk, a code beautifier. Now the appropriate Mscore header is added with the help of another AWK script called mtxheader.awk. The information that was used in the call to cs2mtx.awk can be used again for creating the header. The mtxheader.awk script takes similar arguments. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The program (preset numbers) for tracks 1, 2 and 3 will be 34, nothing and 0. The volumes for tracks 1, 2 and 3 will be 80, 60 and 80. These two files, header.mtx and body.mtx, are simply concatenated. The resulting Mscore score can then be converted into the ascii hex representation of the SMF using mscore.awk, then transformed into the binary MIDI file with hexxer. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
9. File Descriptions |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The script tools included in the Mscore are shown in the following list.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Download Mscore |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Lastest version is 1.2
The installation package is just a set of awk scripts and shell scripts. When the tar-gzip file is unpacked it creates a directory called mscore (not mscore-1.2) and copied the files into it. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|