My OS X Programming Blog
Mac OS X Cocoa and CoreMIDI Programming
About Andrew Choi


MIDI Programs

MIDI File Player (External Device)

MIDI Destination Pop-Up Button

MIDI File Player (Internal Synth)

MusicSequence Sample Code

MIDI File Writer

MIDI Name Document Parser

NameConfigSetup

Fish Creek MIDI Framework

MidnamUtility

SysExSenderX

Other Programs

FCBlogEditor

FCBlog and Patch

Chinese Checkers Program

jyut6 ping3 Cantonese Input Method

Cocoa Sample Programs

Syntax Coloring Using Flex

NSTextField and Undo

NSToolbar

Implementing File Import

Launch Application and Open URL

Saving Uncommitted Text Field Edits

Algorithms

Jazz Chord Analysis as Optimization

Optimal Line Breaking for Music

Optimal Chord Spacing

   

A blog where I will write mostly about programming in Cocoa and CoreMIDI, and experiences from my ports of Emacs and XEmacs to the Mac OS.

Analysis of Jazz Chords as Optimization
Friday February 13, 2004

I didn’t want to write a lot of subscripts in HTML so I wrote up my algorithm in TeX. I’ve tested it on some more chord changes and the results look good. I’ll be fine-tuning the cost function to improve the algorithm’s local decisions.

The algorithm is an interesting discovery because many authors believe music analysis must include a rule-based component (see e.g., The Symbolic vs. Numeric Controversy in Automatic Analysis of Music by Mouton and Pachet). This algorithm seems to suggest otherwise for the problem of analyzing jazz chord changes.

This algorithm works well because not only does it follow the principles of legality and minimization described by Pachet, it also takes the latter a step further by preferring modulations to “closer keys” when possible. In this sense it’s in fact more powerful than the rule-based system described there.

Blues For Alice
Thursday February 12, 2004

I won’t have time to write about my algorithm today because I’m finishing a little late. But let me show you what it outputs for the changes for Blues For Alice!

Fmaj7  F Major
Em7b5  D HarmonicMinor
A7  D HarmonicMinor
Dm7  C Major
G7  C Major
Cm7  Bb Major
F7  Bb Major
Bbmaj7  Bb Major
Bbm7  Ab Major
Eb7  Ab Major
Am7  G MelodicMinor
D7  G MelodicMinor
Abm7  Gb Major
Db7  Gb Major
Gm7  F Major
C7  F Major
Fmaj7  F Major
Dm7  F Major
Gm7  F Major
C7  F Major
Perhaps it still need a bit of fine tuning (notice that it chooses the G melodic minor scale for the Am7 D7; is that better than the G major scale?). All of its other choices look good.

What’s remarkable about this algorithm is that it doesn’t possess any high-level knowledge except a single rule for II-V! The rest of it is “mathematical”. It’s implemented by about 250 lines of C++ code, excluding the “jazz theory library”, which is currently about 700 lines of C++ code.

JSSS and THoTH
Wednesday February 11, 2004

Today I found a Windows shareware program called Jazz Scale Suggester System (JSSS) which analyzes chord sequences and suggests scales that can be played over the chords. I also found the web page of an unpublished program called THoTH, which performs a similar function. It wasn’t possible to deduce from the web pages of these programs how they work. Posts in a newsgroup by the authors of the two programs provide some information on how JSSS works: it is written in CLIPS and it’s implemented by about 200 rules. THoTH’s author didn’t explain how that program works.

I still believe tonality analysis of chords can be formulated as a simple optimization problem and implemented using dynamic programming. I’ll work on this and explain what I mean tomorrow.

Possible Tonalities for a Chord
Tuesday February 10, 2004

For a given chord, we might like to detemine the scales that can be played over it. E.g., if we only consider major scales and harmonic and melodic minor scales in common key signatures, the C major scale, G major scale, and the E harmonic minor scale can be played over the Cmaj7 chord.

This is quite straightforward to implement using the classes I already have.

bool Contains(const Scale& s, const Chord& c)
{
  NoteVector sn = s.notes();
  NoteVector cn = c.notes();
  for (NoteVector::size_type i = 0; i < cn.size(); i++)
    if (std::find(sn.begin(), sn.end(), cn[i]) == sn.end())
      return false;
  return true;
}
The function Contains determines whether all the notes in a chord are contained in a scale. Using Contains, we can implement a function PossibleScales to prints all the scales in which a given chord is embedded. Thus, the code
int main()
{
  PossibleScales(Chord(Note(C), "maj7"));
  std::cout << std::endl;
  PossibleScales(Chord(Note(F, Sharp), "maj7"));
  std::cout << std::endl;
  PossibleScales(Chord(Note(G, Flat), "maj7"));
  std::cout << std::endl;
  PossibleScales(Chord(Note(D), "m7"));
  std::cout << std::endl;
  PossibleScales(Chord(Note(B), "m7b5"));
  std::cout << std::endl;
  PossibleScales(Chord(Note(E, Flat), "maj7#5"));

return 0; }

prints the output
C Major
G Major
E HarmonicMinor

F# Major

Db Major Bb HarmonicMinor

Bb Major F Major C Major A HarmonicMinor C MelodicMinor

C Major A HarmonicMinor C MelodicMinor D MelodicMinor

C HarmonicMinor C MelodicMinor

Scale Tone Chords for C Harmonic Minor
Monday February 9, 2004

I’ve added two constructors to the Chord class today. Chords can now be created from a root and a vector of intervals or from a vector of notes. In addition to the map for looking up interval vectors from chord names, I added a new map for looking up chord names from interval vectors. The STL map and vector class templates allow this to be implemented without writing a lot of code.

Once this is done, the scale tone chords of any given scale can be computed easily. Of course I had to look up a method book to find out that the scale tone chords for C harmonic minor are indeed CmMaj7, Dm7b5, Ebmaj7#5, Fm7, G7, Abmaj7, and Bdim.


#include <iostream>
#include "JazzTheoryClasses.h"

int main (int argc, char * const argv[]) { Scale CHarmonicMinorScale = Scale(Note(C), "HarmonicMinor"); std::cout << CHarmonicMinorScale << " [" << CHarmonicMinorScale.notes() << ']' << std::endl;

NoteVector nv = CHarmonicMinorScale.notes(); for (NoteVector::size_type i = 0; i < nv.size(); i++) { NoteVector chordNotes; chordNotes.push_back(nv[i]); chordNotes.push_back(nv[(i + 2) % nv.size()]); chordNotes.push_back(nv[(i + 4) % nv.size()]); chordNotes.push_back(nv[(i + 6) % nv.size()]); std::cout << Chord(chordNotes) << std::endl; }

return 0; } C HarmonicMinor [C D Eb F G Ab B ] CmMaj7 Dm7b5 Ebmaj7#5 Fm7 G7 Abmaj7 Bdim

February 2004
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29
Jan  Mar

xml

Search this blog with


Lists

Less-Known Facts About Emacs

Emacs Rants

Chinese Restaurants in Calgary

Calgary/Banff Tourist Attractions

C++ Reading List

Science Fiction Series

Top-10 Reason I Stopped Working on Emacs

Top-10 Types of Questions I Get About Emacs

10 Defining Moments as Programmer


Misc

Carbon XEmacs

Emacs for Mac OS X


Copyright © 2003, 2004, 2005 Andrew Choi (Contact Information). Created with FCBlog