restoring to vanilla js
This commit is contained in:
19
app.js
19
app.js
@@ -1,9 +1,5 @@
|
|||||||
import {
|
import { pitchsets } from "./src/harmonyUtil.js";
|
||||||
sopranoTones, altoTones, tenorTones, bassTones,
|
import { extractPitchset } from "./src/vector_logic/extractPitchset.js";
|
||||||
extractPitchset,
|
|
||||||
} from "./js/toneGeneration.js";
|
|
||||||
|
|
||||||
const pitchsets = [sopranoTones, altoTones, tenorTones, bassTones];
|
|
||||||
|
|
||||||
// initialize four synth voices
|
// initialize four synth voices
|
||||||
const soprano = new Tone.Synth().toDestination();
|
const soprano = new Tone.Synth().toDestination();
|
||||||
@@ -20,8 +16,9 @@ export const audioTest = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// allows a chord to be generated with input from another function
|
// allows a chord to be generated with input from another function
|
||||||
export const soundChord = (pitches) => {
|
// pitchNames: array of strings
|
||||||
const [s,a,t,b] = pitches;
|
export const soundChord = (pitchNames) => {
|
||||||
|
const [s,a,t,b] = pitchNames;
|
||||||
soprano.triggerAttackRelease(s, "8n");
|
soprano.triggerAttackRelease(s, "8n");
|
||||||
alto.triggerAttackRelease(a, "8n");
|
alto.triggerAttackRelease(a, "8n");
|
||||||
tenor.triggerAttackRelease(t, "8n");
|
tenor.triggerAttackRelease(t, "8n");
|
||||||
@@ -54,13 +51,8 @@ export const fullRandomChord = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set up transport
|
// set up transport
|
||||||
let clock = 0;
|
|
||||||
let slowClock = 0;
|
|
||||||
|
|
||||||
const transportStart = document.getElementById('transport-start');
|
const transportStart = document.getElementById('transport-start');
|
||||||
|
|
||||||
let transport;
|
|
||||||
|
|
||||||
const loop = new Tone.Loop((time) => {
|
const loop = new Tone.Loop((time) => {
|
||||||
audioTest();
|
audioTest();
|
||||||
}, "8n").start(0);
|
}, "8n").start(0);
|
||||||
@@ -70,4 +62,3 @@ loop.probability = 0.8;
|
|||||||
transportStart.onclick = () => {
|
transportStart.onclick = () => {
|
||||||
Tone.Transport.start();
|
Tone.Transport.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
14
index.html
14
index.html
@@ -118,9 +118,15 @@
|
|||||||
<!-- Tone.js library -->
|
<!-- Tone.js library -->
|
||||||
<script type="module" src="https://unpkg.com/tone@14.7.77/build/Tone.js"></script>
|
<script type="module" src="https://unpkg.com/tone@14.7.77/build/Tone.js"></script>
|
||||||
<!-- internal scripts -->
|
<!-- internal scripts -->
|
||||||
<script type="module" src="./js/inputHandling.js"></script>
|
<script type="module" src="./src/styleUtils.js"></script>
|
||||||
<script type="module" src="./js/toneGeneration.js"></script>
|
<script type="module" src="./src/inputHandling.js"></script>
|
||||||
<script type="module" src="./js/styleUtils.js"></script>
|
<script type="module" src="./src/harmonyUtil.js"></script>
|
||||||
<script type="module" src="app.js"></script>
|
<script type="module" src="./src/audioUtil.js"></script>
|
||||||
|
<script type="module" src="./app.js"></script>
|
||||||
|
<!-- vector logic scripts -->
|
||||||
|
<script type="module" src="./src/vector_logic/evaluateVector.js"></script>
|
||||||
|
<script type="module" src="./src/vector_logic/extractPitchset.js"></script>
|
||||||
|
<script type="module" src="./src/vector_logic/findVector.js"></script>
|
||||||
|
<script type="module" src="./src/vector_logic/numbersToPitches.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -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);
|
|
||||||
@@ -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
|
|
||||||
10
src/audioUtil.js
Normal file
10
src/audioUtil.js
Normal file
@@ -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);
|
||||||
|
}
|
||||||
46
src/harmonyUtil.js
Normal file
46
src/harmonyUtil.js
Normal file
@@ -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;
|
||||||
|
}
|
||||||
0
src/vector_logic/evaluateVector.js
Normal file
0
src/vector_logic/evaluateVector.js
Normal file
22
src/vector_logic/extractPitchset.js
Normal file
22
src/vector_logic/extractPitchset.js
Normal file
@@ -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;
|
||||||
|
}
|
||||||
26
src/vector_logic/findVector.js
Normal file
26
src/vector_logic/findVector.js
Normal file
@@ -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;
|
||||||
|
}
|
||||||
0
src/vector_logic/numbersToPitches.js
Normal file
0
src/vector_logic/numbersToPitches.js
Normal file
Reference in New Issue
Block a user