Skip to content

Commit

Permalink
Display hardness and chroma alongside the MOS pattern in Rank 2
Browse files Browse the repository at this point in the history
Update info section of the Rank 2 generation modal.

ref #379
  • Loading branch information
frostburn committed Jan 7, 2025
1 parent e88439b commit 45eb0db
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 1 deletion.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Change log

## 3.2.0 (unreleased)
* Feature: Display hardness and chroma alongside the MOS pattern in Rank 2 modal [#379](https://github.com/xenharmonic-devs/scale-workshop/issues/379)

## 3.1.0
* Feature: Implement the missing size inequality operator `~<>` (i.e. the negation of `~=`)
* Feature: Accept lone vals for `commaBasis` and `mappingBasis`
Expand Down
43 changes: 42 additions & 1 deletion src/components/modals/generation/RankTwo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import { useRank2Store } from '@/stores/tempering'
import { Interval, intervalValueAs } from 'sonic-weave'
import { useScaleStore } from '@/stores/scale'
import { mmod } from 'xen-dev-utils'
import type { MosInfo } from 'moment-of-symmetry'
const EPSILON = 1e-12
const scale = useScaleStore()
const rank2 = useRank2Store()
Expand Down Expand Up @@ -78,6 +81,44 @@ function updateCircleGenerator(value: number) {
rank2.generatorFineCents = '0'
}
function chromaAndHardness(size: number) {
const g = rank2.generatorPerPeriod
const scalePerPeriod = [...Array(size).keys()].map((i) => mmod(i * g, 1))
scalePerPeriod.sort((a, b) => a - b)
scalePerPeriod.push(1)
let L = scalePerPeriod[1]
let s = scalePerPeriod[1]
for (let i = 0; i < size; ++i) {
const other = scalePerPeriod[i + 1] - scalePerPeriod[i]
// Epsilon works around floating point noise
if (other + EPSILON < s) {
s = other
break
} else if (other - EPSILON > L) {
L = other
break
}
}
const p = rank2.period.totalCents()
if (!p) {
return {
chroma: 0,
hardness: L / s
}
}
L *= p
s *= p
return {
chroma: L - s,
hardness: L / s
}
}
function setPreview(mosInfo: MosInfo) {
const { chroma, hardness } = chromaAndHardness(mosInfo.size)
rank2.previewMosPattern = `${mosInfo.mosPattern}, L/s: ${hardness.toFixed(2)}, L-s: ${chroma.toFixed(1)}¢`
}
function generate(expand = true) {
if (rank2.method === 'circle') {
consolidateCircle()
Expand Down Expand Up @@ -376,7 +417,7 @@ function generate(expand = true) {
<button
v-for="(mosInfo, i) of rank2.mosPatterns"
:key="i"
@mouseenter="rank2.previewMosPattern = mosInfo.mosPattern"
@mouseenter="setPreview(mosInfo)"
@mouseleave="rank2.previewMosPattern = ''"
@click="selectMosSize(mosInfo.size)"
>
Expand Down

0 comments on commit 45eb0db

Please sign in to comment.