|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var ChordTrack = function ChordTrack(numVoices, chordsOff, midiOptions, meter) { |
|
|
this.chordTrack = []; |
|
|
this.chordTrackFinished = false; |
|
|
this.chordChannel = numVoices; |
|
|
this.currentChords = []; |
|
|
this.lastChord; |
|
|
this.chordLastBar; |
|
|
this.chordsOff = !!chordsOff |
|
|
this.gChordTacet = this.chordsOff; |
|
|
this.hasRhythmHead = false; |
|
|
this.transpose = 0; |
|
|
this.lastBarTime = 0; |
|
|
this.meter = meter; |
|
|
this.tempoChangeFactor = 1; |
|
|
|
|
|
|
|
|
this.bassInstrument = midiOptions.bassprog && midiOptions.bassprog.length >= 1 ? midiOptions.bassprog[0] : 0; |
|
|
this.chordInstrument = midiOptions.chordprog && midiOptions.chordprog.length >= 1 ? midiOptions.chordprog[0] : 0; |
|
|
|
|
|
|
|
|
this.bassOctaveShift = midiOptions.bassprog && midiOptions.bassprog.length === 2 ? midiOptions.bassprog[1] : 0; |
|
|
this.chordOctaveShift = midiOptions.chordprog && midiOptions.chordprog.length === 2 ? midiOptions.chordprog[1] : 0; |
|
|
|
|
|
this.boomVolume = midiOptions.bassvol && midiOptions.bassvol.length === 1 ? midiOptions.bassvol[0] : 64; |
|
|
this.chickVolume = midiOptions.chordvol && midiOptions.chordvol.length === 1 ? midiOptions.chordvol[0] : 48; |
|
|
|
|
|
|
|
|
if (midiOptions.gchord && (midiOptions.gchord.length > 0)) { |
|
|
this.overridePattern = parseGChord(midiOptions.gchord[0]) |
|
|
} |
|
|
else { |
|
|
this.overridePattern = undefined; |
|
|
} |
|
|
}; |
|
|
|
|
|
ChordTrack.prototype.setMeter = function (meter) { |
|
|
this.meter = meter |
|
|
}; |
|
|
|
|
|
ChordTrack.prototype.setTempoChangeFactor = function (tempoChangeFactor) { |
|
|
this.tempoChangeFactor = tempoChangeFactor |
|
|
}; |
|
|
|
|
|
ChordTrack.prototype.setLastBarTime = function (lastBarTime) { |
|
|
this.lastBarTime = lastBarTime |
|
|
}; |
|
|
|
|
|
ChordTrack.prototype.setTranspose = function (transpose) { |
|
|
this.transpose = transpose |
|
|
}; |
|
|
|
|
|
ChordTrack.prototype.setRhythmHead = function (isRhythmHead, elem) { |
|
|
this.hasRhythmHead = isRhythmHead |
|
|
var ePitches = []; |
|
|
if (isRhythmHead) { |
|
|
if (this.lastChord && this.lastChord.chick) { |
|
|
for (var i2 = 0; i2 < this.lastChord.chick.length; i2++) { |
|
|
var note2 = Object.assign({},elem.pitches[0]); |
|
|
note2.actualPitch = this.lastChord.chick[i2]; |
|
|
ePitches.push(note2); |
|
|
} |
|
|
} |
|
|
} |
|
|
return ePitches |
|
|
}; |
|
|
|
|
|
ChordTrack.prototype.barEnd = function (element) { |
|
|
if (this.chordTrack.length > 0 && !this.chordTrackFinished) { |
|
|
this.resolveChords(this.lastBarTime, timeToRealTime(element.time)); |
|
|
this.currentChords = []; |
|
|
} |
|
|
this.chordLastBar = this.lastChord; |
|
|
}; |
|
|
|
|
|
ChordTrack.prototype.gChordOn = function (element) { |
|
|
if (!this.chordsOff) |
|
|
this.gChordTacet = element.tacet; |
|
|
}; |
|
|
|
|
|
ChordTrack.prototype.paramChange = function (element) { |
|
|
switch (element.el_type) { |
|
|
case "gchord": |
|
|
|
|
|
if (element.param && element.param.length > 0) { |
|
|
this.overridePattern = parseGChord(element.param); |
|
|
|
|
|
|
|
|
|
|
|
} else |
|
|
this.overridePattern = undefined; |
|
|
break; |
|
|
case "bassprog": |
|
|
this.bassInstrument = element.value; |
|
|
if ((element.octaveShift != undefined) && (element.octaveShift != null)) { |
|
|
this.bassOctaveShift = element.octaveShift; |
|
|
} |
|
|
else { |
|
|
this.bassOctaveShift = 0; |
|
|
} |
|
|
break; |
|
|
case "chordprog": |
|
|
this.chordInstrument = element.value; |
|
|
if ((element.octaveShift != undefined) && (element.octaveShift != null)) { |
|
|
this.chordOctaveShift = element.octaveShift; |
|
|
} |
|
|
else { |
|
|
this.chordOctaveShift = 0; |
|
|
} |
|
|
break; |
|
|
case "bassvol": |
|
|
this.boomVolume = element.param; |
|
|
break; |
|
|
case "chordvol": |
|
|
this.chickVolume = element.param; |
|
|
break; |
|
|
default: |
|
|
console.log("unhandled midi param", element) |
|
|
} |
|
|
}; |
|
|
|
|
|
ChordTrack.prototype.finish = function () { |
|
|
if (!this.chordTrackEmpty()) |
|
|
this.chordTrackFinished = true; |
|
|
}; |
|
|
|
|
|
ChordTrack.prototype.addTrack = function (tracks) { |
|
|
if (!this.chordTrackEmpty()) |
|
|
tracks.push(this.chordTrack); |
|
|
}; |
|
|
|
|
|
ChordTrack.prototype.findChord = function (elem) { |
|
|
if (this.gChordTacet) |
|
|
return 'break'; |
|
|
|
|
|
|
|
|
if (this.chordTrackFinished || !elem.chord || elem.chord.length === 0) |
|
|
return null; |
|
|
|
|
|
|
|
|
for (var i = 0; i < elem.chord.length; i++) { |
|
|
var ch = elem.chord[i]; |
|
|
if (ch.position === 'default') |
|
|
return ch.name; |
|
|
if (this.breakSynonyms.indexOf(ch.name.toLowerCase()) >= 0) |
|
|
return 'break'; |
|
|
} |
|
|
return null; |
|
|
} |
|
|
|
|
|
ChordTrack.prototype.interpretChord = function (name) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (name.length === 0) |
|
|
return undefined; |
|
|
if (name === 'break') |
|
|
return { chick: [] }; |
|
|
var root = name.substring(0, 1); |
|
|
if (root === '(') { |
|
|
name = name.substring(1, name.length - 2); |
|
|
if (name.length === 0) |
|
|
return undefined; |
|
|
root = name.substring(0, 1); |
|
|
} |
|
|
var bass = this.basses[root]; |
|
|
if (!bass) |
|
|
return undefined; |
|
|
|
|
|
var chordTranspose = this.transpose; |
|
|
while (chordTranspose < -8) |
|
|
chordTranspose += 12; |
|
|
while (chordTranspose > 8) |
|
|
chordTranspose -= 12; |
|
|
bass += chordTranspose; |
|
|
|
|
|
|
|
|
|
|
|
if (bass < 33){ |
|
|
bass += 12; |
|
|
} |
|
|
else if (bass > 44){ |
|
|
bass -= 12; |
|
|
} |
|
|
|
|
|
|
|
|
var unshiftedBass = bass; |
|
|
|
|
|
bass += this.bassOctaveShift * 12; |
|
|
|
|
|
var bass2 = bass - 5; |
|
|
var chick; |
|
|
if (name.length === 1) |
|
|
chick = this.chordNotes(bass, ''); |
|
|
var remaining = name.substring(1); |
|
|
var acc = remaining.substring(0, 1); |
|
|
if (acc === 'b' || acc === '♭') { |
|
|
unshiftedBass--; |
|
|
bass--; |
|
|
bass2--; |
|
|
remaining = remaining.substring(1); |
|
|
} else if (acc === '#' || acc === '♯') { |
|
|
unshiftedBass++; |
|
|
bass++; |
|
|
bass2++; |
|
|
remaining = remaining.substring(1); |
|
|
} |
|
|
var arr = remaining.split('/'); |
|
|
chick = this.chordNotes(unshiftedBass, arr[0]); |
|
|
|
|
|
if (chick.length >= 3) { |
|
|
var fifth = chick[2] - chick[0]; |
|
|
bass2 = bass2 + fifth - 7; |
|
|
} |
|
|
|
|
|
if (arr.length === 2) { |
|
|
var explicitBass = this.basses[arr[1].substring(0, 1)]; |
|
|
if (explicitBass) { |
|
|
var bassAcc = arr[1].substring(1); |
|
|
var bassShift = { '#': 1, '♯': 1, 'b': -1, '♭': -1 }[bassAcc] || 0; |
|
|
bass = this.basses[arr[1].substring(0, 1)] + bassShift + chordTranspose; |
|
|
|
|
|
|
|
|
bass += this.bassOctaveShift * 12; |
|
|
|
|
|
bass2 = bass; |
|
|
} |
|
|
} |
|
|
return { boom: bass, boom2: bass2, chick: chick }; |
|
|
} |
|
|
|
|
|
ChordTrack.prototype.chordNotes = function (bass, modifier) { |
|
|
var intervals = this.chordIntervals[modifier]; |
|
|
if (!intervals) { |
|
|
if (modifier.slice(0, 2).toLowerCase() === 'ma' || modifier[0] === 'M') |
|
|
intervals = this.chordIntervals.M; |
|
|
else if (modifier[0] === 'm' || modifier[0] === '-') |
|
|
intervals = this.chordIntervals.m; |
|
|
else |
|
|
intervals = this.chordIntervals.M; |
|
|
} |
|
|
bass += 12; |
|
|
|
|
|
|
|
|
bass += (this.chordOctaveShift * 12); |
|
|
|
|
|
var notes = []; |
|
|
for (var i = 0; i < intervals.length; i++) { |
|
|
notes.push(bass + intervals[i]); |
|
|
} |
|
|
return notes; |
|
|
} |
|
|
|
|
|
ChordTrack.prototype.writeNote = function (note, beatLength, volume, beat, noteLength, instrument) { |
|
|
|
|
|
if (note !== undefined) |
|
|
this.chordTrack.push({ cmd: 'note', pitch: note, volume: volume, start: this.lastBarTime + beat * durationRounded(beatLength, this.tempoChangeFactor), duration: durationRounded(noteLength, this.tempoChangeFactor), gap: 0, instrument: instrument }); |
|
|
} |
|
|
|
|
|
ChordTrack.prototype.chordTrackEmpty = function () { |
|
|
var isEmpty = true; |
|
|
for (var i = 0; i < this.chordTrack.length && isEmpty; i++) { |
|
|
if (this.chordTrack[i].cmd === 'note') |
|
|
isEmpty = false |
|
|
} |
|
|
return isEmpty; |
|
|
} |
|
|
|
|
|
ChordTrack.prototype.resolveChords = function (startTime, endTime) { |
|
|
|
|
|
if (this.hasRhythmHead) |
|
|
return |
|
|
|
|
|
var num = this.meter.num; |
|
|
var den = this.meter.den; |
|
|
var beatLength = 1 / den; |
|
|
var noteLength = beatLength / 2; |
|
|
var thisMeasureLength = parseInt(num, 10) / parseInt(den, 10); |
|
|
var portionOfAMeasure = thisMeasureLength - (endTime - startTime) / this.tempoChangeFactor; |
|
|
if (Math.abs(portionOfAMeasure) < 0.00001) |
|
|
portionOfAMeasure = 0; |
|
|
|
|
|
|
|
|
|
|
|
if (this.currentChords.length === 0 || this.currentChords[0].beat !== 0) { |
|
|
this.currentChords.unshift({ beat: 0, chord: this.chordLastBar }); |
|
|
} |
|
|
|
|
|
|
|
|
var currentChordsExpanded = expandCurrentChords(this.currentChords, 8*num/den, beatLength) |
|
|
|
|
|
var thisPattern = this.overridePattern ? this.overridePattern : this.rhythmPatterns[num + '/' + den] |
|
|
if (portionOfAMeasure) { |
|
|
thisPattern = []; |
|
|
var beatsPresent = ((endTime - startTime) / this.tempoChangeFactor) * 8; |
|
|
for (var p = 0; p < beatsPresent/2; p += 2) { |
|
|
thisPattern.push("chick"); |
|
|
thisPattern.push(""); |
|
|
} |
|
|
} |
|
|
if (!thisPattern) { |
|
|
thisPattern = [] |
|
|
for (var p = 0; p < (8*num/den)/2; p++) { |
|
|
thisPattern.push('chick') |
|
|
thisPattern.push(""); |
|
|
} |
|
|
} |
|
|
var firstBoom = true |
|
|
|
|
|
var minLength = Math.min(thisPattern.length, currentChordsExpanded.length) |
|
|
for (var p = 0; p < minLength; p++) { |
|
|
if (p > 0 && currentChordsExpanded[p-1] && currentChordsExpanded[p] && currentChordsExpanded[p-1].boom !== currentChordsExpanded[p].boom) |
|
|
firstBoom = true |
|
|
var type = thisPattern[p] |
|
|
var isBoom = type.indexOf('boom') >= 0 |
|
|
|
|
|
var newBass = !isBoom && |
|
|
p !== 0 && |
|
|
thisPattern[0].indexOf('boom') >= 0 && |
|
|
(!currentChordsExpanded[p-1] || currentChordsExpanded[p-1].boom !== currentChordsExpanded[p].boom) |
|
|
var pitches = resolvePitch(currentChordsExpanded[p], type, firstBoom, newBass) |
|
|
if (isBoom) |
|
|
firstBoom = false |
|
|
for (var oo = 0; oo < pitches.length; oo++) { |
|
|
this.writeNote(pitches[oo], |
|
|
0.125, |
|
|
isBoom || newBass ? this.boomVolume : this.chickVolume, |
|
|
p, |
|
|
noteLength, |
|
|
isBoom || newBass ? this.bassInstrument : this.chordInstrument |
|
|
) |
|
|
if (newBass) |
|
|
newBass = false |
|
|
else |
|
|
isBoom = false |
|
|
} |
|
|
} |
|
|
return |
|
|
} |
|
|
|
|
|
ChordTrack.prototype.processChord = function (elem) { |
|
|
if (this.chordTrackFinished) |
|
|
return |
|
|
var chord = this.findChord(elem); |
|
|
if (chord) { |
|
|
var c = this.interpretChord(chord); |
|
|
|
|
|
if (c) { |
|
|
|
|
|
|
|
|
if (this.chordTrack.length === 0) { |
|
|
this.chordTrack.push({ cmd: 'program', channel: this.chordChannel, instrument: this.chordInstrument }); |
|
|
} |
|
|
|
|
|
this.lastChord = c; |
|
|
var barBeat = calcBeat(this.lastBarTime, timeToRealTime(elem.time)); |
|
|
this.currentChords.push({ chord: this.lastChord, beat: barBeat, start: timeToRealTime(elem.time) }); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
function resolvePitch(currentChord, type, firstBoom, newBass) { |
|
|
var ret = [] |
|
|
if (!currentChord) |
|
|
return ret |
|
|
if (type.indexOf('boom') >= 0) |
|
|
ret.push(firstBoom ? currentChord.boom : currentChord.boom2) |
|
|
else if (newBass) |
|
|
ret.push(currentChord.boom) |
|
|
var numChordNotes = currentChord.chick.length |
|
|
if (type.indexOf('chick') >= 0) { |
|
|
for (var i = 0; i < numChordNotes; i++) |
|
|
ret.push(currentChord.chick[i]) |
|
|
} |
|
|
switch (type) { |
|
|
case 'DO': ret.push(currentChord.chick[0]); break; |
|
|
case 'MI': ret.push(currentChord.chick[1]); break; |
|
|
case 'SOL': ret.push(extractNote(currentChord,2)); break; |
|
|
case 'TI': ret.push(extractNote(currentChord,3)); break; |
|
|
case 'TOP': ret.push(extractNote(currentChord,4)); break; |
|
|
case 'do': ret.push(currentChord.chick[0]+12); break; |
|
|
case 'mi': ret.push(currentChord.chick[1]+12); break; |
|
|
case 'sol': ret.push(extractNote(currentChord,2)+12); break; |
|
|
case 'ti': ret.push(extractNote(currentChord,3)+12); break; |
|
|
case 'top': ret.push(extractNote(currentChord,4)+12); break; |
|
|
} |
|
|
return ret |
|
|
} |
|
|
|
|
|
function extractNote(chord, index) { |
|
|
|
|
|
var octave = Math.floor(index / chord.chick.length) |
|
|
var note = chord.chick[index % chord.chick.length] |
|
|
|
|
|
return note + octave * 12 |
|
|
} |
|
|
|
|
|
function parseGChord(gchord) { |
|
|
|
|
|
var pattern = [] |
|
|
for (var i = 0; i < gchord.length; i++) { |
|
|
var ch = gchord[i] |
|
|
switch(ch) { |
|
|
case 'z' : pattern.push(''); break; |
|
|
case '2' : pattern.push(''); break; |
|
|
case 'c' : pattern.push('chick'); break; |
|
|
case 'b' : pattern.push('boom&chick'); break; |
|
|
case 'f' : pattern.push('boom'); break; |
|
|
case 'G' : pattern.push('DO'); break; |
|
|
case 'H' : pattern.push('MI'); break; |
|
|
case 'I' : pattern.push('SOL'); break; |
|
|
case 'J' : pattern.push('TI'); break; |
|
|
case 'K' : pattern.push('TOP'); break; |
|
|
case 'g' : pattern.push('do'); break; |
|
|
case 'h' : pattern.push('mi'); break; |
|
|
case 'i' : pattern.push('sol'); break; |
|
|
case 'j' : pattern.push('ti'); break; |
|
|
case 'k' : pattern.push('top'); break; |
|
|
} |
|
|
} |
|
|
return pattern |
|
|
} |
|
|
|
|
|
|
|
|
function expandCurrentChords(currentChords, num8thNotes, beatLength) { |
|
|
beatLength = beatLength * 8 |
|
|
var chords = [] |
|
|
if (currentChords.length === 0) |
|
|
return chords |
|
|
|
|
|
var currentChord = currentChords[0].chord |
|
|
for (var i = 1; i < currentChords.length; i++) { |
|
|
var current = currentChords[i] |
|
|
while (chords.length < current.beat) { |
|
|
chords.push(currentChord) |
|
|
} |
|
|
currentChord = current.chord |
|
|
} |
|
|
while (chords.length < num8thNotes) |
|
|
chords.push(currentChord) |
|
|
return chords |
|
|
} |
|
|
|
|
|
function calcBeat(measureStart, currTime) { |
|
|
var distanceFromStart = currTime - measureStart; |
|
|
return distanceFromStart * 8; |
|
|
} |
|
|
|
|
|
ChordTrack.prototype.breakSynonyms = ['break', '(break)', 'no chord', 'n.c.', 'tacet']; |
|
|
|
|
|
ChordTrack.prototype.basses = { |
|
|
'A': 33, 'B': 35, 'C': 36, 'D': 38, 'E': 40, 'F': 41, 'G': 43 |
|
|
}; |
|
|
|
|
|
ChordTrack.prototype.chordIntervals = { |
|
|
|
|
|
'dim': [0, 3, 6], |
|
|
'°': [0, 3, 6], |
|
|
'˚': [0, 3, 6], |
|
|
|
|
|
'dim7': [0, 3, 6, 9], |
|
|
'°7': [0, 3, 6, 9], |
|
|
'˚7': [0, 3, 6, 9], |
|
|
|
|
|
'ø7': [0, 3, 6, 10], |
|
|
'm7(b5)': [0, 3, 6, 10], |
|
|
'm7b5': [0, 3, 6, 10], |
|
|
'm7♭5': [0, 3, 6, 10], |
|
|
'-7(b5)': [0, 3, 6, 10], |
|
|
'-7b5': [0, 3, 6, 10], |
|
|
|
|
|
'7b5': [0, 4, 6, 10], |
|
|
'7(b5)': [0, 4, 6, 10], |
|
|
'7♭5': [0, 4, 6, 10], |
|
|
|
|
|
'7(b9,b5)': [0, 4, 6, 10, 13], |
|
|
'7b9,b5': [0, 4, 6, 10, 13], |
|
|
'7(#9,b5)': [0, 4, 6, 10, 15], |
|
|
'7#9b5': [0, 4, 6, 10, 15], |
|
|
'maj7(b5)': [0, 4, 6, 11], |
|
|
'maj7b5': [0, 4, 6, 11], |
|
|
'13(b5)': [0, 4, 6, 10, 14, 21], |
|
|
'13b5': [0, 4, 6, 10, 14, 21], |
|
|
|
|
|
|
|
|
'm': [0, 3, 7], |
|
|
'-': [0, 3, 7], |
|
|
'm6': [0, 3, 7, 9], |
|
|
'-6': [0, 3, 7, 9], |
|
|
'm7': [0, 3, 7, 10], |
|
|
'-7': [0, 3, 7, 10], |
|
|
|
|
|
'-(b6)': [0, 3, 7, 8], |
|
|
'-b6': [0, 3, 7, 8], |
|
|
'-6/9': [0, 3, 7, 9, 14], |
|
|
'-7(b9)': [0, 3, 7, 10, 13], |
|
|
'-7b9': [0, 3, 7, 10, 13], |
|
|
'-maj7': [0, 3, 7, 11], |
|
|
'-9+7': [0, 3, 7, 11, 13], |
|
|
'-11': [0, 3, 7, 11, 14, 17], |
|
|
'm11': [0, 3, 7, 11, 14, 17], |
|
|
'-maj9': [0, 3, 7, 11, 14], |
|
|
'-∆9': [0, 3, 7, 11, 14], |
|
|
'mM9': [0, 3, 7, 11, 14], |
|
|
|
|
|
|
|
|
'M': [0, 4, 7], |
|
|
'6': [0, 4, 7, 9], |
|
|
'6/9': [0, 4, 7, 9, 14], |
|
|
'6add9': [0, 4, 7, 9, 14], |
|
|
'69': [0, 4, 7, 9, 14], |
|
|
|
|
|
'7': [0, 4, 7, 10], |
|
|
'9': [0, 4, 7, 10, 14], |
|
|
'11': [0, 7, 10, 14, 17], |
|
|
'13': [0, 4, 7, 10, 14, 21], |
|
|
'7b9': [0, 4, 7, 10, 13], |
|
|
'7♭9': [0, 4, 7, 10, 13], |
|
|
'7(b9)': [0, 4, 7, 10, 13], |
|
|
'7(#9)': [0, 4, 7, 10, 15], |
|
|
'7#9': [0, 4, 7, 10, 15], |
|
|
'(13)': [0, 4, 7, 10, 14, 21], |
|
|
'7(9,13)': [0, 4, 7, 10, 14, 21], |
|
|
'7(#9,b13)': [0, 4, 7, 10, 15, 20], |
|
|
'7(#11)': [0, 4, 7, 10, 14, 18], |
|
|
'7#11': [0, 4, 7, 10, 14, 18], |
|
|
'7(b13)': [0, 4, 7, 10, 20], |
|
|
'7b13': [0, 4, 7, 10, 20], |
|
|
'9(#11)': [0, 4, 7, 10, 14, 18], |
|
|
'9#11': [0, 4, 7, 10, 14, 18], |
|
|
'13(#11)': [0, 4, 7, 10, 18, 21], |
|
|
'13#11': [0, 4, 7, 10, 18, 21], |
|
|
|
|
|
'maj7': [0, 4, 7, 11], |
|
|
'∆7': [0, 4, 7, 11], |
|
|
'Δ7': [0, 4, 7, 11], |
|
|
'maj9': [0, 4, 7, 11, 14], |
|
|
'maj7(9)': [0, 4, 7, 11, 14], |
|
|
'maj7(11)': [0, 4, 7, 11, 17], |
|
|
'maj7(#11)': [0, 4, 7, 11, 18], |
|
|
'maj7(13)': [0, 4, 7, 14, 21], |
|
|
'maj7(9,13)': [0, 4, 7, 11, 14, 21], |
|
|
|
|
|
'7sus4': [0, 5, 7, 10], |
|
|
'm7sus4': [0, 3, 7, 10, 17], |
|
|
'sus4': [0, 5, 7], |
|
|
'sus2': [0, 2, 7], |
|
|
'7sus2': [0, 2, 7, 10], |
|
|
'9sus4': [0, 5, 7, 10, 14], |
|
|
'13sus4': [0, 5, 7, 10, 14, 21], |
|
|
|
|
|
|
|
|
'aug7': [0, 4, 8, 10], |
|
|
'+7': [0, 4, 8, 10], |
|
|
'+': [0, 4, 8], |
|
|
'7#5': [0, 4, 8, 10], |
|
|
'7♯5': [0, 4, 8, 10], |
|
|
'7+5': [0, 4, 8, 10], |
|
|
'9#5': [0, 4, 8, 10, 14], |
|
|
'9♯5': [0, 4, 8, 10, 14], |
|
|
'9+5': [0, 4, 8, 10, 14], |
|
|
'-7(#5)': [0, 3, 8, 10], |
|
|
'-7#5': [0, 3, 8, 10], |
|
|
'7(#5)': [0, 4, 8, 10], |
|
|
'7(b9,#5)': [0, 4, 8, 10, 13], |
|
|
'7b9#5': [0, 4, 8, 10, 13], |
|
|
'maj7(#5)': [0, 4, 8, 11], |
|
|
'maj7#5': [0, 4, 8, 11], |
|
|
'maj7(#5,#11)': [0, 4, 8, 11, 18], |
|
|
'maj7#5#11': [0, 4, 8, 11, 18], |
|
|
'9(#5)': [0, 4, 8, 10, 14], |
|
|
'13(#5)': [0, 4, 8, 10, 14, 21], |
|
|
'13#5': [0, 4, 8, 10, 14, 21], |
|
|
|
|
|
'5': [0, 7], |
|
|
'5(8)': [0, 7, 12], |
|
|
'5add8': [0, 7, 12] |
|
|
|
|
|
}; |
|
|
|
|
|
ChordTrack.prototype.rhythmPatterns = { |
|
|
"2/2": ['boom', '', '', '', 'chick', '', '', ''], |
|
|
"3/2": ['boom', '', '', '', 'chick', '', '', '', 'chick', '', '', ''], |
|
|
"4/2": ['boom', '', '', '', 'chick', '', '', '', 'boom', '', '', '', 'chick', '', '', ''], |
|
|
|
|
|
"2/4": ['boom', '', 'chick', ''], |
|
|
"3/4": ['boom', '', 'chick', '', 'chick', ''], |
|
|
"4/4": ['boom', '', 'chick', '', 'boom', '', 'chick', ''], |
|
|
"5/4": ['boom', '', 'chick', '', 'chick', '', 'boom', '', 'chick', ''], |
|
|
"6/4": ['boom', '', 'chick', '', 'boom', '', 'chick', '', 'boom', '', 'chick', ''], |
|
|
|
|
|
"3/8": ['boom', '', 'chick'], |
|
|
"5/8": ['boom', 'chick', 'chick', 'boom', 'chick'], |
|
|
"6/8": ['boom', '', 'chick', 'boom', '', 'chick'], |
|
|
"7/8": ['boom', 'chick', 'chick', 'boom', 'chick', 'boom', 'chick'], |
|
|
"9/8": ['boom', '', 'chick', 'boom', '', 'chick', 'boom', '', 'chick'], |
|
|
"10/8": ['boom', 'chick', 'chick', 'boom', 'chick', 'chick', 'boom', 'chick', 'boom', 'chick'], |
|
|
"11/8": ['boom', 'chick', 'chick', 'boom', 'chick', 'chick', 'boom', 'chick', 'boom', 'chick', 'chick'], |
|
|
"12/8": ['boom', '', 'chick', 'boom', '', 'chick', 'boom', '', 'chick', 'boom', '', 'chick'], |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
function timeToRealTime(time) { |
|
|
return time / 1000000; |
|
|
} |
|
|
|
|
|
function durationRounded(duration, tempoChangeFactor) { |
|
|
return Math.round(duration * tempoChangeFactor * 1000000) / 1000000; |
|
|
} |
|
|
|
|
|
module.exports = ChordTrack; |
|
|
|