From abbb3c606876e05e5a406e7f715aacefe17b0733 Mon Sep 17 00:00:00 2001 From: Mikayla Dobson <93477693+innocuous-symmetry@users.noreply.github.com> Date: Thu, 12 May 2022 11:13:34 -0500 Subject: [PATCH 1/5] restoring to vanilla js --- app.js | 19 +++------ index.html | 14 ++++-- js/harmonyUtil.js | 64 ---------------------------- js/toneGeneration.js | 35 --------------- src/audioUtil.js | 10 +++++ src/harmonyUtil.js | 46 ++++++++++++++++++++ {js => src}/inputHandling.js | 0 {js => src}/styleUtils.js | 0 src/vector_logic/evaluateVector.js | 0 src/vector_logic/extractPitchset.js | 22 ++++++++++ src/vector_logic/findVector.js | 26 +++++++++++ src/vector_logic/numbersToPitches.js | 0 12 files changed, 119 insertions(+), 117 deletions(-) delete mode 100644 js/harmonyUtil.js delete mode 100644 js/toneGeneration.js create mode 100644 src/audioUtil.js create mode 100644 src/harmonyUtil.js rename {js => src}/inputHandling.js (100%) rename {js => src}/styleUtils.js (100%) create mode 100644 src/vector_logic/evaluateVector.js create mode 100644 src/vector_logic/extractPitchset.js create mode 100644 src/vector_logic/findVector.js create mode 100644 src/vector_logic/numbersToPitches.js diff --git a/app.js b/app.js index 75cf0c8..7ceae65 100644 --- a/app.js +++ b/app.js @@ -1,9 +1,5 @@ -import { - sopranoTones, altoTones, tenorTones, bassTones, - extractPitchset, -} from "./js/toneGeneration.js"; - -const pitchsets = [sopranoTones, altoTones, tenorTones, bassTones]; +import { pitchsets } from "./src/harmonyUtil.js"; +import { extractPitchset } from "./src/vector_logic/extractPitchset.js"; // initialize four synth voices const soprano = new Tone.Synth().toDestination(); @@ -20,8 +16,9 @@ export const audioTest = () => { } // allows a chord to be generated with input from another function -export const soundChord = (pitches) => { - const [s,a,t,b] = pitches; +// pitchNames: array of strings +export const soundChord = (pitchNames) => { + const [s,a,t,b] = pitchNames; soprano.triggerAttackRelease(s, "8n"); alto.triggerAttackRelease(a, "8n"); tenor.triggerAttackRelease(t, "8n"); @@ -54,13 +51,8 @@ export const fullRandomChord = () => { } // set up transport -let clock = 0; -let slowClock = 0; - const transportStart = document.getElementById('transport-start'); -let transport; - const loop = new Tone.Loop((time) => { audioTest(); }, "8n").start(0); @@ -70,4 +62,3 @@ loop.probability = 0.8; transportStart.onclick = () => { Tone.Transport.start(); } - diff --git a/index.html b/index.html index bb9cd11..50c49fb 100644 --- a/index.html +++ b/index.html @@ -118,9 +118,15 @@ - - - - + + + + + + + + + + \ No newline at end of file diff --git a/js/harmonyUtil.js b/js/harmonyUtil.js deleted file mode 100644 index f433593..0000000 --- a/js/harmonyUtil.js +++ /dev/null @@ -1,64 +0,0 @@ -import { extractPitchset } from "./toneGeneration.js"; - -// interval definitions: -const intervals = { - 0: "unison", - 1: "minor second", - 2: "major second", - 3: "minor third", - 4: "major third", - 5: "perfect fourth", - 6: "tritone" - // all intervals beyond this invert to one of the previous intervals -} - -// helper functions -const transposePitches = (pitchNames, interval) => { - let transposed = []; - pitchNames.forEach(pitch => transposed.push((pitch + interval) % 12)); - return transposed; -} - -const findVector = (pitches) => { - 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 = []; - 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 = (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; -} - -// analysis -let dMajor = extractPitchset(["D", "F#", "A", "D"]); -const eMajor = transposePitches(dMajor, 2); -console.log(eMajor); -console.log(''); - -let dMajVector = findVector(dMajor); -console.log(dMajVector); - -let complexVector = findVector([0,3,4,7,8,11]); -console.log(complexVector); - -let splitThird = findVector([0,3,4,7]); -console.log(splitThird); diff --git a/js/toneGeneration.js b/js/toneGeneration.js deleted file mode 100644 index 9787eaf..0000000 --- a/js/toneGeneration.js +++ /dev/null @@ -1,35 +0,0 @@ -// we start with a selection of pitches that generally work okay together -export const sopranoTones = ["B5", "A5", "G5", "F#5", "F5", "E5", "D5", "C5", "B4", "Bb4", "A4", "G4", "F#4", "F4", "E4"]; -export const altoTones = ["E5", "D5", "C5", "B4", "Bb4", "A4", "G4", "F#4", "F4", "E4", "D4", "C4", "B3", "Bb3", "A3", "G3"]; -export const tenorTones = ["G4", "F#4", "F4", "E4", "D4", "C4", "B3", "Bb3", "A3", "G3", "F3", "E3", "D3", "C3"]; -export const bassTones = ["C2", "D2", "E2", "F2", "G2", "A2", "Bb2", "B2", "C3", "D3", "E3", "F3", "G3"]; - -// now we define some rules to allow for the program to follow so it can some basic tenets of music theory -// we're going to include all pitches, so that it can use semitone-based pitch logic. -// this is focused on base-12, something computers understand quite well -const musicalPitches = ['A', "Bb", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"]; - -export const extractPitchset = (pitches) => { - // 1) determine pitch set from given array of pitches - let pitchset = []; - - 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); - console.log(pitchset); - - return pitchset; -} - -// no tritones -// no minor 2nds or major 7ths \ No newline at end of file diff --git a/src/audioUtil.js b/src/audioUtil.js new file mode 100644 index 0000000..c88de0c --- /dev/null +++ b/src/audioUtil.js @@ -0,0 +1,10 @@ +import { soundChord } from "../app.js"; +import { getRandomPitches } from "./harmonyUtil.js"; + +// initial test: generate a single, random chord +export const fullRandomChord = () => { + let pitches = getRandomPitches(); + + soundChord(pitches); + extractPitchset(pitches); +} \ No newline at end of file diff --git a/src/harmonyUtil.js b/src/harmonyUtil.js new file mode 100644 index 0000000..6a72c77 --- /dev/null +++ b/src/harmonyUtil.js @@ -0,0 +1,46 @@ +import { extractPitchset } from "./vector_logic/extractPitchset.js"; + +export const sopranoTones = ["B5", "A5", "G5", "F#5", "F5", "E5", "D5", "C5", "B4", "Bb4", "A4", "G4", "F#4", "F4", "E4"]; +export const altoTones = ["E5", "D5", "C5", "B4", "Bb4", "A4", "G4", "F#4", "F4", "E4", "D4", "C4", "B3", "Bb3", "A3", "G3"]; +export const tenorTones = ["G4", "F#4", "F4", "E4", "D4", "C4", "B3", "Bb3", "A3", "G3", "F3", "E3", "D3", "C3"]; +export const bassTones = ["C2", "D2", "E2", "F2", "G2", "A2", "Bb2", "B2", "C3", "D3", "E3", "F3", "G3"]; + +export const pitchsets = [sopranoTones, altoTones, tenorTones, bassTones]; + +export const musicalPitches = ['A', "Bb", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"]; + +// interval definitions: +export const intervalNames = { + 0: "unison", + 1: "minor second", + 2: "major second", + 3: "minor third", + 4: "major third", + 5: "perfect fourth", + 6: "tritone" + // all intervals beyond this invert to one of the previous intervals +} + +// helper functions +const transposePitches = (pitchNames, interval) => { + let transposed = []; + pitchNames.forEach(pitch => transposed.push((pitch + interval) % 12)); + return transposed; +} + +export const getRandomPitches = () => { + // pitches stored in Tone.js string format + let pitches = []; + for (let voice of pitchsets) { + // finds a random index, excluding any which may already exist in the array + let index; + + do { + index = Math.floor(Math.random() * 100) % voice.length; + } while (pitches.includes(voice[index])); + + pitches.push(voice[index]); + } + + return pitches; +} diff --git a/js/inputHandling.js b/src/inputHandling.js similarity index 100% rename from js/inputHandling.js rename to src/inputHandling.js diff --git a/js/styleUtils.js b/src/styleUtils.js similarity index 100% rename from js/styleUtils.js rename to src/styleUtils.js diff --git a/src/vector_logic/evaluateVector.js b/src/vector_logic/evaluateVector.js new file mode 100644 index 0000000..e69de29 diff --git a/src/vector_logic/extractPitchset.js b/src/vector_logic/extractPitchset.js new file mode 100644 index 0000000..33b74a8 --- /dev/null +++ b/src/vector_logic/extractPitchset.js @@ -0,0 +1,22 @@ +import { musicalPitches } from '../harmonyUtil.js'; + +// converts pitches in Tone.js string format to base-12 number pitchsets +export const extractPitchset = (pitches) => { + // 1) determine pitch set from given array of pitches + let pitchset = []; + + 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.js b/src/vector_logic/findVector.js new file mode 100644 index 0000000..2457b00 --- /dev/null +++ b/src/vector_logic/findVector.js @@ -0,0 +1,26 @@ +// takes pitches as numbers and converts them to a vector +export const findVector = (pitches) => { + let sorted = pitches.sort((x,y) => x - y); + + // finds each interval and logs it as a duple + let intervalClasses = []; + 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 = (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; +} diff --git a/src/vector_logic/numbersToPitches.js b/src/vector_logic/numbersToPitches.js new file mode 100644 index 0000000..e69de29 From 65ce76411c231831afc2ad22807e1073506aaf59 Mon Sep 17 00:00:00 2001 From: Mikayla Dobson <93477693+innocuous-symmetry@users.noreply.github.com> Date: Thu, 12 May 2022 12:11:53 -0500 Subject: [PATCH 2/5] random chord method checks for distinct members --- app.js | 25 ------------------------- index.html | 1 + src/audioUtil.js | 6 ++++-- src/harmonyUtil.js | 22 +++++++++++++++++----- src/helper.js | 30 ++++++++++++++++++++++++++++++ src/inputHandling.js | 3 ++- src/vector_logic/evaluateVector.js | 21 +++++++++++++++++++++ 7 files changed, 75 insertions(+), 33 deletions(-) create mode 100644 src/helper.js diff --git a/app.js b/app.js index 7ceae65..bbb610c 100644 --- a/app.js +++ b/app.js @@ -25,31 +25,6 @@ export const soundChord = (pitchNames) => { bass.triggerAttackRelease(b, "8n"); } -// initial test: generate a single, random chord -export const fullRandomChord = () => { - let pitches = []; - for (let voice of pitchsets) { - // finds a random index, excluding any which may already exist in the array - let index; - - do { - index = Math.floor(Math.random() * 100) % voice.length; - } while (pitches.includes(voice[index])); - - pitches.push(voice[index]); - console.log(voice[index]); - } - - for (let i = 0; i < pitches.length; i++) { - if (pitches[i] === pitches[i+1]) { - console.log("CAUGHT"); - } - } - - soundChord(pitches); - extractPitchset(pitches); -} - // set up transport const transportStart = document.getElementById('transport-start'); diff --git a/index.html b/index.html index 50c49fb..3a9dfbe 100644 --- a/index.html +++ b/index.html @@ -112,6 +112,7 @@ + diff --git a/src/audioUtil.js b/src/audioUtil.js index c88de0c..fb97911 100644 --- a/src/audioUtil.js +++ b/src/audioUtil.js @@ -1,10 +1,12 @@ import { soundChord } from "../app.js"; import { getRandomPitches } from "./harmonyUtil.js"; +import { extractPitchset } from "./vector_logic/extractPitchset.js"; // initial test: generate a single, random chord export const fullRandomChord = () => { let pitches = getRandomPitches(); - soundChord(pitches); - extractPitchset(pitches); + let pitchset = extractPitchset(pitches); + + return pitchset; } \ No newline at end of file diff --git a/src/harmonyUtil.js b/src/harmonyUtil.js index 6a72c77..eca3e0d 100644 --- a/src/harmonyUtil.js +++ b/src/harmonyUtil.js @@ -31,16 +31,28 @@ const transposePitches = (pitchNames, interval) => { export const getRandomPitches = () => { // pitches stored in Tone.js string format let pitches = []; + let formattedPitches = []; + for (let voice of pitchsets) { // finds a random index, excluding any which may already exist in the array let index; - - do { - index = Math.floor(Math.random() * 100) % voice.length; - } while (pitches.includes(voice[index])); + const regex = /[A-Gb#]/g; + let pitch; + let formattedPitch; - pitches.push(voice[index]); + // loops until four distinct chord members are received + while (formattedPitches.length < 4) { + index = Math.floor(Math.random() * 100) % voice.length; + pitch = voice[index]; + formattedPitch = pitch.match(regex).join(''); + if (!formattedPitches.includes(formattedPitch)) { + formattedPitches.push(formattedPitch); + pitches.push(pitch); + } + } } + console.log(formattedPitches); + console.log(pitches); return pitches; } diff --git a/src/helper.js b/src/helper.js new file mode 100644 index 0000000..f7a7b7e --- /dev/null +++ b/src/helper.js @@ -0,0 +1,30 @@ +import { pitchsets } from "./harmonyUtil.js"; + +let index; +let pitch; +let formattedPitch = 'caught'; +let regex = /[A-Gb#]/g; + +let pitches = []; +let formattedPitches = []; + +// index = Math.floor(Math.random() * 100) % pitchsets[0].length; + +// const toParse = pitchsets[0][index]; +// const parsed = toParse.match(regex).join(''); +// console.log(parsed); + +for (let voice of pitchsets) { + while (formattedPitches.length < 4) { + index = Math.floor(Math.random() * 100) % voice.length; + pitch = voice[index]; + formattedPitch = pitch.match(regex).join(''); + if (!formattedPitches.includes(formattedPitch)) { + formattedPitches.push(formattedPitch); + pitches.push(pitch); + } + } +} + +console.log(formattedPitches) +console.log(pitches); \ No newline at end of file diff --git a/src/inputHandling.js b/src/inputHandling.js index cb4ff7f..3effa91 100644 --- a/src/inputHandling.js +++ b/src/inputHandling.js @@ -1,4 +1,5 @@ -import { audioTest, fullRandomChord } from '../app.js'; +import { audioTest } from '../app.js'; +import { fullRandomChord } from './audioUtil.js'; // slider variables referring to DOM export const sopranoVol = document.getElementById('soprano-vol'); diff --git a/src/vector_logic/evaluateVector.js b/src/vector_logic/evaluateVector.js index e69de29..035c4b2 100644 --- a/src/vector_logic/evaluateVector.js +++ b/src/vector_logic/evaluateVector.js @@ -0,0 +1,21 @@ +import { getRandomPitches } from "../harmonyUtil.js"; +import { extractPitchset } from "./extractPitchset.js"; +import { findVector } from "./findVector.js"; + +export const evaluateVector = (vector) => { + return ((vector.includes(1) || vector.includes(6))); +} + +export const rejectDissonance = (pitchset) => { + const vector = findVector(pitchset); + + // returns the pitchset and its vector if evaluateVector returns true, + if (evaluateVector(vector)) return vector; + + // and recursively calls the function otherwise. + if (!evaluateVector(vector)) { + let newPitches = getRandomPitches(); + let newPitchset = extractPitchset(newPitches); + rejectDissonance(newPitchset); + }; +} \ No newline at end of file From 998b0fb5be74f2e5bab9d7275917a964b591b5d3 Mon Sep 17 00:00:00 2001 From: Mikayla Dobson <93477693+innocuous-symmetry@users.noreply.github.com> Date: Thu, 12 May 2022 12:26:22 -0500 Subject: [PATCH 3/5] separation of concerns --- src/audioUtil.js | 4 ++++ src/harmonyUtil.js | 21 ++++++++++++++++--- src/helper.js | 30 ---------------------------- src/inputHandling.js | 5 ++++- src/vector_logic/extractPitchName.js | 2 ++ src/vector_logic/extractPitchset.js | 4 ++-- 6 files changed, 30 insertions(+), 36 deletions(-) delete mode 100644 src/helper.js create mode 100644 src/vector_logic/extractPitchName.js diff --git a/src/audioUtil.js b/src/audioUtil.js index fb97911..97feba5 100644 --- a/src/audioUtil.js +++ b/src/audioUtil.js @@ -9,4 +9,8 @@ export const fullRandomChord = () => { let pitchset = extractPitchset(pitches); return pitchset; +} + +export const evaluatedChord = () => { + return fullRandomChord(); } \ No newline at end of file diff --git a/src/harmonyUtil.js b/src/harmonyUtil.js index eca3e0d..bd01f6b 100644 --- a/src/harmonyUtil.js +++ b/src/harmonyUtil.js @@ -1,4 +1,6 @@ import { extractPitchset } from "./vector_logic/extractPitchset.js"; +import { evaluateVector } from "./vector_logic/evaluateVector.js"; +import { extractPitchName } from "./vector_logic/extractPitchName.js"; export const sopranoTones = ["B5", "A5", "G5", "F#5", "F5", "E5", "D5", "C5", "B4", "Bb4", "A4", "G4", "F#4", "F4", "E4"]; export const altoTones = ["E5", "D5", "C5", "B4", "Bb4", "A4", "G4", "F#4", "F4", "E4", "D4", "C4", "B3", "Bb3", "A3", "G3"]; @@ -36,15 +38,15 @@ export const getRandomPitches = () => { for (let voice of pitchsets) { // finds a random index, excluding any which may already exist in the array let index; - const regex = /[A-Gb#]/g; let pitch; let formattedPitch; // loops until four distinct chord members are received - while (formattedPitches.length < 4) { + while (formattedPitches.length <= pitchsets.indexOf(voice)) { index = Math.floor(Math.random() * 100) % voice.length; pitch = voice[index]; - formattedPitch = pitch.match(regex).join(''); + + formattedPitch = extractPitchName(pitch); if (!formattedPitches.includes(formattedPitch)) { formattedPitches.push(formattedPitch); pitches.push(pitch); @@ -56,3 +58,16 @@ export const getRandomPitches = () => { console.log(pitches); return pitches; } + +// an additional method based on the structure of the method above, +// but taking principles of music theory into account. +export const getProceduralPitches = () => { + let pitches = []; + let formattedPitches = []; + + for (let voice of pitchsets) { + let index; + let pitch; + let formattedPitch; + } +} diff --git a/src/helper.js b/src/helper.js deleted file mode 100644 index f7a7b7e..0000000 --- a/src/helper.js +++ /dev/null @@ -1,30 +0,0 @@ -import { pitchsets } from "./harmonyUtil.js"; - -let index; -let pitch; -let formattedPitch = 'caught'; -let regex = /[A-Gb#]/g; - -let pitches = []; -let formattedPitches = []; - -// index = Math.floor(Math.random() * 100) % pitchsets[0].length; - -// const toParse = pitchsets[0][index]; -// const parsed = toParse.match(regex).join(''); -// console.log(parsed); - -for (let voice of pitchsets) { - while (formattedPitches.length < 4) { - index = Math.floor(Math.random() * 100) % voice.length; - pitch = voice[index]; - formattedPitch = pitch.match(regex).join(''); - if (!formattedPitches.includes(formattedPitch)) { - formattedPitches.push(formattedPitch); - pitches.push(pitch); - } - } -} - -console.log(formattedPitches) -console.log(pitches); \ No newline at end of file diff --git a/src/inputHandling.js b/src/inputHandling.js index 3effa91..d2dfaff 100644 --- a/src/inputHandling.js +++ b/src/inputHandling.js @@ -1,5 +1,5 @@ import { audioTest } from '../app.js'; -import { fullRandomChord } from './audioUtil.js'; +import { fullRandomChord, evaluatedChord } from './audioUtil.js'; // slider variables referring to DOM export const sopranoVol = document.getElementById('soprano-vol'); @@ -65,3 +65,6 @@ synthButton.onclick = audioTest; const randChord = document.getElementById('rand-chord'); randChord.onclick = fullRandomChord; + +const evalChord = document.getElementById('eval-chord'); +evalChord.onclick = evaluatedChord; diff --git a/src/vector_logic/extractPitchName.js b/src/vector_logic/extractPitchName.js new file mode 100644 index 0000000..016d63a --- /dev/null +++ b/src/vector_logic/extractPitchName.js @@ -0,0 +1,2 @@ +const regex = /[A-Gb#]/g; +export const extractPitchName = (tonePitchName) => tonePitchName.match(regex).join(''); diff --git a/src/vector_logic/extractPitchset.js b/src/vector_logic/extractPitchset.js index 33b74a8..62c9b1e 100644 --- a/src/vector_logic/extractPitchset.js +++ b/src/vector_logic/extractPitchset.js @@ -1,4 +1,5 @@ import { musicalPitches } from '../harmonyUtil.js'; +import { extractPitchName } from './extractPitchName.js'; // converts pitches in Tone.js string format to base-12 number pitchsets export const extractPitchset = (pitches) => { @@ -8,8 +9,7 @@ export const extractPitchset = (pitches) => { for (let each of pitches) { // filters numbers from above tones const str = each; - const regex = /[0-9]/g; - const withoutNums = str.replace(regex, ''); + const withoutNums = extractPitchName(str); const pitchNumber = musicalPitches.indexOf(withoutNums); // ... so that they may be mapped onto numbers corresponding to the chromatic scale From 4b9fbdfa3663df975a76ef71b6078aa9e07b151d Mon Sep 17 00:00:00 2001 From: Mikayla Dobson <93477693+innocuous-symmetry@users.noreply.github.com> Date: Thu, 12 May 2022 13:19:39 -0500 Subject: [PATCH 4/5] repairs to file system --- app.js | 3 -- index.html | 5 --- src/audioUtil.js | 11 ++++-- src/harmonyUtil.js | 48 +----------------------- src/vector_logic/evaluateVector.js | 2 +- src/vector_logic/getProceduralPitches.js | 34 +++++++++++++++++ src/vector_logic/getRandomPitches.js | 29 ++++++++++++++ 7 files changed, 73 insertions(+), 59 deletions(-) create mode 100644 src/vector_logic/getProceduralPitches.js create mode 100644 src/vector_logic/getRandomPitches.js diff --git a/app.js b/app.js index bbb610c..aab2115 100644 --- a/app.js +++ b/app.js @@ -1,6 +1,3 @@ -import { pitchsets } from "./src/harmonyUtil.js"; -import { extractPitchset } from "./src/vector_logic/extractPitchset.js"; - // initialize four synth voices const soprano = new Tone.Synth().toDestination(); const alto = new Tone.Synth().toDestination(); diff --git a/index.html b/index.html index 3a9dfbe..09e22de 100644 --- a/index.html +++ b/index.html @@ -124,10 +124,5 @@ - - - - - \ No newline at end of file diff --git a/src/audioUtil.js b/src/audioUtil.js index 97feba5..39c74c4 100644 --- a/src/audioUtil.js +++ b/src/audioUtil.js @@ -1,6 +1,7 @@ import { soundChord } from "../app.js"; -import { getRandomPitches } from "./harmonyUtil.js"; +import { getRandomPitches } from "./vector_logic/getRandomPitches.js"; import { extractPitchset } from "./vector_logic/extractPitchset.js"; +import { getProceduralPitches } from "./vector_logic/getProceduralPitches.js"; // initial test: generate a single, random chord export const fullRandomChord = () => { @@ -11,6 +12,10 @@ export const fullRandomChord = () => { return pitchset; } -export const evaluatedChord = () => { - return fullRandomChord(); +export const evaluatedChord = (prevPitches = ["C3", "G3", "C4", "G4"]) => { + let pitches = getProceduralPitches(prevPitches); + soundChord(pitches); + let pitchset = extractPitchset(pitches); + + return pitchset; } \ No newline at end of file diff --git a/src/harmonyUtil.js b/src/harmonyUtil.js index bd01f6b..696320b 100644 --- a/src/harmonyUtil.js +++ b/src/harmonyUtil.js @@ -1,13 +1,9 @@ -import { extractPitchset } from "./vector_logic/extractPitchset.js"; -import { evaluateVector } from "./vector_logic/evaluateVector.js"; -import { extractPitchName } from "./vector_logic/extractPitchName.js"; - export const sopranoTones = ["B5", "A5", "G5", "F#5", "F5", "E5", "D5", "C5", "B4", "Bb4", "A4", "G4", "F#4", "F4", "E4"]; export const altoTones = ["E5", "D5", "C5", "B4", "Bb4", "A4", "G4", "F#4", "F4", "E4", "D4", "C4", "B3", "Bb3", "A3", "G3"]; export const tenorTones = ["G4", "F#4", "F4", "E4", "D4", "C4", "B3", "Bb3", "A3", "G3", "F3", "E3", "D3", "C3"]; export const bassTones = ["C2", "D2", "E2", "F2", "G2", "A2", "Bb2", "B2", "C3", "D3", "E3", "F3", "G3"]; -export const pitchsets = [sopranoTones, altoTones, tenorTones, bassTones]; +export const pitchsets = [bassTones, tenorTones, altoTones, sopranoTones]; export const musicalPitches = ['A', "Bb", "B", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#"]; @@ -29,45 +25,3 @@ const transposePitches = (pitchNames, interval) => { pitchNames.forEach(pitch => transposed.push((pitch + interval) % 12)); return transposed; } - -export const getRandomPitches = () => { - // pitches stored in Tone.js string format - let pitches = []; - let formattedPitches = []; - - for (let voice of pitchsets) { - // finds a random index, excluding any which may already exist in the array - let index; - let pitch; - let formattedPitch; - - // loops until four distinct chord members are received - while (formattedPitches.length <= pitchsets.indexOf(voice)) { - index = Math.floor(Math.random() * 100) % voice.length; - pitch = voice[index]; - - formattedPitch = extractPitchName(pitch); - if (!formattedPitches.includes(formattedPitch)) { - formattedPitches.push(formattedPitch); - pitches.push(pitch); - } - } - } - - console.log(formattedPitches); - console.log(pitches); - return pitches; -} - -// an additional method based on the structure of the method above, -// but taking principles of music theory into account. -export const getProceduralPitches = () => { - let pitches = []; - let formattedPitches = []; - - for (let voice of pitchsets) { - let index; - let pitch; - let formattedPitch; - } -} diff --git a/src/vector_logic/evaluateVector.js b/src/vector_logic/evaluateVector.js index 035c4b2..db32ff6 100644 --- a/src/vector_logic/evaluateVector.js +++ b/src/vector_logic/evaluateVector.js @@ -1,4 +1,4 @@ -import { getRandomPitches } from "../harmonyUtil.js"; +import { getRandomPitches } from './getRandomPitches.js'; import { extractPitchset } from "./extractPitchset.js"; import { findVector } from "./findVector.js"; diff --git a/src/vector_logic/getProceduralPitches.js b/src/vector_logic/getProceduralPitches.js new file mode 100644 index 0000000..0a542f1 --- /dev/null +++ b/src/vector_logic/getProceduralPitches.js @@ -0,0 +1,34 @@ +import { pitchsets } from "../harmonyUtil.js"; +import { extractPitchName } from "./extractPitchName.js"; + +// an additional method based on the structure of getRandomPitches, +// but taking some principles of music theory into account. +export const getProceduralPitches = (prevPitches) => { + // prevPitches is passed in to ensure there is no linear dissonance within voices + let pitches = []; + let formattedPitches = []; + + for (let voice of pitchsets) { + let index; + let formattedPitch; + + while (pitches.length <= pitchsets.indexOf(voice)) { + // the first section of this while loop is more free. + index = Math.floor(Math.random() * 100) % voice.length; + formattedPitch = extractPitchName(voice[index]); + + // this initial condition will apply only to the bass voice, + if (!pitches.length) { + pitches.push(voice[index]); + } else { + // now we need some repeating logic for the remaining four voices + while (pitches.length !== (pitchsets.indexOf(voice) + 1)) { + pitches.push(pitchsets.indexOf(voice)); + } + } + } + } + + console.log(pitches); + return pitches; +} diff --git a/src/vector_logic/getRandomPitches.js b/src/vector_logic/getRandomPitches.js new file mode 100644 index 0000000..a041b44 --- /dev/null +++ b/src/vector_logic/getRandomPitches.js @@ -0,0 +1,29 @@ +import { pitchsets } from "../harmonyUtil.js"; +import { extractPitchName } from "./extractPitchName.js"; + +export const getRandomPitches = () => { + // pitches stored in Tone.js string format + let pitches = []; + let formattedPitches = []; + + for (let voice of pitchsets) { + // finds a random index, excluding any which may already exist in the array + let index; + let formattedPitch; + + // loops until four distinct chord members are received + while (formattedPitches.length <= pitchsets.indexOf(voice)) { + index = Math.floor(Math.random() * 100) % voice.length; + + formattedPitch = extractPitchName(voice[index]); + if (!formattedPitches.includes(formattedPitch)) { + formattedPitches.push(formattedPitch); + pitches.push(voice[index]); + } + } + } + + console.log(formattedPitches); + console.log(pitches); + return pitches; +} From fa8a12128ba24bcbc77c9327ee37142fb3de815f Mon Sep 17 00:00:00 2001 From: Mikayla Dobson <93477693+innocuous-symmetry@users.noreply.github.com> Date: Thu, 12 May 2022 14:32:51 -0500 Subject: [PATCH 5/5] working on procedural gen --- src/vector_logic/getProceduralPitches.js | 26 +++++++- src/vector_logic/getRandomPitches.js | 5 +- src/vector_logic/helper.js | 80 ++++++++++++++++++++++++ 3 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 src/vector_logic/helper.js diff --git a/src/vector_logic/getProceduralPitches.js b/src/vector_logic/getProceduralPitches.js index 0a542f1..bd9c5e6 100644 --- a/src/vector_logic/getProceduralPitches.js +++ b/src/vector_logic/getProceduralPitches.js @@ -1,5 +1,6 @@ -import { pitchsets } from "../harmonyUtil.js"; +import { pitchsets, musicalPitches } from "../harmonyUtil.js"; import { extractPitchName } from "./extractPitchName.js"; +import { getRandomIndex } from "./getRandomPitches.js"; // an additional method based on the structure of getRandomPitches, // but taking some principles of music theory into account. @@ -14,7 +15,7 @@ export const getProceduralPitches = (prevPitches) => { while (pitches.length <= pitchsets.indexOf(voice)) { // the first section of this while loop is more free. - index = Math.floor(Math.random() * 100) % voice.length; + index = getRandomIndex(voice); formattedPitch = extractPitchName(voice[index]); // this initial condition will apply only to the bass voice, @@ -23,7 +24,26 @@ export const getProceduralPitches = (prevPitches) => { } else { // now we need some repeating logic for the remaining four voices while (pitches.length !== (pitchsets.indexOf(voice) + 1)) { - pitches.push(pitchsets.indexOf(voice)); + index = getRandomIndex(voice); + pitches.push(voice[index]); + + + for (let i = 0; i < pitches.length; i++) { + let numVals = []; + + for (let j = i; j < i + 2; j++) { + console.log(pitches[j]); + let extracted = extractPitchName(pitches[j]); + numVals.push(musicalPitches.indexOf(extracted) + 1); + } + + let difference = Math.abs(numVals.reduce((x,y) => x - y)); + if (difference === 1 || difference === 6) { + pitches.pop(); + } else { + continue; + } + } } } } diff --git a/src/vector_logic/getRandomPitches.js b/src/vector_logic/getRandomPitches.js index a041b44..fb31de6 100644 --- a/src/vector_logic/getRandomPitches.js +++ b/src/vector_logic/getRandomPitches.js @@ -1,6 +1,9 @@ import { pitchsets } from "../harmonyUtil.js"; import { extractPitchName } from "./extractPitchName.js"; +// helper function for assigning a random index for a given voice's pitchset +export const getRandomIndex = (voice) => Math.floor(Math.random() * 100) % voice.length; + export const getRandomPitches = () => { // pitches stored in Tone.js string format let pitches = []; @@ -13,7 +16,7 @@ export const getRandomPitches = () => { // loops until four distinct chord members are received while (formattedPitches.length <= pitchsets.indexOf(voice)) { - index = Math.floor(Math.random() * 100) % voice.length; + index = getRandomIndex(voice); formattedPitch = extractPitchName(voice[index]); if (!formattedPitches.includes(formattedPitch)) { diff --git a/src/vector_logic/helper.js b/src/vector_logic/helper.js new file mode 100644 index 0000000..77fd2d9 --- /dev/null +++ b/src/vector_logic/helper.js @@ -0,0 +1,80 @@ +import { pitchsets, musicalPitches } from '../harmonyUtil.js'; +import { extractPitchName } from './extractPitchName.js'; +import { getRandomIndex } from './getRandomPitches.js'; + +const iteratePitchsets = () => { + let pitches = []; + let result = []; + + const tryNewPitch = () => { + result = []; + + for (let voice of pitchsets) { + let idx = getRandomIndex(voice); + let pitchNum = musicalPitches.indexOf(extractPitchName(voice[idx])); + + pitches.push([pitchNum, voice[idx]]); + } + + console.log(pitches); + + for (let i = 0; i < pitches.length; i++) { + for (let j = i; j < pitches.length; j++) { + let difference = Math.abs(pitches[i][0] - pitches[j][0]); + if (difference === 1 || difference === 6) { + result.push(["BAD", [i, j], pitches[i], pitches[j]]); + } else { + result.push(["GOOD", [i, j], pitches[i], pitches[j]]); + } + } + } + console.log(result); + } + + tryNewPitch(); + + for (let entry in result) { + if (entry[0] === "BAD") { + iteratePitchsets(); + } + } + + console.log(pitches); +} + +iteratePitchsets(); + + + +function twoPointIteration() { + let caught = false; + let data = [1,2,3,4,5,6]; + + for (let i = 0; i < data.length; i++) { + console.log(data[i]); + for (let j = 0; j < data.length; j++) { + if (data[i] === data[j]) continue; + + let difference = Math.abs(data[j] - data[i]); + + if (difference === 3) { + difference = "caught: 3"; + } + + console.log([difference, [data[i], data[j]]]); + } + + console.log('next'); + } + + return caught; +} + +function selfReferentialPointer() { + for (let i = 0; i < 5; i++) { + console.log(`i: ${i}`); + for (let j = i; j < i+2; j++) { + console.log(`jjjjjjj: ${j % 3}`); + } + } +}