diff --git a/package.json b/package.json index 89de011..4d0d881 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "main": "dist/index.js", "types": "dist/index.d.ts", "scripts": { - "test": "jest" + "test": "jest", + "coverage": "npm test -- --coverage --watchAll=true" }, "files": [ "/dist" diff --git a/src/Chord.ts b/src/Chord.ts new file mode 100644 index 0000000..474dc39 --- /dev/null +++ b/src/Chord.ts @@ -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; + } +} diff --git a/src/CoordenadaTonal.ts b/src/CoordenadaTonal.ts new file mode 100644 index 0000000..56c4b2c --- /dev/null +++ b/src/CoordenadaTonal.ts @@ -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; + } +} diff --git a/src/Tonality.ts b/src/Tonality.ts new file mode 100644 index 0000000..e48c5c5 --- /dev/null +++ b/src/Tonality.ts @@ -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; +// } diff --git a/src/UniversoTonal.ts b/src/UniversoTonal.ts new file mode 100644 index 0000000..18ac4ce --- /dev/null +++ b/src/UniversoTonal.ts @@ -0,0 +1,162 @@ +import { Tonality } from "./Tonality"; +import { Chord } from "./Chord"; +// import Armonia from "./Armonia"; +// import CoordenadaTonal from "./CoordenadaTonal"; +// import { mod } from "./defs/Oper"; +const dictStringTonality: TonalityInfo[] = [ + { name: "CM", base: 0, kind: "M" }, + // TODO: implement alternate names + { name: "C#M", base: 1, kind: "M" }, + { name: "DM", base: 2, kind: "M" }, + { name: "D#M", base: 3, kind: "M" }, + { name: "EM", base: 4, kind: "M" }, + { name: "FM", base: 5, kind: "M" }, + { name: "F#M", base: 6, kind: "M" }, + { name: "GM", base: 7, kind: "M" }, + { name: "G#M", base: 8, kind: "M" }, + { name: "AM", base: 9, kind: "M" }, + { name: "A#M", base: 10, kind: "M" }, + { name: "BM ", base: 11, kind: "M" }, + // Minor + { name: "Cm", base: 0, kind: "m" }, + { name: "C#m", base: 1, kind: "m" }, + { name: "Dm", base: 2, kind: "m" }, + { name: "D#m", base: 3, kind: "m" }, + { name: "Em", base: 4, kind: "m" }, + { name: "Fm", base: 5, kind: "m" }, + { name: "F#m", base: 6, kind: "m" }, + { name: "Gm", base: 7, kind: "m" }, + { name: "G#m", base: 8, kind: "m" }, + { name: "Am", base: 9, kind: "m" }, + { name: "A#m", base: 10, kind: "m" }, + { name: "Bm ", base: 11, kind: "m" }, +]; + +export interface TonalityInfo { + name: string; + base: number; + kind: string; +} +export interface UniverseTonality { + base: number; + kind: string; + tonality: Tonality; +} +export class UniversoTonal { + universeDictionary: UniverseTonality[] = []; + tonalityMain: TonalityInfo = { + name: "CM", + base: 0, + kind: "M", + }; + + constructor() { + this.universeDictionary = dictStringTonality.map(({ name, base, kind }) => { + return { + name, + base, + kind, + tonality: new Tonality(base, kind), + }; + }); + } + + getMainTonality() { + // Return main tonality + const found = this.universeDictionary.find( + (e) => + e.base === this.tonalityMain.base && e.kind === this.tonalityMain.kind + ); + return found !== undefined ? found : this.tonalityMain; + } + + changeMainTonality(name: string) { + const found = dictStringTonality.find((e) => e.name === name); + this.tonalityMain = found !== undefined ? found : this.tonalityMain; + } + + getTonalityByName(name: string) { + // From string name, find tonality info + // Return tonality reference to that info + const found = dictStringTonality.find((e) => e.name === name); + return found !== undefined + ? this.getTonalityByInfo(found.base, found.kind) + : undefined; + } + + getTonalityByInfo(base: number, kind: string) { + // From base and kind, return tonality + return this.universeDictionary.find( + (e) => e.base === base && e.kind === kind + ); + } + + calculateFunctions(chord: Chord) { + // Check degree of chord in each tonality. + // Write better form for this + return this.universeDictionary.map((ton) => [ + ton.tonality.degreeChord(chord), + ton.tonality.base + "" + ton.tonality.kind, + ]); + // .filter((e) => e[0] > -1); + } + + calculateTableCSV(chord: Chord) { + let funcs = this.calculateFunctions(chord); + return funcs.reduce((p, e) => p + e[1] + ": " + e[0] + "\n", ""); + } + + // calculateFunctionsFirstDegree(chord: Armonia) { + // calculate function for each tonality + // first degree + // } + // Simple degree. maybe it should be calculated from + // inside tonality, not in the universe + + // gradoSecundario(unArm: Armonia, escala: Tonality) { + // let coor = new CoordenadaTonal(); + // let fund = escala.baseEsc; + // let tipo = "M"; + // // bool cond = false; + // let esc: Tonality; + // if (this.gradoSencillo(unArm, escala) > 0) { + // // Si es acorde de la tonalidad + // coor.setReg(1, escala.tipoEsc, this.gradoSencillo(unArm, escala)); + // } else { + // //Debug.Log("Entro 1"); + // // Si es dominante de otra escala + // for (let i = 0; i < escala.notasTonalidad.length; i++) { + // // Debug.Log("Entro 2 " ); + + // fund = escala.notasTonalidad[i]; + // tipo = "" + escala.getTipoTriada(i)[0]; + // esc = this.getTonalityByInfo(fund, tipo); + // // esc.imprimir(); + // let grad = this.gradoSencillo(unArm, esc); + // //Aqui los grados 0-6 + // tipo = escala.getTipoTriada(i); + // //Debug.Log(fund+" "+tipo+" "+grad); + // if (grad == 5) { + // // Debug.Log("Entro 3"); + // coor.setReg(i + 1, esc.tipoEsc, grad); + // // AQUI VOY + // } + // if (grad == 7) { + // // FALTA CORREGIR o7 + // // Debug.Log("Entro 4"); + // // Aqui se revisa si es o7 + // // CUIDADO CON COMPARAR STRINGS + // if (unArm.tipoDeAcordeStr === "o7") { + // for (let j = 0; j < unArm.notasArmonia.length; j++) { + // if (esc.gradoNota(unArm.notasArmonia[j]) == 7) { + // coor.setReg(i + 1, esc.tipoEsc, grad); + // break; + // } + // } + // } + // } + // } + // } + // return coor; + // } +} diff --git a/src/__tests__/Chord.test.ts b/src/__tests__/Chord.test.ts new file mode 100644 index 0000000..d5dd926 --- /dev/null +++ b/src/__tests__/Chord.test.ts @@ -0,0 +1,113 @@ +import { Chord } from "../Chord"; + +test("should create an empty harmony", () => { + let a = new Chord(); + expect(a.notes).toEqual([]); +}); + +test("should create an harmony with an Array", () => { + let a = new Chord([0, 4, 7]); + expect(a.notes).toEqual([0, 4, 7]); +}); + +test("should get set simplificado of mayor chord", () => { + let a = new Chord([0 + 12, 4 + 12, 7 + 12]); + expect(a.notesReduced).toEqual([0, 4, 7]); +}); + +test("should simplify of mayor chord with repeated notes", () => { + let a = new Chord([0 + 12, 4 + 12, 7 + 12, 4]); + expect(a.notesReduced).toEqual([0, 4, 7]); +}); + +test("should set kind of chord type string", () => { + let a = new Chord([0, 4, 7]); + expect(a.chordDefinition.name).toEqual("M"); +}); + +test(`should set kind of chord with + multiple dispositions`, () => { + let a = new Chord([7, 4, 4 + 12, 0]); + expect(a.chordDefinition.name).toEqual("M"); +}); + +test("Should get inversion value on am6", () => { + let a = new Chord([0, 4, 9]); + expect(a.chordName()).toBe("am"); + expect(a.chordDefinition.name).toEqual("m"); + expect(a.invertion()).toEqual(1); +}); + +test("Should get inversion value on CM6", () => { + let a = new Chord([64, 67, 72]); + expect(a.chordDefinition.name).toEqual("M"); + expect(a.invertion()).toEqual(1); +}); + +test("Should get inversion value on CM64", () => { + let a = new Chord([67, 64, 72]); + expect(a.chordDefinition.name).toEqual("M"); + expect(a.invertion()).toEqual(2); +}); +test("Should get inversion string value on CM64", () => { + let a = new Chord([67, 64, 72]); + expect(a.chordDefinition.name).toEqual("M"); + expect(a.invertion(true)).toEqual("64"); +}); +test("Should get inversion value on CM6 as string", () => { + let a = new Chord([64, 67, 72]); + expect(a.chordDefinition.name).toEqual("M"); + expect(a.invertion(true)).toEqual("6"); +}); + +test("Should verify that two equivalent chords are equal", () => { + let a = new Chord([64, 67, 72]); + let b = new Chord([0, 4, 7]); + expect(a.isEquivalent(b)).toBe(true); + expect(b.isEquivalent(a)).toBe(true); +}); + +test(`Should verify that two non equivalent +chords are different`, () => { + let a = new Chord([64, 67, 72]); + let b = new Chord([0, 5, 7]); + expect(a.isEquivalent(b)).toBe(false); + expect(b.isEquivalent(a)).toBe(false); +}); + +test("Should get fundamental number of a structured c# chord", () => { + let a = new Chord([65, 68, 73]); + expect(a.fundamental()).toBe(1); + let b = new Chord([65, 69, 74]); + expect(a.fundamental()).toBe(1); + expect(b.fundamental()).toBe(2); +}); + +test(`Should get fundamental string of a +structured chord with sharps #`, () => { + let a = new Chord([65, 68, 73]); + expect(a.fundamentalString()).toBe("c#"); +}); + +test("Should get chord name", () => { + let a = new Chord([65, 68, 73]); + expect(a.chordName()).toBe("c#M"); +}); + +test("Should test GD7 chord", () => { + let a = new Chord([7 + 2, 0 + 2, 4 + 2, 10 + 2]); + expect(a.fundamental()).toBe(2); + expect(a.invertion()).toBe(2); + expect(a.chordName()).toBe("dD7"); +}); + +test("Should not assign structure if not identified", () => { + let a = new Chord([1, 1, 1, 1]); + expect(a.fundamental()).toBe(-1); + expect(a.invertion()).toBe(-1); + expect(a.chordName()).toBe("b*"); +}); +// If chord has no structure, return base +// Check notes reduced +// Check definition +// check multiple chords diff --git a/src/__tests__/CoordenadaTonal.test.ts b/src/__tests__/CoordenadaTonal.test.ts new file mode 100644 index 0000000..57781f0 --- /dev/null +++ b/src/__tests__/CoordenadaTonal.test.ts @@ -0,0 +1,39 @@ +import CoordenadaTonal from "../CoordenadaTonal"; + +// here the whole foo var is mocked deeply + +test("should create an empty harony", () => { + // Arrange + let coord = new CoordenadaTonal(); + // Act + + // Assert + expect(coord.escala).toBe(0); + expect(coord.tipo).toBe(""); + expect(coord.grado).toBe(0); +}); + +test("should set region", () => { + // Arrange + let coord = new CoordenadaTonal(); + + // Act + coord.setReg(1, "M", 5); + + // Assert + expect(coord.escala).toBe(1); + expect(coord.tipo).toBe("M"); + expect(coord.grado).toBe(5); +}); + +test("should return string version of coordinate", () => { + // Arrange + let coord = new CoordenadaTonal(); + + // Act + coord.setReg(1, "M", 5); + let str = coord.stringify(); + + // Assert + expect(str).toBe("Escala 1 M grado 5"); +}); diff --git a/src/__tests__/Tonalidad.test.ts b/src/__tests__/Tonalidad.test.ts new file mode 100644 index 0000000..8c41956 --- /dev/null +++ b/src/__tests__/Tonalidad.test.ts @@ -0,0 +1,89 @@ +import { Tonality } from "../Tonality"; +import { Chord } from "../Chord"; + +// 🇵🇷 + +test("should create a default tonality CM", () => { + let t = new Tonality(); + expect(t.notes).toEqual([0, 2, 4, 5, 7, 9, 11]); + expect(t.base).toBe(0); + expect(t.kind).toEqual("M"); +}); + +test("should create tonality Cm", () => { + let t = new Tonality(0, "m"); + expect(t.notes).toEqual([0, 2, 3, 5, 7, 8, 10]); + expect(t.base).toBe(0); + expect(t.kind).toEqual("m"); +}); + +test("should calculate distance between tonalities", () => { + let cM = new Tonality(0, "M"); + let gM = new Tonality(7, "M"); + expect(cM.distance(gM)).toEqual(1); +}); + +test("should get degrees of tonality notes in Major", () => { + let cM = new Tonality(0, "M"); + expect(cM.degreeNote(0)).toEqual(1); + expect(cM.degreeNote(2)).toEqual(2); + expect(cM.degreeNote(4)).toEqual(3); + expect(cM.degreeNote(5)).toEqual(4); + expect(cM.degreeNote(7)).toEqual(5); + expect(cM.degreeNote(9)).toEqual(6); + expect(cM.degreeNote(11)).toEqual(7); +}); + +test("should check if notes belong to C Mayor tonality", () => { + let cM = new Tonality(0, "M"); + expect(cM.noteBelongs(0)).toBe(true); + expect(cM.noteBelongs(1 + 12)).toBe(false); + expect(cM.noteBelongs(2 + 12 * 3)).toBe(true); + expect(cM.noteBelongs(3)).toBe(false); + expect(cM.noteBelongs(4 + 12 * 4)).toBe(true); + expect(cM.noteBelongs(5)).toBe(true); + expect(cM.noteBelongs(6 + 12)).toBe(false); + expect(cM.noteBelongs(7)).toBe(true); + expect(cM.noteBelongs(8)).toBe(false); + expect(cM.noteBelongs(9 + 12 * 2)).toBe(true); + expect(cM.noteBelongs(10)).toBe(false); + expect(cM.noteBelongs(11)).toBe(true); +}); + +test("should return percentage of notes belonging on tonality", () => { + let cM = new Tonality(0, "M"); + let notes = [0, 1, 2, 3, 4]; + expect(cM.percentageNotes(notes)).toBe(0.6); +}); + +test("Should check kind of triad number degree number, CM", () => { + let cM = new Tonality(0, "M"); + expect(cM.getTriadType(0)).toBe("M"); + expect(cM.getTriadType(1)).toBe("m"); + expect(cM.getTriadType(2)).toBe("m"); + expect(cM.getTriadType(3)).toBe("M"); + expect(cM.getTriadType(4)).toBe("M"); + expect(cM.getTriadType(5)).toBe("m"); + expect(cM.getTriadType(6)).toBe("o"); +}); + +test("Should check kind of triad number degree number, am", () => { + let am = new Tonality(9, "m"); + expect(am.getTriadType(0)).toBe("m"); + expect(am.getTriadType(1)).toBe("o"); + expect(am.getTriadType(2)).toBe("+"); + expect(am.getTriadType(3)).toBe("m"); + expect(am.getTriadType(4)).toBe("M"); + expect(am.getTriadType(5)).toBe("M"); + expect(am.getTriadType(6)).toBe("o"); +}); + +test("Should return degree of chord", () => { + let cM = new Tonality(0, "M"); + // const chord = new Chord([0, 4, 7]); + const chordAmin = new Chord([0, 4, 9]); + const chordBdim = new Chord([2, 5, 11]); + // expect(cM.gradoSencillo(chord)).toBe(1); + expect(cM.degreeChord(chordAmin)).toBe(6); + expect(cM.degreeChord(chordBdim)).toBe(7); +}); diff --git a/src/__tests__/UniversoTonal.test.ts b/src/__tests__/UniversoTonal.test.ts new file mode 100644 index 0000000..26dae84 --- /dev/null +++ b/src/__tests__/UniversoTonal.test.ts @@ -0,0 +1,56 @@ +import { UniversoTonal } from "../UniversoTonal"; +import { Chord } from "../Chord"; + +test(`Create default tonal university +it should have 24 tonalityies in dictonary`, () => { + let u = new UniversoTonal(); + // console.log(u); + expect(u.universeDictionary.length).toBe(24); + expect(u.tonalityMain.name).toBe("CM"); +}); + +test("Should set main tonality with function", () => { + let u = new UniversoTonal(); + u.changeMainTonality("Am"); + + expect(u.getMainTonality().base).toBe(9); + expect(u.getMainTonality().kind).toBe("m"); +}); + +test("Should get tonality main from function", () => { + let u = new UniversoTonal(); + u.changeMainTonality("G#m"); + expect(u.getMainTonality().base).toBe(8); + expect(u.getMainTonality().kind).toBe("m"); +}); + +test("Should get tonality by name string", () => { + let u = new UniversoTonal(); + expect(u.getTonalityByName("FM")?.base).toBe(5); + expect(u.getTonalityByName("FM")?.kind).toBe("M"); + expect(u.getTonalityByName("Dm")?.base).toBe(2); + expect(u.getTonalityByName("Dm")?.kind).toBe("m"); +}); + +test("Should return undefined if tonality name not valid", () => { + let u = new UniversoTonal(); + expect(u.getTonalityByName("FxM")).toBe(undefined); +}); + +test("Should calculate functions of CM chord", () => { + let u = new UniversoTonal(); + let chord = new Chord([0, 3, 7]); + let coord = u.calculateFunctions(chord); + + expect(coord.length).toBe(24); + expect(coord[0][0]).toBe(0); + expect(coord[3][0]).toBe(6); +}); + +test("Should print csv table from funcitonality", () => { + let u = new UniversoTonal(); + let chord = new Chord([0, 3, 7]); + let table = u.calculateTableCSV(chord); + + expect(typeof table).toBe("string"); +}); diff --git a/src/__tests__/defs/DefAcordesJazz.test.ts b/src/__tests__/defs/DefAcordesJazz.test.ts new file mode 100644 index 0000000..4d89827 --- /dev/null +++ b/src/__tests__/defs/DefAcordesJazz.test.ts @@ -0,0 +1,30 @@ +import * as chords from "../../defs/DefAcordesJazz"; + +test("should create arms def list", () => { + let a = chords.chordDictionary; + expect(a.length).toBe(65); +}); + +test("should create empty chord array if not valid string entered", () => { + let a = chords.createNotesList(7, "x"); + expect(a).toEqual([]); +}); + +test("should create chord from base and string", () => { + let a = chords.createNotesList(7, "M"); + expect(a).toEqual([7, 11, 14]); +}); + +test("should create empty chord from not valid string", () => { + let a = chords.str2Ac("x"); + expect(a).toEqual([]); +}); +test("should create chord from string", () => { + let a = chords.str2Ac("M"); + expect(a).toEqual([0, 4, 7]); +}); + +test("should create Sus4 chord from string", () => { + let a = chords.str2Ac("Sus4"); + expect(a).toEqual([0, 5, 7]); +}); diff --git a/src/__tests__/defs/DefEscalasAcordes.test.ts b/src/__tests__/defs/DefEscalasAcordes.test.ts new file mode 100644 index 0000000..84e6d66 --- /dev/null +++ b/src/__tests__/defs/DefEscalasAcordes.test.ts @@ -0,0 +1,18 @@ +import { calculateChords } from "../../defs/DefEscalasAcordes"; + +test("create default chordlist", () => { + let chords = calculateChords(); + expect(chords.length).toBe(26); + expect(chords[0]).toEqual([0, 4, 7]); +}); +test(" create arms def list C major", () => { + let chords = calculateChords(0, "M"); + expect(chords.length).toBe(26); + expect(chords[0]).toEqual([0, 4, 7]); +}); + +test(" create arms def list a minor", () => { + let chords = calculateChords(9, "m"); + expect(chords.length).toEqual(25); + expect(chords[0]).toEqual([0 + 9, 3 + 9, 7 + 9]); +}); diff --git a/src/__tests__/defs/Oper.test.ts b/src/__tests__/defs/Oper.test.ts new file mode 100644 index 0000000..cb8d76f --- /dev/null +++ b/src/__tests__/defs/Oper.test.ts @@ -0,0 +1,47 @@ +import { numRomano, num2nota12 } from "../../defs/Oper"; + +test("Should convert integer to roman string", () => { + expect(numRomano(1)).toMatch("I"); + expect(numRomano(2)).toMatch("II"); + expect(numRomano(3)).toMatch("III"); + expect(numRomano(4)).toMatch("IV"); + expect(numRomano(5)).toMatch("V"); + expect(numRomano(6)).toMatch("VI"); + expect(numRomano(7)).toMatch("VII"); + expect(numRomano(0)).toMatch("*"); + expect(numRomano(8)).toMatch("*"); +}); + +test("Should convert number to string note", () => { + expect(num2nota12(0)).toMatch("c"); + expect(num2nota12(1)).toMatch("c#"); + expect(num2nota12(2)).toMatch("d"); + expect(num2nota12(3)).toMatch("d#"); + expect(num2nota12(4)).toMatch("e"); + expect(num2nota12(5)).toMatch("f"); + expect(num2nota12(6)).toMatch("f#"); + expect(num2nota12(7)).toMatch("g"); + expect(num2nota12(8)).toMatch("g#"); + expect(num2nota12(9)).toMatch("a"); + expect(num2nota12(10)).toMatch("a#"); + expect(num2nota12(11)).toMatch("b"); + // flat + + expect(num2nota12(0, "b")).toMatch("c"); + expect(num2nota12(1, "b")).toMatch("db"); + expect(num2nota12(2, "b")).toMatch("d"); + expect(num2nota12(3, "b")).toMatch("eb"); + expect(num2nota12(4, "b")).toMatch("e"); + expect(num2nota12(5, "b")).toMatch("f"); + expect(num2nota12(6, "b")).toMatch("gb"); + expect(num2nota12(7, "b")).toMatch("g"); + expect(num2nota12(8, "b")).toMatch("ab"); + expect(num2nota12(9, "b")).toMatch("a"); + expect(num2nota12(10, "b")).toMatch("bb"); + expect(num2nota12(11, "b")).toMatch("b"); + expect(num2nota12(11, "b")).toMatch("b"); +}); + +test("Should return original note if accidental is not s or b", () => { + expect(num2nota12(0, "x")).toMatch(""); +}); diff --git a/src/defs/DefAcordes.ts b/src/defs/DefAcordes.ts new file mode 100644 index 0000000..252f3df --- /dev/null +++ b/src/defs/DefAcordes.ts @@ -0,0 +1,91 @@ +/** + * Clasifica el acorde de acuerdo a tipo y el cruce de voces. Revisar articulo + * para el significado de los numeros % Notacion tipos de acordes 000000xx + * DER-IZQ primeros dos digitos base del acorde modulo 12 0000xx00 segundos dos + * digitos tipo del acorde 000x0000 terceros dos digitos es la inversion + * 00x00000 cruce de voces 2 : cruce, 1 : bueno 0x000000 algun par de voces sep + * por mas de una octava 2:sep,1:bueno + * + * 00 01 02 03 04 + * + * 00 : No definido + * + * 01 : Mayor (TM) [0,4,7] + * + * 02 : Menor (Tm) [0,3,7] + * + * 03 : Dim (To) [0,3,6] + * + * 04 : Aum (T+) [0,4,8] + * + * 05 : M7 * Major seventh M7 (TM,7M) [0,4,7,11] + * + * 06 : Mm7 * Major minor seventh Mm7 (TM,7m) [0,4,7,10] + * + * 07 : m7 * Minor seventh m7 (Tm,7m) [0,3,7,10] + * + * 08 : o/7 * Half-dim seventh o/7 (To,7m) [0,3,6,10] + * + * 09 : o7 * dim seventh o7 (To,7o) [0,3,6, 9] + * + * 10 : I+ * acorde I escala menor con VII grado aumentado [0,3,7,11] + * + * 11 : III+ * acorde III escala menor con VII grado aumentado [0,4,8,11] + * + * 12 : acorde D7 sin quinta [0,4,10] + * + * 13 : Tonica menor sin quinta [0,4] + * + * 14 : Tonica mayor sin quinta + * + * Triadas Diatonicos en escala mayor I ii iii IV V vi viio + * + * Septimos Diatonicos en escala Mayor I_M7 ii_m7 iii_m7 IV_M7 V_Mm7 vi_m7 + * vii/o_o/7 + * + * Revisar con piano Triadas Diatonicos en escala menor i iio ii III III+ iv IV + * v V VI #vio VII viio + * + * Septimos Diatonicos en escala menor i_m7 ii/o_o/7 III_M7 iv_m7 V_Mm7 VI_M7 + * viio_o7 + */ +export default { + aS_mayor: "M", + a_mayor: [0, 4, 7], + bS_menor: "m", + b_menor: [0, 3, 7], + cS_dim: "o", + c_dim: [0, 3, 6], + dS_aum: "+", + d_aum: [0, 4, 8], + eS_M7: "M7", + e_M7: [0, 4, 7, 11], + fS_Mm7: "Mm7", + f_Mm7: [0, 4, 7, 10], + gS_m7: "m7", + g_m7: [0, 3, 7, 10], + hS_semiDim7: "o/7", + h_semiDim7: [0, 3, 6, 10], + iS_dim7: "o7", + i_dim7: [0, 3, 6, 9], + // Acordes que surgen del menor arm y mel + jS_ImenVIIdim: "I+", //"o7" + j_ImenVIIdim: [0, 3, 7, 11], + kS_IIImenVIIaum: "III+", //"o7" + k_IIImenVIIaum: [0, 4, 8, 11], + lS_D7_sin5: "D7*5", //Septimo incompleto sin quinta + l_D7_sin5: [0, 4, 10], + // Alteraciones de acordes + S_nap: "IIb1", + nap: [0, 4, 7], + // Dominantes alterados + S_VM7p5: "VM7#5", + VM7p5: [0, 4, 8, 10], + //Dominante novena + S_V9Ms5: "V9Ms5", + V9Ms5: [0, 2, 4, 10], + // V9Ms5 : [0, 4, 10, 2], + + S_V9ms5: "V9ms5", + V9ms5: [0, 1, 4, 10], +}; diff --git a/src/defs/DefAcordesJazz.ts b/src/defs/DefAcordesJazz.ts new file mode 100644 index 0000000..7ecbdf9 --- /dev/null +++ b/src/defs/DefAcordesJazz.ts @@ -0,0 +1,89 @@ +export interface ChordDef { + name: string; + notes: number[]; +} +export const chordDictionary: ChordDef[] = [ + { name: "M", notes: [0, 4, 7] }, + { name: "m", notes: [0, 3, 7] }, + { name: "o", notes: [0, 3, 6] }, + { name: "+", notes: [0, 4, 8] }, + { name: "M7", notes: [0, 4, 7, 11] }, + { name: "D7", notes: [0, 4, 7, 10] }, + { name: "m7", notes: [0, 3, 7, 10] }, + { name: "o/7", notes: [0, 3, 6, 10] }, + { name: "o7", notes: [0, 3, 6, 9] }, + { name: "mM7", notes: [0, 3, 7, 11] }, + { name: "D7*5", notes: [0, 4, 10] }, + { name: "DM9*5", notes: [0, 2, 4, 10] }, + { name: "Dm9*5", notes: [0, 1, 4, 10] }, + + { name: "5", notes: [0, 7] }, + { name: "Sus4", notes: [0, 5, 7] }, + { name: "Sus2", notes: [0, 2, 7] }, + { name: "9", notes: [0, 2, 4, 7, 10] }, + { name: "m9", notes: [0, 2, 3, 7, 10] }, + { name: "M9", notes: [0, 2, 4, 7, 11] }, + { name: "mM9", notes: [0, 2, 3, 7, 11] }, + { name: "11", notes: [0, 2, 4, 5, 7, 10] }, + { name: "m11", notes: [0, 2, 3, 5, 7, 10] }, + { name: "M11", notes: [0, 2, 4, 5, 7, 11] }, + { name: "mM11", notes: [0, 2, 3, 5, 7, 11] }, + { name: "13", notes: [0, 2, 4, 7, 9, 10] }, + { name: "m13", notes: [0, 2, 3, 7, 9, 10] }, + { name: "M13", notes: [0, 2, 4, 7, 9, 11] }, + { name: "mM13", notes: [0, 2, 3, 7, 9, 11] }, + { name: "add9", notes: [0, 2, 4, 7] }, + { name: "Madd9", notes: [0, 2, 3, 7] }, + { name: "6add9", notes: [0, 2, 4, 7, 9] }, + { name: "m6add9", notes: [0, 2, 3, 7, 9] }, + { name: "D7add11", notes: [0, 4, 5, 7, 10] }, + { name: "M7add11", notes: [0, 4, 5, 7, 11] }, + { name: "m7add11", notes: [0, 3, 5, 7, 10] }, + { name: "mM7add11", notes: [0, 3, 5, 7, 11] }, + { name: "D7add13", notes: [0, 4, 7, 9, 11] }, + { name: "M7add13", notes: [0, 4, 7, 9, 11] }, + { name: "m7add13", notes: [0, 3, 7, 9, 10] }, + { name: "mM7add13", notes: [0, 3, 7, 9, 11] }, + { name: "7b5", notes: [0, 4, 6, 10] }, + { name: "7#5", notes: [0, 4, 8, 10] }, + { name: "7b9", notes: [0, 1, 4, 7, 10] }, + { name: "7#9", notes: [0, 3, 4, 7, 10] }, + { name: "7#5b9", notes: [0, 1, 4, 8, 10] }, + { name: "m7#5", notes: [0, 3, 8, 10] }, + { name: "m7b9", notes: [0, 1, 3, 7, 10] }, + { name: "9#11", notes: [0, 2, 4, 6, 7, 11] }, + { name: "9b13", notes: [0, 2, 4, 7, 8, 11] }, + { name: "6sus4", notes: [0, 5, 7, 9] }, + + { name: "7sus4", notes: [0, 5, 7, 10] }, + { name: "M7sus4", notes: [0, 5, 7, 11] }, + { name: "9sus4", notes: [0, 2, 5, 7, 10] }, + { name: "M9sus4", notes: [0, 2, 5, 7, 11] }, + + { name: "2m", notes: [0, 1] }, + { name: "2M", notes: [0, 2] }, + { name: "3m", notes: [0, 3] }, + { name: "3M", notes: [0, 4] }, + { name: "4P", notes: [0, 5] }, + { name: "6+", notes: [0, 6] }, + { name: "5P", notes: [0, 7] }, + { name: "6m", notes: [0, 8] }, + { name: "6M", notes: [0, 9] }, + { name: "7m", notes: [0, 10] }, + { name: "7M", notes: [0, 11] }, +]; + +export function str2Ac(tip: string) { + const foundChord: ChordDef | undefined = chordDictionary.find( + (e) => tip === e.name + ); + return foundChord !== undefined ? foundChord.notes : []; +} + +export function createNotesList(bas: number, tip: string) { + const foundChord: ChordDef | undefined = chordDictionary.find( + (e) => tip === e.name + ); + const notes = foundChord !== undefined ? foundChord.notes : []; + return notes.map((note) => bas + note); +} diff --git a/src/defs/DefEnlace.ts b/src/defs/DefEnlace.ts new file mode 100644 index 0000000..8f9e8bd --- /dev/null +++ b/src/defs/DefEnlace.ts @@ -0,0 +1,160 @@ +export default class DefEnlace { + strCortoL: string[]; + strLargoL: string[]; + constructor() { + this.strCortoL = []; + this.strLargoL = []; + + // + this.strCortoL.push("58Par"); + this.strLargoL.push("Paralelas prohibidas"); + // + this.strCortoL.push("Arm"); + this.strLargoL.push("Armonico"); + // + this.strCortoL.push("Mel"); + this.strLargoL.push("Melodico"); + // + this.strCortoL.push("Tdir"); + this.strLargoL.push("Traslado directo"); + // + this.strCortoL.push("Tcon"); + this.strLargoL.push("Traslado contrario"); + // + this.strCortoL.push("Tobl"); + this.strLargoL.push("Traslado oblicuo"); + // + this.strCortoL.push("Sop3"); + this.strLargoL.push("Salto de terceras \nen Soprano"); + // + this.strCortoL.push("Ten3"); + this.strLargoL.push("Salto de terceras \nen Tenor"); + // + this.strCortoL.push("PCad"); + this.strLargoL.push("Prepara \nAcorde cadencial K64"); + // + this.strCortoL.push("RCad"); + this.strLargoL.push("Resuelve \nAcorde cadencial K64"); + // + this.strCortoL.push("Arm6"); + this.strLargoL.push("Armonico, inversion"); + // + this.strCortoL.push("Tra6"); + this.strLargoL.push("Traslado, inversion"); + // + this.strCortoL.push("Slt6"); + this.strLargoL.push("Salto, inversion"); + // + this.strCortoL.push("6-6"); + this.strLargoL.push("Enlace de 6-6"); + // + this.strCortoL.push("6-6b"); + this.strLargoL.push("Enlace de 6-6 \ncorrelacion segunda"); + // + this.strCortoL.push("6-6c"); + this.strLargoL.push("Enlace de 6-6 \nmenor t6-D6, D6-t6"); + // + this.strCortoL.push("6-6d"); + this.strLargoL.push("Enlace de 6-6 \nmenor S6-D6"); + // + this.strCortoL.push("6-6d"); + this.strLargoL.push("Enlace de 6-6 \nmenor S6-D6"); + // + this.strCortoL.push("6-6d"); + this.strLargoL.push("Enlace de 6-6 \nmenor S6-D6"); + // + this.strCortoL.push("6,4Pas"); + this.strLargoL.push("Enlace de 6,4 \ncorde de paso"); + // + this.strCortoL.push("D7Prep"); + this.strLargoL.push("Prepara D7 por salto\n o paso"); + // + this.strCortoL.push("D7PrepB"); + this.strLargoL.push("Prepara D7 por nota\ncomun"); + // + this.strCortoL.push("S-D7*"); + this.strLargoL.push("Preparacion de D7\nincompletopor medio de S"); + // + this.strCortoL.push("D7-T*5"); + this.strLargoL.push("Resolucion de D7\na tonica sin quinta"); + // + this.strCortoL.push("D7-T"); + this.strLargoL.push("Resolucion de D7\na tonica completa"); + // + this.strCortoL.push("D7*5-T"); + this.strLargoL.push("Resolucion de D7\nincompleto a tonica completa"); + // + this.strCortoL.push("D7i-T"); + this.strLargoL.push("Resolucion de D7\ninversion a tonica completa"); + // + this.strCortoL.push("Slt5"); + this.strLargoL.push("Salto de 5tas\nde D2 a T6"); + // + this.strCortoL.push("Slt5-1"); + this.strLargoL.push("Salto de 5tas\ny 1ras de D2 a T6"); + // + this.strCortoL.push("VII7-T"); + this.strLargoL.push("VII7 a Tonica 3ra duplicada"); + // + this.strCortoL.push("VII7-D7"); + this.strLargoL.push("VII7 a D7 e inversiones"); + // + this.strCortoL.push("VII7-D7b"); //261 + this.strLargoL.push("VII7 a D7 e inversiones"); + // + this.strCortoL.push("Pr-SII6"); + this.strLargoL.push("Preparacion SII6"); + // + this.strCortoL.push("SII6-Rs"); + this.strLargoL.push("Resolucion de SII6"); + // + this.strCortoL.push("Pr-SII"); + this.strLargoL.push("Preparacion de SII"); + // + this.strCortoL.push("SII-Rs"); + this.strLargoL.push("Resolucion de SII"); + // + this.strCortoL.push("V-VI"); + this.strLargoL.push("Giro interrumpido"); + // + this.strCortoL.push("TSVI Esl"); + this.strLargoL.push("Eslabon intermedio"); + // + this.strCortoL.push("TSVI sub"); + this.strLargoL.push("TSVI Funcion Subdominante"); + // + this.strCortoL.push("Pr-SII7"); + this.strLargoL.push("Preparacion SII7"); + // + this.strCortoL.push("SII7-V"); + this.strLargoL.push("Resolucion de SII7 a V "); + // + this.strCortoL.push("SII7-K"); + this.strLargoL.push("Resolucion de SII7 a K63 "); + // + this.strCortoL.push("SII7-T"); + this.strLargoL.push("Resolucion de SII7 a T"); + // + this.strCortoL.push("SII7-D7"); + this.strLargoL.push("Resolucion de SII7 a D7 e inv "); + // + this.strCortoL.push("SII-SII2"); + this.strLargoL.push("SII2 de paso"); + // + this.strCortoL.push("III-mel"); + this.strLargoL.push("Movimiento de paso en III"); + // + this.strCortoL.push("Cant"); + this.strLargoL.push("Enlace vocal"); + // + this.strCortoL.push("Cool"); + this.strLargoL.push("Enlace Cool ;)"); + // + this.strCortoL.push("x"); + this.strLargoL.push("N/D"); + } + + gIdx(sr:string) { + return this.strCortoL.indexOf(sr); + } +} diff --git a/src/defs/DefEscalasAcordes.ts b/src/defs/DefEscalasAcordes.ts new file mode 100644 index 0000000..1128f57 --- /dev/null +++ b/src/defs/DefEscalasAcordes.ts @@ -0,0 +1,103 @@ +import * as def from "./DefAcordesJazz"; + +export function calculateChords(bas: number = 0, tipo: string = "M") { + let valueReturn: number[][] = [[]]; + switch (tipo) { + case "M": + let major = [ + def.createNotesList(bas + 0, "M"), + def.createNotesList(bas + 2, "m"), + def.createNotesList(bas + 4, "m"), + def.createNotesList(bas + 5, "M"), + def.createNotesList(bas + 7, "M"), + def.createNotesList(bas + 9, "m"), + def.createNotesList(bas + 11, "o"), + // Septimos + def.createNotesList(bas + 0, "M7"), + def.createNotesList(bas + 2, "m7"), + def.createNotesList(bas + 4, "m7"), + def.createNotesList(bas + 5, "M7"), + def.createNotesList(bas + 7, "D7"), + def.createNotesList(bas + 9, "m7"), + def.createNotesList(bas + 11, "o/7"), + def.createNotesList(bas + 4, "m7"), + // Mayor armonica + def.createNotesList(bas + 2, "o"), + // Mayor armonicos septimo + def.createNotesList(bas + 11, "o7"), + //Napolitano + def.createNotesList(bas + 1, "m"), + //Subdominante armonico + def.createNotesList(bas + 5, "m"), + //Dominante noveno + def.createNotesList(bas + 7, "9"), + def.createNotesList(bas + 7, "DM9*5"), + def.createNotesList(bas + 7, "Dm9*5"), + // 9na de Cristian + def.createNotesList(bas + 7, "7b9"), + //Dominantes alterados + def.createNotesList(bas + 7, "7b5"), + def.createNotesList(bas + 7, "7#5"), + def.createNotesList(bas + 7, "D7*5"), + ]; + + valueReturn = major; + + break; + case "m": + // armsList.push(new Armonia(def.crearAcorde(bas+0,"M"), + + // Menor natural + // {"m", "o", "M", "m", "m", "M", "M"}; + let minor = [ + def.createNotesList(bas + 0, "m"), + def.createNotesList(bas + 2, "o"), + def.createNotesList(bas + 3, "M"), + def.createNotesList(bas + 5, "m"), + def.createNotesList(bas + 7, "m"), + def.createNotesList(bas + 8, "M"), + def.createNotesList(bas + 10, "M"), + //public static String[] Ac7EscMenNat = {"m7", "o/7", "M7", "m7", "m7", "M7", "D7"}; + def.createNotesList(bas + 0, "m7"), + // armsList.push(new Armonia(def.crearAcorde(bas+2,"o/7"), + def.createNotesList(bas + 3, "M7"), + def.createNotesList(bas + 5, "m7"), + def.createNotesList(bas + 7, "m7"), + def.createNotesList(bas + 8, "M7"), + def.createNotesList(bas + 10, "D7"), + //Menor armonico + // armsList.push(new Armonia(def.crearAcorde(bas+3,"+"), + def.createNotesList(bas + 7, "M"), + // armsList.push(new Armonia(def.crearAcorde(bas+11,"o"), + //Setpimos + // armsList.push(new Armonia(def.crearAcorde(bas+0,"I+"), + // armsList.push(new Armonia(def.crearAcorde(bas+3,"III+"), + def.createNotesList(bas + 7, "D7"), + def.createNotesList(bas + 11, "o7"), + //Menor Melódico + // Menor melodica + def.createNotesList(bas + 2, "m"), + // armsList.push(new Armonia(def.crearAcorde(bas+3,"+"), + def.createNotesList(bas + 5, "M"), + // armsList.push(new Armonia(def.crearAcorde(bas+9,"o"), + // armsList.push(new Armonia(def.crearAcorde(bas+11,"o"), + //Septimos + def.createNotesList(bas + 2, "m7"), + def.createNotesList(bas + 5, "D7"), + // armsList.push(new Armonia(def.crearAcorde(bas+9,"o/7"), + // armsList.push(new Armonia(def.crearAcorde(bas+11,"o/7"), + //Napolitano + // No jala el napolitano :/ + def.createNotesList(bas + 1, "M"), + //Dominante noveno + def.createNotesList(bas + 7, "DM9*5"), + def.createNotesList(bas + 7, "Dm9*5"), + def.createNotesList(bas + 7, "D7*5"), + // 9na de Cristian + def.createNotesList(bas + 7, "7b9"), + ]; + valueReturn = minor; + break; + } + return valueReturn; +} diff --git a/src/defs/Oper.ts b/src/defs/Oper.ts new file mode 100644 index 0000000..b038649 --- /dev/null +++ b/src/defs/Oper.ts @@ -0,0 +1,155 @@ +/** + * + * @author Cristian + */ + +export function equalArr(arr1: any[], arr2: any[]) { + // console.log(arr1, arr2); + return JSON.stringify(arr1) === JSON.stringify(arr2); +} +/** + * Funcion modulo como la de matlab + * + * @param num + * @param base + * @return + */ +export function mod(base: number) { + return function (num: number) { + num = num % base; + if (num < 0) num = base + num; + return num; + }; +} + +export function numRomano(num: any) { + let nota = ""; + switch (num) { + case 1: + nota += "I"; + break; + case 2: + nota += "II"; + break; + case 3: + nota += "III"; + break; + case 4: + nota += "IV"; + break; + case 5: + nota += "V"; + break; + case 6: + nota += "VI"; + break; + case 7: + nota += "VII"; + break; + default: + nota += "*"; + break; + } + return nota; +} + +/** + * Funcion que le asigna un numero a cada nota de la escala, utilizando + * sostenidos. Consiste de siete octavas. + * Debe poner bemoles o sostenidos de acuerdo a que tipo de escala. + * + * @param midinum + * @return + */ +export function num2nota12(midinum: number, acc: string = "s") { + // 21= A0, 108 = C8 + // 21=12+9; + // Ver que clase de nota es modulo 12; + + let modu = mod(12)(midinum); + // Corregir de acuerdo a bemoles o sostenidos + let nota = ""; + + if (acc == "s") { + switch (modu) { + case 0: + nota += "c"; + break; + case 1: + nota += "c#"; + break; + case 2: + nota += "d"; + break; + case 3: + nota += "d#"; + break; + case 4: + nota += "e"; + break; + case 5: + nota += "f"; + break; + case 6: + nota += "f#"; + break; + case 7: + nota += "g"; + break; + case 8: + nota += "g#"; + break; + case 9: + nota += "a"; + break; + case 10: + nota += "a#"; + break; + case 11: + nota += "b"; + break; + } + } else { + if (acc == "b") { + switch (modu) { + case 0: + nota += "c"; + break; + case 1: + nota += "db"; + break; + case 2: + nota += "d"; + break; + case 3: + nota += "eb"; + break; + case 4: + nota += "e"; + break; + case 5: + nota += "f"; + break; + case 6: + nota += "gb"; + break; + case 7: + nota += "g"; + break; + case 8: + nota += "ab"; + break; + case 9: + nota += "a"; + break; + case 10: + nota += "bb"; + break; + case 11: + nota += "b"; + break; + } + } + } + return nota; +} diff --git a/src/index.ts b/src/index.ts index d3b9cab..e82cf58 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1 +1,3 @@ -export { libraryInit, closeLibrary } from "./logs"; +export { Chord } from "./Chord"; +export { Tonality } from "./Tonality"; +export { UniversoTonal } from "./UniversoTonal"; diff --git a/src/logs.test.ts b/src/logs.test.ts deleted file mode 100644 index 3313b0c..0000000 --- a/src/logs.test.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { sum } from "./logs"; - -describe("My math library", () => { - it("should be able to add things correctly", () => { - expect(sum(3, 4)).toEqual(7); - }); -});