Skip to content

Commit

Permalink
Tweak Piano Roll
Browse files Browse the repository at this point in the history
  • Loading branch information
okaxaki committed Dec 10, 2023
1 parent 163bae1 commit 49d898a
Show file tree
Hide file tree
Showing 8 changed files with 1,058 additions and 630 deletions.
1,341 changes: 797 additions & 544 deletions package-lock.json

Large diffs are not rendered by default.

28 changes: 14 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "m3disp",
"private": true,
"version": "0.10.0-beta.0",
"version": "0.11.0",
"type": "module",
"scripts": {
"dev": "vite",
Expand All @@ -10,30 +10,30 @@
"server": "http-server -c-1 ./dist --ssl --key ./cert/localhost+2-key.pem --cert ./cert/localhost+2.pem"
},
"dependencies": {
"@emotion/react": "^11.10.6",
"@emotion/styled": "^11.10.6",
"@fontsource/roboto": "^4.5.8",
"@mui/icons-material": "^5.11.11",
"@mui/material": "^5.12.0",
"@types/sha1": "^1.1.3",
"fflate": "^0.7.4",
"libkss-js": "2.2.0-beta.0",
"@emotion/react": "^11.11.0",
"@emotion/styled": "^11.11.0",
"@fontsource/roboto": "^5.0.8",
"@mui/icons-material": "^5.14.19",
"@mui/material": "^5.14.20",
"@types/sha1": "^1.1.5",
"fflate": "^0.8.1",
"libkss-js": "^2.2.0",
"md5": "^2.3.0",
"mgsc-js": "^2.0.0-beta.1",
"mgsc-js": "^2.0.0",
"mgsrc-js": "^2.0.0",
"react": "^18.2.0",
"react-beautiful-dnd": "^13.1.1",
"react-dom": "^18.2.0",
"react-file-drop": "^3.1.6",
"webaudio-stream-player": "^1.1.0"
"webaudio-stream-player": "^1.2.1"
},
"devDependencies": {
"@types/md5": "^2.3.2",
"@types/react": "^18.0.28",
"@types/react-beautiful-dnd": "^13.1.4",
"@types/react-dom": "^18.0.11",
"@vitejs/plugin-react": "^3.1.0",
"typescript": "^4.9.3",
"vite": "^4.2.0"
"@vitejs/plugin-react": "^4.2.1",
"typescript": "^5.3.3",
"vite": "^5.0.7"
}
}
55 changes: 55 additions & 0 deletions src/contexts/AppContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,14 @@ const defaultTheme = createTheme({
});

export type KeyHighlightColorType = "primary" | "secondary";
export type PianoRollMode = "2d" | "3d";

type AppContextData = {
theme: Theme;
keyHighlightColorType: KeyHighlightColorType;
pianoRollRangeInSec: number;
pianoRollLayered: boolean;
pianoRollMode: string;
openMap: { [key: string]: boolean };
anchorElMap: { [key: string]: HTMLElement | null };
isOpen: (id: string) => boolean;
Expand All @@ -45,6 +49,9 @@ type AppContextData = {
setPrimaryColor: (id: string) => void;
setSecondaryColor: (id: string) => void;
setKeyHighlightColorType: (id: KeyHighlightColorType) => void;
setPianoRollRangeInSec: (value: number) => void;
setPianoRollLayered: (value: boolean) => void;
setPianoRollMode: (value: PianoRollMode) => void;
};

const noop = () => {
Expand All @@ -54,6 +61,9 @@ const noop = () => {
const defaultContextData: AppContextData = {
theme: defaultTheme,
keyHighlightColorType: "primary",
pianoRollRangeInSec: 4.0,
pianoRollLayered: false,
pianoRollMode: "2d",
openMap: {},
anchorElMap: {},
isOpen: () => false,
Expand All @@ -64,13 +74,19 @@ const defaultContextData: AppContextData = {
setPrimaryColor: noop,
setSecondaryColor: noop,
setKeyHighlightColorType: noop,
setPianoRollRangeInSec: noop,
setPianoRollLayered: noop,
setPianoRollMode: noop,
};

export const AppContext = createContext(defaultContextData);

const keyPrimaryColor = "m3disp.palette.primary.main";
const keySecondaryColor = "m3disp.palette.secondary.main";
const keyKeyHighlightColorType = "m3disp.keyHighlightColorType";
const keyPianoRollRangeInSec = "m3disp.pianoRoll.rangeInSec";
const keyPianoRollLayered = "m3disp.pianoRoll.layered";
const keyPianoRollMode = "m3disp.pianoRoll.mode";

export function AppContextProvider(props: PropsWithChildren) {
const isOpen = (id: string) => {
Expand Down Expand Up @@ -132,6 +148,33 @@ export function AppContextProvider(props: PropsWithChildren) {
}
};

const setPianoRollRangeInSec = (value: number, save: boolean = true) => {
setState((oldState) => {
return { ...oldState, pianoRollRangeInSec: value };
});
if (save) {
localStorage.setItem(keyPianoRollRangeInSec, value.toString());
}
};

const setPianoRollLayered = (value: boolean, save: boolean = true) => {
setState((oldState) => {
return { ...oldState, pianoRollLayered: value };
});
if (save) {
localStorage.setItem(keyPianoRollLayered, value.toString());
}
};

const setPianoRollMode = (value: string, save: boolean = true) => {
setState((oldState) => {
return { ...oldState, pianoRollMode: value };
});
if (save) {
localStorage.setItem(keyPianoRollMode, value);
}
};

const [state, setState] = useState(defaultContextData);
const [initialized, setInitialized] = useState(false);

Expand All @@ -150,6 +193,15 @@ export function AppContextProvider(props: PropsWithChildren) {
state.keyHighlightColorType) as KeyHighlightColorType,
false
);

let str = localStorage.getItem(keyPianoRollRangeInSec);
if (str != null) {
setPianoRollRangeInSec(parseFloat(str), false);
}
str = localStorage.getItem(keyPianoRollLayered);
if (str != null) {
setPianoRollLayered(str == "true", false);
}
}, []);

useEffect(() => {
Expand All @@ -171,6 +223,9 @@ export function AppContextProvider(props: PropsWithChildren) {
setPrimaryColor,
setSecondaryColor,
setKeyHighlightColorType,
setPianoRollRangeInSec,
setPianoRollLayered,
setPianoRollMode,
}}
>
{initialized ? props.children : null}
Expand Down
19 changes: 12 additions & 7 deletions src/kss/channel-status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export type ChannelStatus = {
mode?: string | null;
keyKeepFrames?: number | null;
voice?: string | Uint8Array | null;
vnum?: number | null; // voice number
};

function createPSGVoiceName(ton: boolean, non: boolean) {
Expand Down Expand Up @@ -48,9 +49,9 @@ function createPSGStatus(regs: Uint8Array, id: ChannelId): ChannelStatus {
const non = (regs[7] & (8 << (ch - 3))) == 0;
const voice = createPSGVoiceName(ton, non);
if (non && vol > 0) {
return { id, freq, kcode: freq, vol, mode: "noise", voice };
return { id, freq, kcode: freq, vol, mode: "noise", voice, vnum: 8 };
} else {
return { id, freq, vol, mode: "noise", voice };
return { id, freq, vol, mode: "noise", voice, vnum: 0 };
}
}
}
Expand All @@ -64,12 +65,13 @@ function createSCCStatus(regs: Uint8Array, id: ChannelId): ChannelStatus {

const vch = regs[0xe0] & 1 ? ch : ch < 5 ? ch : 4;
const voice = new Uint8Array(regs.buffer, regs.byteOffset + vch * 32, 32);
const vnum = (voice[4] + voice[20]) >> 4;

if (vol > 0 && freq > 0) {
const kcode = 57 + Math.round(Math.log2(freq / A4) * 12);
return { id, freq, kcode, vol, voice };
return { id, freq, kcode, vol, voice, vnum };
} else {
return { id, freq, vol, voice };
return { id, freq, vol, voice, vnum };
}
}

Expand Down Expand Up @@ -103,12 +105,15 @@ function createOPLLStatus(

let kon = false;
let vol: number = 0;
let vnum: number = 0;

if (ch < 9) {
kon = (regs[0x20 + pch] & 0x10) != 0;
vol = 0x0f - (regs[0x30 + pch] & 0xf);
vnum = (regs[0x30 + pch] & 0xf0) >> 4;
} else {
mode = "rch";
vnum = ch + 7;
if (rflag) {
let ron;
if (ch == 9) {
Expand Down Expand Up @@ -169,9 +174,9 @@ function createOPLLStatus(

if (kon) {
const kcode = 57 + Math.round(Math.log2(freq / A4) * 12);
return { id, freq, kcode, vol, mode, keyKeepFrames: keyKeepFrames[ch], voice };
return { id, freq, kcode, vol, mode, keyKeepFrames: keyKeepFrames[ch], voice, vnum };
} else {
return { id, freq, vol, mode, keyKeepFrames: keyKeepFrames[ch], voice };
return { id, freq, vol, mode, keyKeepFrames: keyKeepFrames[ch], voice, vnum };
}
}

Expand All @@ -198,7 +203,7 @@ export function getChannelStatusArray(
player: KSSPlayer,
id: ChannelId,
pastSpanInFrames: number,
futureSpanInFrames: number,
futureSpanInFrames: number
): (ChannelStatus | null)[] {
const currentFrame = player.progress?.renderer?.currentFrame ?? 0;

Expand Down
37 changes: 22 additions & 15 deletions src/views/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { OpenUrlDialog } from "./OpenUrlDialog";
import packageJson from "../../package.json";
import ghlogo from "../assets/github-mark-white.svg";
import { PianoRoll } from "../widgets/PianoRoll";
import { PianoRollControl } from "../widgets/PianoRollControl";

const gap = { xs: 0, sm: 1, md: 1.5, lg: 2 };

Expand Down Expand Up @@ -154,6 +155,7 @@ function DesktopAppBar() {
}

function AppRootDesktop() {
const appContext = useContext(AppContext);
const context = useContext(PlayerContext);
const [panelHeight, setPanelHeight] = useState<number | null>(null);
const leftPaneRef = useRef<HTMLDivElement>(null);
Expand Down Expand Up @@ -202,25 +204,26 @@ function AppRootDesktop() {
<Grid xs={12} sm={7} md={8} lg={8} xl={8}>
<Stack ref={leftPaneRef} spacing={gap}>
<Box sx={{ borderBottom: 1, borderColor: "divider" }}>
<Tabs value={tabIndex} onChange={handleTabChange}>
<Tab label="Keyboard" value={0} />
<Tab
label={
<>
<Typography variant="inherit">
Piano Roll <BetaSign />
</Typography>
</>
}
value={1}
/>
</Tabs>
<Box sx={{ display: "flex", flexDirection: "row" }}>
<Tabs value={tabIndex} onChange={handleTabChange} sx={{ flex: 2 }}>
<Tab label="Keyboard" value={0} />
<Tab
label={<Typography variant="inherit">Piano Roll</Typography>}
value={1}
/>
</Tabs>
<Box
sx={{ display: "flex", flex: 1, justifyContent: "end", alignItems: "center" }}
>
{tabIndex == 1 ? <PianoRollControl /> : null}
</Box>
</Box>
</Box>
<TabPanel value={tabIndex} index={0}>
<KeyboardList spacing={gap} />
</TabPanel>
<TabPanel value={tabIndex} index={1}>
<PianoRoll />
<PianoRoll mode={appContext.pianoRollMode} />
</TabPanel>
{isMd ? <WaveSliderCard /> : null}
</Stack>
Expand Down Expand Up @@ -278,5 +281,9 @@ function TabPanel(props: TabPanelProps) {
}

function BetaSign() {
return <Typography variant="caption" sx={{ textTransform: "none"}}>(Beta)</Typography>;
return (
<Typography variant="caption" sx={{ textTransform: "none" }}>
(Beta)
</Typography>
);
}
Loading

0 comments on commit 49d898a

Please sign in to comment.