Djazz

Djazz is a generative music program that improvises using material from pre-recorded scores or live human contributions. Born of jazz improvisation, it has been extended to world music and electro, and uses a data structure known as the factor oracle to improvise beat by beat.

Installation & Usage

Djazz needs no special installation. Download the Djazz folder here.

License

Djazz is licensed under the GNU GPLv3 license.

Credits

Marc Chemillier in collaboration with GĂ©rard Assayag, JĂ©rĂŽme Nika, Mikhail Malt, Jean-Louis Giavitto, Georges Bloch IRCAM REACH Project IRCAM Musical Representations Team
Djazz v2 coded by Daniel Brown

Subsections of Djazz

Chapter 1

Manual

Subsections of Manual

Installation

Djazz needs no special installation. Download the djazz folder here

Or, if you have git installed, via Terminal:

git clone https://github.com/DYCI2/Djazz_2.0

Open Max.

Select Options from the menu bar at the top of the screen.

Select File Preferences from the dropdown menu that appears.

In the File Preferences window that appears, select “choose path.”

In the file browser menu that appears, select the “djazz” folder you have just downloaded. pic1 pic1

Djazz uses externals that are included in the Djazz folder. They do not require extra installation, although your operating system may ask if you want to allow them to run.

Main Window

pic1 pic1

1. MIDI/audio window selectors

pic1 pic1

Clicking on the button labeled “MIDI” or “Audio” will open and close the MIDI or audio interface window, respectively.
You can also use the key commands “m” (lowercase) to open/close the MIDI window or “a” (lowercase) to open/close the audio window.

2. Beat input window

3. Song selector

pic1 pic1

To load a song grid, select a song using one of these controls. Songs are loaded by selecting folders, not individual files. Each folder contains various files pertaining to the song like scores and JSON metadata files.

  1. Drag and drop a song folder here.
  2. Browse for a song folder. To select a song, click on its folder.
  3. Clear the current song.
  4. Select a preloaded song from the dropdown menu.

4. Song Grid

5. Data View

data view data view

  1. BEATS: total number of beats in the song
  2. SECTION: whether section is looped, and number of beats in current section
  3. TEMPO: current tempo. Note: if the [beat input] comes from Djazz’s metronome or a remote metronome, this will not change. If the beat input is manual, or if the remote source is a manual tap, this may fluctuate.
  4. BEAT Number of current beat playing
  5. LABEL Label of current beat playing, according to the loaded song file

6. Global Effects

global effects global effects

These effects are the same as the ones used in MIDI scores, MIDI tracks, and audio tracks. Changing a control in the global effects bar will change the corresponding effect in every one of these other effects bars.

7. GLOBAL AUDIO INPUT/OUTPUT

pic1 pic1

Audio On

Clicking on either the microphone icon or the loudspeaker icon will turn the audio on.

Audio Monitor Level (Microphone)

Controls the monitor level of the audio input. The button labeled “M” below the microphone-icon button mutes audio input.

Audio Record Level

Controls the recorded volume level of the audio input. The button labeled “M” below the microphone-icon button mutes audio input.

Audio Out (Speakers)

Controls the level of the global audio output. The button labeled “M” below the loudspeaker-icon button mutes audio output.

8. MIDI Input Selector

9. External Controllers Selection Menu

When an external controller such as a Launchpad is plugged in, its name will appear in the dropdown menu. If Djazz supports it, selecting its name from the dropdown menu will open its interface window.

10. UDP Send Port Select

Select the host and port to send view messages from Djazz.

11. Settings Window Open/Close Button

Subsections of Main Window

Beat Input

2. BEAT INPUT

pic1 pic1

Input Selector

Djazz plays a beat each time it receives a message (a “tap,” or “click”), if it is engaged (how to engage Djazz will be explained below). When not engaged, it will not play when a beat message is received. When this is the case, you can click on bars or chapters (“cells” of the grid) in the song grid without triggering playback. Once engaged, djazz will begin playing on the next beat after a cell has been clicked on.

The cells of the grid change color depending on whether Djazz is engaged and whether a cell is currently playing or not. The colors represent the following:

  • Light gray: not the current measure/chapter of the song
  • Dark gray: the current measure measure/chapter of the song, but Djazz is not engaged
  • Blue: the current measure measure/chapter of the song, but not playing
  • Orange: the current measure measure/chapter of the song, and playing

There are three ways to send Djazz a beat message; you select one from the dropdown menu: manual, metronome, or remote. Selecting from the dropdown menu will change the controls on the left side of this box. When one option is selected, the other two are not responsive.

pic1 pic1

The right-hand side of the window lets you change the sound and output port of the click.

1. INPUT SELECTOR: Select if the input beat will come from one of the following:

  1. Djazz’s metronome
  2. a manual tap from the user
  3. a remote source, such as another DAW.

pic1 pic1

2. OUTPUT CLICK MIDI PITCH: Changes the pitch of the click. The number indicates the MIDI value of the pitch.

3. OUTPUT CLICK MIDI CHANNEL: The MIDI channel of the click (1-16). 4. SELECTED INPUT VIEW: metronome, manual, or remote.

5. OUTPUT CLICK VOLUME CONTROL: The volume of the click. When muted, this will be gray.
6. OUTPUT CLICK MUTE BUTTON: Mutes/unmutes the click
7. OUTPUT CLICK MIDI PORT: The output port of the click.

BEAT INPUT VIEWS

Metronome

pic1 pic1

  1. The button marked with a triangle turns the metronome on and off. When you turn this button on and then select a grid cell, the metronome will trigger a new beat each time it clicks, beginning with the beat represented by the grid cell. No beat will be triggered until a grid cell has been selected.
  2. The number selector sets the metronome tempo. This is automatically set when a new song is loaded, but you can change it.
  3. This flashes each time the metronome sends a beat.

Manual

pic1 pic1

  1. The triangle button engages Djazz.
  2. Clicking on the circle button sends Djazz a beat message. You can also press the space bar to send a manual click.

Djazz expects the starting tempo given in the song file!

Remote

pic1 pic1 This will send a beat message to Djazz every time a MIDI note on message is received (i.e., with a non-zero velocity) on any channel.

  1. The dropdown menu selects the MIDI input port for the click.
  2. The triangle button engages Djazz.
  3. This flashes each time a beat is received.

pic1 pic1

Song Grid

When a song is loaded, its grid will appear. The cells of the grid change color depending on whether Djazz is engaged and whether a cell is currently playing or not. The colors represent the following:

  • Light gray: not the current measure/chapter of the song
  • Dark gray: the current measure measure/chapter of the song, but Djazz is not engaged
  • Blue: the current measure measure/chapter of the song, but not playing
  • Orange: the current measure measure/chapter of the song, and playing

pic1 pic1

1. Chapter Select

pic1 pic1
At the top are listed the “chapters” of the song–different sections like verses, choruses, and bridges. Clicking on a chapter will take you to the first measure of the chapter. If Djazz is engaged, it will start playing from here when the next beat is received.

2. Bar Select

pic1 pic1
When a chapter is selected, the bars in the chapter are shown below it. Each bar contains the number of beats given by the song’s time signature. Clicking on a bar will take you to the first beat in the bar. If Djazz is engaged, it will start playing from here when the next beat is received.

3. Rewind-to-beginning Button

Click to go to the beginning (first bar of first chapter) of the song.

4. Lock button

When the lock button next to the rewind button is on, Djazz will rewind to the beginning of the song every time it is disengaged (i.e., when the metronome is turned off, or when the engage button is unselected in manual or remote beat input.)

5. Loop Button

pic1 pic1 When selected, Djazz will loop the current chapter or the whole song, depending on the choice selected to the right of the button. That is, it will start from the beginning immediately when the end of the current chapter or song is reached

5. Loop-Chapter/Song Select

Selects whether to loop the current chapter or the whole song when the loop-chapter button is on.

MIDI Input Selector

pic1 pic1

1. MIDI Flush

This will clear any sounding MIDI output.

2. MIDI input port selection menu

This menu will update to list all possible MIDI input ports, from other applications like Logic or Ableton, for instance. Default is “none:” no MIDI input will come through.

3. Computer keyboard window open/close

When selected, the computer keyboard window will open.

4. MIDI input monitor on/off

When illuminated, MIDI in will be heard. This does not affect nor is not affected by the recording status in the Live MIDI Input window .

5. MIDI monitor output port selection menu

This menu will update to list all possible MIDI output ports to send MIDI monitor output. Default is “none:” no MIDI output will be sent.

6. MIDI volume meter

When the monitor button is on, this will show the MIDI input volume level in green, orange, and red. When the monitor is off, it will be grey.

Computer Keyboard Window

computer keyboard window computer keyboard window

1. Output Port

2. MIDI Channel select

3. Number keys enable

When enabled, the computer keys 0-9 will play the MIDI values C3-D4.

4. Mode selection menu

Select between monophonic and polyphonic mode

5. Keyboard

Click a key with the mouse to play it. If the mode selected is polyphonic, you must click the key again to stop it playing.

Subsections of MIDI Window

MIDI Live Input View

pic pic

You can record MIDI input into Djazz, and then inmprovise on the recorded input using all the effects and the improviser. Live MIDI input, like live audio input, is recorded only when a chapter or a song is looped . Each time a chapter (or the song) is looped, a new oval representing this repeition will light up in the bar next to the record button. From the two tracks below the record track, you can choose any oval beneath an illuminated oval to play. This will play the corresponding recorded repetition.

When clicked and illuminated, the record button arms the buffer for recording. It does not start recording until the first beat that advances the grid.

1. Save/Load/Clear Live Input Session

Save the current a MIDI live session. These sessions are saved as folders (see [saving and loading files]({{ .Page.Dir }})) containing - a MIDI file - a JSON file containing beat, note, label, and repetition metadata, so that this can be reloaded into a Live Input session. This is not the same format as score files, and will not load into the [score file loader].

2. Input Track Repetitions

Each oval in the track represents a repetition of the current looped section. When recording, each time the end of the section is reached, a new oval will illuminate.

3. Maximum Number of Repetitions

This selects the maximum number of repetitions that can be recorded. The default is 16.

4. Output track repetitions

There are two MIDI live input tracks. They use MIDI outs are 1 and 2. Ovals can be selected to be played if the corresponding input oval is illuminated.

MIDI Scores View

pic pic

Score Player/Loader Window

MIDI Score Effect and load window MIDI Score Effect and load window

MIDI scores are made up of multiple MIDI tracks. They are saved in a special format. When a score is loaded, the corresponding MIDI tracks will load.

Djazz uses two scores. They correspond to the following tracks:

Score 1: Tracks 8-15
Score 2: Tracks 3-7

Effect controls in each score bar will change all the effects in the tracks belonging to the score.

Score Loader

pic pic

Scores can be loaded by dragging a score onto the button with an icon of a folder. If a song folder is loaded that contains scores in its new and new2 subdirectories, these scores will be available in the dropdown menus. Choosing a score from the menu will load it.

MIDI Out Bank

midi out bank midi out bank

The MIDI out bank contains 15 tracks output controls.
1-2: Live Output
3-15: Tracks/Score output

midi out midi out

Volume Dial

Changes the volume of the MIDI track. If you click just above the dial, the dial will reset to its default value of 80.

Active Button

If not illuminated, the MIDI track will not be audible, and its volume in the volume meter will be gray. When illuminated, the MIDI track will be audible.

Solo Button

When illuminated, this will “solo” the MIDI track. If a single track is soloed, it is the only track that you will hear. If several MIDI tracks are soloed, only these tracks will be audible. If no tracks are soloed, all the tracks will be audible.

Volume Meter

Shows the level of the MIDI output. When a track is inactive, this will be grey. When active, the output will be green, orange, and red, depending on the volume level.

Channel Select

Allows the user to change the MIDI channel of track. Options are 1 through 16.

Port Select

Allows the user to select the output port of the MIDI track. These are usually Max’s internal MIDI playback (which will be called something like “DAC synth”), and outputs to other applications (called “from Max 1” and “from Max 2”).

global port select global port select

Global Port Select

This changes the output port of all the MIDI channels.

global port select global port select

MIDI Tracks View

tracks tracks

Track effects

tracks tracks

See effects .

File/track info select

Selecting either the folder button or the information (i) button will open the view to either load a track, or see the current playback data of the track.

Load MIDI track

tracks tracks
You can load a track that does not follow the chord progression in the song file. If the track contains chords that are used in the song file, though, the improviser will use this chord information to create a harmonically correct solo!

Track info view

tracks tracks
This displays the current beat, the current tempo, and the current transposition that the improviser has found , if this setting is on.

Subsections of Audio Window

Live Input

live input view live input view

These controls are similar to the MIDI live input controls.

When clicked and illuminated, the record button arms the buffer for recording. It does not start recording until the first beat that advances the grid.

1. Save/Load/Clear Live Input Session

Save the current a audio live session. These sessions are saved as folders (see saving and loading files ) containing two (2) files:

  • an audio file in WAV format
  • a JSON file containing beat, note, label, and repetition metadata, so that this can be reloaded into a Live Input session.

Note: to save and load an audio file, you actually save and load a folder. Just name the folder in the dialog window, and the folder will be created and appropriately named files (.wav and .json) will be saved in the folder. For loading, choose the folder from the dialog.

2. Input Track Repetitions

Each oval in the track represents a repetition of the current looped section. When recording, each time the end of the section is reached, a new oval will illuminate.

3. Maximum Number of Repetitions

This selects the maximum number of repetitions that can be recorded. The default is 16.

4. Recorded repetitions

There are two audio live input tracks. They use audio outs are 1 and 2. Ovals can be selected to be played if the corresponding input oval is illuminated.

audio output tracks audio output tracks

Audio output repetitions are selected and played the same way as MIDI output repetitions .

audio output tracks audio output tracks

Audio Out Bank

audio out bank audio out bank

The audio out bank contains three (3) audio output controls. These are similar to MIDI output controls.


audio out audio out

Volume Dial

Changes the volume of the MIDI track. If you click just above the dial, the dial will reset to its default value of 80.

Active Button

If not illuminated, the MIDI track will not be audible, and its volume in the volume meter will be gray. When illuminated, the MIDI track will be audible.

Solo Button

When illuminated, this will “solo” the MIDI track. If a single track is soloed, it is the only track that you will hear. If several MIDI tracks are soloed, only these tracks will be audible. If no tracks are soloed, all the tracks will be audible.

Volume Meter

Shows the level of the MIDI output. When a track is inactive, this will be grey. When active, the output will be green, orange, and red, depending on the volume level.

Effects Bar

Effects

Pitch Transposition

pic pic
Changes the pitch of the MIDI output

Octave Transposition

pic pic
Changes the octave of the MIDI output

Speed

pic pic
Changes the speed of the MIDI output

Loop

pic pic
Loops the previous n beats of the MIDI output

“Jam” (Improvise) Section

pic pic

“Jam” Button

pic pic Turns the improviser on. When this is on, the MIDI track(s) is/are not played back straight, but beats are chosen based on the harmony and the next two controls, continuity and potch range:

Continuity

pic pic
This determines the length in beats that sections of the score will be played back in sequence. Once this many beats has been played in sequence, the improviser will jump to a new section of the score.
The maximum coninuity is 255 beats. When the “MAX” button is on, this will be the continuity–i.e., the score will be played back without improvising, i.e. jumping around through it (given that the score is < 255 beats long. If you’re using this with a score that’s longer than 255 beats and you just want to play the score straight, there’s no reason to be even using the improviser.)

Transposition Window

pic pic
The improviser tries to match beats that have the same harmony as the current beat. By adjusting the pitch range, it will look for beats with a similar chord type but with roots above or below the current chord root. A pitch range of n will look for chords between (and including) n semitones below and n semitones above the current chord root. Set to zero, it will match the chord root exactly. Beats with different roots will be transposed to the proper harmony.

External Controllers

External controllers such as Launchpads or MIDI keyboards can be used to trigger controls in Djazz.

Djazz has been tested with the Novation Launchpad Mini and the Launchpad Pro MK3.

To use a new kind of Launchpad, an interface must be added to the Djazz patch

Connect/disconnect a device

controller selector controller selector
When a device is connected to the computer, Djazz will automatically recognize it and its name will be added to the external controllers menu, and a popup window will also open. This popup window can be reopened at any time by selecting the interface name from the menu.
To disconnect all devices, click the “X” button above and to the left of the menu.

Device interface window

controller window controller window

Connect/Disconnect button

Click to connect or disconnect a device. By default, devices are disconnected.

Mapping Buttons

Load a saved mapping, save the current mapping, clear the current mapping, or open the editor widow to edit the current mapping.

Mapping file name window

Displays the current loaded mapping, if any.

Remember most recent mapping

If you want Djazz to remember the mapping it was using the last time the program was closed, do the following:

  1. With the device interface window in focus, select Modify Read-Only from the Max File Menu, or press ⌄⌘M.
  2. From the Max File menu, select Save, or press ⌘S.

Grid View

The top four rows of each launchpad are reserved for the bars of the song grid. The CC controls along the right side of a Launchpad change the chapters.

Parameter controls

The bottom four rows are available as parameter controls, which can be set by the user using the preset editor window.

The mapping editor window

editor window editor window

Create/edit a mapping

To create a new mapping from a launchpad cell to a Djazz control, click the Edit button in the device interface window to open the mapping editor window. Follow the instructions to set the mapping. To save the mapping, click “Save” in the interface device window.

Example mappings included with Djazz

There are three (3) Launchpad mappings included with Djazz, for the Novation Launchpad Mini and the Launchpad Pro MK3. They can be found in the djazz_user/mappings folder. The mappings are as follows:

MAPPING EXAMPLE 1

LAUNCHPAD PRO MK3
AUDIO 1 LOOP 1AUDIO 1 LOOP 2AUDIO 1 LOOP 3AUDIO 1 LOOP 4AUDIO 2 LOOP 1AUDIO 2 LOOP 2AUDIO 2 LOOP 3AUDIO 2 LOOP 4
AUDIO 1 SPEED 2AUDIO 1 PITCH UPAUDIO 1 OCTAVE UPAUDIO 1 UNMUTEAUDIO 2 SPEED 2AUDIO 2 PITCH UPAUDIO 2 OCTAVE UPAUDIO 2 UNMUTE
AUDIO 1 SPEED 3/2AUDIO 1 RESET PITCHAUDIO 1 RESET OCTAVEAUDIO 1 TRACK ONAUDIO 2 SPEED 3/2AUDIO 2 RESET PITCHAUDIO 2 RESET OCTAVEAUDIO 2 TRACK ON
AUDIO 1 SPEED 1/2AUDIO 1 PITCH DOWNAUDIO 1 OCTAVE DOWNAUDIO 1 IMPROVISEAUDIO 1 SPEED 1/2AUDIO 1 PITCH DOWNAUDIO 1 OCTAVE DOWNAUDIO 2 IMPROVISE
LAUNCHPAD MINI
AUDIO 1 LOOP 1AUDIO 1 LOOP 2AUDIO 1 LOOP 3AUDIO 1 LOOP 4AUDIO 2 LOOP 1AUDIO 2 LOOP 2AUDIO 2 LOOP 3AUDIO 2 LOOP 4
AUDIO 1 SPEED 2AUDIO 1 PITCH UPAUDIO 1 OCTAVE UPAUDIO 1 UNMUTEAUDIO 2 SPEED 2AUDIO 2 PITCH UPAUDIO 2 OCTAVE UPAUDIO 2 UNMUTE
AUDIO 1 SPEED 3/2AUDIO 1 RESET PITCHAUDIO 1 RESET OCTAVEAUDIO 1 TRACK ONAUDIO 2 SPEED 3/2AUDIO 2 RESET PITCHAUDIO 2 RESET OCTAVEAUDIO 2 TRACK ON
AUDIO 1 SPEED 1/2AUDIO 1 PITCH DOWNAUDIO 1 OCTAVE DOWNAUDIO 1 IMPROVISEAUDIO 1 SPEED 1/2AUDIO 1 PITCH DOWNAUDIO 1 OCTAVE DOWNAUDIO 2 IMPROVISE

MAPPING EXAMPLE 2

LAUNCHPAD PRO MK3 & LAUNCHPAD PRO MK3
MIDI OUT 1 UNMUTEMIDI OUT 2 UNMUTEMIDI OUT 3 UNMUTEMIDI OUT 4 UNMUTEMIDI OUT 5 UNMUTEMIDI OUT 6 UNMUTEMIDI OUT 7 UNMUTEMIDI OUT 8 UNMUTE
MIDI TRACK 1 IMPROVISEMIDI TRACK 2 IMPROVISEMIDI TRACK 3 IMPROVISEMIDI TRACK 4 IMPROVISEMIDI TRACK 5 IMPROVISEMIDI TRACK 6 IMPROVISEMIDI TRACK 7 IMPROVISEMIDI TRACK 8 IMPROVISE
MIDI OUT 9 UNMUTEMIDI OUT 10 UNMUTEMIDI OUT 11 UNMUTEMIDI OUT 12 UNMUTEMIDI OUT 13 UNMUTEMIDI OUT 14 UNMUTEMIDI OUT 15 UNMUTE
MIDI TRACK 9 IMPROVISEMIDI TRACK 10 IMPROVISEMIDI TRACK 11 IMPROVISEMIDI TRACK 12 IMPROVISEMIDI TRACK 13 IMPROVISEMIDI TRACK 14 IMPROVISEMIDI TRACK 15 IMPROVISE

MAPPING EXAMPLE 3 (Marc Chemillier’s original)

LAUNCHPAD MINI & PRO MK3
GLOBAL SPEED 1/2MIDI OUT 8 UNMUTEMIDI OUT 9 UNMUTEMIDI OUT 10 UNMUTEMIDI OUT 11 UNMUTEMIDI OUT 12 UNMUTEGLOBAL LOOP 5GLOBAL LOOP 1
GLOBAL SPEED 3/2MIDI OUT 13 UNMUTEMIDI OUT 14 UNMUTEGLOBAL RESET OCTAVEGLOBAL OCTAVE DOWNGLOBAL OCTAVE UPGLOBAL LOOP 6GLOBAL LOOP 2
GLOBAL SPEED 2MIDI OUT 3 UNMUTEMIDI OUT 4 UNMUTEMIDI OUT 5 UNMUTEMIDI OUT 6 UNMUTEMIDI OUT 7 UNMUTEGLOBAL LOOP 7GLOBAL LOOP 3
GLOBAL SPEED 4AUDIO OUT 1 UNMUTEAUDIO OUT 2 UNMUTEAUDIO OUT 3 UNMUTEGLOBAL LOOP 8GLOBAL LOOP 4

Tools

Djazz comes with many preloaded songs, but you can also load your own songs to play and improvise on. To do this, you need to make two files: a song file and a score file. This section contains instructions on the two included tools that let you create these files.

Subsections of Tools

Making a Song File

Djazz uses a song file to play a song, whether you are plaing back scores or using live MIDI or audio. A song file is not a score file. It does not contain any notes to play. Where a score file contains the notes in each beat of the song, a song file contains all the metadata for each beat: its label, its position in the song, and what chapter of the song it is in, in order to make the grid and send the master clock and factor oracle the appropriate data. Djazz uses labels that represent chords. In this way, a song file is like a chord chart.

To create a song file for a new song you want to play with Djazz, the make_song_file Max patcher is provided for you in the tools folder.

make-song-file-tool make-song-file-tool

SONG NAME

Enter the name of the given song; this will be displayed when the song file is loaded, and will also appear in the song dropdown menu if it is placed in the djazz_user/scores/ folder

BEATS

Enter here the total number of beats in the song.

TEMPO

Enter the song tempo. This tempo will be loaded into Djazz’s metronome when the song is loaded, and is also the tempo that will be expected if manual tap entry is performed

TIME SIGNATURE

Enter the number of beats per measure, i.e. the top number in the time signature. The duration of the beats, i.e. the bottom number in the time signature (4 for quarter note, 8 for eighth note, etc.) does not matter; do not include it.

CHAPTER START BARS

If the song is divided into chapters, enter here the bar (i.e. measure) numbers at which the chapters begin. For instance, if a song contains four chapters of 16, 16, 32, and 64 bars, in that order, the chapter start bars will be 1, 17, 33, and 65. Enter these numbers without commas

Putting all this together, here’s what you would enter for a song in 4/4 time, with chapters of duration as above: 16, 16, 32, and 32 bars. The number of beats is the total number of bars multiplied by the time signature; in this case (16 + 16 + 32 + 64) * 4 = 128 * 4 = 516

make-song-file-tool-example make-song-file-tool-example

BEAT LABELS

Beat labels are input in a text-based format. They can be entered directly into the tool’s window, or cut and pasted from a text editor.

A chord label has two parts, the root and the quality. The way of entering labels is as follows:

  (< chord root >   < chord quality >   < number of consecutive beats >)

< chord root > can be the symbol C, C#, Db, D, D#, Eb, E, F, F#, Gb, G, G#, Ab, A, A#, Bb, or B.

< chord quality > can be any symbol that does not contain an underscore ("_") or a semicolon(";").

The improvisation algorithm functions in part by matching these symbols with the symbols on the beats in score files, so if you want it to work correctly, keep the format of these symbols the same. For instance, the preloaded songs in Djazz use the following symbols:

  maj7, min7, 7, dim7, maj6, min6

But you can define any symbols you want:

  dom7#9b9#11, maj6add9, min6withanextraweirdnoteatthetop, etc.

< number of consecutive beats > is how many beats this particular label is repeated.

So for instance, the chord sequence

  Amaj7   Amaj7   Dmin7   Amaj7
  Amaj7   Dmin7   E7       Amaj7

would be entered as

chord-labels-1 chord-labels-1

It could also be entered as

chord-labels-2 chord-labels-2

if this is easier to read.
Indentation and carriage returns are ignored by the tool.

MAKING A SONG FILE

In summary, to make a new song file, follow the seven steps listed below.

  1. Open the patcher “djazz.make_song_file.maxpat” from the folder “patchers/data_conversion_tools” in the current djazz folder.

  2. In the appropriate fields, put in the song name, beat count, tempo, time signature, and the starting bars for each chapter.

  3. Fill in the “Beat Labels” box.

  4. Press the “save” button.

  5. Save the song file in the folder of the same song name that contains the subfolders “new” and “new2.” The file name and the song folder name should be exactly the same.

  6. That’s all. If you put the song file in a folder with scores in “new” and “new2” subfolders , this song can now be played as usual by Djazz.

  7. Press the “clear” button to clear the data.

Making a Score File

make score file tool make score file tool

Score files contain preloaded notes, formatted so that Djazz can play them and use them to improvise. Djazz comes preloaded with many score files of jazz standards and songs from Madagascar. You can also convert your own MIDI files into Djazz scores with the make_score_file Max patcher, located in the tools folder.

1. Load a song file

load song file load song file
If you haven’t yet made a song file for this song, make one using the make_song_file tool. Import the song file by pressing the LOAD button. If the file is loaded properly, the light on the left side will illuminate.

2. Load a click track

load click track load click track

A click track is needed to divide the notes in the MIDI tracks into the proper beats. A click track must be imported from a MIDI file in which eat beat is designated by a single MIDI event at pitch C1 and non-zero velocity The click track be exported at the same tempo as the notes.

click track image click track image

Import the MIDI file by pressing the “IMPORT MIDI” button and selecting the file from the dialog that opens. Once imported, you can save this file to a JSON format using the “SAVE JSON” button. If the click track file is loaded properly, the light on the left side will illuminate.

3. Load a single or multiple tracks

If both the song file and click track have loaded successfully, the regions for loading MIDI tracks will be activated. You can load either a single MIDI track, or multiple tracks at once. If you import multiple tracks, the resulting JSON file will represent a Djazz score, which you will need to put into a folder in order to play it in Djazz (see below).
make multiple tracks make multiple tracks

NOTE: Tracks available for Djazz are 3 through 15, because tracks 1 and 2 are used for Live MIDI. Make sure the MIDI tracks are exported from your DAW with appropriate track numbers.

Once you have imported, either in the single or multiple MIDI track format, save your import by pressing the “Save” button. The resulting file will be a JSON file.

To play a single MIDI track, see these instructions.

To play multiple MIDI tracks, you need to put your saved file in an appropriately named folder.

MAKING A SCORE FOLDER

Multiple MIDI tracks saved together are called a score in Djazz. Score files and their corresponding song files need to be organized into a certain folder structure–a song folder–for Djazz to read them.

The format for a song folder is this:

MySongFolder
├── MySongFolder.json
├── new
│   ├── score_1.json
│   ├── another_score.json
│   ├── another-score_1.json
│   └── ... 
├── new2
│   ├── some_score.json
│   └── may_song_score.json
│   └── ...

The song folder must have the same name as the JSON song file. The top level of the song folder contains three things: - the JSON song file - two directories for score files. These directories must be labeled “new” and “new2.”

A song folder placed into the djazz_user/scores folder inside the Djazz directory will appear in the song dropdown menu .

The contents of the two score directories will be loaded when a song folder is loaded and their contents displayed in the respective dropdown menus .

Preloaded Songs

AllINeed, 64 164 4 " 1";
AllOfMe, 160 135 4 " 1 33";
Allthethingsyouare, 144 180 4 " 1 33";
AutumnleavesDoMin, 192 182 4 " 1 33";
BandeOrgueZay, 40 140 4 " 1";
BesameMucho, 160 110 4 " 1 33";
BluesFamaj, 48 120 4 " 1";
Boomerang, 236 58 4 " 1 4 36 44";
CamelBluesTernaire8, 32 103 4 " 1";
CamelSahelien, 96 103 4 " 1";
Capharnaum, 128 131 4 " 1";
Caravan, 256 220 4 " 1 33";
Carlos, 32 80 4 " 1";
Cerebral, 608 125 4 " 1 9 33 49 73 105 121";
CheektoCheek, 532 184 4 " 1 6 38 62 78 102";
CheektoCheekDjin, 224 184 4 " 1 33";
Cheerleader, 208 118 4 " 1 9 13 21";
ChegadeSaudade, 300 135 4 " 1 9 41 71";
Dang, 64 105 4 " 1";
Embona, 532 150 4 " 1 24 56 86 118";
Equilibrium, 56 118 4 " 1 3";
Espion, 752 129 4 " 1 17 49 61 93 125 157";
EtrangeJournee, 144 125 4 " 1 13";
EveryBreath, 400 103 4 " 1 11 35 45 69";
Fahatsia, 128 149 4 " 1";
Formidable, 324 135 4 " 1 5 37 39 71";
Free1, 4 100 4 " 1";
Free4, 16 100 4 " 1";
Free8, 32 100 4 " 1";
Free16, 64 200 4 " 1";
Free24, 96 200 4 " 1";
Free32, 128 200 4 " 1";
FreedomJazzDance, 32 105 4 " 1";
Guerre, 240 119 2 " 1 27 48 65 97";
Handfulofkeys, 344 240 4 " 1 9 41 50";
HandfulofkeysTheme1, 160 240 4 " 1 9 41";
Happy, 192 160 4 " 1 17 33";
Helmut, 128 130 4 " 1";
Hoany, 190 133 1 " 1 22 40 66 96 119 151 159";
Ifarakely, 444 102 4 " 1 33 65 81 88";
Jabeau, 48 120 3;
JakeFine, 32 83 4 " 1";
JustAGigolo, 272 124 4 " 1 5 37";
JustTheWay, 64 130 4 " 1 11";
KillerJoe, 128 135 4 " 1";
Kissamile, 32 170 4 " 1";
L-O-V-E, 504 157 4 " 1 5 37 69 101";
LaJavanaise, 72 110 3 " 1";
Lasa, 672 120 4 " 1 33 53 78 95 103 112 144";
Liana, 748 120 4 " 1 27 56 67 92 124 156";
LianaIntro16, 64 270 4 " 1";
LoveYourself, 160 100 4 " 1 33";
Lullaby, 536 129 4 " 1 11 43 75 79 95";
MakingFlippy, 64 130 4 " 1";
Malaky, 346 145 2 " 1 19 43 75 99 119 144";
Mezerg, 128 132 4 " 1";
MieuxQue, 608 126 4 " 1 9 33 57 81 97 121";
Nightintunisia, 320 170 4 " 1 17 49 65";
Padam, 618 181 3 " 1 24 46 76 95 117 149 175";
PasAVendre, 616 134 4 " 1 9 25 43 75 91 123";
PasJalouse, 608 139 4 " 1 17 33 49 65 81 89 121";
PasPeur, 592 120 4 " 1 5 33 61 89 117";
Perfect, 190 46 2 " 1 5 32 58 64";
Perhaps, 304 103 4 " 1 5 37 53";
Rasputin, 148 123 4 " 1 29";
Rasputincourt, 116 123 4 " 1";
SatinDoll, 144 125 4 " 1 5";
Save, 406 144 2 " 1 5 37 69 101 120 148 180";
SoWhat, 128 135 4 " 1";
Spain, 220 240 4 " 1 11 19 32";
StarWazzz, 32 135 4 " 1";
Summertime, 64 180 4 " 1";
TakeFive, 200 170 5 " 1 33";
TheseBoots, 624 164 4 " 1 32 63 94 102 125";
Tsofyrano, 672 178 4 " 1 17 45 61 93 105 137";
Walk, 504 102 4 " 1 9 23 45 59 73 97 111";
Williason, 56 140 4 " 1";
WizKhalifa, 32 194 4 " 1";
Zay, 420 140 4 " 1 21 34 66 80";

Saving and Loading Files

In several cases, instead of saving individual files, Djazz saves groups of files together in folders. This means that interacting with Max’s save and load dialogs is slightly different than it would be for individual files.

The following cases uses folders when saving and loading:

The following cases use individual files:

In one of the first three cases, when you click the pertinent “Save” button, a dialog will appear. To save to a folder, perform the following steps in the dialog:

  1. Click “New Folder.”
  2. Enter a name for the folder in the popup window that appears
  3. Click “Save” in the dialog.

To load a folder, when you click the pertinent “Load” button, a dialog will appear. Choose the folder you want; don’t choose a file inside it. When you click on “Open,” the folder and all its files will load.

View Messages

The following messages are sent out of Djazz via its UDP send port:

pulse

sent whenever a new beat occurs

bpm

float - the current tempo

loop_length

int - the current loop length of score “new2”

octave

int - the current octave transposition of score “new2”

speed

float - the current speed of score “new2”

bar

int - the current bar of score “new2”

chapter

int - the current chapter of score “new2”

Settings

Pressing the settings button opens the settings window. The two settings you can change relate to the live audio playback.

AUDIO OFFSET (ms)

Sets the latency of the audio playback in milliseconds. Max has a natural latency between recording and playing; this setting offsets the latency. Default is 170.

XFADE TIME (ms)

Sets the crossfade time between live audio playback beats. Default is 203 milliseconds.

Improvising with Djazz

Each track or score can be played in improvise mode or not, by selecting or deselecting the “jam” button.

When not in improvise mode–we’ll call this play mode–the beats will be played one after the other as they were written/recorded in the loaded tracks. In improvise mode, at each new beat, Djazz calculates a new beat’s worth of music to play. The calculation consists of finding a beat in the database that is the “best match” (or at least a “good match”) based on the data that exists at the beginning of the new beat. The selection is made using a data structure called a factor oracle.

In play mode, Djazz uses the beat number to calculate the next beat. In improvise mode, the beat number is not considered; the chord label from the song file is used.In each of these two modes changing the speed control will make play at the tempo given by the tap or play at a different speed: double speed, quadruple speed, half speed, and one and a half speed. The result is different, because play mode uses beat number messages and improvise mode uses beat label messages.

In play mode, if the Speed Control is active, beat numbers are output at a different tempo than the input tap. The musical result is an interesting version of “playing out:” beats are played at a different rate, meaning their internal harmony, given by each beat’s chord label, no longer aligns with that of the other tracks:

Master Clock Input:Am7D7Gmaj7Cmaj7
Internal Clock Follower Output:Am7D7Gmaj7Cmaj7Am7D7Gmaj7Cmaj7

In improvise mode, with the speed control on, labels are still passed in at the original tempo. The result is that the improviser outputs beats that conform to the harmony of the given beat, even though they are at a different tempo:

Master Clock Input:Am7D7Gmaj7Cmaj7
Improviser Output:Am7Am7D7D7Gmaj7Gmaj7Cmaj7Cmaj7
Chapter 3

API

Subsections of API

Abstraction Reference

Hmmmm…

Subsections of Abstraction Reference

darr.get_size

Returns the number of keys in a dict

When using a dict to mimic an array, use this to retrieve the length of the array.

OUTLETS
0   int

number of keys in dict

MESSAGES

symbol
dict name

SEE ALSO

djazz

flowchart TB;

AudioIn1((Audio\nIn L))
AudioIn2((Audio\nIn R))
MidiIn((MIDI In))
TapIn((Tap\nIn))
PattrIn((Pattr\nIn))
DataIn((File\nData\nIn))
PresetIn((Presets In))

Master[Master Control]
Audio[Djazz Audio]
Midi[Djazz MIDI]
PattrStorage[PattrStorage]

click Master "./../components/master_control.html" "Master Control"
click Audio "audio.html" "Master Control"
click Midi "midi.html" "Master Control"


AudioOut1(((Audio\nOut 1L)))
AudioOut2(((Audio\nOut 1R)))
AudioOut3(((Audio\nOut 2L)))
AudioOut4(((Audio\nOut 2R)))
AudioOut5(((Audio\nOut 3L)))
AudioOut6(((Audio\nOut 3R)))
MidiOut(((MIDI Out)))
PattrOut(((Pattr Out)))


AudioIn1--->Audio
AudioIn2--->Audio

TapIn-->Master

PattrIn-->Master
PattrIn-->Audio
PattrIn-->Midi

DataIn-->Audio
DataIn-->Midi
DataIn-->Master

Master-->Audio
Master-->Midi

MidiIn-->Midi

Audio-->AudioOut1
Audio-->AudioOut2
Audio-->AudioOut3
Audio-->AudioOut4
Audio-->AudioOut5
Audio-->AudioOut6

Midi-->MidiOut

PresetIn-->PattrStorage
PattrStorage-->PattrOut

INLETS

1   signal

Audio In 1

signal Audio signal is sent to djazz_audio_in

2   signal

Audio In 2

signal Audio signal is sent to djazz_audio_in

3   list

Midi In

list (int pitch, int velocity, int channel) sent to djazz_midi_in

4   bang

Triggers next beat

bang All active tracks MIDI and audio tracks will play their data located at the current beat in tempo when a bang is received. Any armed recording tracks will record any input during this beat in tempo.

5   list

Asynchronous input (such as that sent from pattr objects)

list (symbol argument-name anything argument-value) See the section on pattrs

6   symbol

Loads records needed for playback

symbol The name of a Max dict that has been loaded with a JSON file. These are either song files or score files.

7   anything

Messages to the pattrstorage objects

anything This is only used to send the “clientwindow” message to the pattrstorage object, which is useful for debugging. Any preset-related messages could be sent, but they should actually be sent to djazz_control.

OUTLETS

0   signal

Audio Track 1 Out 1

Audio signal

1   signal

Audio Track 1 Out 2

Audio signal

2   signal

Audio Track 2 Out 1

Audio signal

3   signal

Audio Track 2 Out 2

Audio signal

4   signal

Audio Track 3 Out 1

Audio signal

5   signal

Audio Track 3 Out 2

Audio signal

6   list

MIDI output

A MIDI note is sent out as a list (int pitch, int velocity, int channel)

7   list

View control data

ATTRIBUTES

None

MESSAGES

### MESSAGES
-See asynchronous messages.
-See

Page not found: /3_api/1_abstraction_references/components/master_control

for details about the following:

/master_control

Page not found: /3_api/1_abstraction_references/components/master_control#loop-section-active

0/1

Page not found: /3_api/1_abstraction_references/components/master_control

list (int int) start-beat end-beat master::start_beat int
master::end_beat int
master::initial_tempo float
-See Audio In for details about the following:
/audio_in
audio::audio_in::record_active 0/1
audio::audio_in::max_repetitions int
audio::audio_in::save::folder_path symbol
-See Audio Out for details about the following:
/audio_out
(for n from 1-3):
audio::audio_out::beat_players::beat_player_n::crossfade_time_in_ms int
audio::audio_out::beat_players::beat_player_n::audio_buffer_offset_in_ms int
(for n from 1-3):
audio::audio_out::listeners::listener_n 0/1
audio::audio_out::listeners::include_master 0/1
(for n from 1-3):
audio::audio_out::audio_out_bank::track_n::volume int 0-127
audio::audio_out::audio_out_bank::track_n::mute 0/1
audio::audio_out::audio_out_bank::track_n::solo 0/1
audio::audio_out::audio_out_bank::track_n::active 0/1
(for n from 1-3):
audio::audio_out::generators::audio_beat_generator_n::loop_length int
audio::audio_out::generators::audio_beat_generator_n::speed_numerator int
audio::audio_out::generators::audio_beat_generator_n::end_beat int
audio::audio_out::generators::audio_beat_generator_n::next_beat int
audio::audio_out::generators::audio_beat_generator_n::loop_section_active 0/1
audio::audio_out::generators::audio_beat_generator_n::speed_denominator int
audio::audio_out::generators::audio_beat_generator_n::speed_active 0/1
audio::audio_out::generators::audio_beat_generator_n::loop_section_beats int
audio::audio_out::generators::audio_beat_generator_n::pitch_range int
audio::audio_out::generators::audio_beat_generator_n::max_continuity int
audio::audio_out::generators::audio_beat_generator_n::improvise 0/1
audio::audio_out::generators::audio_beat_generator_n::transpose_octave int
audio::audio_out::generators::audio_beat_generator_n::transpose_pitch int
(for n from 1-3):
audio::audio_out::data_loaders::track_loader_n::repetition int
(for n from 1-15):
midi::midi_out::midi_out_bank::track_n::mute 0/1
midi::midi_out::midi_out_bank::track_n::active 0/1
midi::midi_out::midi_out_bank::track_n::solo 0/1
midi::midi_out::midi_out_bank::track_n::volume int 0-127
midi::midi_out::midi_out_bank::track_n::port symbol
midi::midi_out::midi_out_bank::track_n::channel_out int 1-16
midi::midi_out::midi_out_bank::track_n::ctrl_msg int
midi::midi_out::midi_out_bank::track_n::effect_list::transpose_octave::octaves int -255-+255
midi::midi_out::midi_out_bank::track_n::effect_list::transpose_pitch::semitones int -255-+255
midi::midi_out::data_loaders::scores::score_file_1::file_path symbol
midi::midi_out::data_loaders::scores::score_file_2::file_path symbol
midi::midi_out::data_loaders::track_loader_1::repetition int 0-255
midi::midi_out::data_loaders::track_loader_2::repetition int 0-255
(for n from 1-15):
midi::midi_out::listeners::listener_n
midi::midi_out::listeners::include_master
(for n from 1-15):
midi::midi_out::generators::midi_beat_generator_n::loop_length int
midi::midi_out::generators::midi_beat_generator_n::speed_numerator int
midi::midi_out::generators::midi_beat_generator_n::end_beat int
midi::midi_out::generators::midi_beat_generator_n::start_beat int
midi::midi_out::generators::midi_beat_generator_n::loop_section_active 0/1
midi::midi_out::generators::midi_beat_generator_n::speed_denominator int
midi::midi_out::generators::midi_beat_generator_n::speed_active 0/1
midi::midi_out::generators::midi_beat_generator_n::loop_section_beats list (int int)
midi::midi_out::generators::midi_beat_generator_n::pitch_range 0-255
midi::midi_out::generators::midi_beat_generator_n::max_continuity 0-255
midi::midi_out::generators::midi_beat_generator_n::improvise 0/1
midi::midi_in::folder_path symbol
midi::midi_in::record_active 0/1
midi::midi_in::save::folder_path symbol
SEE ALSO

SEE ALSO

djazz_data djazz_control djazz_view_control

darr.set_at

Sets the entry at the given index

When using a dict to mimic an array, use this as the assignment operator [] or set.

MESSAGES

list
left inlet: (int anything) index, entry

symbol
right inlet: dict name

SEE ALSO

djazz view

djazz.analyzer

Takes a label representing the current musical state, and returns another label to be used by the improvisation algorithm.

The input label can be passed to it by anything–the master control, other generators, or the same generator in which this analyzer resides.
Currently only passes the chord label for the next beat, passed by the master control, directly through without modification.
So for now this object exists more as a placeholder. This is where real-time music analysis code should go.

OUTLETS
0   list: symbol symbol

label + new symbol

MESSAGES

symbol
a label representing the current musical state to be used by the improvisation algorithm.

SEE ALSO

djazz.listener_control
djazz.listeners_router
djazz.beat_generator
djazz.midi.midi_beat_generator
djazz.audio.beat_generator

djazz view control

djazz.antescofo_file_to_tracks_dict

Converts an antescofo file into a Max dict (which can then be saved as a JSON file).

Dict format:
tracks
int
beat
int
notes
int: note data
int: note data
int

OUTLETS
0   symbol

tracks dict name

MESSAGES

symbol
full path to antescofo file

clear
clears the Max dict

SEE ALSO

djazz.antescofo_get_tempo

Uses antescofo to infer the current tempo based on time between input messages.

Loads the file antescofo_djazz.txt, which must be in the Max search path (currently in data/antescofo_scores).

OUTLETS
0   float

tempo inferred from time between inputs

MESSAGES

bang
left inlet: bangs will cause inferred tempo to be output. Initial tempo must be set and bangs must not deviate far from current tempo. Two bangs must occur before tempo is inferred.

initial_tempo
left inlet: ( + float) tempo to set antescofo’s tempo inference mechanism. Initial input tempo must be close to this.

SEE ALSO

djazz.audio.beat_generator

Upon receipt of a beat number, label, and tempo, sends data about the next beat to read to the beat reader.

Pattr messages (must be passed via an external pattrhub/pattrstorage):
transpose_pitch (int) -255 - +255
transpose_octave (int) -255 - +255
next_beat (int) 0-255
end_beat (int) 0-255
speed_active (int) 0/1
speed_numerator (int) 1-255
speed_denominator (int) 1-255
loop_length (int) 1-8
loop_section_active (int) 0/1
loop_section_beats (list: int int)
improvise (int) 0/1
pitch_range (int) 0-11
max_continuity (int) 0-255

OUTLETS
0   list

(int int int int) 1. beat generator number, 2. track number, 3. start time in ms, 4. end time in ms

MESSAGES

symbol
right inlet: label for analyzer

beat
left inlet: (+ int) incoming beat number

label
left inlet: (+ symbol) incoming beat label

tempo
left inlet: (+ float) current tempo

factor_oracle
left inlet: (+ symbol) dict name

beat_dict_name
left inlet: (+ symbol) dict name

SEE ALSO

djazz.beat_generator
djazz.audio.audio_out

djazz.audio.beat_player

Plays back a beat of audio at a time from a buffer, where beats are passed in in a dict.

Uses supervp to playback in tempo and with pitch transposition.

OUTLETS
0   signal

audio out 1

1   signal

audio out 2

MESSAGES

list
left inlet: (int float int int) 1. pitch transposition, 2. tempo, 3. start time, 4. end time

audio_buffer_offset_in_ms
middle inlet: (+ int) adjusts the latency of the audio output. Default is 170 ms.

crossfade_time_in_ms
middle inlet: (+ int) adjusts the crossfade time between beats.

audio_buffer_name
right inlet: (+ symbol) audio buffer to play from

SEE ALSO

djazz.audio.beat_generator
djazz.audio.supervp_player

djazz.audio.beat_reader

Reads the note data at the given beat data and sends it out to the beat player.

OUTLETS
0   list

(int int int) 1. track number, 2. start time in ms 3. end time in ms

1   int

beat count

MESSAGES

list
left inlet: (symbol int float) 1. beat dict name, 2. pitch transposition, 3. tempo

symbol
right inlet: beat list dict name

SEE ALSO

djazz.audio.listeners_router

Controls which other audio generator(s) a generator will listen to

Pattr messages (must be passed via an external pattrhub/pattrstorage):
include_master (int) 0/1
listener_1 (int 1-3) which player listener 1 is listening to
listener_2 (int 1-3) which player listener 2 is listening to
listener_3 (int 1-3) which player listener 3 is listening to

OUTLETS
0   symbol

label received from player being listened to

MESSAGES

list
right inlet: (int symbol) listener number and label passed from listener

label
left inlet: (symbol) the label passed from the master control. Will be passed through if include_master is set to 1

SEE ALSO

djazz.analyzer

djazz.audio.record

Records an audio buffer and a beat list, given the appropriate input.

OUTLETS
0   repetitions + int

sends every time a new repetition is added to beat list

1   setsize + int, crop 0 + int

sets the size of the buffer when recording is started/stopped, with/without clearing it, respectively

MESSAGES

signal
left inlet: audio in 1

signal
in1: audio in 2

audio_buffer_name
right inlet: (+ symbol) name of audio buffer to record to

audio_score_dict_name
right inlet: (+ symbol) name of audio score (+ beat list) to write to

beat
right inlet: (+ int) starts writing a new beat when received

initial_tempo
right inlet: (+ float) bpm by which to calculate next beat and note durations

loop_section_beats
right inlet: (+ list: int int) start beat, end beat
will begin a new repetition whenever end beat is reached, restarting at start beat

SEE ALSO

djazz.audio

djazz.audio.supervp_player

Wraps the supervp player for audio playback

OUTLETS
0   signal

audio out 1

1   signal

audio out 2

2   signal

position in audio file

MESSAGES

list
left inlet: float float float int:1. start time in ms, 2. end time in ms, 3. duration in ms, 4. transposition (in semitones)

int
in1: crossfade time between beats in ms

symbol
right inlet: buffer name to play from

SEE ALSO

djazz control

djazz.audio.transpose_octaves

Adjusts message being sent to djaz.audio.beat_player so that the audio will be transposed up the desired number of octaves.

Pattr messages (must be passed via an external pattrhub/pattrstorage):
octaves (int) -255 to 255

OUTLETS
0   list

(symbol int float) 1. beat dict name, 2. pitch transposition, 3. tempo

MESSAGES

list
left inlet: (+ list: symbol int float) 1. beat dict name, 2. pitch transposition 3. tempo

SEE ALSO

djazz.audio.transpose_pitch

Adjusts message being sent to djaz.audio.beat_player so that the audio will be transposed up the desired number of semitones.

Pattr messages (must be passed via an external pattrhub/pattrstorage):
semitones (int) -255 to 255

OUTLETS
0   list

symbol int float; 1. beat dict name, 2. pitchtransposition, 3. tempo

MESSAGES

list
left inlet: (+ list: symbol int float) 1. beat dict name, 2. pitch transposition, 3. tempo

SEE ALSO

djazz.audio

Handles all the audio portion of djazz.

OUTLETS
0   signal

audio out 1 left

1   signal

audio out 1 right

2   signal

audio out 2 left

3   signal

audio out 2 right

4   signal

audio out 3 left

5   signal

audio out 3 right

MESSAGES

signal
left inlet: audio in 1

signal
in1: audio in 2
-

audio_buffer_name
in2: (+ symbol) name of audio buffer to record to and play from

record_active
in2: (+ 0/1) 1 arms the audio buffer to record; will not start recording until a beat number is received. 0 turns off record state.

initial_tempo
in2: (+ float) bpm by which to calculate next beat and note durations

loop_section_beats
in2: (+ list: int int) start beat, end beat
will begin a new repetition whenever end beat is reached, restarting at start beat

max_repetitions
in2: (+ int) will stop recording when this number is reached

in
right inlet: (+ symbol) folder name audio data to load for audio in subpatcher

out
right inlet: (+ symbol) folder name audio data to load for audio out subpatcher

SEE ALSO

djazz.audio.record
djazz.audio.supervp_player

djazz.audio_out_track

Passes audio signal through. Control with djazz.view.audio_track.

Pattr messages (must be passed via an external pattrhub/pattrstorage):
volume (int) 0-127
active (int) 0/1
solo (int) 0/1
mute (int) 0/1

OUTLETS
0   signal

audio signal 1/L

1   signal

audio signal 2/R

MESSAGES

signal
left inlet: audio signal 1/L
right inlet: audio signal 2/R

SEE ALSO

djazz.view.audio_out_track
djazz.solo_bank

djazz.bang_speed

When active, will output beats in the polyrhythm given by numerator/denominator. Incoming beats will not be output, except for those that fall in phase with the output beats.

OUTLETS
0   bang

-bangs over time in the polyrhythm determined by numerator and denominator

1   float

-tempo using output bangs as beat

MESSAGES

bang
depends on polyrhythm state
left inlet: When effect off (active = 0), passed directly through. When effect on (active = 1), triggers a new polyrhythm, or is ignored if a polyrhythm is in course.

active
left inlet: (+ 0/1) turns effect off or on

numerator
left inlet: (+ int) number of evenly spaced bangs to output in the space of denominator beats at the given tempo

denominator
left inlet: (+ int) number of beats to output numerator evenly spaced bangs over

SEE ALSO

djazz.beat_clock

Inputs bangs and outputs a beat number, based on loop, step, start, and end parameters.

Will not output when end beat is reached or after.

OUTLETS
0   int

next beat

1   bang

bang when loop occurs

2   bang

bang when end is reached

MESSAGES

bang
left inlet: bang for next beat

next_beat
right inlet: (+ int) sets the next beat to play when next bang is received

end
right inlet: (+ int) sets the end beat; when reached, no more output will occur

step
right inlet: (+ int) how many beats to advance upon receiving a bang; default is 1

SEE ALSO

Externals

Subsections of Externals

Antescofo

Antescofo is used in two places:

  1. The master control , in its subpatcher djazz.antescofo_get_tempo to calculate the tempo. Uses the score “djazz_antescofo.txt” in the djazz_data/scores folder.

  2. The MIDI beat reader , to sequence and send out midi notes in the proper tempo and rhythm. Uses the score “antescofo_play_beat.txt” in the djazz_data/scores folder.

Midifile

This is a small C application that is called from the shell in the make-score-file tool. It converts MIDI data to a .txt file, which is then converted by the tool into JSON.

File formats used

Audio data is saved in WAV form. Besides this, all Djazz data is saved to and loaded from JSON in order to be imported into Max dictionaries. This includes MIDI data.

The antescofo .txt files included with song folders is converted to JSON when loaded.

Improvisation

Subsections of Improvisation

Generator Components

flowchart TB;

in(( ))
out(( ))

subgraph SP[Score Player];
direction TB
    in1(( ))
    speed1[Speed Control]
    bc[Beat Clock]
    out1(( ))
    in1 -->|bang| speed1 -->|bang| bc -->|beat number| out1
end


subgraph I[Improviser];
direction TB
    in2(( ))
    speed2[Speed Control]
    label[hold label]
    FOP[Factor Oracle Player]
    out2(( ))
    in2 --> |label |label
    in2 -->|label| speed2 -->|bang| label -->|label| FOP -->|beat number| out2
end

in-->in1
in-->in2
out1-->out
out2-->out


The generator uses the beat number when improvise mode is not on; it uses this to play the next beat or a different beat if one has been selected by the user. In improvise mode, the beat number is not considered. The label produced by the analyzer is used, as described above.

The beat generator can play in two modes: score player and improviser. Each of these also contain two modes: play at the tempo given by the tap, or play at a different speed: double speed, quadruple speed, half speed, and one and a half speed. This speed change is controlled by an object–the “Speed Control” that, when messages are passed to the generator, modifies the timing of their distribution to the generator’s internal objects. Even though both the score player and the improviser use the Speed Control, the musical result is different, because the Score Player receives beat number messages and the Improviser receives beat label messages. The musical result is described in the manual section on improvisation . Following is a description of the abstractions that control these processes.

The Score Player contains two subpatchers, a “Master Clock Follower” and an “Internal Clock Follower.” In Score Player mode, if the Speed Control is active, beat numbers are sent to the Internal Clock Follower. The Internal Clock Follower contains its own Beat Clock object. It is passed the same asynchronous messages as the Master Beat Clock, concerning the song beat data like the end beat, the current section beats, and whether the current chapter is being looped. If the Speed Control is inactive, the beat number messages given by the Master Beat Clock are simply passed through. If Speed Control is active, beat numbers are output at a different tempo than the input tap.

In the Improviser, it is the beat label messages are passed. Beat labels are passed in at the master tempo. When a label is received, it is saved in a message object and a bang is sent to the Speed Control. If active, the speed control at its modified tempo, which trigger the saved label to be passed to the factor oracle player. The result is that the factor oracle player outputs beats that conform to the harmony of the given beat, even though they are at a different tempo.

Factor Oracle and Player

The factor oracle

The factor oracle data structure is described in detail in the following references: reference 1 reference 2 reference 3

The factor oracle player

The factor oracle player creates the improvisation. As its name suggests, it contains and makes use of the “factor_oracle” Max abstraction.

The algorithm for choosing beats from the factor oracle is described in this paper.

When the maximum continuity is reached, it takes a suffix link and searches for a matching label. If no matching label is found, it chooses a random state.

The analyzer uses the same set of symbols as the factor oracle. It is used both offline, to create a file of labeled beats for a song, and online, to convert the data at the beginning of each beat into a symbol to be passed to the factor oracle player. This symbol is then used as the query to the factor oracle to produce the next beat.

Labels

Definition:

A beat is a collection of notes that occurs between two timepoints. These timepoints are considered to occur at regular intervals. Thus a piece of music that has a pulse can be considered a sequence of beats.

At each new beat, calculate a new beat’s worth of music to play. The calculation consists of finding a beat in the database that is the “best match” (or at least a “good match”) based on the data that exists at the beginning of the new beat.

This data can be based on any of the following:

  1. The location in the song/musical piece. For example, “the A minor 7 chord that occurs at the beginning of measure 13.” A good match is a beat from the database that occurs over the same chord. This could be the same beat as in the original piece, or it could be a different beat that has the same chord, which is more interesting. This creates correct adherence to musical form, if such form exists in the piece.

  2. What we just played in the last beat. For example, an ascending scale in the previous beat could look for a melody that starts on the next note in the scale in the next beat. This creates continuity.

  3. What other listeners have played. This creates responsiveness.

In the current usage of Djazz, this match is based only on option 1: the chord symbol that occurs on the given beat.

Label matching

Matching is done by comparing labels. Each beat has a label which reflects the data described above. It is a string of symbols. The nature of this string is determined by the user. In the current usage of Djazz, this string represents the chord symbol, which consists of the chord root and its quality, separated by an underline. Chord roots are numbered from zero to eleven, with zero representing C; thus, C# (or Db) is 1, D is 2, etc. For example, “0_maj7” represents a C major seventh chord.

A match can be made by exact comparison, or by “fuzzy” methods. In the current usage of Djazz, a chord represents a match if the quality is the same, but the root can be a small distance away from the desired one. The melody is then transposed to match the correct root.

Offline analysis currently consists of adding the chord labels to each beat. The user inputs this using a graphical tool that takes chord information and stores it in a list of beats; that is, no analysis is done save for copying the “chord chart” into a data file. This data file, which also contains other data like the song tempo, time signature, section starting and ending beats, and song title, is loaded into Djazz when a song is played.

Online analysis, as a result, is just a case of reading the chord label from the dictionary when a beat number is generated. This is in fact done by the master clock: it sends out the tempo, chord label, beat number, in immediate succession each time a tap is input.

The methods here are general, and the current usage of Djazz can be changed to admit other types of music. This would involve using an extant system, devising a new one, or modifying an extant one to label beats. Optionally defining the definition of a match, if it is not defined as exact.

The following criteria must be met: The online analyzer uses the same set of labels as the offline analyzer, if an offline analyzer is used.

Also, the architecture is modular, which means that other methods of improvisation are possible. That means that another object can replace the factor oracle player within “improviser” as long as it adheres to the following criteria:

  1. It receives a label at the beginning of each beat
  2. It produces a beat number, in response to the label, that represents the next beat to play.

Example: Song with the same chord for all beats.

In the case where all the beat labels are the same, the factor oracle player algorithm will ground out to simply choosing a measure aleatorically.

In some cases this could be desired. It is perhaps more interesting, though, to take advantage of the label-matching behavior to create one’s own labels, and thus direct the improvisation.

Following the description of the matching criteria, the first half of the label must be a chord root symbol, but the second half can be anything: it will be matched by exact string matching.

A song with beats labeled thus:

E m7E m7E m7E m7E m7E m7E m7E m7
E m7E m7E m7E m7E m7E m7E m7E m7

courld be written as

E 1E 2E 3E 4E 1E 2E 3E 4
E 1E 2E 3E 4E 1E 2E 3E 4

which would always select a measure labelled with a 2 to follow a measure labelled with a 1, a 3 to follow a 2, etc. Like this, formal positions in sections could be preserved.

E aE fE dE cE aE bE aE b
E dE fE cE 4E 1E 2E 3E 4

Djazz supplies a software framework for empirical inquiry into the suitability of a particular data encoding for music: ascertaining the “correctness” of an analysis via listening to the resulting synthesis.

External controls and views

To use a new kind of Launchpad, a Launchpad device file must be created and added to the djazz_data/presets folder, and a corresponding Max objects added in the external_controllers subpatcher at the top level of the.

Subsections of External controls and views

Parameters

Parameters

Djazz uses Max parameters to attach a device, ewither a controller or a view, to the system. The Max parameter system is similar to its pattr system: when a message is received in the form <parameter name > <parameter value >, the parameter with the called name is updated with the given value. Unlike pattrs, though, whose scope is contained within an object or abstraction, parameters have global scope.

All pattrs in djazz.view are parameter enabled.

The object _djazz.parameter_handler.js_ß maintains an array of parameter listeners, one for each parameter, and outputs parameter names and values upon when values are changed. Device interfaces can be connected to the inlet or outlet of this object to modify or display parameter values.

To create a Max patcher that serves as an interface for an external device:
  • Control devices should output messages in the form <parameter name> <parameter value>.
  • View devices should output messages in the form <parameter name> <parameter value>. See the djazz.launchpad_interface patcher as an example of an abstraction that does both.

A list of all parameters and their current values can be accessed by opening “Parameters” in the Max menu.

NOTE to developers interested in JS Max listeners: The JS Max objects Parameterlistener and maxobjlisteners are actually hard to deal with because you can’t delete them. So they continue to live, inaccessible but possibly still affecting output, until garbage collection comes their way.

Dicts

Dictionaries are used in Djazz in different ways, for representing songs, architecture, and as another example for the launchpad, to keep track of how buttons are mapped to parameters and how parameters are mapped to lights. For this, several different types of dictionaries were required:

The format for each of these dicts can be done in different ways. Some criteria exist:

  • User-created files should be easy to create, either by editing the text or with a max object; prefereably both.
  • Data access in the dicts at runtime must be efficient.

These two criteria ask for different formats. Also, we might need to change them in the future, to accomodate new devices.

To address these issues, database accessor files exist to translate between the formats of the various dicts. Each one exports a set of methods that access data or modify data. the implementation of the methods are hidden to the user. Each one is specific to the context it acts in. The exported methods have the same names, but the implementation is different depending on the structure of the dict it reads or writes to. thus, we can use a single javascript object to read the desired dictionaries and then translate them into the format the system needs. Each accessor is imported into the module using a require statement. The module names passed to these require statements are given as jsarguments to the object. If we change or add a new dict format, we write a new reader, which only involves rewriting the implementation of the exported methods—and replace it in the appropriate require field.

Device-specific dicts

The two device-specific dicts are imported from JSON files; thus are two device-specific files:

  • the device file
  • the grid file

These must be written in order to connect a new device with view and control capabilities, like a Launchpad, to Djazz.

Device dict

the device file contains device-specific data:

  • the device name (used for routing messages in Djazz)
  • any metadata about the device itself
  • the number of midi controls
  • the number of cc controls
  • the MIDI/CC codes for each color. Colors are represented by two variables, their hue (the name of the color itself) and their value (bright or dim).
  • the MIDI/CC codes for each button’s illumination behavior. For the Launchpad Pro MK3, buttons can glow statically, they can flash, or they can pulse.

For the Launchpad Pro MK3, the data file is this:

{
    "device" : "Launchpad Mini"
    ,
    "manual" : "https://leemans.ch/latex/doc_launchpad-programmers-reference.pdf"
    ,
    "midi_count" : 120 
    ,
    "cc_count" : 0
    ,
	"colors" : 	    {
        "none" : {
            "bright"    : 0
            ,
            "dim"       : 0
        }
        ,
		"red" : {
            "dim"       : 1
            ,
            "bright"    : 3
        }
        ,
        "orange" : {
            "dim"       : 17
            ,
            "bright"    : 51
        }
        ,
        "yellow" : {
            "dim"       : 41
            , 
            "bright"    : 51
        }
        ,
        "green" : {
            "dim"       : 16
            ,
            "bright"    : 48
        }
        ,
        "brown" : {
            "dim"       : 38
            ,
            "bright"    : 35
        }

    }
    ,
    "behaviors" : {
        "static"        : 12
        ,
        "flashing"      : 8
    }
}
Grid dict

the grid file describes the way a song grid can be represented on the Launchpad. It contains the following information:

  • the device name

  • the cell numbers that represent song chapters. these are listed in order of the chapters they represent. In the following code example, then, “cc 89” represents chapter 1, “cc 79” represents chapter 2, etc.

  • the colors that represent the state of a chapter in the grid. A grid cell (chapter or bar) is in one of the following states:

    • playing: the cell is currently being played
    • waiting: the cell has been selected to be played, and will start playing as soon as the next beat occurs
    • off: neither waiting or playing
    • unused: the song does not contain the chapter or bar associated with this cell
  • the cell numbers that represent song bars (listed in order like chapter numbers)

  • the colors that represent the state of a bar in the grid (same as chapter states).

  • optional metadata about the device, such as the links to manufacturer’s information

For the Launchpad Pro MK3, the grid file is this:

{
    "device" : "Launchpad Pro MK3"
    ,
    "manual" : "https://fael-downloads-prod.focusrite.com/customer/prod/s3fs-public/downloads/LPP3_prog_ref_guide_200415.pdf"
    ,
    "grid" : {
        "chapter" :     {
            "cells" : [
                "cc 89", "cc 79", "cc 69", "cc 59", 
                "cc 49", "cc 39", "cc 29", "cc 19"
            ]
                ,
                "colors" : {
                    "unused"    : "none",
                    "off"       : "green dim static",  
                    "waiting"   : "green dim static",
                    "playing"   : "green bright static"
                }
        }
        ,
        "bar" :         {
            "cells" : [
                "midi 81", "midi 82", "midi 83", "midi 84", "midi 85", "midi 86", "midi 87", "midi 88", 
                "midi 71", "midi 72", "midi 73", "midi 74", "midi 75", "midi 76", "midi 77", "midi 78", 
                "midi 61", "midi 62", "midi 63", "midi 64", "midi 65", "midi 66", "midi 67", "midi 68", 
                "midi 51", "midi 52", "midi 53", "midi 54", "midi 55", "midi 56", "midi 57", "midi 58"
            ]
            ,
            "colors" :  {
                "unused"    : "none",
                "off"       : "brown dim static",  
                "waiting"   : "red dim static",
                "playing"   : "red bright static"
            }
        }
    }
}
Mapping dict

A mapping file is a file that the user creates, using the editing tool in Djazz, that contains the mappings between the Launchpad cells and the parameters she wants to control. It also imports into it the grid.

Runtime parameter dicts

Launchpads have both view and control capabilities; that is, they can send input to Djazz (control) as well as show output (view).

System Architecture

Synchronous and Asynchoronous Input

Input is passed to patchers two ways: synchronously and asynchronously, depending on the type of input data. Synchoronous data;

  • beat number (int),
  • current tempo (float)
  • beat label (symbol)
  • loop section beats (list: int int) the start and end beat of the section being looped. This is used to calculate the length of repetitions for live MIDI and audio input. It can change when the current beat advances to the next chapter, so this data is triggered and sent out by the master control instead of asynchronously.
  • dict names (symbol), such as those for beat lists and factor oracles . This is because data must be loaded before other control variables can be set.

This data is passed serially through patch cords. Send and receive Max objects are not used, to ensure synchrony, as well as to aid debugging and avoid complicating the control flow.

Asynchronous data is anything changed by the user using the GUI. A lot of this data is well known to audio interface users: track volume, MIDI and audio effects like pitch transposition, for instance.

Subsections of System Architecture

General Approach

Synchronous data is passed using patch lines. Sends and receives are avoided in order to allow event probes, protect encapsulation, and generally keep patchers readable.

Asynchronous data is stored in pattrs, and updated with pattrhubs and pattrstorages.

Asynchronous Data and the MVCVC Design

ARCHITECTURE

Djazz uses the familiar Model-View-Control-View Control (MVCVC) design pattern. Each of these components will be discussed below. This particular interpretation of MVCVC was influenced by the design specifications for audio plugin development for the WWISE audio engine distributed by Audiokinetic.

flowchart TB;

V[View];
C[Control];
M[Model];
VC[View Control];

V --> C
C --> M
M --> VC
VC --> V

This design is primarily to maintain an organised control flow of asynchronous data–data that is input by the user. This is done using Max’s pattr system; any user-controlled variable is stored as a separate pattr in the view, control, the model, and possibly the view control. Their values are passed through each of these components in a directed path, possibly undergoing name translation or value conversion along the way:

flowchart TB;

subgraph V[View];
end

subgraph C[Control];
direction TB
    tvc[translate view to control]
    ctrlpattrs[control pattrs]
    tcm[translate control to model]
    tvc --> ctrlpattrs--> tcm
end

subgraph M[Model];
end

subgraph VC[View Control];
direction TB
    tmv[translate model to view]
end

V --> tvc
tcm --> M
tmv --> V
M --> tmv

While the path resembles a loop, output restriction in the view in fact keep messages from being passed on, thus avoiding circularity.

MODEL

The model (djazz.maxpat) is the actual Djazz patcher, in the sense that all the functionality occurs in this patcher: MIDI and audio input and output processing, timing synchronization, improvisation calculation, etc.

Abstractions in the model contain pattrs which are set by sending messages in the form <pattr name> <pattr value>. The pattrhub Max object distributes these messages to the appropriate pattr objects.

CONTR0L

The control acts as the interface to pass messages to the model. It is similar to a shell in an operating system, or a parameter bank in an audio plugin. Its input represents the set of all possible asynchronous messages that can be sent to Djazz. Its job is to translate these messages to their appropriate messages that the model understands, and to handle any value initialization and message dependencies.

There are many pattrs in the model.

  • Not all pattrs may be desired to be used, or exposed to the user.
  • The organization of the pattr hierarchy in the model may not reflect the user’s conception
  • it may be wished to call pattrs in the model via other variables that need some processing to determine their value.

The control, then, acts a shell which exposes the messages that can be sent to Djazz. By replacing the control, you can change the commands it responds to without changing the model itself.

To make modularity easier, pattrs in the control are grouped in encapsulations. This means that calling nested pattrs demands the “::” syntax (see example below).

VIEW CONTROL

The model outputs pattrs to any view that wants to receive them. It does this the same way as the control: a pattrstorage object is at the top level of the model patcher, and when a pattr value is updated, it outputs the pattr name and value.

There are two types of pattrs that the model outputs: those that are specifically for a view, and the parameters that were sent from the control. Values in abstractions in the model that are to be sent to the view control are stored as pattrs inside subpatchers named “view,” so that they can be extracted from the other pattrs passed out of hte model.

VIEW

The view is a collection of bpatchers containing graphical controls and data fields. It triggers messages to be sent to the control. Different views could be used, and even several views at the same time. The Launchpad interfaces are also views.

Note: with this method, the interior pattrhub objects end up not being used at all, but it’s still good to leave them in so that these objects can be reused and are not dependent on being called this way.

Finally, unused variables simply aren’t called. But to be absolutely sure that uncalled variables don’t give us trouble, by storing state that have forgotten about, or by accidentally being called, due to sharing names accidentally with a control variable, we can turn off their visibility to the pattrstorage system, which means they can never be called.

To avoid an infinite loop, we make use the pattrstorage object’s outputmode attribute. In the control and model, the pattrstorage outputmode is set to 2: any changed values are sent out. But in the view, the output mode is 6: values that are changed by objects in the pattr system are not sent out from the pattrstorage object. That is, only values that are changed by user interaction are sent out. Thus the values received by pattrhub are set, but not sent to the control. This way, pattr values can be sent back from the model into the view (via the view control object which filters them and translates their names if necessary), without these pattr values being again passed out to the control (which would create an infinite loop).

EXAMPLE

As an example, we follow the message sent when the pitch on MIDI track 13 is changed, using either the up, down, or reset-pitch button:
midi track labeled midi track labeled

The corresponding pattr in the view is named transpose_pitch, and takes an integer value. The up, down, and reset buttons are proper to the usage conceived for this particular graphical interface, so their logic is contained within the view; they modify the transpose_pitch pattr and do not send any messages directly to the control.

midi track labeled midi track labeled

In the view, the triggered pattr is located in the bpatcher named track_13, which itself is inside the bpatcher named midi. When triggered, the pattrstorage object inside the view updates its value and sends out the message midi::track_13::transpose_pitch 0. This message is sent out the second view outlet and into djazz.control.

In djazz_control, the pattrhub object distributes the message to the corresponding subpatcher named midi, which contains a djazz.control.track abstraction named__track_13_, which contains a pattr object named transpose_pitch. midi track labeled midi track labeled midi track labeled midi track labeled midi track labeled midi track labeled

This pattr now sends its updated value 0 directly (not via the pattrstorage object in djazz.control) through the djazz.control.midi.translate_track abstraction in order to rename it for the correct pattr object in the model:

midi track labeled midi track labeled midi track labeled midi track labeled

The message sent to the model is midi::midi_out::midi_out_bank::track_13::effect_list::transpose_pitch::semitones 0. It is received by the pattrhub object in the model and sent to the corresponding patcher:
midi track labeled midi track labeled midi track labeled midi track labeled midi track labeled midi track labeled midi track labeled midi track labeled midi track labeled midi track labeled midi track labeled midi track labeled midi track labeled midi track labeled

When the pattr in the model is updated, the model’s pattrstorage sends its name and value to the view control, which translates it and sends it back to the view.

The state of the variable can be seen in each of the four debug windows (view, control, model, and view control).

midi track labeled midi track labeled midi track labeled midi track labeled

Pattr Visibility

For more complex abstractions that use several pattrs, as well as abstractions that lend themselves to reuse, such as the beat-generators which are nested in midi- and audio-beat-generators, Djazz uses the second method of pattr passing:

flowchart LR;
in(( ))
subgraph A[A];
    subgraph B[B];
        subgraph C[C];
        direction TB
            p[pattr my_pattr]
        end
    end
end
in -->|A::B::C::my_pattr|p

flowchart LR;
in(( ))
subgraph A[A];
direction TB
    pA[pattr my_pattr_A]
subgraph B[B];
direction TB
    pB[pattr my_pattr_B]
subgraph C[C];
direction TB
    pC[pattr my_pattr_C]
end
end
end
in -->|my_pattr_A|pA
pA -->|my_pattr_B|pB
pB -->|my_pattr_C|pC

Pattrs within nested abstractions are “hidden” from calls to the exterior abstraction. They are updated by calling a pattr in the exterior abstraction, which translates them to the appropriate pattr call to the interior abstraction; sometimes this sequence of calls to nested pattrs has several levels. In Max, a pattr is never actually hidden, as it can always be called using the double-colon syntax corresponding to the object in which it is located. But a pattr can be hidden to the pattrstorage object that references it by setting the pattr’s visibility attribute to zero. The small object pattrvis.js was written to turn on and off the visibility of all the pattrs in an abstraction; it can act hierarchically as well, turning on or off all the visibility of pattrs in subpatchers.
The pattrvis.js object is used in the appropriate abstractions, and does not have an effect on the functionnality of the program. It can be used to keep the debugging windows more readable, when nested pattrs have their visibility off. To inspect pattr messages passed to nested abstractions, turn their visibilities on by passing 1 to the pattrvis.js object in the corresponding abstraction.

Synchronous Data in the Model

Because Djazz is beat-based, most objects are built to receive and process information at recurring instances. Djazz is played by inputting a tap, either manually, or from a built-in metronome, or from another application. The tap triggers a beat, which triggers notes to be output from the factor oracle or the score, which triggers note data to be output from antescofo, which triggers sound to be output by the audio or midi outputs.

Upon receiving a tap, Djazz plays music by selecting sections from scores in one of two ways: playing it back “straight,” or by calculating an improvisation using the factor oracle algorithm. This results in a reshuffling of the beats, which lines up with the harmonic content of the song. The factor oracle algorithm can be modified with pattern-matching methods. The input to the factor oracle come from scores and real-time input, either audio or MIDI, and is output as audio or MIDI. It uses Antescofo to generate notes both from scores and generated as improvisations in tempo.

TOP LEVEL
graph TB;
    A[Master Clock] 
	B[Audio]
	C[MIDI]
	A-->|tempo, beat number, label| B
	A-->|tempo, beat number, label| C

In a nutshell, Djazz is made up of the following:

  • several players which function independently.
  • master control for synchronising timing and for broadcasting global commands.

The master control sends out the following data synchronously to all the players:

  1. tempo,
  2. beat,
  3. beat label.

It sends this data immediately in succession and in this order to midi and audio generators. This order is important, so that the generators can calculate the correct information to play at the beginning of each beat. It determinmes this data in the following ways:

  • It contains a beat clock abstraction which acts as a master clock; it outputs a beat number when it receives a bang. It increments its beat number with each output, but also keeps track of position in a song form and adjusts the beat in accordance if looped.
  • It keeps track of tempo if tempo is manually input and fluctuates. This uses antescofo.
  • It reads from the song dict to get label.
GENERATORS

The abstractions that do most of the work in Djazz are the generators. They accept the data passed by the master control and convert them into appropriate musical output. There are two types of generators: MIDI and audio. Their construction is very similar; the difference is a result of the way audio data is played differently from MIDI data.

MIDI GENERATORS
flowchart TB;
gIn(( ))
g1[Generator 1]
g2[Generator 2]
g3[Generator 3]
g4[Generator 4]
g5[Generator 5]

mbPlayer[MIDI Beat Player]

t1[MIDI\nTrack 1]
t2[MIDI\nTrack 2]
t3[MIDI\nTrack 3]
t4[MIDI\nTrack 4]
t5[MIDI\nTrack 5]

gOut((( )))

gIn --> g1 --> mbPlayer
gIn --> g2 --> mbPlayer
gIn --> g3 --> mbPlayer
gIn --> g4 --> mbPlayer
gIn --> g5 --> mbPlayer

mbPlayer --> t1 --> gOut
mbPlayer --> t2 --> gOut
mbPlayer --> t3 --> gOut
mbPlayer --> t4 --> gOut
mbPlayer --> t5 --> gOut

AUDIO GENERATORS

To write

Adding to Djazz

Subsections of Adding to Djazz

Adding to Djazz

To add functionality to Djazz, use the following method:

IN MODEL:
  • Create your patcher. Use pattr objects for asynchronous input. You can include a pattrhub object to broadcast pattr messages for reusability’s sake, but this is not needed if the patcher is inside the model patcher (djazz.maxpat).
  • Connect your patcher in the appropriate place inside djazz.maxpat. See the specific descriptions for examples.
IN CONTROL:
  • Inside djazz.control, place a subpatcher, possibly containing other subpatchers, with pattr objects, so that the patcher/pattr hierarchy reflects the way in which you want your new functionality to be called.
  • Create a translator subpatcher and connect the output of the control subpatcher to it. This translator subpatcher should convert the message passed into djazz.control (<control variable name> <control variable value>) to the message needed by the model (<model variable name> <model variable value>). The Max regexp and __ objects are good for this. You can use the Debug View button to open the lists of pattrs in the model and control to make sure things are being named properly.
  • Parameter-enable the pattrs if you want to trigger them with external devices via Djazz’s parameter handler patcher. Alternatively, you could pattern-enable the pattrs in the view (following section). Only parameter-enable one set of pattrs: those in the control or those in the view.
  • Connect the translator to the control output that goes to the model.
IN A VIEW:
  • Create a bpatcher containing the graphic controls and views for your patcher. Attach pattr objects to the controls.
  • Create a translator subpatcher and connect the output of the control subpatcher to it. This translator subpatcher should convert the message passed out of your bpatcher (<view variable name> <view variable value>) to the message needed by the control (<control variable name> <control variable value>). The Max regexp and __ objects are good for this.
  • When placed in djazz.view, the pattrstorage system will handle the messaging; you don’t have to connect your bpatcher to an output.
IN A VIEW CONTROL:
  • If necessary, add a subpatcher with pattrs, and a corresponding trnaslator, to djazz.view_control if you want to pass data from the model back into your view subpatcher.

Be sure to give all your pattrs initial values, and that these initial values are the same in the view, control, model, and possibly view control.

MIDI Effects

Effects that modify MIDI output should be placed inside the djazz.midi_out_effect_list abstraction inside the djazz.midi_out_track abstraction:

Audio Effects

Effects that modify audio output should be placed in one of two places, depending how they function. There are two places where audio can be modified:

  1. If the object does not process audio data itself, but determines parameters to pass to the supervp player, so that it plays audio data back differently, it should be placed in the djazz.audio_beat_generator abstraction. This is how Djazz’s audio_transpose_pitch and audio_transpose_octave effects work:

  2. If the object processes audio itself, it should be placed between an djazz.beat_player object and an audio.out object:

Audio Effects

The factor oracle player, which Djazz uses to improvise, can be modified or replaced by another algorithm. There are several levels of depth to which you can modify the improvisation functionality; read the API section on improvisation . Here is just an explanation for where to put a new improviser Max object or abstraction.

Replace the improviser.maxpat abstraction in djazz.beat_generator. Your new improviser object should conform to the same input and output messages as the improviser.maxpat (see the reference page ).

Going further

The sections in this chapter refer to functionality that is not in Djazz, but where the architecture is organized to offer a development environment that encourages musical exploration as well as design issues in music programming.

Subsections of Going further

Changing the analysis in the factor oracle

Enabling listeners and Real-Time Analysis

Dynamic Object Creation and Destruction

This section describes an untested method for simplifying dynamic object creation and destruction in Max, using the MVC design described in another section. It was originally intended to be used with Djazz. It was coded using Javascript arrays and dictionaries of Max object instances, which ran into threading issues when these instances were created and destroyed before the Javascript thread was updated. Since then, Max has introduced Array objects (non-Javascript), which hopefully will obviate this problem; all code could be done in pure Max.

Dynamic creation and destruction of objects: arrays and dicts
  • Hierarchies
  • Saving and reloading architecture

Objects in Djazz should be created and destroyed, so you can set up variable numbers of different types of players, and different midi and audio outputs. The resulting configurations can then be saved and reloaded.

There are two data structures for saving objects: dictionaries and arrays, because some objects occur as ordered sets [midi tracks, effects], while others don’t (players, although they could).

Ordered sets are placed in arrays using javascript. This way they can be addressed using their indices in the array, and array operations can be used to keep track and change them.

In javascript you can make arrays of objects. To delete them, you have to both remove them from the patcher and remove them from the array or you will get undefined stuff.

The midi out bank is an example of a hierarchy of objects containing arrays. The bank contains tracks, and the tracks contain (among other things) midi effects. Tracks can be created and deleted, and so can effects. [SLIDE: tree]

In addition, there are effects that apply to groups of tracks:

  • BANK
  • TRACK GROUP
  • TRACK
  • EFFECT_LIST
  • EFFECT

To make this structure:
Each object in the hierarchy contains a javascript object with the variable name “components,” which is responsible for creating, deleting, and dispatching messages to, and gathering data from the hierarchy objects it contains.
Each « component » object contains an array of objects.
When objects are created, they are also placed in the array.

The code in each of these component objects is similar, and they could be abstracted into classes (prototypes) that components are derived from, if this method seems important enough to do that.

The bank can be saved as a dictionary.

Dictionary entries can be dictionaries and arrays, and array entries can be dictionaries and arrays.
The midi bank dictionary contains arrays which contain dictionaries which contain arrays. Arbitrary nesting of dictionaries and arrays is possible. Access and modification becomes complicated, which I’ll talk about in section 4.

To save a midi bank layout:

Javascript objects can declare attributes: values that can be accessed like normal max objects. Attributes can be dictionaries. Attribute values can also have custom getters and setters, which means that the attribute value does not have be something actually stored. A getter can dynamically construct it when it is invoked, and a setter can do something other than save the given value.
The midi bank thus has an attribute « bank_dict » that, when queried, builds a dictionary from its components’ data. It writes an array of its tracks, calling each of its tracks to give it the required data for its given array index. It calls each track by requesting a dict attribute from the track representing its components. The track builds a dict in the same way, calling its effect components. This process continues until a recursively-built dictionary is completed, then the midi bank passes it to the caller which writes it as a json file.
To reload the midi bank, the opposite occurs: the attribute value setter builds the track list by creating each track and then sending it the corresponding track dict so that it can build itself.
The actual dict values are at no time saved.

[EXAMPLE]

This can be applied to the entire architecture of a session, including all the players. It will be once we’ve worked out what all the players will be and how they will be arranged.
Because of the hierarchical arrangement of dictionaries, the midi bank can have its own set of presets that can be loaded and saved inside the preset of an entire session.
To load an entire session including the pattr presets, the architecture dictionary has to be loaded first, and then the preset file.
Both the model and the view contain these component objects.
Communication between the view and model is in the rightmost wire.
Building from these dicts in the model and the view treat the dict like a model, and the model and view become its views.
Communication between the control and model during construction must be handled carefully and I’m interested in how to do it better. Originally I thought it would be great to include the dict attributes in the pattr system. Then they could be controlled in the same way that the rest of the parameters are controlled.
The problem is this. [SLIDE] Javascript operates on a different (low-priority) thread than Max objects. When it calls Max to creat an object (new default), it passes control to this thread and continues to the next javascript command—we don’t know when the max command will finish in relation to the javascript.
As components in the view hierarchy are built, we can’t assume that their analogs in the model are built at the same time. Thus messages cannot be passed from one to the other.
Thus we cannot count on the pattr system working when the hierarchies are constructed. It has to use a different system.

Creating effects: to create a midi effect, several easy standards must be met:

  • MIDI notes follow a given value (list of numbers)
  • MIDI comes in the left inlet and out the left inlet
  • A control/view and a model patch
  • Communication btw control and model occur via pattr, so pattrs with the same name (possibly hierarchic) must exist in both patches
  • Control and model patchers must be put in appropriately named subfolders of a folder titled by the effect name.

If you do this, the effect will show up in the effect list.
This gives an easy, max-less way for developers to add their own effects.

Notes on Rewriting Djazz

Subsections of Notes on Rewriting Djazz

Dicts in Max and javascript

Dicts, like colls, are persistent and global, so use them only as read-only. Don’t use them as variables to pass around or for keeping track of state. Pattrs basically do this anyway so just use them to keep track of state snapshots.

You can’t put max objects in a dictionary. But you can put them in a javascript array. Max patchers basically are dictionaries, though, for objects in them with scripting names (varnames). They must both use hash tables to access their contents.