The last tutorial used cell addresses to access data within the pattern. Accessing data and memory is a core operation in all programming, where variables, pointers, and arrays allow coders to label and address data for easy recall. Such functionality is available in Manhattan, using labels.
Labels are annotations you can add to a pattern to insert comments, or mark cells and sections. To add a label, move to a cell or make a selection and press " (Shift-', or @ on some computers). Enter a short phrase in the red box that appears and press Enter. To remove a label, press " again to edit it and press BackSpace until it disappears.
- In this way, label the topmost cell in Channel 2 (containing a C-5) with the text, "MyLabel".
- Label the cell below it (containing the parameter 04) with the text, "MyVariable".
In code, labels act as references to cell locations. These locations can be referenced using the @ prefix, i.e. @MyLabel and @MyVariable. This provides an alternative to cell addresses, while still allowing access to cell properties. For example, the following copies the pitch from the cell at MyLabel:
- In an unused cell in the pattern (e.g. below row 8), use the @ syntax to copy the labelled cell's pitch.
Labels are useful as a way of naming cells to use as variables. For example, the cell labelled "MyVariable" provides several spaces for storing generic data values (volume, pan, effect parameter), inaudible by themselves (e.g. in an empty or muted channel), but accessible from anywhere in the pattern:
Indeed, because it is so useful to store values as variables in the .param property, Manhattan knows to look there when it's expecting a number, allowing you to refer to it without using the ".param" suffix:
- Use the parameter in MyVariable to transpose the pitch from MyLabel, in your previous pitch formula:
Variables can be used to store anything represented by a number (i.e. most values in the pattern), but are particularly useful for keeping track of the state of things that change in your music - counters, bar numbers, etc. - as well as changeable values that other formulas in the pattern rely on - key pitches, settings, choices, tempo.
- Click 2 (top) to learn about arrays.
| Useful Keys | |
| " / @ | Add or edit a label for the current / selected cell(s). |
| Ctrl-1 to 0 | Change the colour of a label (while editing). |
| Shift-Up/Dn | Select multiple cells (e.g. for labelling blocks). |
Labels also support array functionality. An array is a collection of data values, widely used in programming. In Manhattan, a label acts as a pointer to the start of a range of cells, from which you can also access surrounding cells by appending a relative cell address. The result is an array syntax, familiar in coding:
Arrays can be used to store any kind of musical or pattern data, such as chords, scales, melodies, number sequences, rhythms, musical forms, note patterns, arpeggios, etc. and are one of the key tools in adding complexity to a piece in Manhattan.
In Manhattan, arrays are created by labelling a range of cells: selecting a range of several cells (e.g. using Shift-Cursors - across multiple rows and/or channels) and hitting " (or @), as before.
Using an array to generate music:
Channels 2-5 contain a simple generative piano part, based on random numbers and pitch relationships. When played, a basic piano arpeggio is heard, but it's not very musical - it has no sense of key or the tonal relations important in music.
To fix this, we can define a musical scale using an array, and tell the piano to select notes from it:
- In the unused space in muted Channel 1, write out the notes of the C-Major scale from C-4 to C-6.
(Hint: these are the white notes: C, D, E, F, G, A, B)
- Select the entire sequence (of 15 notes) and label the range with the name, Scale.
- Now replace the existing pitch formula in [3:0] (which defines the root of our chord) with:
.pitch@Scale[rnd(0,7)].pitchNote how we have moved from randomising pitch directly, instead randomising which note we select from the scale (from the first eight notes).
- Play the pattern (Alt-Space) to hear the change.
The root note is now guaranteed to be within our scale, but the other notes are fixed intervals from the root, which sometimes fall outside the scale. We need to somehow constrain these notes to the scale, but also maintain a relationship with the root. However, we can't use rnd() again, as this will generate a new random number, rather than the one our root used!
- Click 3 (top) to see how a variable can fix this...
| Useful Keys | |
| " / @ | Add or edit a label for the current / selected cell(s). |
| Ctrl-1 to 0 | Change the colour of a label (while editing). |
| Shift-Up/Dn | Select multiple cells (e.g. for labelling blocks). |
To ensure the subsequent notes are in our scale, we need to get them from the array, but we also need them to be related to the root. So, instead of stepping in semitones by simply adding to the pitch, we step in scale steps by adding to our position in the array. For this, we need to record where our root comes from.
Get all notes from the scale/array:
The solution is to generate the random number in advance and store it in a variable, which the root and all the other notes can read from...
- Remove your current variables, MyLabel and MyVariable, and create a new label for the top cell of Channel 2 called Random.
The random number must be generated here, to be available before it is needed by the root note.
- Insert the code to generate the random number in the .param formula of the Random cell:
.paramrnd(0,7)
- Now update the array expression for our root note in [3:0], to use the variable...
.pitch@Scale[@Random].pitch... which we can now also use in [4:4]:.pitch@Scale[@Random+4].pitch... and finally in [5:2]:.pitch@Scale[@Random+2].pitchNote how our relationships are now not added to the pitch as semitones, but to the array offset to move within our scale.
To finish, audition the pattern to hear the change. The music should sound more consonant and harmonically consistent, because it is forced to use the notes and interval relationships within the scale.
| Useful Keys | |
| " / @ | Add or edit a label for the current / selected cell(s). |
| Ctrl-1 to 0 | Change the colour of a label (while editing). |
| Shift-Up/Dn | Select multiple cells (e.g. for labelling blocks). |