From 048fe69bc5557aea0e136163023b5c73e3aac2db Mon Sep 17 00:00:00 2001 From: Lumi Pakkanen Date: Sat, 18 May 2024 14:38:29 +0300 Subject: [PATCH] Compute virtual keyboard frequencies and cents Fixes issues when accessing outside the pre-computed range. ref #696 --- src/components/VirtualKeyboard.vue | 13 +++++-------- src/scale.ts | 20 +++++++++++++++++++- src/views/VirtualKeyboardView.vue | 5 +---- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/components/VirtualKeyboard.vue b/src/components/VirtualKeyboard.vue index c00295f9..e9184a4c 100644 --- a/src/components/VirtualKeyboard.vue +++ b/src/components/VirtualKeyboard.vue @@ -2,6 +2,7 @@ import { computed, ref } from 'vue' import VirtualKeyboardKey from '@/components/VirtualKeyboardKey.vue' import VirtualKeyInfo from '@/components/VirtualKeyInfo.vue' +import type { Scale } from '@/scale' type NoteOff = () => void type NoteOnCallback = (index: number) => NoteOff @@ -10,14 +11,11 @@ type LabelMap = (index: number) => string const props = defineProps<{ baseIndex: number // Should incorporate equave shift - baseMidiNote: number isomorphicHorizontal: number isomorphicVertical: number noteOn: NoteOnCallback heldNotes: Map - baseFrequency: number - frequencies: number[] - centss: number[] + scale: Scale colorMap: ColorMap labelMap: LabelMap showLabel: boolean @@ -41,15 +39,14 @@ const virtualKeys = computed(() => { const horizontal = props.isomorphicHorizontal const vertical = props.isomorphicVertical const result: [number, VirtualKey[]][] = [] - const inverseBaseFreq = 1 / props.baseFrequency for (let y = 3; y >= -1; y--) { const row = [] for (let x = 0; x <= 12; ++x) { const index = props.baseIndex + x * horizontal + y * vertical const color = props.colorMap(index) - const frequency = props.frequencies[index] - const cents = props.centss[index] - const ratio = frequency * inverseBaseFreq + const ratio = props.scale.getRatio(index) + const frequency = props.scale.baseFrequency * ratio + const cents = props.scale.getCents(index) const label = props.labelMap(index) row.push({ x, diff --git a/src/scale.ts b/src/scale.ts index 6aab29ec..3f1ec782 100644 --- a/src/scale.ts +++ b/src/scale.ts @@ -39,7 +39,7 @@ export class Scale { } /** - * Obtain the ratio agains the base MIDI note. + * Obtain the ratio against the base MIDI note. * @param index MIDI index of a note. * @returns Ratio associated with the MIDI index. */ @@ -63,6 +63,24 @@ export class Scale { return this.baseFrequency * this.getRatio(index) } + /** + * Obtain the cents offset from the base MIDI note. + * @param index MIDI index of a note. + * @returns Cents associated with the MIDI index. + */ + getCents(index: number) { + // Deal with implicit 0c + index -= 1 + // Center on base MIDI note + index -= this.baseMidiNote + + const baseIndex = mmod(index, this.size) + const numEquaves = (index - baseIndex) / this.size + return ( + valueToCents(this.intervalRatios[baseIndex]) + valueToCents(this.equaveRatio) * numEquaves + ) + } + /** * Obtain a range of frequencies in the scale. * More efficient to compute than getting individual frequencies. diff --git a/src/views/VirtualKeyboardView.vue b/src/views/VirtualKeyboardView.vue index 32c99e98..3c2098fa 100644 --- a/src/views/VirtualKeyboardView.vue +++ b/src/views/VirtualKeyboardView.vue @@ -38,15 +38,12 @@ type NoteOnCallback = (index: number) => NoteOff