Skip to content

Commit

Permalink
tests
Browse files Browse the repository at this point in the history
  • Loading branch information
beggers committed Mar 8, 2024
1 parent b871dcf commit 06d1532
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 23 deletions.
6 changes: 3 additions & 3 deletions src/audio.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { Chord, Interval, Note, Scale } from "tonal";

// TODO find a better way to do this. Probably need a button to be clicked
// on load?
addEventListener('mousemove', () => {
Tone.start()
})
// addEventListener('mousemove', () => {
// Tone.start()
// })

export default class AmbientAudio {
constructor() {
Expand Down
7 changes: 7 additions & 0 deletions src/audio.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use strict'

import * as a from './audio.js'

test('filler test', () => {
expect(true).toBe(true)
})
23 changes: 15 additions & 8 deletions src/chordexplorer.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as Chord from "tonal";
import { Chord } from "tonal";

const defaultInversions = [
[1, 2, 3, 4],
Expand All @@ -9,9 +9,11 @@ const defaultInversions = [
const defaultNotes = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
const defaultChords = ["m", "M"]
const defaultOctaves = [2, 3, 4]
let defaultDistance = 2

// Simple metric space on chords.Counts notes which belong to
// one chord but not the other.Octave - sensitive.
// TODO this should be levenstein distance.
const chordDistance = (a, b) => {
let aSet = new Set(a)
let bSet = new Set(b)
Expand Down Expand Up @@ -40,36 +42,41 @@ class ChordExplorer {

// TODO this could be a much more clever data structure.
// But linear scanning is probably fine.
let allChords = []
this.allChords = []
for (let i = 0; i < roots.length; i++) {
for (let j = 0; j < chords.length; j++) {
for (let k = 0; k < octaves.length; k++) {
let degrees = Chord.degrees(chords[j], roots[i] + octaves[k])
let degrees = Chord.steps(chords[j], roots[i] + octaves[k])
for (let l = 0; l < inversions.length; l++) {
let inversion = inversions[l]
allChords.push(inversion.map(degrees))
this.allChords.push(inversion.map(degrees))
}
}
}
}
}

nextChord(chord) {
possibleNextChords(chord) {
let possibles = []
for (let i = 0; i < this.allChords.length; i++) {
if (this.distance(chord, this.allChords[i]) < this.distance) {
if (chordDistance(chord, this.allChords[i]) === this.distance) {
possibles.push(this.allChords[i])
}
}
return possibles
}

nextChord(chord) {
let possibles = this.possibleNextChords(chord)
return possibles[Math.floor(Math.random() * possibles.length)]
}
}

class DefaultChordExplorer extends ChordExplorer {
constructor() {
super(defaultInversions, defaultNotes, defaultChords, defaultOctaves, chordDistance)
super(defaultInversions, defaultNotes, defaultChords, defaultOctaves, defaultDistance)
}
}

export { chordDistance, ChordExplorer, DefaultChordExplorer }
export { chordDistance, ChordExplorer, DefaultChordExplorer, defaultDistance }
export default ChordExplorer
100 changes: 97 additions & 3 deletions src/chordexplorer.test.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,116 @@
'use strict'
import { chordDistance } from './chordexplorer.js';
import { chordDistance, ChordExplorer, DefaultChordExplorer, defaultDistance } from './chordexplorer.js';

// TODO figure out why proptests were so slow and maybe bring them back.

test('distance between a chord and itself should be zero', () => {
let chord = ["C4", "E4", "G4"]
expect(chordDistance(chord, chord)).toBe(0)
})

test('distance between a chord and itself with different order should be zero', () => {
test('chordDistance between a chord and itself with different order should be zero', () => {
let chord = ["C4", "E4", "G4"]
let transposition = ["E4", "G4", "C4"]
expect(chordDistance(chord, transposition)).toBe(0)
expect(chordDistance(transposition, chord)).toBe(0)
})

test('distance between chords should be one if they have one note different', () => {
test('chordDistance between chords should be one if they have one note different', () => {
let chord = ["C4", "E4"]
let other = ["C4", "E4", "A4"]
expect(chordDistance(chord, other)).toBe(1)
expect(chordDistance(other, chord)).toBe(1)
})

test('ChordExplorer generates chords correctly', () => {
let chord = ["C4", "E4", "G4"]
let e = new ChordExplorer(
[[0, 1, 2]],
["C"],
["M"],
[4],
0,
)
expect(e.allChords).toEqual([chord])
})

test('ChordExplorer generates possible chords correctly', () => {
let chord = ["C4", "E4", "G4"]
let invertedChords = [
["C4", "E4", "G4"],
["E4", "G4", "C5"],
["G4", "C5", "E5"]
]
let inversions = [
[0, 1, 2],
[1, 2, 3],
[2, 3, 4]
]
let e = new ChordExplorer(
inversions,
["C"],
["M"],
[4],
2,
)
let possibles = e.possibleNextChords(chord)
expect(possibles).toEqual([invertedChords[1]])
})

test('ChordExplorer never generates the same chord', () => {
let chord = ["C4", "E4", "G4"]
let e = new ChordExplorer(
[[0, 1, 2]],
["C"],
["M"],
[4],
1,
)
let next = e.nextChord(chord)
expect(next).toBeUndefined()
})

test('ChordExplorer generates inversions of C major', () => {
let chord = ["C4", "E4", "G4"]
let invertedChords = [
["C4", "E4", "G4"],
["E4", "G4", "C5"],
["G4", "C5", "E5"]
]
let inversions = [
[0, 1, 2],
[1, 2, 3],
[2, 3, 4]
]
let e = new ChordExplorer(
inversions,
["C"],
["M"],
[4],
2,
)
for (let i = 0; i < 100; i++) {
let next = e.nextChord(chord)
expect(next).toBeDefined()
let found = false
for (let j = 0; j < invertedChords.length; j++) {
if (chordDistance(next, invertedChords[j]) === 0) {
found = true
break
}
}
expect(found).toBe(true)
}
})

test('DefaultChordExplorer always generates chords defaultDistance away', () => {
let e = new DefaultChordExplorer()
let chord = e.allChords[0]
for (let i = 0; i < 1000; i++) {
let next = e.nextChord(chord)
expect(next).toBeDefined()
expect(next).not.toEqual(chord)
expect(chordDistance(chord, next)).toBe(defaultDistance)
chord = next
}
})
2 changes: 0 additions & 2 deletions src/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import { TrackballControls } from 'three/addons/controls/TrackballControls.js';
import { FontLoader } from 'three/examples/jsm/loaders/FontLoader.js'
import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry.js'

import ChordExplorer from './chordexplorer'

//import AmbientAudio from './audio'
//let a = new AmbientAudio()
// a.play()
Expand Down
11 changes: 4 additions & 7 deletions src/style.css
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
*
{
* {
margin: 0;
padding: 0;
}

html,
body
{
body {
overflow: hidden;
}

.webgl
{
.webgl {
position: fixed;
top: 0;
left: 0;
outline: none;
}
}

0 comments on commit 06d1532

Please sign in to comment.