diff --git a/front/components/VirtualPiano/Octave.tsx b/front/components/VirtualPiano/Octave.tsx
index bec5028..2c18796 100644
--- a/front/components/VirtualPiano/Octave.tsx
+++ b/front/components/VirtualPiano/Octave.tsx
@@ -3,7 +3,7 @@ import {
PianoKey,
NoteNameBehavior,
octaveKeys,
- Accidental,
+ isAccidental,
HighlightedKey,
} from "../../models/Piano";
import { Box, Row, Pressable, Text } from "native-base";
@@ -74,15 +74,15 @@ const Octave = (props: OctaveProps) => {
onNoteUp,
} = props;
const oK: PianoKey[] = octaveKeys.map((k) => {
- return new PianoKey(k.note, k.accidental, number);
+ return new PianoKey(k.note, number);
});
const startNoteIndex = getKeyIndex(startNote, oK);
const endNoteIndex = getKeyIndex(endNote, oK);
const keys = oK.slice(startNoteIndex, endNoteIndex + 1);
- const whiteKeys = keys.filter((k) => k?.accidental === undefined);
- const blackKeys = keys.filter((k) => k?.accidental !== undefined);
+ const whiteKeys = keys.filter((k) => !isAccidental(k));
+ const blackKeys = keys.filter(isAccidental);
const whiteKeyWidthExpr = "calc(100% / 7)";
const whiteKeyHeightExpr = "100%";
@@ -94,18 +94,17 @@ const Octave = (props: OctaveProps) => {
{whiteKeys.map((key, i) => {
const highlightedKey = highlightedNotes.find(
- (h) =>
- h.key.note === key.note && h.key.accidental === key.accidental
+ (h) => h.key.note === key.note
);
const isHighlighted = highlightedKey !== undefined;
const highlightColor =
highlightedKey?.bgColor ?? defaultHighlightColor;
return (
onNoteDown(key)}
@@ -114,14 +113,12 @@ const Octave = (props: OctaveProps) => {
width: whiteKeyWidthExpr,
height: whiteKeyHeightExpr,
}}
-
/>
);
})}
{blackKeys.map((key, i) => {
const highlightedKey = highlightedNotes.find(
- (h) =>
- h.key.note === key.note && h.key.accidental === key.accidental
+ (h) => h.key.note === key.note
);
const isHighlighted = highlightedKey !== undefined;
const highlightColor =
diff --git a/front/components/VirtualPiano/PianoKeyComp.tsx b/front/components/VirtualPiano/PianoKeyComp.tsx
index f1bd7f9..4b2d859 100644
--- a/front/components/VirtualPiano/PianoKeyComp.tsx
+++ b/front/components/VirtualPiano/PianoKeyComp.tsx
@@ -6,8 +6,6 @@ import {
PianoKey,
NoteNameBehavior,
octaveKeys,
- Accidental,
- HighlightedKey,
keyToStr,
} from "../../models/Piano";
diff --git a/front/components/VirtualPiano/VirtualPiano.tsx b/front/components/VirtualPiano/VirtualPiano.tsx
index 77c93af..4c5ae1b 100644
--- a/front/components/VirtualPiano/VirtualPiano.tsx
+++ b/front/components/VirtualPiano/VirtualPiano.tsx
@@ -1,7 +1,13 @@
import { Row, Box } from "native-base";
import React, { useState, useEffect } from "react";
import Octave from "./Octave";
-import { Note, PianoKey, NoteNameBehavior, KeyPressStyle, keyToStr } from "../../models/Piano";
+import {
+ Note,
+ PianoKey,
+ NoteNameBehavior,
+ KeyPressStyle,
+ keyToStr,
+} from "../../models/Piano";
type VirtualPianoProps = Parameters[0] & {
onNoteDown: (note: PianoKey) => void;
@@ -21,71 +27,74 @@ type VirtualPianoProps = Parameters[0] & {
};
const VirtualPiano = ({
- onNoteDown,
- onNoteUp,
- startOctave,
- startNote,
- endOctave,
- endNote,
- showNoteNames,
- highlightedNotes,
- highlightColor,
- specialHighlightedNotes,
- specialHighlightColor,
- showOctaveNumbers,
- keyPressStyle,
- vividKeyPressColor,
+ onNoteDown,
+ onNoteUp,
+ startOctave,
+ startNote,
+ endOctave,
+ endNote,
+ showNoteNames,
+ highlightedNotes,
+ highlightColor,
+ specialHighlightedNotes,
+ specialHighlightColor,
+ showOctaveNumbers,
+ keyPressStyle,
+ vividKeyPressColor,
}: VirtualPianoProps) => {
- const notesList: Array = [
- Note.C,
- Note.D,
- Note.E,
- Note.F,
- Note.G,
- Note.A,
- Note.B,
- ];
- const octaveList = [];
+ const notesList: Array = [
+ Note.C,
+ Note.D,
+ Note.E,
+ Note.F,
+ Note.G,
+ Note.A,
+ Note.B,
+ ];
+ const octaveList = [];
- for (let octaveNum = startOctave; octaveNum <= endOctave; octaveNum++) {
- octaveList.push(octaveNum);
- };
+ for (let octaveNum = startOctave; octaveNum <= endOctave; octaveNum++) {
+ octaveList.push(octaveNum);
+ }
return (
- {octaveList.map((octaveNum) => {
- return (
-
- );
- })}
-
+ {octaveList.map((octaveNum) => {
+ return (
+
+ );
+ })}
+
);
};
VirtualPiano.defaultProps = {
- onNoteDown: (n) => {
- console.log("Note down: " + keyToStr(n));
- },
- onNoteUp: (n) => {
- console.log("Note up: " + keyToStr(n));
- },
+ onNoteDown: (n) => {
+ console.log("Note down: " + keyToStr(n));
+ },
+ onNoteUp: (n) => {
+ console.log("Note up: " + keyToStr(n));
+ },
startOctave: 2,
startNote: Note.C,
endOctave: 2,
endNote: Note.B,
showNoteNames: NoteNameBehavior.onpress,
- highlightedNotes: [],
+ highlightedNotes: [{ key: Note.D }, { key: Note.G, bgColor: "blue" }],
highlightColor: "red",
specialHighlightedNotes: [Note.D, Note.G],
specialHighlightColor: "blue",
diff --git a/front/models/Piano.ts b/front/models/Piano.ts
index 71e4182..f15d0f2 100644
--- a/front/models/Piano.ts
+++ b/front/models/Piano.ts
@@ -1,20 +1,18 @@
export enum Note {
"C",
+ "C#",
"D",
+ "D#",
"E",
"F",
+ "F#",
"G",
+ "G#",
"A",
+ "A#",
"B",
}
-export enum Accidental {
- "#",
- "b",
- "##",
- "bb",
-}
-
export enum NoteNameBehavior {
"always",
"onpress",
@@ -25,7 +23,7 @@ export enum NoteNameBehavior {
export enum KeyPressStyle {
"subtle",
"vivid",
-};
+}
export type HighlightedKey = {
key: PianoKey;
// if not specified, the default color for highlighted notes will be used
@@ -34,83 +32,136 @@ export type HighlightedKey = {
export class PianoKey {
public note: Note;
- public accidental?: Accidental;
public octave?: number;
- constructor(note: Note, accidental?: Accidental, octave?: number) {
+ constructor(note: Note, octave?: number) {
this.note = note;
- this.accidental = accidental;
this.octave = octave;
}
public toString = () => {
- return this.note as unknown as string + (this.accidental || "") + (this.octave || "");
+ return (this.note as unknown as string) + (this.octave || "");
};
}
export const strToKey = (str: string): PianoKey => {
- let note : Note;
- switch (str[0]) {
- case "C": note = Note.C; break;
- case "D": note = Note.D; break;
- case "E": note = Note.E; break;
- case "F": note = Note.F; break;
- case "G": note = Note.G; break;
- case "A": note = Note.A; break;
- case "B": note = Note.B; break;
- default: throw new Error("Invalid note name");
- }
- if (str.length === 1) {
- return new PianoKey(note);
- }
- let accidental : Accidental;
- switch (str[1]) {
- case "#": accidental = Accidental["#"]; break;
- case "b": accidental = Accidental["b"]; break;
- case "x": accidental = Accidental["##"]; break;
- case "n": accidental = Accidental["bb"]; break;
- default: throw new Error("Invalid accidental");
- }
- if (str.length === 2) {
- return new PianoKey(note, accidental);
- }
- const octave = parseInt(str[2] as unknown as string);
- return new PianoKey(note, accidental, octave);
+ let note: Note;
+ switch (str[0]) {
+ case "C":
+ note = Note.C;
+ break;
+ case "D":
+ note = Note.D;
+ break;
+ case "E":
+ note = Note.E;
+ break;
+ case "F":
+ note = Note.F;
+ break;
+ case "G":
+ note = Note.G;
+ break;
+ case "A":
+ note = Note.A;
+ break;
+ case "B":
+ note = Note.B;
+ break;
+ case "C#":
+ note = Note["C#"];
+ break;
+ case "D#":
+ note = Note["D#"];
+ break;
+ case "F#":
+ note = Note["F#"];
+ break;
+ case "G#":
+ note = Note["G#"];
+ break;
+ case "A#":
+ note = Note["A#"];
+ break;
+ default:
+ throw new Error("Invalid note name");
+ }
+ if (str.length < 3) {
+ return new PianoKey(note);
+ }
+ const octave = parseInt(str[2] as unknown as string);
+ return new PianoKey(note, octave);
};
export const keyToStr = (key: PianoKey, showOctave: boolean = true): string => {
- let s = "";
- switch (key.note) {
- case Note.C: s += "C"; break;
- case Note.D: s += "D"; break;
- case Note.E: s += "E"; break;
- case Note.F: s += "F"; break;
- case Note.G: s += "G"; break;
- case Note.A: s += "A"; break;
- case Note.B: s += "B"; break;
- }
- if (key.accidental !== undefined) {
- switch (key.accidental) {
- default: s += "#"; break;
- }
- }
- if (showOctave && key.octave) {
- s += key.octave;
- }
- return s;
+ let s = "";
+ switch (key.note) {
+ case Note.C:
+ s += "C";
+ break;
+ case Note.D:
+ s += "D";
+ break;
+ case Note.E:
+ s += "E";
+ break;
+ case Note.F:
+ s += "F";
+ break;
+ case Note.G:
+ s += "G";
+ break;
+ case Note.A:
+ s += "A";
+ break;
+ case Note.B:
+ s += "B";
+ break;
+ case Note["C#"]:
+ s += "C#";
+ break;
+ case Note["D#"]:
+ s += "D#";
+ break;
+ case Note["F#"]:
+ s += "F#";
+ break;
+ case Note["G#"]:
+ s += "G#";
+ break;
+ case Note["A#"]:
+ s += "A#";
+ break;
+ default:
+ throw new Error("Invalid note name");
+ }
+ if (showOctave && key.octave) {
+ s += key.octave;
+ }
+ return s;
+};
+
+export const isAccidental = (key: PianoKey): boolean => {
+ return (
+ key.note === Note["C#"] ||
+ key.note === Note["D#"] ||
+ key.note === Note["F#"] ||
+ key.note === Note["G#"] ||
+ key.note === Note["A#"]
+ );
};
export const octaveKeys: Array = [
new PianoKey(Note.C),
- new PianoKey(Note.C, Accidental["#"]),
- new PianoKey(Note.D),
- new PianoKey(Note.D, Accidental["#"]),
- new PianoKey(Note.E),
- new PianoKey(Note.F),
- new PianoKey(Note.F, Accidental["#"]),
- new PianoKey(Note.G),
- new PianoKey(Note.G, Accidental["#"]),
- new PianoKey(Note.A),
- new PianoKey(Note.A, Accidental["#"]),
- new PianoKey(Note.B),
-];
\ No newline at end of file
+ new PianoKey(Note["C#"]),
+ new PianoKey(Note.D),
+ new PianoKey(Note["D#"]),
+ new PianoKey(Note.E),
+ new PianoKey(Note.F),
+ new PianoKey(Note["F#"]),
+ new PianoKey(Note.G),
+ new PianoKey(Note["G#"]),
+ new PianoKey(Note.A),
+ new PianoKey(Note["A#"]),
+ new PianoKey(Note.B),
+];