diff --git a/app.ts b/app.ts index c8b0f95..6bfcda9 100644 --- a/app.ts +++ b/app.ts @@ -1,6 +1,4 @@ import * as Tone from 'tone'; -import { pitchsets } from "./src/toneGeneration.js"; -import { extractPitchset } from './src/harmonyUtil.js'; // initialize four synth voices const soprano = new Tone.Synth().toDestination(); diff --git a/index.html b/index.html index 89ac1e5..bdfb6df 100644 --- a/index.html +++ b/index.html @@ -119,10 +119,5 @@ - - - - - \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 9ea39a7..6855304 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,9 @@ "dependencies": { "tone": "^14.7.77", "typescript": "^4.6.4" + }, + "devDependencies": { + "@types/node": "^17.0.32" } }, "node_modules/@babel/runtime": { @@ -24,6 +27,12 @@ "node": ">=6.9.0" } }, + "node_modules/@types/node": { + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.32.tgz", + "integrity": "sha512-eAIcfAvhf/BkHcf4pkLJ7ECpBAhh9kcxRBpip9cTiO+hf+aJrsxYxBeS6OXvOd9WqNAJmavXVpZvY1rBjNsXmw==", + "dev": true + }, "node_modules/automation-events": { "version": "4.0.16", "resolved": "https://registry.npmjs.org/automation-events/-/automation-events-4.0.16.tgz", @@ -87,6 +96,12 @@ "regenerator-runtime": "^0.13.4" } }, + "@types/node": { + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.32.tgz", + "integrity": "sha512-eAIcfAvhf/BkHcf4pkLJ7ECpBAhh9kcxRBpip9cTiO+hf+aJrsxYxBeS6OXvOd9WqNAJmavXVpZvY1rBjNsXmw==", + "dev": true + }, "automation-events": { "version": "4.0.16", "resolved": "https://registry.npmjs.org/automation-events/-/automation-events-4.0.16.tgz", diff --git a/package.json b/package.json index 8609a1d..474ae86 100644 --- a/package.json +++ b/package.json @@ -14,5 +14,8 @@ "dependencies": { "tone": "^14.7.77", "typescript": "^4.6.4" + }, + "devDependencies": { + "@types/node": "^17.0.32" } } diff --git a/src/audioUtils.ts b/src/audioUtils.ts index b8314f2..568098e 100644 --- a/src/audioUtils.ts +++ b/src/audioUtils.ts @@ -1,6 +1,9 @@ -import { evaluateVector, pitchsets } from "./toneGeneration"; -import { extractPitchset, findVector } from "./harmonyUtil"; -import { soundChord } from '../app'; +import { soundChord } from '../app.js'; +import { pitchsets } from "./harmonyUtil.js"; + +import { evaluateVector } from "./vector_logic/evaluateVector.js"; +import { findVector } from "./vector_logic/findVector.js"; +import { extractPitchset } from "./vector_logic/extractPitchset.js"; export const fullRandomChord = () => { let pitches: string[]; diff --git a/src/harmonyUtil.ts b/src/harmonyUtil.ts index e5b7ae1..5ba32df 100644 --- a/src/harmonyUtil.ts +++ b/src/harmonyUtil.ts @@ -1,3 +1,14 @@ +// pitchset definitions, grouped into matrix before export +const sopranoTones = ["B5", "A5", "G5", "F#5", "F5", "E5", "D5", "C5", "B4", "Bb4", "A4", "G4", "F#4", "F4", "E4"]; +const altoTones = ["E5", "D5", "C5", "B4", "Bb4", "A4", "G4", "F#4", "F4", "E4", "D4", "C4", "B3", "Bb3", "A3", "G3"]; +const tenorTones = ["G4", "F#4", "F4", "E4", "D4", "C4", "B3", "Bb3", "A3", "G3", "F3", "E3", "D3", "C3"]; +const bassTones = ["C2", "D2", "E2", "F2", "G2", "A2", "Bb2", "B2", "C3", "D3", "E3", "F3", "G3"]; + +export const pitchsets: string[][] = [sopranoTones, altoTones, tenorTones, bassTones]; + +// mapping of musical pitches, refer to this by index, maps onto base 12 +export const musicalPitches = ['A', "Bb", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"]; + // interval definitions: export interface IntervalDef { number: string @@ -14,8 +25,6 @@ export const IntervalDefNames = { // ... all intervals beyond this invert to one of the previous intervals } -export const musicalPitches = ['A', "Bb", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"]; - // helper functions const transposePitches = (pitches: number[], interval: number) => { let transposed = []; @@ -23,55 +32,6 @@ const transposePitches = (pitches: number[], interval: number) => { return transposed; } -export const extractPitchset = (pitches: string[]) => { - // 1) determine pitch set from given array of pitches - let pitchset: number[] = []; - - for (let each of pitches) { - // filters numbers from above tones - const str = each; - const regex = /[0-9]/g; - const withoutNums = str.replace(regex, ''); - const pitchNumber = musicalPitches.indexOf(withoutNums); - - // ... so that they may be mapped onto numbers corresponding to the chromatic scale - pitchset.push(pitchNumber); - } - - // these are sorted from lowest to highest index (something like an interval vector) - pitchset.sort((a,b) => a - b); - return pitchset; -} - -export const findVector = (pitches: number[]) => { - let sorted = pitches.sort((x,y) => x - y); - // sorted = sorted.filter((num, idx) => { - // return sorted.indexOf(num) === idx; - // }); - - // finds each interval and logs it as a duple - let intervalClasses: number[] = []; - for (let i = 0; i < sorted.length; i++) { - let j = i+1; - - // does not allow out of range values in the proceeding loop - if (j >= sorted.length) { - break; - } - - do { - let thing: number = (sorted[j] - sorted[i]) % 6 - if (!(intervalClasses.includes(thing))) { - intervalClasses.push(thing); - } - j++; - } while (j < sorted.length); - } - - intervalClasses = intervalClasses.sort((x,y) => x-y); - return intervalClasses; -} - export const labelIntervals = (vector: number[]): [number, IntervalDef][] => { let result: [number, IntervalDef][] = []; @@ -82,12 +42,6 @@ export const labelIntervals = (vector: number[]): [number, IntervalDef][] => { return result; } -// analysis -let dMajor = extractPitchset(["D", "F#", "A", "D"]); -const eMajor = transposePitches(dMajor, 2); -console.log(eMajor); -console.log(''); - /** * sample uses of these functions detailed below: * diff --git a/src/styleUtils.ts b/src/styleUtils.ts index 94e17bb..8231e4c 100644 --- a/src/styleUtils.ts +++ b/src/styleUtils.ts @@ -1,4 +1,4 @@ -import * as Tone from "tone"; +import * as Tone from 'tone'; export const startButton = document.getElementById("start-tone"); export const synthButton = document.getElementById("synth-button"); diff --git a/src/toneGeneration.ts b/src/toneGeneration.ts deleted file mode 100644 index 94959b3..0000000 --- a/src/toneGeneration.ts +++ /dev/null @@ -1,22 +0,0 @@ -// we start with a selection of pitches that generally work okay together -const sopranoTones = ["B5", "A5", "G5", "F#5", "F5", "E5", "D5", "C5", "B4", "Bb4", "A4", "G4", "F#4", "F4", "E4"]; -const altoTones = ["E5", "D5", "C5", "B4", "Bb4", "A4", "G4", "F#4", "F4", "E4", "D4", "C4", "B3", "Bb3", "A3", "G3"]; -const tenorTones = ["G4", "F#4", "F4", "E4", "D4", "C4", "B3", "Bb3", "A3", "G3", "F3", "E3", "D3", "C3"]; -const bassTones = ["C2", "D2", "E2", "F2", "G2", "A2", "Bb2", "B2", "C3", "D3", "E3", "F3", "G3"]; - -export const pitchsets: string[][] = [sopranoTones, altoTones, tenorTones, bassTones]; - -/** - * now we define some rules to allow for the program to follow so it can some basic tenets of music theory - * we include all pitches, so that it can use semitone-based pitch logic focused on base-12 - * - * some basic rules: - * no tritones - * no minor 2nds or major 7ths -*/ - -export const evaluateVector = (vector: number[]): boolean => ((vector.includes(1) || vector.includes(6))); - -export const rejectDissonance = (vector: number[]) => { - -} diff --git a/src/vector_logic/evaluateVector.ts b/src/vector_logic/evaluateVector.ts new file mode 100644 index 0000000..3f11878 --- /dev/null +++ b/src/vector_logic/evaluateVector.ts @@ -0,0 +1,7 @@ +export const evaluateVector = (vector: number[]): boolean => { + return ((vector.includes(1) || vector.includes(6))); +} + +export const rejectDissonance = (vector: number[]) => { + return; +} \ No newline at end of file diff --git a/src/vector_logic/extractPitchset.ts b/src/vector_logic/extractPitchset.ts new file mode 100644 index 0000000..946a7e9 --- /dev/null +++ b/src/vector_logic/extractPitchset.ts @@ -0,0 +1,21 @@ +import { musicalPitches } from "../harmonyUtil"; + +export const extractPitchset = (pitches: string[]) => { + // 1) determine pitch set from given array of pitches + let pitchset: number[] = []; + + for (let each of pitches) { + // filters numbers from above tones + const str = each; + const regex = /[0-9]/g; + const withoutNums = str.replace(regex, ''); + const pitchNumber = musicalPitches.indexOf(withoutNums); + + // ... so that they may be mapped onto numbers corresponding to the chromatic scale + pitchset.push(pitchNumber); + } + + // these are sorted from lowest to highest index (something like an interval vector) + pitchset.sort((a,b) => a - b); + return pitchset; +} \ No newline at end of file diff --git a/src/vector_logic/findVector.ts b/src/vector_logic/findVector.ts new file mode 100644 index 0000000..2989244 --- /dev/null +++ b/src/vector_logic/findVector.ts @@ -0,0 +1,28 @@ +export const findVector = (pitches: number[]) => { + let sorted = pitches.sort((x,y) => x - y); + // sorted = sorted.filter((num, idx) => { + // return sorted.indexOf(num) === idx; + // }); + + // finds each interval and logs it as a duple + let intervalClasses: number[] = []; + for (let i = 0; i < sorted.length; i++) { + let j = i+1; + + // does not allow out of range values in the proceeding loop + if (j >= sorted.length) { + break; + } + + do { + let thing: number = (sorted[j] - sorted[i]) % 6 + if (!(intervalClasses.includes(thing))) { + intervalClasses.push(thing); + } + j++; + } while (j < sorted.length); + } + + intervalClasses = intervalClasses.sort((x,y) => x-y); + return intervalClasses; +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index b7b0f55..494906a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,7 +3,8 @@ "outDir": "./built", "allowJs": true, "target": "es2017", - "moduleResolution": "node" + "module": "CommonJS", + "moduleResolution": "node", }, - "include": ["./src/**/*"] + "include": ["./src/**/*", "./app"] } \ No newline at end of file