-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9 from holomorfo:holomorfo/issue7
import universo tonal library from phd code
- Loading branch information
Showing
19 changed files
with
1,460 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import { ChordDef, chordDictionary } from "./defs/DefAcordesJazz"; | ||
import { mod, equalArr, num2nota12 } from "./defs/Oper"; | ||
|
||
export class Chord { | ||
notes: number[] = []; | ||
notesReduced: number[] = []; | ||
chordDefinition: ChordDef = { name: "*", notes: [] }; | ||
invertionValue: number; | ||
fundamentalValue: number = -1; | ||
isSeventh: boolean = false; | ||
|
||
constructor(notes: number[] = []) { | ||
this.notes = notes; | ||
this.notesReduced = notes | ||
// Modulo 12 | ||
.map(mod(12)) | ||
// Remove duplicates | ||
.filter((v, i, mod12) => mod12.indexOf(v) === i); | ||
|
||
let substract = 0; | ||
const foundChord: ChordDef | undefined = chordDictionary | ||
// Find if belongs in chord li>st | ||
.find((e) => { | ||
const { condition, minus } = this._belongsInList(e.notes); | ||
substract = condition ? minus : 0; | ||
return condition; | ||
}); | ||
if (foundChord !== undefined) this.chordDefinition = foundChord; | ||
this.fundamentalValue = this._calculateFundamental(substract); | ||
this.invertionValue = this._calculateInversion(substract); | ||
} | ||
|
||
_belongsInList(notes: number[]) { | ||
let minus = 0; | ||
const foundChord = this.notesReduced | ||
// Search in chords dabases | ||
.find((note, _, ls) => { | ||
// substract each of the components of note simplified | ||
const substracted = ls.map((e) => mod(12)(e - note)); | ||
substracted.sort((a, b) => a - b); | ||
minus = note; | ||
return equalArr(notes, substracted); | ||
}); | ||
return { condition: foundChord !== undefined, minus }; | ||
} | ||
|
||
_calculateFundamental(substract: number) { | ||
let index = -1; | ||
this.notes.forEach((val, i) => { | ||
if (mod(12)(val) === mod(12)(this.chordDefinition.notes[0] + substract)) | ||
index = i; | ||
}); | ||
|
||
return index > -1 ? mod(12)(this.notes[index]) : -1; | ||
} | ||
_calculateInversion(substract: number) { | ||
// Check which part of the structure the base note is is | ||
// Only checks the fundamental | ||
// TODO: set parts of other voices | ||
let bass = mod(12)(this.notes[0]); | ||
let index = -1; | ||
|
||
this.chordDefinition.notes.find((val, i) => { | ||
const cond = mod(12)(val + substract) === bass; | ||
if (cond) index = i; | ||
return cond; | ||
}); | ||
return index; | ||
} | ||
|
||
_invertionString(invertion: number) { | ||
return ["", "6", "64"][invertion]; | ||
} | ||
|
||
// TODO: separate into two functions | ||
invertion(isString: boolean = false) { | ||
const fundNum = this.invertionValue; | ||
return isString ? this._invertionString(fundNum) : fundNum; | ||
} | ||
|
||
isEquivalent(chord: Chord) { | ||
// Change to compare fundamentaland string | ||
return ( | ||
mod(12)(this.fundamental()) === mod(12)(chord.fundamental()) && | ||
this.chordDefinition.name === chord.chordDefinition.name | ||
); | ||
} | ||
|
||
// TODO: separate into two functions | ||
fundamentalString(accidental: string = "s") { | ||
return num2nota12(this.fundamentalValue, accidental); | ||
} | ||
|
||
fundamental() { | ||
return this.fundamentalValue; | ||
} | ||
chordName() { | ||
// TODO: #8 add and check fundamental | ||
return this.fundamentalString() + "" + this.chordDefinition.name; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/** | ||
* | ||
* @author Cristian | ||
*/ | ||
export default class CoordenadaTonal { | ||
escala: number; | ||
grado: number; | ||
tipo: string; | ||
// Los grados van del 1 al 7 | ||
|
||
constructor(esc: number = 0, tp: string = "", gra: number = 0) { | ||
this.escala = esc; | ||
this.tipo = tp; | ||
this.grado = gra; | ||
} | ||
|
||
setReg(esc: any, tp: string, gra: number) { | ||
this.escala = esc; | ||
this.grado = gra; | ||
this.tipo = tp; | ||
} | ||
|
||
stringify() { | ||
return "Escala " + this.escala + " " + this.tipo + " grado " + this.grado; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
import { calculateChords } from "./defs/DefEscalasAcordes"; | ||
import { Chord } from "./Chord"; | ||
|
||
export class Tonality { | ||
notes: number[] = []; | ||
base: number = 0; | ||
kind: string = ""; | ||
defEscAcordes: number[][]; | ||
|
||
constructor(base: number = 0, kind: string = "M") { | ||
// doMRef = new Tonalidad(0, "M"); | ||
let major = [0, 2, 4, 5, 7, 9, 11]; | ||
// float[] menArm = { 0, 2, 3, 5, 7, 8, 11 }; | ||
let minorHarmonic = [0, 2, 3, 5, 7, 8, 10]; | ||
|
||
//notasTonalidad = new float[12]; | ||
this.notes = []; | ||
this.base = base; | ||
switch (kind) { | ||
case "M": | ||
for (let i = 0; i < major.length; i++) { | ||
// notasTonalidad[i] = (this.baseEsc + mayor[i]) % 12; | ||
this.notes.push((this.base + major[i]) % 12); | ||
} | ||
break; | ||
|
||
case "m": | ||
for (let i = 0; i < minorHarmonic.length; i++) { | ||
//notasTonalidad[i] = (this.baseEsc + menArm[i]) % 12; | ||
this.notes.push((this.base + minorHarmonic[i]) % 12); | ||
} | ||
break; | ||
} | ||
this.kind = kind; | ||
this.defEscAcordes = calculateChords(this.base, kind); | ||
} | ||
|
||
percentageNotes(listaNotas: number[]) { | ||
let numNotas = 0; | ||
for (let i = 0; i < listaNotas.length; i++) | ||
if (this.noteBelongs(listaNotas[i])) numNotas++; | ||
|
||
let reg = numNotas / listaNotas.length; | ||
return reg; | ||
} | ||
|
||
noteBelongs(notaAc: number) { | ||
return this.notes.indexOf(notaAc % 12) > -1; | ||
} | ||
|
||
degreeNote(notaAc: number) { | ||
let reg = 0; | ||
let grad = this.notes.indexOf(notaAc % 12); | ||
if (grad > -1) reg = grad + 1; | ||
return reg; | ||
} | ||
|
||
getTriadType(grado: number) { | ||
let str = ""; | ||
let mayor = ["M", "m", "m", "M", "M", "m", "o"]; | ||
let menor = ["m", "o", "+", "m", "M", "M", "o"]; | ||
switch (this.kind) { | ||
case "M": | ||
str = mayor[grado % this.notes.length]; | ||
break; | ||
case "m": | ||
str = menor[grado % this.notes.length]; | ||
break; | ||
} | ||
return str; | ||
} | ||
|
||
distance(ton: Tonality) { | ||
let cuantosIgual = 0; | ||
if (this.notes.length == ton.notes.length) { | ||
for (let i = 0; i < this.notes.length; i++) { | ||
for (let j = 0; j < ton.notes.length; j++) { | ||
if (this.notes[i] == ton.notes[j]) { | ||
cuantosIgual++; | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
return this.notes.length - cuantosIgual; | ||
} | ||
|
||
degreeChord(unArm: Chord) { | ||
// Check degree of a harmony with respect a tonality | ||
// Run through chords in tonality, | ||
|
||
// TODO: optimize, to avoid creating lots of chords | ||
let found: | ||
| number[] | ||
| undefined = this.defEscAcordes.find((notes: number[]) => | ||
unArm.isEquivalent(new Chord(notes)) | ||
); | ||
// check if is o7 | ||
// check if neapolitan | ||
// return degree of chord | ||
let chord = new Chord(found); | ||
return this.degreeNote(Number(chord.fundamental())); | ||
} | ||
} | ||
|
||
// gradoAcordeRomSencillo(unAcorde: Chord, escala: Tonality) { | ||
// let cor = this.gradoSecundario(unAcorde, escala); | ||
// let grado = cor.grado; | ||
// let es = cor.escala; | ||
// // System.out.println(es+"Escala.gradoArodeRomano: " + grado); | ||
// let gradStr = ""; | ||
// let graS = "", | ||
// pertS = ""; | ||
// // let esS = ""; | ||
// if (grado > 0) { | ||
// switch (grado) { | ||
// case 1: | ||
// if (unAcorde.invertion() == 2) { | ||
// graS = "I"; // Aqui cambiar a K para cadencial | ||
// } else { | ||
// graS = "I"; | ||
// } | ||
// break; | ||
// case 2: | ||
// if ( | ||
// mod(12)(Number(unAcorde.fundamental(false))) == | ||
// this.baseEsc + 1 | ||
// ) { | ||
// // graS = "N"; | ||
// graS = "II"; | ||
// } else { | ||
// graS = "II"; | ||
// } | ||
// break; | ||
// case 3: | ||
// graS = "III"; | ||
// break; | ||
// case 4: | ||
// graS = "IV"; | ||
// break; | ||
// case 5: | ||
// if (unAcorde.chordDefinition.name === "D7") { | ||
// // graS = "N"; | ||
// graS = "DV"; | ||
// } else { | ||
// graS = "V"; | ||
// } | ||
// break; | ||
// case 6: | ||
// graS = "VI"; | ||
// break; | ||
// case 7: | ||
// if (unAcorde.chordDefinition.name === "o7") { | ||
// // graS = "N"; | ||
// graS = "Dvii"; | ||
// } else { | ||
// graS = "VII"; | ||
// } | ||
// // graS = "VII"; | ||
// break; | ||
// } | ||
// if (escala.perteneceListaNotas(unAcorde.notesReduced) == false) { | ||
// // if (escala.perteneceArmonia(unAcorde) == false) | ||
// pertS = "*"; | ||
// } | ||
// if (es != 1) { | ||
// // gradStr = pertS + graS + "" + unAcorde.inversionStr + "/" | ||
// // + esS; | ||
// } else { | ||
// gradStr = pertS + "" + graS + "" + unAcorde.invertion(true); | ||
// } | ||
// } else { | ||
// gradStr = ""; | ||
// } | ||
// return gradStr; | ||
// } |
Oops, something went wrong.