Skip to content

Commit

Permalink
Compute virtual keyboard frequencies and cents
Browse files Browse the repository at this point in the history
Fixes issues when accessing outside the pre-computed range.

ref #696
  • Loading branch information
frostburn committed May 18, 2024
1 parent 8284f55 commit 048fe69
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 13 deletions.
13 changes: 5 additions & 8 deletions src/components/VirtualKeyboard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<number, number>
baseFrequency: number
frequencies: number[]
centss: number[]
scale: Scale
colorMap: ColorMap
labelMap: LabelMap
showLabel: boolean
Expand All @@ -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,
Expand Down
20 changes: 19 additions & 1 deletion src/scale.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand All @@ -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.
Expand Down
5 changes: 1 addition & 4 deletions src/views/VirtualKeyboardView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,12 @@ type NoteOnCallback = (index: number) => NoteOff
<VirtualKeyboard
v-else
:baseIndex="baseIndex"
:baseMidiNote="scale.scale.baseMidiNote"
:isomorphicHorizontal="state.isomorphicHorizontal"
:isomorphicVertical="state.isomorphicVertical"
:colorMap="scale.colorForIndex"
:noteOn="noteOn"
:heldNotes="state.heldNotes"
:baseFrequency="scale.scale.baseFrequency"
:frequencies="scale.frequencies"
:centss="scale.centss"
:scale="scale.scale"
:labelMap="scale.labelForIndex"
:showLabel="state.showKeyboardLabel"
:showCents="state.showKeyboardCents"
Expand Down

0 comments on commit 048fe69

Please sign in to comment.