Skip to content

Commit bf30218

Browse files
authored
feat(pc-keyboard): Octave shift on z/x press & layout independent key handling (#417)
1 parent 9adc786 commit bf30218

3 files changed

Lines changed: 81 additions & 26 deletions

File tree

neothesia-core/src/config/mod.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ mod model;
55
pub use model::ColorSchemaV1;
66
use model::{
77
AppearanceConfig, AppearanceConfigV1, DevicesConfig, DevicesConfigV1, History, HistoryV1,
8-
LayoutConfig, LayoutConfigV1, Model, PlaybackConfig, PlaybackConfigV1, SynthConfig,
9-
SynthConfigV1, WaterfallConfig, WaterfallConfigV1,
8+
LayoutConfig, LayoutConfigV1, Model, PcKeyboardConfig, PcKeyboardConfigV1, PlaybackConfig,
9+
PlaybackConfigV1, SynthConfig, SynthConfigV1, WaterfallConfig, WaterfallConfigV1,
1010
};
1111

1212
fn ron_options() -> ron::Options {
@@ -44,6 +44,7 @@ impl Model {
4444
synth,
4545
keyboard_layout,
4646
appearance,
47+
pc_keyboard,
4748
} = config;
4849

4950
Self {
@@ -54,6 +55,7 @@ impl Model {
5455
keyboard_layout: LayoutConfig::V1(keyboard_layout),
5556
devices: DevicesConfig::V1(devices),
5657
appearance: AppearanceConfig::V1(appearance),
58+
pc_keyboard: PcKeyboardConfig::V1(pc_keyboard),
5759
}
5860
}
5961

@@ -80,6 +82,9 @@ impl Model {
8082
keyboard_layout: match self.keyboard_layout {
8183
LayoutConfig::V1(v) => v,
8284
},
85+
pc_keyboard: match self.pc_keyboard {
86+
PcKeyboardConfig::V1(v) => v,
87+
},
8388
}
8489
}
8590
}
@@ -93,6 +98,7 @@ pub struct Config {
9398
synth: SynthConfigV1,
9499
history: HistoryV1,
95100
keyboard_layout: LayoutConfigV1,
101+
pc_keyboard: PcKeyboardConfigV1,
96102
}
97103

98104
impl Default for Config {
@@ -255,6 +261,21 @@ impl Config {
255261
self.playback.speed_multiplier = speed_multiplier.max(0.0);
256262
}
257263

264+
pub fn pc_keyboard_octave(&self) -> u8 {
265+
self.pc_keyboard.octave_shift.min(10)
266+
}
267+
268+
pub fn pc_keyboard_shift_octave_up(&mut self) {
269+
self.pc_keyboard.octave_shift += 1;
270+
}
271+
272+
pub fn pc_keyboard_shift_octave_down(&mut self) {
273+
if self.pc_keyboard.octave_shift == 0 {
274+
return;
275+
}
276+
self.pc_keyboard.octave_shift -= 1;
277+
}
278+
258279
pub fn save(&self) {
259280
let res = ron_options().to_string_pretty(
260281
&Model::from_config(self.clone()),

neothesia-core/src/config/model.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ pub struct Model {
1919
pub devices: DevicesConfig,
2020
#[serde(default)]
2121
pub appearance: AppearanceConfig,
22+
#[serde(default)]
23+
pub pc_keyboard: PcKeyboardConfig,
2224
}
2325

2426
#[derive(Serialize, Deserialize, Clone)]
@@ -195,6 +197,25 @@ impl Default for AppearanceConfig {
195197
}
196198
}
197199

200+
#[derive(Serialize, Deserialize, Clone)]
201+
pub struct PcKeyboardConfigV1 {
202+
#[serde(default = "default_octave_shift")]
203+
pub octave_shift: u8,
204+
}
205+
206+
#[derive(Serialize, Deserialize)]
207+
pub enum PcKeyboardConfig {
208+
V1(PcKeyboardConfigV1),
209+
}
210+
211+
impl Default for PcKeyboardConfig {
212+
fn default() -> Self {
213+
Self::V1(PcKeyboardConfigV1 {
214+
octave_shift: default_octave_shift(),
215+
})
216+
}
217+
}
218+
198219
fn default_piano_range() -> (u8, u8) {
199220
(21, 108)
200221
}
@@ -267,3 +288,7 @@ fn default_color_schema() -> Vec<ColorSchemaV1> {
267288
fn default_output() -> Option<String> {
268289
Some("Buildin Synth".into())
269290
}
291+
292+
fn default_octave_shift() -> u8 {
293+
5
294+
}

neothesia/src/scene/mod.rs

Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use std::{collections::HashMap, time::Duration};
1111
use winit::{
1212
dpi::{LogicalPosition, LogicalSize},
1313
event::{ElementState, KeyEvent, WindowEvent},
14-
keyboard::Key,
14+
keyboard::{KeyCode, PhysicalKey},
1515
};
1616

1717
pub trait Scene {
@@ -26,7 +26,7 @@ pub fn handle_pc_keyboard_to_midi_event(ctx: &mut Context, event: &WindowEvent)
2626
event:
2727
KeyEvent {
2828
state,
29-
logical_key: Key::Character(ch),
29+
physical_key: PhysicalKey::Code(key_code),
3030
repeat: false,
3131
..
3232
},
@@ -36,31 +36,40 @@ pub fn handle_pc_keyboard_to_midi_event(ctx: &mut Context, event: &WindowEvent)
3636
return;
3737
};
3838

39-
let mut note: u8 = match ch.as_str() {
40-
"a" => 0,
41-
"w" => 1,
42-
"s" => 2,
43-
"e" => 3,
44-
"d" => 4,
45-
"f" => 5,
46-
"t" => 6,
47-
"g" => 7,
48-
"y" => 8,
49-
"h" => 9,
50-
"u" => 10,
51-
"j" => 11,
52-
"k" => 12,
53-
"o" => 13,
54-
"l" => 14,
55-
"p" => 15,
56-
";" => 16,
57-
"'" => 17,
39+
if *state == ElementState::Pressed {
40+
match key_code {
41+
KeyCode::KeyZ => ctx.config.pc_keyboard_shift_octave_down(),
42+
KeyCode::KeyX => ctx.config.pc_keyboard_shift_octave_up(),
43+
_ => {}
44+
}
45+
}
46+
47+
let mut note = match key_code {
48+
KeyCode::KeyA => 0,
49+
KeyCode::KeyW => 1,
50+
KeyCode::KeyS => 2,
51+
KeyCode::KeyE => 3,
52+
KeyCode::KeyD => 4,
53+
KeyCode::KeyF => 5,
54+
KeyCode::KeyT => 6,
55+
KeyCode::KeyG => 7,
56+
KeyCode::KeyY => 8,
57+
KeyCode::KeyH => 9,
58+
KeyCode::KeyU => 10,
59+
KeyCode::KeyJ => 11,
60+
KeyCode::KeyK => 12,
61+
KeyCode::KeyO => 13,
62+
KeyCode::KeyL => 14,
63+
KeyCode::KeyP => 15,
64+
KeyCode::Semicolon => 16,
65+
KeyCode::Quote => 17,
5866
_ => return,
5967
};
6068

61-
note += 21; // Start of 88 keyboard
62-
note += 3; // Offset to C
63-
note += 12 * 3; // Move 3oct up
69+
note += 12 * ctx.config.pc_keyboard_octave();
70+
if note > 127 {
71+
return;
72+
}
6473

6574
let message = match state {
6675
ElementState::Pressed => MidiMessage::NoteOn {

0 commit comments

Comments
 (0)