in progress: implementing some rules of tonal harmony as graph
This commit is contained in:
74
src/chordChart.ts
Normal file
74
src/chordChart.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import Edge from "./lib/Graph/Edge";
|
||||
import GraphNode from "./lib/Graph/GraphNode";
|
||||
import Graph from "./lib/Graph/index";
|
||||
import { ChordQuality, EventData } from "./lib/helpers/index";
|
||||
|
||||
// factory to create data to populate graph
|
||||
function createChord(root: string, quality: ChordQuality): EventData {
|
||||
return {
|
||||
root: root,
|
||||
quality: quality
|
||||
}
|
||||
}
|
||||
|
||||
// primary usable triads in C major
|
||||
const cmaj = createChord("C", ChordQuality.Major);
|
||||
const dmin = createChord("D", ChordQuality.Minor);
|
||||
const emin = createChord("E", ChordQuality.Minor);
|
||||
const fmaj = createChord("F", ChordQuality.Major);
|
||||
const gmaj = createChord("G", ChordQuality.Major);
|
||||
const amin = createChord("A", ChordQuality.Minor);
|
||||
|
||||
// borrowed triads
|
||||
const dmaj = createChord("D", ChordQuality.Major);
|
||||
const emaj = createChord("E", ChordQuality.Major);
|
||||
const ebmaj = createChord("Eb", ChordQuality.Major);
|
||||
const fmin = createChord("F", ChordQuality.Minor);
|
||||
const gmin = createChord("G", ChordQuality.Minor);
|
||||
const abmaj = createChord("Ab", ChordQuality.Major);
|
||||
const bbmaj = createChord("Bb", ChordQuality.Major);
|
||||
const bmaj = createChord("B", ChordQuality.Major);
|
||||
|
||||
// graph to host music theory logic
|
||||
class ChordNode<EventData> extends GraphNode<EventData> {
|
||||
constructor(data: EventData, id = -1, edges?: Edge<EventData>[]) {
|
||||
super(data, id, edges);
|
||||
}
|
||||
|
||||
override print() {
|
||||
if (this.edges.length) {
|
||||
for (let edge of this.edges) {
|
||||
console.log(this);
|
||||
console.log(`${this.data.root, ChordQuality[this.data.quality]} --> ${edge.end.data.root, ChordQuality[edge.end.data.quality]}`);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(this.data.root, ChordQuality[this.data.quality]);
|
||||
}
|
||||
}
|
||||
|
||||
const chordChart = new Graph<EventData>(true, true);
|
||||
|
||||
chordChart.addPoints(
|
||||
new ChordNode<EventData>(cmaj),
|
||||
new ChordNode<EventData>(dmin),
|
||||
new ChordNode<EventData>(emin),
|
||||
new ChordNode<EventData>(fmaj),
|
||||
new ChordNode<EventData>(gmaj),
|
||||
new ChordNode<EventData>(amin),
|
||||
new ChordNode<EventData>(dmaj),
|
||||
new ChordNode<EventData>(emaj),
|
||||
new ChordNode<EventData>(ebmaj),
|
||||
new ChordNode<EventData>(fmin),
|
||||
new ChordNode<EventData>(gmin),
|
||||
new ChordNode<EventData>(abmaj),
|
||||
new ChordNode<EventData>(bbmaj),
|
||||
new ChordNode<EventData>(bmaj)
|
||||
);
|
||||
|
||||
const cmajnode = chordChart.getPointByData(cmaj) as ChordNode<EventData>;
|
||||
const dminnode = chordChart.getPointByData(dmin) as ChordNode<EventData>;
|
||||
|
||||
chordChart.addEdge(cmajnode, dminnode);
|
||||
|
||||
export default chordChart;
|
||||
@@ -2,12 +2,16 @@ import Node from "../helpers/Node";
|
||||
import Edge from "./Edge";
|
||||
|
||||
export default class GraphNode<T> extends Node<T> {
|
||||
edges: Edge<T>[]
|
||||
id: number
|
||||
protected edges: Edge<T>[]
|
||||
protected id: number
|
||||
|
||||
constructor(data: T, id: number, edges?: Edge<T>[]) {
|
||||
constructor(data: T, id?: number, edges?: Edge<T>[]) {
|
||||
super(data);
|
||||
this.edges = edges || new Array<Edge<T>>();
|
||||
this.id = id || -1;
|
||||
}
|
||||
|
||||
setID(id: number) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import GraphNode from "./GraphNode";
|
||||
|
||||
export default class Graph<T> {
|
||||
private isWeighted: boolean;
|
||||
private isDirected: boolean;
|
||||
private points: GraphNode<T>[];
|
||||
private count = 0;
|
||||
protected isWeighted: boolean;
|
||||
protected isDirected: boolean;
|
||||
protected points: GraphNode<T>[];
|
||||
protected count = 0;
|
||||
|
||||
constructor(isWeighted: boolean, isDirected: boolean, points?: GraphNode<T>[]) {
|
||||
this.isWeighted = isWeighted;
|
||||
@@ -12,14 +12,21 @@ export default class Graph<T> {
|
||||
this.points = points || new Array<GraphNode<T>>();
|
||||
}
|
||||
|
||||
createPoint(data: T) {
|
||||
const newPoint = new GraphNode<T>(data, this.count);
|
||||
createPoint(data: T | GraphNode<T>) {
|
||||
let newPoint: GraphNode<T>;
|
||||
if (data instanceof GraphNode<T>) {
|
||||
data.setID(this.count);
|
||||
newPoint = data;
|
||||
} else {
|
||||
newPoint = new GraphNode<T>(data, this.count);
|
||||
}
|
||||
|
||||
this.points.push(newPoint);
|
||||
this.count++;
|
||||
return newPoint;
|
||||
}
|
||||
|
||||
addPoints(...points: T[]) {
|
||||
addPoints(...points: T[] | GraphNode<T>[]) {
|
||||
for (let point of points) {
|
||||
this.createPoint(point);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
**/
|
||||
|
||||
export default class Node<T> {
|
||||
data?: T
|
||||
public data: T
|
||||
|
||||
constructor(data: any) {
|
||||
this.data = data;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
export interface EventData {
|
||||
root: string
|
||||
root: string | number
|
||||
quality: ChordQuality
|
||||
duration: number
|
||||
beatStrength: 'Weak' | 'Moderate' | 'Strong'
|
||||
duration?: number
|
||||
beatStrength?: 'Weak' | 'Moderate' | 'Strong'
|
||||
}
|
||||
|
||||
export enum ChordQuality {
|
||||
|
||||
15
src/main.ts
15
src/main.ts
@@ -1,14 +1,3 @@
|
||||
import data from "./lib/helpers/sample";
|
||||
const { eventlist, eventgraph } = data;
|
||||
import chordChart from "./chordChart";
|
||||
|
||||
// eventlist.print();
|
||||
eventgraph.print();
|
||||
|
||||
// export default content;
|
||||
|
||||
// const parser = new DOMParser();
|
||||
// const document = parser.parseFromString(content, 'text/html');
|
||||
|
||||
// // const target = document.getElementById("where-thing-go") as HTMLElement;
|
||||
|
||||
// // target.appendChild(document);
|
||||
chordChart.print();
|
||||
|
||||
Reference in New Issue
Block a user