From e91e5df34946b1b701cf2ec48d087ea682ea6275 Mon Sep 17 00:00:00 2001 From: Lumi Pakkanen Date: Mon, 29 Jul 2024 11:13:54 +0300 Subject: [PATCH] Apply CS margin to variety signature on Analysis tab. Approximate Tenney-tall fractions on Analysis tab. ref #796 --- CHANGELOG.md | 2 ++ src/analysis.ts | 22 ++++++++++++++++++++++ src/views/AnalysisView.vue | 36 +++++++++++++++++++++++++----------- 3 files changed, 49 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae759d25..ddc49047 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Change log ## 3.0.1 + * Feature: Apply CS margin to variety signature on Analysis tab [#796](https://github.com/xenharmonic-devs/scale-workshop/issues/796) + * Feature: Approximate Tenney-tall fractions on Analysis tab [#796](https://github.com/xenharmonic-devs/scale-workshop/issues/796) * Regression: Show pitch associated with MIDI base index [#795](https://github.com/xenharmonic-devs/scale-workshop/issues/795) ## 3.0.0 diff --git a/src/analysis.ts b/src/analysis.ts index 09f84748..6a8f7f25 100644 --- a/src/analysis.ts +++ b/src/analysis.ts @@ -475,6 +475,28 @@ export function varietySignature(matrix: Interval[][]) { return result } +export function marginVarietySignature(centsMatrix: number[][], margin: number) { + const result: number[] = [] + if (!centsMatrix.length) { + return result + } + for (let i = 0; i < centsMatrix[0].length; ++i) { + let variety = 1 + for (let j = 1; j < centsMatrix.length; ++j) { + variety++ + const cents = centsMatrix[j][i] + for (let k = 0; k < j; ++k) { + if (Math.abs(centsMatrix[k][i] - cents) < margin) { + variety-- + break + } + } + } + result.push(variety) + } + return result +} + export function brightnessSignature(centsMatrix: number[][]) { const totals = centsMatrix.map((row) => row.reduce((prev, cur) => prev + cur, 0)) const minimum = Math.min(...totals) diff --git a/src/views/AnalysisView.vue b/src/views/AnalysisView.vue index c1508a47..f1fb82f7 100644 --- a/src/views/AnalysisView.vue +++ b/src/views/AnalysisView.vue @@ -4,6 +4,7 @@ import { constantStructureViolations, freeEquallyTemperedChord, intervalMatrix, + marginVarietySignature, marginViolations, rootedEquallyTemperedChord, varietySignature @@ -31,6 +32,7 @@ const entropy = useHarmonicEntropyStore() const subtab = ref<'matrix' | 'wheels' | 'entropy'>('matrix') const cellFormat = ref<'best' | 'fraction' | 'cents' | 'et' | 'decimal'>('best') const simplifyTolerance = ref(3.5) +const fractionMaxHeight = ref(26) const showOptions = ref(false) const trailLongevity = ref(70) const maxOtonalRoot = ref(16) @@ -86,31 +88,34 @@ const etDenominator = computed(() => { // While interval.name suffices for the tuning table // we want more accurate results here. function formatMatrixCell(interval: Interval) { + const monzo = interval.value if (cellFormat.value === 'fraction') { - if (interval.value.isFractional()) { - const node = interval.value.asFractionLiteral() + if ( + monzo.isFractional() && + (!fractionMaxHeight.value || monzo.tenneyHeight() < fractionMaxHeight.value) + ) { + const node = monzo.asFractionLiteral() if (node) { return literalToString(node) } } try { return ( - '~' + - new Fraction(interval.valueOf()).simplifyRelative(simplifyTolerance.value).toFraction() + '~' + new Fraction(monzo.valueOf()).simplifyRelative(simplifyTolerance.value).toFraction() ) } catch { return '?' } } if (cellFormat.value === 'cents') { - return interval.totalCents(true).toFixed(1) + return monzo.totalCents(true).toFixed(1) } if (cellFormat.value === 'decimal') { // Consistent with tuning table localization. - return interval.valueOf().toFixed(3) + return monzo.valueOf().toFixed(3) } if (cellFormat.value === 'et') { - const fractionOfEquave = interval.value.log(scaleEquave.value) + const fractionOfEquave = monzo.log(scaleEquave.value) if (typeof fractionOfEquave === 'number') { return `~${Math.round(fractionOfEquave * 100)}%` } @@ -139,12 +144,17 @@ const violations = computed(() => { const margin = state.constantStructureMargin if (margin) { return marginViolations(centsMatrix.value, margin) - } else { - return constantStructureViolations(matrix.value) } + return constantStructureViolations(matrix.value) }) -const variety = computed(() => varietySignature(matrix.value)) +const variety = computed(() => { + const margin = state.constantStructureMargin + if (margin) { + return marginVarietySignature(centsMatrix.value, margin) + } + return varietySignature(matrix.value) +}) const brightness = computed(() => brightnessSignature(centsMatrix.value).map((b) => Math.round(100 * b)) @@ -408,6 +418,10 @@ const sSlider = computed({ v-model="simplifyTolerance" /> +
+ + +
Show constant structure violations
- +