diff --git a/package-lock.json b/package-lock.json index 1caef265..a1ec8b22 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "scale-workshop", - "version": "3.0.0-beta.28", + "version": "3.0.0-beta.29", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "scale-workshop", - "version": "3.0.0-beta.28", + "version": "3.0.0-beta.29", "dependencies": { "isomorphic-qwerty": "^0.0.2", "ji-lattice": "^0.0.3", diff --git a/package.json b/package.json index 76267354..a0920983 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "scale-workshop", - "version": "3.0.0-beta.28", + "version": "3.0.0-beta.29", "scripts": { "dev": "vite", "build": "run-p type-check \"build-only {@}\" --", diff --git a/src/constants.ts b/src/constants.ts index c5ad088e..9ede2306 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -64,6 +64,10 @@ export const FIFTH_12TET = new Interval( TimeMonzo.fromEqualTemperament('7/12', 2, DEFAULT_NUMBER_OF_COMPONENTS), 'logarithmic' ) +export const UNISON = new Interval( + TimeMonzo.fromFraction(1, DEFAULT_NUMBER_OF_COMPONENTS), + 'linear' +) export const INTERVALS_12TET = [...Array(12).keys()].map( (i) => diff --git a/src/views/AnalysisView.vue b/src/views/AnalysisView.vue index 8fe562e7..43e2b097 100644 --- a/src/views/AnalysisView.vue +++ b/src/views/AnalysisView.vue @@ -13,16 +13,17 @@ import ScaleLineInput from '@/components/ScaleLineInput.vue' import { computed, reactive, ref } from 'vue' import { useAudioStore } from '@/stores/audio' import { useStateStore } from '@/stores/state' -import type { Interval } from 'sonic-weave' +import { literalToString, type Interval } from 'sonic-weave' import { useScaleStore } from '@/stores/scale' -import { mmod } from 'xen-dev-utils' -import { OCTAVE } from '@/constants' +import { Fraction, mmod } from 'xen-dev-utils' +import { OCTAVE, UNISON } from '@/constants' const audio = useAudioStore() const state = useStateStore() const scale = useScaleStore() -const cellFormat = ref<'best' | 'cents' | 'decimal'>('best') +const cellFormat = ref<'best' | 'fraction' | 'cents' | 'decimal'>('best') +const simplifyTolerance = ref(3.5) const showOptions = ref(false) const trailLongevity = ref(70) const maxOtonalRoot = ref(16) @@ -67,6 +68,22 @@ const strokeStyle = computed(() => { // While interval.name suffices for the tuning table // we want more accurate results here. function formatMatrixCell(interval: Interval) { + if (cellFormat.value === 'fraction') { + if (interval.value.isFractional()) { + const node = interval.value.asFractionLiteral() + if (node) { + return literalToString(node) + } + } + try { + return ( + '~' + + new Fraction(interval.valueOf()).simplifyRelative(simplifyTolerance.value).toFraction() + ) + } catch { + return '?' + } + } if (cellFormat.value === 'cents') { return interval.totalCents(true).toFixed(1) } @@ -203,7 +220,12 @@ function highlight(y?: number, x?: number) {