@@ -64,7 +67,7 @@ const state = useStateStore()
type="radio"
id="accidentals-double"
value="double"
- v-model="state.accidentalPreference"
+ v-model="scale.accidentalPreference"
/>
@@ -73,7 +76,7 @@ const state = useStateStore()
type="radio"
id="accidentals-single"
value="single"
- v-model="state.accidentalPreference"
+ v-model="scale.accidentalPreference"
/>
@@ -82,7 +85,7 @@ const state = useStateStore()
type="radio"
id="accidentals-ascii"
value="ASCII"
- v-model="state.accidentalPreference"
+ v-model="scale.accidentalPreference"
/>
diff --git a/src/views/ScaleView.vue b/src/views/ScaleView.vue
index b967bc53..89ce7caf 100644
--- a/src/views/ScaleView.vue
+++ b/src/views/ScaleView.vue
@@ -1,9 +1,142 @@
-
+
+
+
diff --git a/src/views/SynthView.vue b/src/views/SynthView.vue
index 1b77591f..ae78c8f5 100644
--- a/src/views/SynthView.vue
+++ b/src/views/SynthView.vue
@@ -2,13 +2,15 @@
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
import TimeDomainVisualizer from '@/components/TimeDomainVisualizer.vue'
import Modal from '@/components/ModalDialog.vue'
-import { WAVEFORMS } from '@/synth'
+import { APERIODIC_WAVEFORMS, WAVEFORMS } from '@/synth'
import { useAudioStore } from '@/stores/audio'
import { useStateStore } from '@/stores/state'
+import { useScaleStore } from '@/stores/scale'
const emit = defineEmits(['panic'])
const state = useStateStore()
+const scale = useScaleStore()
const audio = useAudioStore()
@@ -92,6 +94,18 @@ const releaseTime = computed({
}
})
+const unisonSpread = computed({
+ get: () => audio.spread,
+ set(newValue: number) {
+ if (typeof newValue !== 'number') {
+ newValue = parseFloat(newValue)
+ }
+ if (!isNaN(newValue)) {
+ audio.spread = newValue
+ }
+ }
+})
+
const pingPongDelayTime = computed({
get: () => audio.pingPongDelayTime,
set(newValue: number) {
@@ -237,9 +251,56 @@ onUnmounted(() => {
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
-
+
+
-
-
+
+
-
-
+
+
-
+
Isomorphic key mapping
Distance between adjacent keys on the horizontal/vertical axes, in scale degrees.
@@ -430,6 +473,53 @@ onUnmounted(() => {
+
+ Accidental colors
+ These color(s) in your scale will be used to assemble the piano layout.
+
+
+
+ Keyboard equave shift
+
+
+ Trigger lower or higher notes. (Default shortcut keys: numpad
+ /
and *
)
+
+
+
+
+
+ Keyboard degree shift
+
+
+ Shift down/up by one scale degree. (Default shortcut keys: numpad
+ -
and +
).
+
+
+
+
+
Keyboard shortcuts
Shift
sustain currently held keys after release
diff --git a/src/views/VirtualKeyboardView.vue b/src/views/VirtualKeyboardView.vue
index c41271d2..e34ee474 100644
--- a/src/views/VirtualKeyboardView.vue
+++ b/src/views/VirtualKeyboardView.vue
@@ -2,12 +2,19 @@
import VirtualKeyboard from '@/components/VirtualKeyboard.vue'
import VirtualPiano from '@/components/VirtualPiano.vue'
import { useStateStore } from '@/stores/state'
+import { useScaleStore } from '@/stores/scale'
+import { computed } from 'vue'
defineProps<{
noteOn: NoteOnCallback
}>()
const state = useStateStore()
+const scale = useScaleStore()
+
+const baseIndex = computed(
+ () => scale.baseMidiNote + scale.equaveShift * scale.scale.size + scale.degreeShift
+)
type NoteOff = () => void
type NoteOnCallback = (index: number) => NoteOff
@@ -16,20 +23,25 @@ type NoteOnCallback = (index: number) => NoteOff
diff --git a/src/views/VirtualQwerty.vue b/src/views/VirtualQwerty.vue
index a8d6e524..6e0271bd 100644
--- a/src/views/VirtualQwerty.vue
+++ b/src/views/VirtualQwerty.vue
@@ -2,8 +2,11 @@
import VirtualTypingKeyboard from '@/components/VirtualTypingKeyboard.vue'
import type { Keyboard } from 'isomorphic-qwerty'
import { useStateStore } from '@/stores/state'
+import { useScaleStore } from '@/stores/scale'
+import { computed } from 'vue'
const state = useStateStore()
+const scale = useScaleStore()
type NoteOff = () => void
type NoteOnCallback = (index: number) => NoteOff
@@ -13,20 +16,22 @@ defineProps<{
typingKeyboard: Keyboard
}>()
-defineEmits(['update:equaveShift', 'update:degreeShift'])
+const baseIndex = computed(
+ () => scale.baseMidiNote + scale.equaveShift * scale.scale.size + scale.degreeShift
+)