Skip to content

Commit

Permalink
Optimize CS check of octave-repeating JI GS
Browse files Browse the repository at this point in the history
Temper to 5407372813edo to produce potential counter-examples for JI GS CS.
Update xen-dev-utils and sonic-weave dependencies.
  • Loading branch information
frostburn committed Apr 7, 2024
1 parent 0ed9bd6 commit 87571c4
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 20 deletions.
16 changes: 8 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@
"moment-of-symmetry": "^0.4.2",
"pinia": "^2.1.7",
"qs": "^6.12.0",
"sonic-weave": "github:xenharmonic-devs/sonic-weave#v0.0.9",
"sonic-weave": "github:xenharmonic-devs/sonic-weave#v0.0.10",
"sw-synth": "^0.1.0",
"temperaments": "^0.5.3",
"vue": "^3.3.4",
"vue-router": "^4.3.0",
"webmidi": "^3.1.8",
"xen-dev-utils": "^0.2.8",
"xen-dev-utils": "^0.2.9",
"xen-midi": "^0.1.3"
},
"devDependencies": {
Expand Down
8 changes: 7 additions & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Interval, TimeMonzo } from 'sonic-weave'
import { version } from '../package.json'
import { Fraction } from 'xen-dev-utils'
import { Fraction, PRIME_CENTS } from 'xen-dev-utils'

// GLOBALS
export const APP_TITLE = `Scale Workshop ${version}`
Expand Down Expand Up @@ -71,3 +71,9 @@ export const INTERVALS_12TET = [...Array(12).keys()].map(
'logarithmic'
)
)

export const CS_EDO = 5407372813
export const CS_VAL = new TimeMonzo(new Fraction(0), [])
for (let i = 0; i < DEFAULT_NUMBER_OF_COMPONENTS; ++i) {
CS_VAL.primeExponents.push(new Fraction(Math.round((PRIME_CENTS[i] / 1200.0) * CS_EDO)))
}
62 changes: 53 additions & 9 deletions src/stores/modal.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { computed, reactive, ref, watch } from 'vue'
import { defineStore } from 'pinia'
import { FIFTH, FIFTH_12TET, OCTAVE } from '@/constants'
import { CS_EDO, CS_VAL, FIFTH, FIFTH_12TET, OCTAVE } from '@/constants'
import { computedAndError, splitText } from '@/utils'
import { Fraction, clamp, gcd, mmod } from 'xen-dev-utils'
import { Fraction, clamp, falsifyConstantStructure, gcd, mmod } from 'xen-dev-utils'
import {
anyForEdo,
makeEdoMap,
Expand All @@ -14,6 +14,12 @@ import {
import { TimeMonzo, evaluateExpression, hasConstantStructure, parseChord } from 'sonic-weave'
import { freeVAOs, vao } from '@/analysis'

function scaleGet(monzos: TimeMonzo[], index: number) {
const equave = monzos[monzos.length - 1]
const numEquaves = Math.floor(index / monzos.length)
return monzos[mmod(index, monzos.length)].mul(equave.pow(numEquaves))
}

export const useModalStore = defineStore('modal', () => {
// Generic
const equaveString = ref('2/1')
Expand Down Expand Up @@ -148,24 +154,62 @@ export const useModalStore = defineStore('modal', () => {
if (!monzos.length) {
return
}
let usePrecheck = p.equals(OCTAVE.value)
for (const monzo of monzos) {
if (monzo.timeExponent.n) {
return
}
if (!monzo.isFractional()) {
usePrecheck = false
}
}
const scale: TimeMonzo[] = [p]
let accumulator = new TimeMonzo(new Fraction(0), [])
for (let j = 0; j < maxSizeComputed.value; ++j) {
accumulator = accumulator.mul(monzos[mmod(j, monzos.length)])
scale.push(accumulator.reduce(p, true))
}
for (let i = maxSizeComputed.value; i < maxSize; ++i) {
accumulator = accumulator.mul(monzos[mmod(i, monzos.length)])
scale.push(accumulator.reduce(p, true))
scale.sort((a, b) => a.compare(b))
if (hasConstantStructure(scale)) {
// These sizes are for the full scale.
constantStructureSizes.push(scale.length * numPeriods.value)
// A JI scale has CS if a tempered version has it. (but not vice versa)
if (usePrecheck) {
const gens = monzos.map((m) => m.dot(CS_VAL).valueOf())
const steps: number[] = [CS_EDO]
let stepAccumulator = 0
for (let j = 0; j < maxSizeComputed.value; ++j) {
stepAccumulator += gens[mmod(j, gens.length)]
steps.push(mmod(stepAccumulator, CS_EDO) || CS_EDO)
}
for (let i = maxSizeComputed.value; i < maxSize; ++i) {
accumulator = accumulator.mul(monzos[mmod(i, monzos.length)])
scale.push(accumulator.reduce(p, true))
stepAccumulator += gens[mmod(i, gens.length)]
steps.push(mmod(stepAccumulator, CS_EDO) || CS_EDO)
steps.sort((a, b) => a - b)
const indices = falsifyConstantStructure(steps)
if (indices) {
scale.sort((a, b) => a.compare(b))
const [[i1, i2], [j1, j2]] = indices
// Check the given counter-example. Do the full check if it wasn't valid in JI.
if (
!scaleGet(scale, i2)
.div(scaleGet(scale, i1))
.equals(scaleGet(scale, j2).div(scaleGet(scale, j1))) &&
hasConstantStructure(scale)
) {
constantStructureSizes.push(scale.length * numPeriods.value)
}
} else {
constantStructureSizes.push(scale.length * numPeriods.value)
}
}
} else {
for (let i = maxSizeComputed.value; i < maxSize; ++i) {
accumulator = accumulator.mul(monzos[mmod(i, monzos.length)])
scale.push(accumulator.reduce(p, true))
scale.sort((a, b) => a.compare(b))
if (hasConstantStructure(scale)) {
// These sizes are for the full scale.
constantStructureSizes.push(scale.length * numPeriods.value)
}
}
}
maxSizeComputed.value = maxSize
Expand Down

0 comments on commit 87571c4

Please sign in to comment.