cxchord
Version:
Midi Chord Recognizer
740 lines (588 loc) • 29 kB
text/typescript
import { ChordInstance, ChordMatcher, getChordName, getExtName, getNoteNumber } from "./cxchord"
import * as _ from 'lodash'
// jasmine.getEnv().addReporter(new jasmine.ConsoleReporter(console.log));
describe('Testing CxChord', function () {
var midiChord = [2, 6, 9, 13]
var chordInst = new ChordInstance(midiChord);
it('ChordInst reads and inverts a chord', function () {
expect(chordInst.chordInv.length).toEqual(4);
expect(chordInst.chordInv[0][0]).toEqual(0);
expect(chordInst.chordInv[0][1]).toEqual(4);
expect(chordInst.chordInv[0][2]).toEqual(7);
expect(chordInst.chordInv[0][3]).toEqual(11);
//
expect(chordInst.chordInv[1].length).toEqual(4);
expect(chordInst.chordInv[1][0]).toEqual(0);
expect(chordInst.chordInv[1][1]).toEqual(3);
expect(chordInst.chordInv[1][2]).toEqual(7);
expect(chordInst.chordInv[1][3]).toEqual(8);
//
expect(chordInst.chordInv[2].length).toEqual(4);
expect(chordInst.chordInv[2][0]).toEqual(0);
expect(chordInst.chordInv[2][1]).toEqual(4);
expect(chordInst.chordInv[2][2]).toEqual(5);
expect(chordInst.chordInv[2][3]).toEqual(9);
midiChord = [60, 67, 74, 78, 81 ]
chordInst = new ChordInstance(midiChord)
expect(chordInst.chordInv.length).toEqual(5);
expect(chordInst.chordInv[0][0]).toEqual(0);
expect(chordInst.chordInv[0][1]).toEqual(7);
expect(chordInst.chordInv[0][2]).toEqual(14);
expect(chordInst.chordInv[0][3]).toEqual(18);
expect(chordInst.chordInv[0][4]).toEqual(21);
});
it('ChordMatcher.doMatch can do a full match', function () {
midiChord = [60, 64, 67, 71]
chordInst = new ChordInstance(midiChord)
expect(chordInst.chordInv.length).toEqual(4);
expect(chordInst.chordInv[0][0]).toEqual(0);
expect(chordInst.chordInv[0][1]).toEqual(4);
expect(chordInst.chordInv[0][2]).toEqual(7);
expect(chordInst.chordInv[0][3]).toEqual(11);
var cm = new ChordMatcher()
var chordInst2 = cm.doMatch(chordInst)
expect(chordInst2).toBeDefined()
expect( chordInst2.matchedNotes ).toBeDefined()
expect ( _.keys(chordInst2.matchedNotes).length > 0 )
_.forIn( chordInst2.matchedNotes, function ( value, key ) {
if ( key == "maj,7" ) {
expect(value.invertions[0].length).toEqual(4)
}
else {
expect(value.invertions[0].length > 0).toBeTruthy()
}
});
});
it('ChordMatcher.doMatch can do a partial match with chord extensions', function () {
midiChord = [60, 67, 71, 74 ]
chordInst = new ChordInstance(midiChord)
expect(chordInst.chordInv.length).toEqual(4);
expect(chordInst.chordInv[0][0]).toEqual(0);
expect(chordInst.chordInv[0][1]).toEqual(7);
expect(chordInst.chordInv[0][2]).toEqual(11);
expect(chordInst.chordInv[0][3]).toEqual(14);
var cm = new ChordMatcher()
var chordInst2 = cm.doMatch(chordInst)
expect(chordInst2).toBeDefined()
_.forIn( chordInst2.matchedNotes, function ( value, key ) {
// console.log("Partial Matched:" + key + "(" + value.invertions[0].length + ")")
expect(value.invertions[0].length > 0 && value.invertions[0].length < 5 ).toBeTruthy()
if ( key == "maj,7" ) {
expect(value.invertions[0].length).toEqual(3)
expect(value.extensions[0].length).toEqual(1)
expect(value.extensions[0][0]).toEqual(14)
}
});
});
it('ChordMatcher.doMatch can do multiple extensions', function () {
midiChord = [60, 71, 74, 78, 81 ]
chordInst = new ChordInstance(midiChord)
var cm = new ChordMatcher()
var chordInst2 = cm.doMatch(chordInst)
expect(chordInst2).toBeDefined()
_.forIn( chordInst2.matchedNotes, function ( value, key ) {
if ( key == "maj,7" ) {
expect(value.invertions[0].length).toEqual(2)
expect(value.extensions[0].length).toEqual(3)
expect(value.extensions[0][0]).toEqual(14)
expect(value.extensions[0][1]).toEqual(18)
expect(value.extensions[0][2]).toEqual(21)
}
});
});
it('getChordName can return correct names', function () {
expect(getChordName("Maj,7")).toEqual("CMaj7")
expect(getChordName("Maj,7,9,#11,13")).toEqual("CMaj79#1113")
expect(getChordName("Min,7,9,11,-1")).toEqual("CMin7911-no-root")
expect(getChordName("Maj,7,9,#11,13", 0, 7)).toEqual("CMaj79#1113/G")
expect(getChordName("Maj,7,9,#11,13", 0, -5 )).toEqual("CMaj79#1113/G")
//
expect(getChordName("Maj,7", 2 )).toEqual("DMaj7")
expect(getChordName("Maj,7,9,#11,13", 2)).toEqual("DMaj79#1113")
expect(getChordName("Min,7,9,11,-1", 2)).toEqual("DMin7911-no-root")
expect(getChordName("Maj,7,9,#11,13", 2, 9)).toEqual("DMaj79#1113/A")
expect(getChordName("Maj,7,9,#11,13", 2, -3 )).toEqual("DMaj79#1113/A")
//
expect(getChordName("Maj,7", -1 )).toEqual("BMaj7")
expect(getChordName("Maj,7,9,#11,13", -1)).toEqual("BMaj79#1113")
expect(getChordName("Min,7,9,11,-1", -1)).toEqual("BMin7911-no-root")
expect(getChordName("Maj,7,9,#11,13", -1, 6)).toEqual("BMaj79#1113/Gb")
expect(getChordName("Maj,7,9,#11,13", -1, -6 )).toEqual("BMaj79#1113/Gb")
//
expect(getChordName("Maj,7", -13 )).toEqual("BMaj7")
expect(getChordName("Maj,7,9,#11,13", -13)).toEqual("BMaj79#1113")
expect(getChordName("Min,7,9,11,-1", -13)).toEqual("BMin7911-no-root")
expect(getChordName("Maj,7,9,#11,13", -13, 6)).toEqual("BMaj79#1113/Gb")
expect(getChordName("Maj,7,9,#11,13", -13, -6 )).toEqual("BMaj79#1113/Gb")
expect(getChordName("Maj,7", -2,-2, "sharp" ) ).toEqual("A#Maj7")
expect(getChordName("Maj,7,9,#11,13", -2, -2, "flat" ) ).toEqual("BbMaj79#1113")
expect(getChordName("Min,7,9,11,-1", -2, -2, "sharp") ).toEqual("A#Min7911-no-root")
expect(getChordName("Maj,7,9,#11,13", -1, 6, "sharp") ).toEqual("BMaj79#1113/F#")
expect(getChordName("Maj,7,9,#11,13", -2, -7, "flat" ) ).toEqual("BbMaj79#1113/F")
});
it('ChordMatcher moves a root correctly', function () {
var cm = new ChordMatcher() // [0, 4, 5, 9]
var inv0 = cm.chordMapWithInv["Min,7,9,-1(B)"][0]
expect(inv0.root).toEqual(-10)
// var root = cm.addRootOffset()
var inv1 = cm.chordMapWithInv["Min,7,9,-1(B)"][1]
expect(inv1.inv).toEqual(1)
expect(inv1.root).toEqual(-2)
var inv2 = cm.chordMapWithInv["Min,7,9,-1(B)"][2]
expect(inv2.inv).toEqual(2)
expect(inv2.root).toEqual(-3)
var inv2 = cm.chordMapWithInv["Min,7,9,-1(B)"][3]
expect(inv2.inv).toEqual(3)
expect(inv2.root).toEqual(-7)
});
it('ChordMatcher moves a negative root correctly', function () {
// midiChord = [60, 64, 67, 70 ]
var cm = new ChordMatcher() // [0, 4, 5, 9]
var inv0 = cm.chordMapWithInv["Maj,6,9,-1(A)"][0]
expect(inv0.inv).toEqual(0)
expect(inv0.root).toEqual(-4)
var newChord = cm.addRootOffset(inv0.notes, inv0.root)
var inv1 = cm.chordMapWithInv["Min,7,9,-1(B)"][1]
expect(inv1.inv).toEqual(1)
expect(inv1.root).toEqual(-2)
});
it('ChordMatcher can match a C chord', function () {
midiChord = [60, 64, 67]
// var chord : ChordInstance = new ChordInstance(midiChord)
var cm = new ChordMatcher()
cm.match(midiChord)
var psr = cm.getPosterior()
expect(psr).toBeDefined()
expect(psr.length).toBeGreaterThan(0)
var p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Maj')
});
it('ChordMatcher can match full major chords', function () {
var midiChord = [60, 64, 67, 71, 74, 78, 81]
var cm = new ChordMatcher()
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
// console.log( JSON.stringify( cm.bayes.getTopTeen(), null, 2 ) )
expect(getExtName(p0.hypo.key)).toEqual('Maj79#1113')
midiChord = [60, 64, 67, 71, 74, 78]
cm = new ChordMatcher()
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(getExtName(p0.hypo.key)).toEqual('Maj79#11')
midiChord = [60, 64, 67, 71, 74]
cm = new ChordMatcher()
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(getExtName(p0.hypo.key)).toEqual('Maj79')
midiChord = [60, 64, 67, 69,74]
cm = new ChordMatcher()
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(getExtName(p0.hypo.key)).toEqual('Maj69')
midiChord = [60, 64, 67, 69]
cm = new ChordMatcher()
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
// expect(getExtName(p0.hypo.key)).toEqual('Maj6') // TODO - should be Maj6
});
it('ChordMatcher can match partial major chords', function () {
var midiChord = [60, 64, 71, 74, 78, 81]
var cm = new ChordMatcher()
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
expect(getExtName(p0.hypo.key)).toEqual('Maj79#1113')
midiChord = [60, 64, 71, 74, 78]
cm = new ChordMatcher()
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(getExtName(p0.hypo.key)).toEqual('Maj79#11')
midiChord = [60, 64, 71, 74]
cm = new ChordMatcher()
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(getExtName(p0.hypo.key)).toEqual('Maj79')
midiChord = [60, 64, 69,74]
cm = new ChordMatcher()
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(getExtName(p0.hypo.key)).toEqual('Maj69')
midiChord = [60, 64, 69]
cm = new ChordMatcher()
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
// expect(getExtName(p0.hypo.key)).toEqual('Maj6') // TODO - should be Maj6 in the right context
// console.log( JSON.stringify( cm.bayes.getTopTeen(2), null, 2 ) )
});
it('ChordMatcher can match inverted major chords', function () {
var midiChord = [64, 67, 71, 72, 74, 78, 81 ]
var cm = new ChordMatcher()
var chord = cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
expect(getExtName(p0.hypo.key)).toEqual('Maj79#1113')
midiChord = [67, 71, 72, 74, 76, 78, 81 ]
cm = new ChordMatcher()
chord = cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
// var res: Posterior[] = cm.bayes.getTopX()
expect(getExtName(p0.hypo.key)).toEqual('Maj79#1113')
var midiChord = [67, 71, 72, 74, 76, 78, 81]
var cm = new ChordMatcher()
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Maj,7,9,#11,13')
// console.log( JSON.stringify( cm.bayes.getTopTeen(), null, 2 ) )
midiChord = [60, 64, 67, 71, 74, 78]
cm = new ChordMatcher()
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Maj,7,9,#11')
midiChord = [60, 64, 67, 71, 74]
cm = new ChordMatcher()
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Maj,7,9')
midiChord = [60, 64, 67, 69,74]
cm = new ChordMatcher()
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Maj,6,9')
midiChord = [60, 64, 67, 69]
cm = new ChordMatcher()
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Maj,6')
});
it('Standard Deriviation Works', function () {
var midiChord = [60, 64, 67, 69]
var cm = new ChordMatcher()
var chord = cm.match(midiChord)
// var p0 = cm.bayes.getBestMatch()
var stdDev = cm.bayes.standardDeriviation([1, 2, 3, 4, 5, 6, 7, 8, 9, 25]) // Standard Deviation: 6.48074069840786
expect(stdDev).toEqual(6.48074069840786)
});
it('CxChord getNoteNumber works as expected', function () {
expect( getNoteNumber("C")).toEqual(60)
expect( getNoteNumber("C6")).toEqual(72)
expect( getNoteNumber("C#7")).toEqual(85)
expect( getNoteNumber("db7")).toEqual(85)
expect( getNoteNumber("g10")).toEqual(127)
try {
getNoteNumber("g11")
}
catch (e) {
expect(e).toEqual("getNoteNumber: Illegal octave number. Legal octaves are 0-10")
}
});
it('ChordMatcher can match Minor chords', function () {
midiChord = [60, 63, 67]
var cm = new ChordMatcher()
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Min')
midiChord = [60, 63, 67, 70]
cm = new ChordMatcher()
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Min,7')
// cm.bayes.visualizeTopX("Match -> Min,7", cm.getChord(), 20)
midiChord = [60, 63, 67, 69]
cm = new ChordMatcher()
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Min,6')
midiChord = [60, 63, 67, 69, 74]
cm = new ChordMatcher()
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Min,6,9')
});
it('ChordMatcher can match a Dominant Chords chord', function () {
midiChord = [60, 64, 67, 70]
var cm = new ChordMatcher()
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Dom,7')
midiChord = [64, 67, 70, 72]
cm = new ChordMatcher()
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Dom,7')
midiChord = [67, 70, 72, 76 ]
cm = new ChordMatcher()
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Dom,7')
midiChord = [60, 64, 67, 70, 74]
var cm = new ChordMatcher()
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Dom,7,9')
midiChord = [64, 67, 70, 72, 74]
cm = new ChordMatcher()
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Dom,7,9')
midiChord = [67, 70, 72, 74, 76 ]
cm = new ChordMatcher()
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Dom,7,9')
// cm.bayes.visualizeTopX("Match", cm.getChord(), 20)
});
it('ChordMatcher can match no fifth Dominant Chords chord', function () {
midiChord = [60, 64, 70]
var cm = new ChordMatcher()
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Dom,7')
midiChord = [64, 70, 72]
cm = new ChordMatcher()
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Dom,7')
midiChord = [ 70, 72, 76 ]
cm = new ChordMatcher()
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Dom,7')
midiChord = [60, 64, 70, 74]
var cm = new ChordMatcher()
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Dom,7,9')
midiChord = [64, 70, 72, 74]
cm = new ChordMatcher()
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Dom,7,9')
midiChord = [70, 72, 74, 76 ]
cm = new ChordMatcher()
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Dom,7,9')
});
it('ChordMatcher can match sus chords', function () {
midiChord = [60, 65, 67]
var cm = new ChordMatcher()
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Sus4')
midiChord = [60, 62, 67]
var cm = new ChordMatcher()
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Sus2')
midiChord = [60, 65, 67, 71]
var cm = new ChordMatcher()
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Sus4')
midiChord = [60, 62, 67, 71]
var cm = new ChordMatcher()
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Sus2')
midiChord = [60, 65, 70]
var cm = new ChordMatcher()
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Sus2')
midiChord = [67, 72, 74]
var cm = new ChordMatcher()
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Sus4')
midiChord = [60, 65, 67, 70]
var cm = new ChordMatcher()
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Dom,7,sus4')
midiChord = [60, 62, 67, 70]
cm = new ChordMatcher()
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Dom,7,sus2')
});
it('ChordMatcher can match diminished chords', function () {
midiChord = [60, 63, 66]
var cm = new ChordMatcher()
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Dim')
midiChord = [60, 63, 66, 69]
var cm = new ChordMatcher()
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Dim,7')
midiChord = [60, 63, 66, 69, 71]
var cm = new ChordMatcher()
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Dim,7(WH)')
});
it('ChordMatcher can match a C5 chord', function () {
midiChord = [60, 67]
var cm = new ChordMatcher()
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('5')
midiChord = [55, 60, 67]
var cm = new ChordMatcher()
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('5')
midiChord = [55, 60, 67, 72]
var cm = new ChordMatcher()
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('5')
});
it('ChordMatcher can match major jazz block chords', function () {
midiChord = [64, 67, 69,74 ] // Cmaj,7,9,-1
var cm = new ChordMatcher()
cm.favorJazz( true)
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
// cm.bayes.visualizeTopX("Match", cm.getChord(), 20)
expect(p0.hypo.key).toEqual("Maj,6,9,-1(A)" )
midiChord = [67, 69,74, 76 ]
cm = new ChordMatcher()
cm.favorJazz(true)
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual("Maj,6,9,-1(A)" )
});
it('ChordMatcher can match minor jazz block chords', function () {
var midiChord = [ 63, 67, 69, 74] // This one has an invariant dominant chord version
var cm = new ChordMatcher()
cm.favorJazz(true)
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual("Min,6,9,-1(A)" ) // invariant of "Min,6,9,-1(A)"
midiChord = [ 63, 67, 70, 74]
cm = new ChordMatcher()
cm.favorJazz(true)
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
// cm.bayes.visualizeTopX("Match", cm.getChord(), 10)
expect(p0.hypo.key).toEqual("Min,7,9,-1(A)" )
midiChord = [ 60, 64, 65, 69]
var cm = new ChordMatcher()
cm.favorJazz(true)
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual("Min,7,9,-1(B)" )
midiChord = [ 60, 64, 65, 69]
var cm = new ChordMatcher()
cm.favorJazz(true)
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual("Min,7,9,-1(B)" )
midiChord = [ 60, 62, 65, 68]
var cm = new ChordMatcher()
// cm.favorJazz(true)
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual("Min,6" )
p0 = cm.bayes.getBestPosterior(1)
expect(p0.hypo.key).toEqual('Min,7,b5' )
midiChord = [ 60, 62, 65, 68]
var cm = new ChordMatcher()
cm.favorJazz(true)
cm.match(midiChord)
// cm.bayes.visualizeForm('Min,7,9,-1(A)', cm.getChord())
//
p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual("Min,6" )
// p0 = cm.bayes.getBestMatch(1)
// expect(p0.hypo.key).toEqual('Min,7,b5' )
});
it('A single ChordMatcher can match Jazz Dominant chords', function () {
var midiChord = [17, 21, 23, 28 ]
var cm = new ChordMatcher()
cm.favorJazz( true )
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior(1) // pick the dominant version rather than the min 6,6 invariant
// cm.bayes.visualizeTopX("Match", cm.getChord(), 15)
// cm.bayes.visualizeForm('Dom,7,9,-1(A)', cm.getChord())
expect(p0.hypo.key).toEqual('Dom,7,9,-1(A)')
midiChord = [21, 23, 28 , 29 ]
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior(1) // pick the dominant version rather than the min6 invariant
expect(p0.hypo.key == 'Dom,7,9,-1(A)' || p0.hypo.key == 'Min,6,9,-1(A)' ).toBeTruthy()
midiChord = [23, 28 , 29, 33]
cm.favorJazz( true )
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Dom,7,9,-1(B)')
midiChord = [28 , 29, 33, 35]
cm.favorJazz( true )
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual('Dom,7,9,-1(B)')
});
it('ChordMatcher can deliver a multi-chord result', function () {
var midiChord = [21, 23, 28 , 29 ]
var cm = new ChordMatcher()
cm.favorJazz( true )
cm.match(midiChord)
var res = cm.getMatches()
expect(res[0].type).toEqual('Min,6,9,-1(A)')
expect(res[1].type).toEqual('Dom,7,9,-1(A)')
});
it('ChordMatcher can match Reduced -5 chords', function () {
var midiChord = [60, 64, 71]
var cm = new ChordMatcher()
// cm.favorJazz( true )
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual("Maj,7,-5")
midiChord = [60, 64, 69]
cm = new ChordMatcher()
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual("Maj,6,-5" )
midiChord = [60, 63, 69]
cm = new ChordMatcher('Min,6,-5')
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
cm.bayes.visualizeTopX("Match", cm.getChord(), 15)
// cm.bayes.visualizeForm("Maj,7,-5", cm.getChord())
expect(p0.hypo.key).toEqual("Min,6,-5")
midiChord = [60, 63, 70 ]
cm = new ChordMatcher()
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior()
expect(p0.hypo.key).toEqual("Min,7,-5")
});
it('ChordMatcher can match chords given with tone Names', function () {
// var midiChord = [17, 21, 23, 28 ]
var midiChord = ["F1", "A1", "b1", "e2" ]
var cm = new ChordMatcher()
cm.favorJazz( true )
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior(1) // pick the dominant version rather than the min 6,6 invariant
// cm.bayes.visualizeTopX("Match", cm.getChord(), 15)
// cm.bayes.visualizeForm('Dom,7,9,-1(A)', cm.getChord())
expect(p0.hypo.key).toEqual('Dom,7,9,-1(A)')
var midiChord = ["F", "A", "b", "e6" ]
cm.favorJazz( true )
cm.match(midiChord)
p0 = cm.bayes.getBestPosterior(1) // pick the dominant version rather than the min 6,6 invariant
// cm.bayes.visualizeTopX("Match", cm.getChord(), 15)
// cm.bayes.visualizeForm('Dom,7,9,-1(A)', cm.getChord())
expect(p0.hypo.key).toEqual('Dom,7,9,-1(A)')
});
it('ChordMatcher can match multiple chords with a single match instance', function () {
var cm = new ChordMatcher()
var midiChord = [17, 21, 23, 28 ]
for (var i= 0 ; i < 400 ; i++) {
for ( var d = 0; d < midiChord.length; d++ ) {
midiChord[d] = ( Math.round( Math.random() * 127 ) )
}
cm.match(midiChord)
var p0 = cm.bayes.getBestPosterior(1)
expect(p0.hypo.key).toBeDefined()
}
});
});