Ascore

A Csound Scoring Front End
1. Introduction 2. Time Symbols 3. Note Patterns 4. Start Time
5. Multi-Note Patterns 6. Simultaneous Notes 7. The Track Section 8. Example 1
9. Building the Score Download Advanced Ascore HOWTO Example 2

News

  • September 10, 2009
    Ascore upgrade ver. 4.3

    Ascore enhancements for use as a MIDI front end to Mscore.


1. Introduction

Ascore allows you to create your Csound score visually. You specify pattern names in columns down the page, and each column represents a "track" in the score. For example,

7* Lovely_Melody % %
* | % Trumpet_Notes
3q % Strings |
q Lovely_Melody | %
5* | % %

The above portion of an Ascore "score" section contains 3 "tracks", being the 3 columns starting with Lovely_Melody. The leftmost column is the score's timing track which must consist only of note duration symbols. This structure gives a crude pictorial view of the music as it occurs in time. For instance, Lovely_Melody is a note pattern (previous defined--see below) that starts first. After 7 eighth notes have elapsed, Trumpet_Notes begins. After another eighth note has elapsed, Strings begins. A "|" symbol means that the note pattern above it is still playing. A "%" symbol is a rest symbol. At any row in the score, the current time is given by the sum of all duration symbols in the rows above it. Thus, when Lovely_Melody starts for the second time above 8 eighth notes (7* = 7 eighth notes, * = 1 eighth note) and 3 quarter notes (3q = 3 quarter notes) have already elapsed.

Observe that this accomplishes the most important goal of any Csound front end: you don't need to calculate the note start times by hand. The above block of tracks may be cut-and-pasted into another section of the score as-is without having to worry about score times.

This representation in terms of "tracks" accomplishes, what I consider to be, the second most important goal of a Csound front end: keeping track of the synchronization of different instruments and score sections. Note that the track columns have significance only with respect to the time symbol on the left-hand side of the page. Every pattern found on the same line will start at the same time. The time symbol on the left tells how much time will elapse before the next line is started. If the pattern duration lasts for 4 eighth notes, and the time symbol on the left is one eighth note, then the next line will start while the current line is still playing.



2. Time Symbols

One of the most difficult aspects of working with raw Csound scores is keeping track of the time. In Ascore you keep track of time with relative time symbols. These symbols are musical notes durations such as quarter notes, half notes, etc. You don't have to calculate the time for any of these symbols. They are calculated for you based on the value of the global TEMPO statement that must be at the top of your file. In the timing track of the score section the current time in the score is the sum of all the time duration symbols that precede the current row. In the above example there are five rows. If you append a sixth row at the bottom of the score its note pattern will begin at time (7*) + (*) + (3q) + (q) + (5*), which is 7 eighth notes plus 1 eighth note plus 3 quarter notes plus 1 quarter note plus 5 eighth notes. Thus, the sixth row begins after a time equal to 21 eighth notes.

The TEMPO is in units of beats per minute, where one beat is a quarter note. The duration symbols are

! sixteenth
* eighth
q quarter
h half
o whole



3. Note Patterns

A note pattern is the basic unit given on a score line. Patterns are sequences of notes, and notes are specified by a list of variables or literal numbers that form a Csound score line. Consider the following Csound score line:

i8 0 0.6 0.9 7.02

where p1 is the instrument number, p2 is the start time, p3 is the duration, p4 is the amplitude, and p5 is the pitch. You would define this line as a one-note pattern in Ascore with the following code:

set MyNote & 8 & q 0.9 7.02

The "set" keyword is used to define a variable or list of variables. In a note pattern definition the first element in the list is a local tempo specifier. In the above example, the tempo is given as "&" which means use the global TEMPO. The remaining elements in the list after the tempo specifier have the same order and meaning as the Csound score line. The second elemnt is the instrument number. The third element is the start time. Notice that in the example an "&" symbol is used for the start time. This means that the note starts at the current score time (the sum of the duration symbols in all rows preceding it), so you don't have to keep recalculating the time in seconds. The fourth element is the duration, and here we see the relative duration symbol for a quarter note, again so that you don't have to calculate time in seconds. The fifth element in the list is the amplitude, and the sixth element is the pitch. These values are given as literal numbers, but you can also specify them as variables. Consider the following variable definitions:

set AmpNormal 0.9
set FirstPitch 7.02

Now the note pattern definition can be rewritten with these new variables:

set MyNote & 8 & q AmpNormal FirstPitch

Any other note pattern definition can now use these variables.

Now "MyNote" can be listed in the track section as a pattern to be played.



4. Start Time

In the above examples we saw that the starting time of a note can be specified as the current score time by using the "&" symbol. This "relation symbol", as I call it, is actually a simple linear function that can have a gain and an offset. Specifying "&" is equivalent to writing the following psuedo code

(1 * &) + 0

or, 1 times the current score time plus 0 seconds (the "*" above means multiplication, which is why I say psuedo code). This way you can make subtle modifications to the note starting time such as


0.95&

&+1.01

2.5&+0.001

The syntax of the relation symbols requires that the gain (multiplier) be written with no multiplication symbol so that "2 times &" must be written as "2&" not as "2*&" (the "*" symbol is already used as a duration symbol). Also, there may not be any whitespace between the gain, "&", and offset specifiers.

The offset to a relation symbol can be either a literal number in units of seconds or a duration symbol.


&+[5*]

means the current score time plus 5 eighth notes. The duration symbols must be enclosed in square brackets in a start-time definition.



5. Multi-Note_Patterns

In the above section on Note Patterns we saw how a single-note pattern is defined. It resembles a score line in Csound but with some symbolic replacements. Try to imagine that a Csound score (for the same instrument) is a matrix: each p-field on a line is a separate column of the matrix, and each following line in the score (for the same instrument) is a separate row of the matrix.

i3 0 1 0.7
i3 1 1 0.6
i3 2 1 0.5
i3 3 1 0.4
i3 4 1 0.3

In Ascore, to define a pattern with more than one note, the pattern definition contains column names in place of p-fields. This means that each column must have its own definition, with an entry corresponding to each note in the pattern. For the above sequence of Csound notes the column containing the instrument numbers could be defined as follows:

set ins_a1 3 3 3 3 3

and the column containing the duration times could be defined as follows:

set dur_a1 1 1 1 1 1

But let's say that the note duration of 1 second corresponds to a tempo in which a quarter note is 1 second. Then the duration column would be defined as

set dur_a1 q q q q q

The column containing the amplitudes could be defined as follows:

set amp_a1 0.7 0.6 0.5 0.4 0.3

We could define the columns containing the start time with the following definition:

set str_a1 0 1 2 3 4

however, simply putting numbers for the note start times would defeat the primary purpose of a Csound front end. Instead, for the start time column we define the following definition:

set str_a1 & & & & &

which means that each note starts when the previous note ends. But we can simplify this further by setting the first relation symbol (the "&"), and Ascore will back-fill the column with the last symbol found until all notes are represented.

set str_a1 &

So now we can define the above Csound sequence of notes as a single pattern:

set ins_a1 3
set str_a1 &
set dur_a1 q
set amp_a1 0.7 0.6 0.5 0.4 0.3
set Pattern_a1 & ^ins_a1 ^str_a1 ^dur_a1 ^amp_a1

and now "Pattern_a1" can be listed in the track section as a pattern to be played.

The "^" symbol that is prepended to the column name means that the array is transposed (like in matrix algebra!). If the transpose symbol were not used, then each array would be substituted into "Pattern_a1" across instead of down. That would result in the pattern having many columns but only one row.

At last, notice the single "&" symbol preceding the "ins_a1" entry. This entry represents the local tempo. It means that, withing this pattern only, use this for the tempo. The "&" symbol means simply to use the global song tempo. We did not create an array definition for the local tempo since it doesn't change in the pattern. In fact, we could have simply put a "&" for the start time entry in the "Pattern_a1" line. The "&" symbol will be back-filled into all the notes at compile time.



6. Simultaneous Notes

There are two start time symbols: "&" and "@". The "&" in the above examples is the current score time but also relative to the current note pattern. If the note pattern contained, say, two notes, then the "&" in the second note's start time means "the current score time PLUS the duration of all preceding notes in this pattern". You can think of "&" as a sequential start time for notes in a pattern. If each note in a pattern is defined with "&" as the start time, then the notes follow one after the other in time.

The second start time is the "@" symbol. It means the absolute score time. If all notes in a pattern are defined with "@" as the start time then they all start simultaneously. You can thing of "@" as a parallel start time for notes in a pattern. It would be used for defining a piano chord, for example. Also, if you want notes to overlap, then you would use the "@" start time symbol with offsets:

@ @+[q]

which says that the first note starts at the absolute current score time and the second note starts at the same time, but after a quarter note duration. If the first note was defined with a half note duration, then the second note would start while the first note was still playing.



7. The Track Section

Any line in the Ascore (.asc) file that begins with a time duration symbol

! * q h o

is regarded as a track line. The TEMPO and TRACKS must be defined before any track lines are read.

TEMPO 100
TRACKS 3

The "#" symbol is a comment character.

When you don't want to compile the whole score but work only on some short passage, you can easily "comment out" the other parts of the score by using the SKIPSCORE and STARTSCORE keywords. Every score line after SKIPSCORE is found will be ignored until a STARTSCORE line is found.



8. Example 1

The following simple example illustrates the use of Ascore. (Note: the following example has changed since the 3.5 version. Ascore now requires a BEGIN statement as well as an END statement.)


#	-----------------------------------------------------------
#	ex1_ascore.asc, A. Steffens Jr.,  5/23/2006
#
#	ascore example 1
#	-----------------------------------------------------------
#
#   
#   timing symbols:
#   ---------------
#   ! = 16th note
#   * = 8th note 
#   q = quarter note
#   h = half note
#   o = whole note
#   & = current score time, or current tempo
#   @ = parallel score time
#
#
#	pitch
#	---------------
#	8.00 = middle C in Csound
#
BEGIN


#   ----------------------
#   global volume slider
#   ----------------------
set Amp 1.0


#   -------------------------------
#   volume slider for instrument 1
#   -------------------------------
eval PAmp $Amp * 0.7


#
#   volume macros for instrument 1
#
eval pamp025        $PAmp * 0.25
eval pamp050        $PAmp * 0.5
eval pamp075        $PAmp * 0.75


#	------------------------------------------------------------
#	Pattern 1, instrument 1
#
set ins_pn1_1	1
set str_pn1_1	&
set dur_pn1_1	* q * q q
set amp_pn1_1	$pamp075 $pamp075 $pamp050 $pamp050 $pamp075
set pch_pn1_1	8.00  8.02  9.00  8.10  8.00
#
#
set pn1_rf_1	&  ^ins_pn1_1  ^str_pn1_1  ^dur_pn1_1  ^amp_pn1_1  ^pch_pn1_1
#	------------------------------------------------------------


#	------------------------------------------------------------
#	Pattern 2, instrument 1
#	(same as pattern 1, but up an octave---add 12 to the pitch
#	column)
#
child pn1_rf_2 pn1_rf_1   6  k+  12
#	------------------------------------------------------------


#	------------------------------------------------------------
#	Pattern 3, instrument 1
#	(same as pattern 1, but up with instrument 2 (multiply column
#	2 by 2)
#
child pn1_rf_3 pn1_rf_1   2  *  2
#	------------------------------------------------------------



#   ------------------------------------------------------------
#   a header file that is in Csound .sco format
#   must be done before any score lines
#	THIS IS WHERE FTABLES AND EVERYTHING ELSE THAT IS NOT A NOTE
#	DEFINITION IS INSERTED.
#
HEADER header.sco
#   ------------------------------------------------------------



#	------------------------------------------------------------
#	Score Tracks
#	------------------------------------------------------------
#
#	Tempo is 100 beats per minute
#
TEMPO 100
#
#	Start out with 1 "track", patterns 1 and 2 follow each other
#	then rest for 1 eighth note
#	Then let pattern 1 and 3 play at the same time in two tracks
#	Then rest for a quarter note
#	Then start pattern 1 playing in one track, and let pattern
#	2 start after 3 eighth notes have elapsed.
#	
#
TRACKS 1
#
o      pn1_rf_1
o      pn1_rf_2
#
*          %
#
TRACKS 2
#
o      pn1_rf_3      pn1_rf_1
#
q          %             %
#
3*     pn1_rf_1          %
5*         |         pn1_rf_3
3*         %             |
#
#
#	------------------------------------------------------------
#	end  Score section
#	------------------------------------------------------------


#	------------------------------------------------------------
#	append the Csound "e" to the score
#
END
#	------------------------------------------------------------



9. Building the Score

Ascore is an AWK script. It doesn't get any harder than this brothers and sisters:

    cat  ex1_ascore.asc   |   awk  -f  ascore.awk

    mv  hold.sco  ex1_ascore.sco
    

Ascore writes its output to a temporary file called hold.sco. Now compile ex1_ascore.sco with Csound.



Ascore HOWTO


Contents
  1. How to Create a Basic Score

  2. How to make a comment line

  3. How to define a variable

  4. How to create a pattern

  5. How to make chords and simultaneous notes

  6. How to set the number of pattern tracks

  7. How to skip a section of the score

  8. How to skip specific tracks in the score

  9. How to shift the MIDI note numbers on a given channel

  10. How to send MIDI data to multiple ports

  11. How to program aplaymidi to send MIDI data to multiple ports

  12. How to set a MIDI voice patch

  13. How to set the voice patch with a bank switch

  14. How to insert conditional _IFDEF_ statements

  15. How to change voice effects on a Yamaha ES-6

  16. What is the Yamaha ES6 MSB and LSB in terms of MIDI commands?

  17. How to use System Exclusive MIDI messages

  18. How to change tempo within a pattern

  19. How to insert MIDI control inside a pattern

  20. How to suppress all MIDI channels but one with a single statement

  21. How to Set Bank Switch Statements for Different Synthesizers

  22. How to Ramp (fade) a Midi Control Parameter




HOWTO
  1. How to Create a Basic Score

    The basic score must have these elements:

    1. A "BEGIN" statement
    2. One or more pattern definitions
    3. One or more score lines
    4. An "END" statement

  2. How to make a comment line

    Any line that starts with a "#" symbol is ignored as a comment.

  3. How to define a variable

    An ascore "variable" is a simple word that holds a number or text string for later use in a pattern or a score line.

    set Amp 1.0

    creates a variable called "Amp", case sensitive, that holds the value of 1.0.

    set aval1 2.5

    creates a variable called "aval1" with a value of 2.5.

    set amp_bb_1 0.1 1.102 2.1

    creates a variable called "amp_bb_1" that is an array of values 0.1, 1.102, and 2.1.

    set pan_gt $aval1 $aval2 $aval1 $aval6

    creates a variable called "pan_gt" with references to the eval operations in aval1, aval2, aval6.

    A variable can be created that is the result of an arithmetic operation on another variable by using the "eval" keyword:

    eval hamp020 $Amp * 0.020

    creates a variable called "hamp020" whose value is the value previously stored in "Amp" multiplied by 0.020. The operator can be *, /, +, -. The second value can also be a reference to a variable, for example,

    eval hamp020 $Amp * $bFactor

    Also, the variable references appearing in the eval statement may themselves be the result of eval definitions: the values are not resolved until the matrix is dumped to the Csound score.

    Performing variable operations with ASCORE is very limited--this is not a full-blown programming language. It is just a set of simple rules that get parsed by an AWK script. The ascore.awk file was initially written in about three days as a quick-and-dirty means of creating Csound scores. The fact that it is based upon a modular software design has made ascore.awk a powerful, very easy to improve utility. But we must remember to manage our expectations in regards to its programability.

  4. How to create a pattern

    A "pattern" is a variable that ascore.awk turns into a sequence of Csound-like score lines. If you are unfamiliar with Csound, the following description will help understand an ASCORE pattern.

    A musical note in a Csound score is given as a line (a row) in the score file in which each element (each column) controls some aspect of the note, such as pitch, duration, amplitude, velocity, effect depth, etc. In Csound nomenclature each control element is referred-to with the letter "p" and a number giving its sequential location on the line. For example,

    i4 0.41 2.0 8.01 0.75 101 0.92

    is discussed in the literature as

    p1 p2 p3 p4 p5 p6 ..... pN

    where p1 = "i4" would mean instrument 4; p2 = 0.41 would mean the start time in the score is at 0.41 seconds after the beginning; p3 = 2.0 would mean the duration of the note is 2.0 seconds; p4 = 8.01 would mean a pitch corresponding to the C# just above middle C, etc. Since a Csound score can be written only with numbers, as in the score line above, we can see how hard it would be to write music with Csound without using a "front-end" to write the score. The ascore.awk tool is a "front-end" for writing a Csound score.

    The basic idea that motivated the creation of the ascore.awk tool is that successive lines in a Csound score form a matrix, like in matrix algebra. The following Csound score lines,

    i4 0.41 2.0 8.01 0.75 101 0.50
    i4 0.83 1.0 8.05 0.70 121 0.61
    i4 1.27 2.0 8.03 0.72 89 0.73
    i4 1.96 1.0 8.11 0.64 111 0.87

    form a "matrix" of Csound p-fields with 4 rows and 7 columns. This matrix can be created as an ASCORE pattern: rows are successivre notes, and columns are Csound p-fields. Each column is a parameter that defines that instrument's sound.

    A pattern, in ASCORE, is created by defining a variable that holds an array of columns. For example,

    set bb_rf_11 & ^ins_bb_11 ^stt_bb_11 ^dur_bb_11
    ^key_bb_11 ^vel_bb_11 pad5
    ^amp_bb_11 ^pan_bb_11

    The variable "bb_rf_11" is created to be a note pattern with 9 columns:

    & = column 1
    ^ins_bb_11 = column 2
    ^stt_bb_11 = column 3
    ^dur_bb_11 = column 4
    ^key_bb_11 = column 5
    ^vel_bb_11 = column 6
    pad5 = column 7
    ^amp_bb_11 = column 8
    ^pan_bb_11 = column 9

    The variables ins_bb_11, stt_bb_11, dur_bb_11, key_bb_11, vel_bb_11, amp_bb_11, pan_bb_11 are arrays that are interpeted as columns not rows, because they are prepended with ^ (carat) symbols.

    The variable pad5 is not interpreted as a column because it is not prepended with a ^. The variable pad5 will be expanded as a row. This row will form the top of a set of columns in the pattern. Each of these columns formed by pad5 will have the same values in every row, because ASCORE will back-fill any column with the last value found (in that column) in order to make every column have the same number of rows. This means that the & symbol in the first column of the pattern will be repeated to create a column with the same number of rows as the largest column given.

    The Csound score lines shown above could be created with an ASCORE pattern, named "pattn", whose definition is shown below:

    The first column in the pattern, shown with the "&" symbol above, is always the local tempo. Setting it to a "&" symbol just means use the default tempo of the score. The second column in the pattern, shown above with ^instrm, must always be the instrument number, and it becomes the first column in the Csound score that is output. The next 2 columns must be start time and duration, respectively, as mandated by the Csound program. The remaining columns may be in whatever order you prefer.

    The above variable definitions for the columns: start, dur, key, ampl, veloc, pan, are simplified by giving raw numbers in the definition. Usually, you will put variable references instead of raw numbers. For example, the note durations will be given with duration symbols:

    set instrm 4
    set start 0.41 0.83 1.27 1.96
    set dur 2.0 1.0 2.0 1.0
    set key 8.01 8.05 8.03 8.11
    set ampl 0.75 0.70 0.72 0.64
    set veloc 101 121 89 111
    set pan 0.50 0.61 0.73 0.87
    set pattn & ^instrm ^start ^dur ^key
    ^ampl ^vel ^pan
    set dur o h o h

    being "whole note", "half note", "whole note", "half note". The amplitudes are better given with variables so that whole sections can have their amplitudes adjusted simultaneously:

    set ampl $ja01 $ja01 $ja01 $ja01

    where the variables ja01, ja02, ja03, ja04 would have been defined somewhere above the pattern with definitions such as the following

    set JAmp 0.95
    eval ja01 $JAmp * 0.1
    eval ja02 $JAmp * 0.2
    eval ja03 $JAmp * 0.3
    eval ja04 $JAmp * 0.4

    See the section on note duration symbols and tempo symbols.

  5. How to make chords and simultaneous notes

    Chords are created by using a special symbol for the start time in a pattern definition. When a pattern is created, the start time list can be literal times, in seconds, or start-time symbols. There are two different start time symbols: an "&" symbol and an "@" symbol. The ampersand ("&") symbol is used for sequential notes, and the "@" symbol is used for simultaneous notes. So you must use the "@" symbol for chords. You must not mix these two kinds of symbols in the same pattern.

    For example:

    set stt_bb_1 & & & & & &

    defines a list (named stt_bb_1) of six notes having sequential start times. This means that the notes in this pattern will be ordered to start one after another, sequentially. The whole pattern starts whenever this pattern appears in the score. This is a sequencer style of note pattern. It was designed to make scoring note patterns easy--the next start time is calculated for you. On the other hand,

    set stt_cc_1 @ @ @ @ @ @

    defines a list (named stt_cc_1) of simultaneous notes. The "@" symbol can be adjusted so that the simultaneous notes can be staggered to imitate real-world variations (nothing is really simultaneous). This is done by adding delays to the "@" symbols in the start time list. For example,

    set stt_cc_1 @ @+[!] @+[q] @+[h] @+[o]
    @+[2o]

    makes the simultaneous pattern into a sequential pattern with the second note delayed by a sixteenth note (!), the third note delayed by a quarter note (q), the fourth note delayed by a half note (h), the fifth note delayed by a whole note (o), and the last note delayed by two whole notes.

    Here is how I get the effect of a guitar chord strummed:

    set stt_ff_1 @ @+[0.1!] @+[0.15!] @+[0.2!]
    @+[0.25!] @+[0.3!]
  6. How to set the number of pattern tracks

    The "TRACKS" variable must be set before any score lines are read. This is just a simple mechanism to tell the parser how many tracks to expect. For example,

    TRACKS 3
    7* my_pattern_1 drums_4 horns_2b
    o | % horns_1
    5* my_pattern_1 drums_5 horns_3

    Whatever the "TRACKS" variable is set to, there must be TRACKS+1 fields on the line (the left-hand time column plus the track columns). The "TRACKS" variable can be set as often as needed. For example, each line may be preceded by a "TRACKS" statement:

    TRACKS 3
    7* my_pattern_1 drums_4 horns_2b
    TRACKS 2
    o | horns_1
    TRACKS 4
    5* my_pattern_1 drums_5 % horns_3

    (Programmers may complain that I didn't have to make a TRACKS variable--the code could have been written so that the number of columns are automatically detected and processed--and I agree, but this is a "consistent coding enforcement" B S that I am imposing on you because I can--it keeps the score section well organized.)

  7. How to skip a section of the score

    In the score section, which specifies the columns of tracks and a left hand timing column,

    q guitar_part_1 sax_part1
    3* | sax_part2
    * guitar_note_1 |
    2q % %
    o hold_guitar_note sax_run_1

    lines of the score may be temporarily "disabled", or skipped so that you don't have to replay the whole score each time you work on one little pattern. Place the statement SKIPSCORE on a line by itself, and every score line that follows will be skipped until a line containing STARTSCORE is found. In the example above, let's say we want to work on the last line:

    o hold_guitar_note sax_run_1

    Then we would use the SKIPSCORE, STARTSCORE keywords as in the example below,

    SKIPSCORE
    q guitar_part_1 sax_part1
    3* | sax_part2
    * guitar_note_1 |
    2q % %
    STARTSCORE
    o hold_guitar_note sax_run_1

    These key words may be used as often as is needed in the score to select specific section to "blank out" of the score. Also, repeated occurrences of STARTSCORE are ignored until another SKIPSCORE is found. Likewise, repeated occurrences of SKIPSCORE are ignored until the next STARTSCORE is found, so that sloppy score editing will not break the score(!).

  8. How to skip specific tracks in the score

    In order to "comment out" certain tracks use the "SKIPTRACK" statement. On the line immediately above the score section where the tracks are to be skipped, insert the statement

    SKIPTRACK <list of track numbers>

    and when you want to turn those tracks back on, use the SKIPTRACK statement but without any track numbers. For example,

    TRACKS 3
    q guitar_part_1 sax_part1 flute_part_7
    3* | sax_part2 |
    * guitar_note_1 | piano_run_4
    2q % % %
    o hold_guitar_note sax_run_1 %

    If we want to "comment out", say, the last two tracks to here what the first track sounds like by itself we would use the following syntax:

    TRACKS 3
    #
    # turn of the second and third tracks
    #
    SKIPTRACK 2 3
    q guitar_part_1 sax_part1 flute_part_7
    3* | sax_part2 |
    * guitar_note_1 | piano_run_4
    2q % % %
    o hold_guitar_note sax_run_1 %
    #
    # restore all tracks
    #
    SKIPTRACK
  9. How to shift the MIDI note numbers on a given channel

    In the code block that assigns MIDI channel to instrument number, specify an "nshift" paramemter. It specifies the number of MIDI note numbers (half tones) to offset the note number given in the Ascore score. For example, the following code is used to assign your Csound instrument number 11 to midi channel 2.

    CS2MTX midi_channel 2 instrument 11

    now use the following line to cause all notes sent to this channel to be offset (down) by an octave:

    CS2MTX midi_channel 2 nshift -12
  10. How to send MIDI data to multiple ports

    Use MIDI channels greater than 16. MIDI channels 1-16 correspond to MIDI port 0, channels 17-32 correspond to MIDI port 1, etc.

  11. How to program aplaymidi to send MIDI data to multiple ports

    aplaymidi -p 16:0,20:0 midi_file

    will make Alsa midi port 16:0 the "port 0" and Alsa midi port 20:0 the "port 1" port. This is also how it is done with pmidi.

  12. How to set a MIDI voice patch

    For a general instrument, the following line issues a program change midi command at the start of the playback (in the header of the midi file):

    CS2MTX midi_channel 5 program 93

    where the command is issued to midi channel 5 (numbered 1-16) and to program (voice) number 93 (numbered 0-127).

    To issue a program change command after the playback has already begun, insert a line like the following line into the score section where you want the change:

    PROGRAM 7 5

    where the command is issued to midi channel 5 and program (voice) number 7 (numbered (0-127).

  13. How to set the voice patch with a bank switch

    Bank switching typically requires one or more midi control messages just prior to the program change message. Consult your synthesizer midi reference. The following explanation uses the Yamaha ES6 as the example instrument. (see also, How to Set Bank Switch Statements for Different Synthesizers).

    In the code block that assigns MIDI channel to instrument number, specify an the "bank" and "program" paramemters. For example, to set the "GnarlyBs" voice (bank pre 2, group F, number 14 ==> voice 094), use the following code lines in the same code block that assigns midi channel to the Csound instrument number.

    CS2MTX midi_channel 5 bank 1
    CS2MTX midi_channel 5 program 93

    notice that bank numbers and program numbers are 1 less than what they are on the keyboard control panel.

    To issue a program change command after the playback has already begun, insert a line like the following line into the score section where you want the change:

    CONTROL BANK_MSB 63 5
    CONTROL BANK_LSB 1 5
    PROGRAM 93 5

    where the command is issued to midi channel 5 and program (voice) number 93 (numbered (0-127). The two CONTROL statements issue the bank switch command. The BANK_MSB is always 63 for voice banks, and BANK_LSB is 0=PRE1, 1=PRE2, 2=PRE3, 3=PRE4, 4=PRE5, 5=PRE6, 8=USR1, 9=USR2. For drums BANK_LSB will be 32. To select the ES6 General Midi patches use BANK_MSB=0, BANK_LSB=0. For the General Midi drums: BANK_MSB=127, BANK_LSB=0.

  14. How to insert conditional _IFDEF_ statements

    Sections of the Ascore file may be wrapped in "conditional compilation" statements (like #ifdef in the C language). The following psuedo code illustrates how they are used:

    _IFDEF_ Mode_1
    code lines
    _ELSE_
    code lines
    _ENDIF_

    The lines between _IFDEF_ Mode_1 are included in the macro if variable Mode_1 is defined somewhere above it with the special syntax,

    _DEFINE_ Mode_1

    If no _DEFINE_ Mode_1 is found in the preceding code, then the code between _ELSE_ and _ENDIF_ is included.

  15. How to change voice effects on a Yamaha ES-6

    Reverb Send:

    CONTROL YM_EF1 <value> <ch>

    or

    CONTROL 91 <value> <ch>

    changes the Reverb Send (effect1) where value = 0-127.

    Chorus Send:

    CONTROL YM_EF3 <value> <ch>

    or

    CONTROL 93 <value> <ch>

    changes the Chorus Send (effect3) where value = 0-127.

    For example,

    CONTROL 91 86 4

    sets the reverb send on MIDI channel 4 to a value of 86 (counting from 0 to 127).

  16. What is the Yamaha ES6 MSB and LSB in terms of MIDI commands?

    MSB is a CONTROL 0 command, and LSB is a CONTROL 32 command. For example, sending a BANK_MSB command could be done in either of the following two ways:

    CONTROL BANK_MSB 63 7

    or

    CONTROL 0 63 7

    and the BANK_LSB command could be done as follows:

    CONTROL BANK_LSB 2 7

    or

    CONTROL 32 2 7
  17. How to use System Exclusive MIDI messages

    Warning: system exclusive messages require a user agent (i.e., your midi playback program) that supports system exclusive. For example, on Linux the the ALSA driver "sequencer" interface, which is what aplaymidi and pmidi are built upon, does not support system exclusive messages. Since the ASCORE / MSCORE system basically creates a midi file, it requires you run your midi player program to control your midi instruments. That midi player must support system exclusive messages (good luck).

    Use

    SYSEX <channel> d0 d1 d2 … dn

    where d0 d1 ... are upper-case, 2-digit hexidecimal numbers.

    Warning: this feature is experimental. If it does not work on your synthesizer, that is because this feature is untested. On the other hand, you will find that this feature is not often needed. Most instrument control is done with the midi channel control messages. System exclusive commands are used for things like data dumps and reprogramming patch banks.

  18. How to change tempo within a pattern

    Normally, tempo is changed with the TEMPO keyword in the score section. But this methos only changes the tempo for all notes that follow. Within an individual pattern the tempo can be changed so that only that particular pattern is affected. Recall, in "How to Create a Pattern," that the first column in an ascore pattern definition is the "&" symbol, then the instrument number. This first column is the local tempo, and the "&" symbol by itself means just use the tempo that was set with the last TEMPO keyword.

    The local tempo is adjusted by supplying a separate "&" and modifier for each note, for example

    set tmp_bb_1 1.1& 1.1& 1.1& 1.1&

    corresponds to six notes at 1.1 times the tempo of the other patterns in the section (1.1 times the value of the last TEMPO statement).

    set tmp_bb_1 & 0.9& 0.8& 0.7&

    is a pattern whose tempo slows down.

  19. How to insert MIDI control inside a pattern

    The most general way to insert MIDI CONTROL changes into a score is with the

    CONTROL <type> <value> <ch>

    statement in the score (see above). However, to associate a MIDI control change with an individual note you can put the control change into a pattern definition. Then ASCORE will not only put a parameter value into the Csound note line, but will issue a CONTROL statement into the Csound score so that cs2mtx will convert it into a midi command.

    Use the % (percent sign) symbol prefix in a parameter array to designate a midi control parameter.

    set amp_xx_21 %7_45 %7_55 %7_65 %7_75

    means control type 7 (volume control) with midi values 45, 55, 65, 75.

  20. How to suppress all MIDI channels but one with a single statement

    The MIDI_MASTER statement allows you to mute all but one MIDI channel. This feature was introduced for the sake of recording only one MIDI channel at a time. The necessity for this command may not seem obvious. Most midi keyboards can be set to a single voice mode in which all midi channels are ignored but one. And there are other ways, using Ascore commands, to select only one channel for playback.

    The MIDI_MASTER statement allows you to hold certain MIDI control messages at a flat level (volume, pan, effects, etc) to be tweaked later in the mastering process. The most important consideration underlying the MIDI_MASTER statement is the effort to keep the total number of MIDI messages in the score constant. Adding or removing MIDI messages in the score may have slight effects on the synchronization of the voices. This adverse effect may not be noticable until the voices are recorded separately and mixed as audio files. If whole sections of the score file are removed (commented out) for the sake of muting channels the MIDI message queue in your sequencer will have a lighter burden and may speed up the message transmission slightly.

    The syntax is as follows:

    MIDI_MASTER ch=<channel> ctrlxxx=nnn ctrlxxx=nnn

    There must be a "ch" parameter and at least one "ctrlxxx" parameter. Channel numbers must be given in the range 1--128 (ch 17 is the first channel on the second midi port, ch 33 is the first channel on the third midi port, etc).

    The syntax of the "ctrlxxx=nnn" argument is as follows: the "xxx" is a three digit control ID number in the range 0--127. For example, ctrl001 is the midi modulation wheel message; ctrl007 is the midi volume message; ctrl010 is the midi stereo pan message. The "nnn" is a three-digit control value number in the range 0--127.

    Example:

    MIDI_MASTER ch=5 ctrl007=80

    will mute all MIDI channels but channel 5 and hold the volume of channel 5 to 80, regardless of any volume control messages in the score. But any other control messages for channel 5 will be passed through, unchanged.

    Example:

    MIDI_MASTER ch=5 ctrl007=80 ctrl010=64

    also suppresses all but channel 5, holding the volume constant at 80. But now any MIDI pan messages (control ID 10) will be intercepted and reset to 64 (center).

    Every volume message encountered for one of the ignored channels will be intercepted and its volume value set to zero. Any MIDI control messages encountered that are not specified on the MIDI_MASTER command line will be passed through unchanged.

    One or more channels may be made exempt from being blocked by MIDI_MASTER with the "ignore" option. Using

    ignore=8

    for example, would allow midi channel 8 to be passed through, that is, "ignored". So in the above example we would put

    MIDI_MASTER ch=5 ctrl007=80 ctrl010=64 ignore=8

    to the option line.

    The opposite of MIDI_MASTER mode is MIDI_MUTE mode. With MIDI_MUTE mode you can suppress one or more channels. This allows you to record most of the channels simultaneously, leaving out a few that need to be recorded separately for special effects. The syntax of the MIDI_MUTE statement is similar to the MIDI_MASTER statement:

    MIDI_MUTE ch=<chA> ch=<chB>

    where each of the channels (numbered 1 to 128) listed will be muted.

  21. How to Set Bank Switch Statements for Different Synthesizers

    The musical instrument industry standard for bank switch MIDI messages is a set of two control messages followed by the program (instrument patch) MIDI message. For example, the Yamaha Motif synthesizers would use the following sequence of MIDI messages to set the bank to BANK 3:

    control 0, value 63
    control 32, value 2

    The first control message value (63) is called the "MSB", and the second control message value (2) is called the "LSB." However, the values used for the MSB and LSB are not industry standards. Each musical instrument manufacturer will use different values for the MSB and LSB for bank switching. Although the control numbers 0 and 32 are probably common to most synthesizers, it is likely that there will be some exceptions. In fact, it may be that some devices do not use two control messages but one.

    The ASCORE interpreter allows any sequence of one or more control messages to be defined as a bank switch. Bank switch definitions are like preset settings that assign a sequential number to a bank on your instrument. If you had, hypothetically, some instrument that required three control statements (I'm making this up) to switch to bank "2",

    control 0, value 80
    control 20, value 81
    control 32, value 1

    You could define a bank definition in your ASCORE score like this:

    BANKDEF 0 80 20 81 32 1

    The numbers are all on the same line alternating between the successive control numbers and control values that comprise the three MIDI messages. To see how this works for multiple bank definitions, consider the definitions for banks 1-6 and the drums bank on the Yamaha ES synthesizer:

    BANKDEF 0 63 32 0
    BANKDEF 0 63 32 1
    BANKDEF 0 63 32 2
    BANKDEF 0 63 32 3
    BANKDEF 0 63 32 4
    BANKDEF 0 63 32 5
    BANKDEF 0 63 32 32

    The first "bank number", is 0 in the ASCORE score and corresponds to the instrument's bank 1. The second statement defines the ASCORE bank number 1 and corresponds to bank 2 on the instrument. The last, seventh, statement defines the ASCORE bank number 6 and corresponds to the instrument drum bank.

    It is important to understand that the ASCORE bank number is just the sequential index of the bank definition statement. If you want to assign bank 0 to the drum bank you could just list the drum definition first. The ASCORE bank number will be the number that is entered in the CS2MTX script line in your score. In the above example the drum bank was the last statement and received the assignment to number 6. This number would be used in the ASCORE script according to the following format:

    CS2MTX midi_channel 10 bank 6
  22. How to Ramp (fade) a Midi Control Parameter

    Use either individual midi control statements, or use the automatic ramping feature.

    To manually send control messages use the CONTROL statement. For example, to ramp up (fade in) the volume (control number 7) for the instrument on, say, channel 5 you would use the following commands in your Ascore score file:

    CONTROL 7 0 5
    CONTROL 7 5 5
    CONTROL 7 10 5
    CONTROL 7 15 5
    CONTROL 7 20 5
    CONTROL 7 25 5
    CONTROL 7 127 5

    Note, however, that the above example leaves out the necessary time intervals (all the commands above would be sent simultaneously before any note messages). The CONTROL message actually must be interleaved in the score lines so that there are time intervals between the midi messages. Let's say that pattern "MakeMeSmile" has a duration of 13* (thirteen eighth notes), and you want this channel to fade in over that duration. Assuming (arbitrarily) that there are three tracks at this score position, the command sequence would be changed from

    TRACKS 3
    13* MakeMeSmile other_pattern yet_another

    to

    CONTROL 7 0 5
    TRACKS 3
    0.64! MakeMeSmile other_pattern yet_another
    CONTROL 7 5 5
    0.64! | | |
    CONTROL 7 10 5
    0.64! | | |
    CONTROL 7 15 5
    0.64! | | |
    0.64! | | |
    CONTROL 7 127 5

    where all the 0.64! duration intervals are meant to sum to 13*.

    The automatic control ramp is used with the following syntax in the Ascore score file,

    CTRLRAMP <control> <range> <duration>
    <increment> <channel>

    For example, to fade in the volume (control number 7) on channel 5 over a duration of 32* at intervals of * (eigthth note intervals), the following command would be used:

    CTRLRAMP 7 0,127 32* * 5

    The syntax of this command requires that the control value range be two numbers separated by a comma, no spaces or tabs between them. The control number (7 in the above example) must be a number between 0 and 127. The control value range numbers must also lie within 0 and 127. The duration over which the ramp is executed (32* above) must be a duration symbol having an optional multiplier, no spaces or tabs between the multiplier and symbol. The time increment (time between messages) must adhere to the same syntax as the duration. The duration and time increment parameters are not allowed to be pure numbers (cannot be absolute time).

    The CTRLRAMP command should be inserted just above the score line where the ramping should begin. That way, the first score line will be rendered with the starting control parameter--the first number in the value range. After the last command parameter (the sixth field, that is, the midi channel) a string of comments may be optionally appended.

END of HOWTO


Second Example

As another example of writing an Ascore script, this time with MIDI interface commands, the following auto-generated output from the Attrk sequencer is provided. Notice the CS2MTX statements and the CONTROL statements for MIDI setup.

#
#    example2.asc
#    Generated from Attrk ver. 1.0.1
#
#
BEGIN
#
#

#
#   Midi bank switch definitions
#
BANKDEF    0 63 32 0
BANKDEF    0 63 32 1
BANKDEF    0 63 32 2
BANKDEF    0 63 32 3
BANKDEF    0 63 32 4
BANKDEF    0 63 32 5
BANKDEF    0 63 32 32

#    ------------------------------------------------------------------------
#    ------------------------------------------------------------------------
#
#
#    (from Attrk channel index=1 name=Piano)
#
#
CS2MTX midi_channel 1 instrument 1
CS2MTX midi_channel 1 nshift 0
CS2MTX midi_channel 1 volume 59
CS2MTX midi_channel 1 bank 0
CS2MTX midi_channel 1 program 0
#
#

#    ------------------------------------------------------------------------
#
#    Pian1    (pattern 1, chan 1)
#
set ins_Pian1    1.1 1.2
set stt_Pian1    @ @+[2q]
set dur_Pian1    h
set key_Pian1    8.07 8.00
set vel_Pian1    100 90
set Pian1        &    ^ins_Pian1    ^stt_Pian1    ^dur_Pian1 \
                   ^key_Pian1    ^vel_Pian1
#
#    ------------------------------------------------------------------------


#    ------------------------------------------------------------------------
#
#    Pian2    (pattern 2, chan 1)
#
set ins_Pian2    1.1 1.2
set stt_Pian2    @ @+[2q]
set dur_Pian2    h
set key_Pian2    8.05 7.10
set vel_Pian2    100 85
set Pian2        &    ^ins_Pian2    ^stt_Pian2    ^dur_Pian2  \
                   ^key_Pian2    ^vel_Pian2
#
#    ------------------------------------------------------------------------




#    ------------------------------------------------------------------------
#    ------------------------------------------------------------------------
#
#
#    (from Attrk channel index=2 name=Drone)
#
#
CS2MTX midi_channel 2 instrument 2
CS2MTX midi_channel 2 nshift 0
CS2MTX midi_channel 2 volume 89
CS2MTX midi_channel 2 bank 5
CS2MTX midi_channel 2 program 16
#
#

#    ------------------------------------------------------------------------
#
#    Drone1    (pattern 1, chan 2)
#
set ins_Drone1    2.1
set stt_Drone1    @
set dur_Drone1    o
set key_Drone1    8.00
set vel_Drone1    64
set Drone1        &    ^ins_Drone1    ^stt_Drone1    ^dur_Drone1 \
                     ^key_Drone1    ^vel_Drone1
#
#    ------------------------------------------------------------------------


#    ------------------------------------------------------------------------
#
#    Drone2    (pattern 2, chan 2)
#
set ins_Drone2    2.1
set stt_Drone2    @
set dur_Drone2    o
set key_Drone2    7.10
set vel_Drone2    64
set Drone2        &    ^ins_Drone2    ^stt_Drone2    ^dur_Drone2 \
                    ^key_Drone2    ^vel_Drone2
#
#    ------------------------------------------------------------------------




#    ------------------------------------------------------------------------
#    ------------------------------------------------------------------------
#
#
#    (from Attrk channel index=3 name=Many)
#
#
CS2MTX midi_channel 17 instrument 3
CS2MTX midi_channel 17 nshift 0
CS2MTX midi_channel 17 volume 69
CS2MTX midi_channel 17 bank 1
CS2MTX midi_channel 17 program 24
#
#

#    ------------------------------------------------------------------------
#
#    Many1    (pattern 1, chan 3)
#
set ins_Many1    3.1 3.2 3.3 3.4
set stt_Many1    @ @+[1q] @+[2q] @+[3q]
set dur_Many1    q
set key_Many1    8.07 8.09 8.07 8.05
set vel_Many1    70 60 80 77
set Many1        &    ^ins_Many1    ^stt_Many1    ^dur_Many1  \
                   ^key_Many1    ^vel_Many1
#
#    ------------------------------------------------------------------------


#    ------------------------------------------------------------------------
#
#    Many2    (pattern 2, chan 3)
#
set ins_Many2    3.1 3.2 3.3 3.4
set stt_Many2    @ @+[1q] @+[2q] @+[3q]
set dur_Many2    q
set key_Many2    8.00 8.05 8.00 8.05
set vel_Many2    100
set Many2        &    ^ins_Many2    ^stt_Many2    ^dur_Many2 \
                    ^key_Many2    ^vel_Many2
#
#    ------------------------------------------------------------------------




#    ------------------------------------------------------------------------
#    ------------------------------------------------------------------------
#
#
#    (from Attrk channel index=4 name=Twiddle)
#
#
CS2MTX midi_channel 3 instrument 4
CS2MTX midi_channel 3 nshift 0
CS2MTX midi_channel 3 volume 99
CS2MTX midi_channel 3 bank 2
CS2MTX midi_channel 3 program 81
#
#

#    ------------------------------------------------------------------------
#
#    Twid1    (pattern 1, chan 4)
#
set ins_Twid1    4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8
set stt_Twid1    @ @+[1*] @+[1q] @+[3*] @+[2q] @+[5*] @+[3q] @+[7*]
set dur_Twid1    *
set key_Twid1    8.00 8.05 8.02 8.07 8.09 8.07 8.04 8.02
set vel_Twid1    64
set Twid1        &    ^ins_Twid1    ^stt_Twid1    ^dur_Twid1 \
                    ^key_Twid1    ^vel_Twid1
#
#    ------------------------------------------------------------------------


#    ------------------------------------------------------------------------
#
#    Twid2    (pattern 2, chan 4)
#
set ins_Twid2    4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8
set stt_Twid2    @ @+[1*] @+[1q] @+[3*] @+[2q] @+[5*] @+[3q] @+[7*]
set dur_Twid2    *
set key_Twid2    8.00 8.04 8.02 8.09 8.07 8.00 8.02 8.02
set vel_Twid2    64
set Twid2        &    ^ins_Twid2    ^stt_Twid2    ^dur_Twid2  \
                    ^key_Twid2    ^vel_Twid2
#
#    ------------------------------------------------------------------------



#
#    ------------------------------------------------------------------------

set ins_rest 0
set dur_rest !
set key_rest 0
set vel_rest 0
set rest_1   & ^ins_rest & ^dur_rest ^key_rest ^vel_rest
#
#    ------------------------------------------------------------------------




#    ------------------------------------------------------------------------
#    ------------------------------------------------------------------------
#    SCORE Section
#    ------------------------------------------------------------------------
#    ------------------------------------------------------------------------

TEMPO 140
TRACKS 1
q             rest_1
#
CONTROL   91   100   2
CONTROL   93   60   2
#
TRACKS 4
o            Pian1       Drone1      Many1         |    
o            Pian2         |         Many1         |    
o              |         Drone2      Many1         |    
o            Pian1         |         Many1         |    
o            Pian1       Drone1      Many2         |    
o              |           |         Many2         |    
o            Pian1       Drone2      Many2         |    
o            Pian2         |         Many2         |    
o            Pian1         |           |         Twid1  
o            Pian2         |           |         Twid1  
o              |           |           |         Twid1  
o            Pian1         |           |         Twid1  
o            Pian2         |           |         Twid2  
o              |           |           |         Twid2  
o            Pian1         |           |         Twid2  
o            Pian2         |           |         Twid2  
#
#
#
END
#
        


Download Ascore

Lastest version is 4.3

The installation package just contains the ascore.awk file. It is very simple. When the package ascore-4.3.tgz is unpacked it will create a subdirectory called ascore (not ascore-4.3).




Linux Music Synthesis
[JPG image artwork that is a companion to the text]
© Alfred Steffens Jr., 2009