Skip to content

Commit

Permalink
Merge branch 'channel-config'
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielPXL committed Jun 27, 2024
2 parents 9e93a31 + 3e23696 commit 1448ad2
Show file tree
Hide file tree
Showing 13 changed files with 771 additions and 74 deletions.
4 changes: 4 additions & 0 deletions src/assets/pickercircle.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/assets/pickerline.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 27 additions & 1 deletion src/core/AudioWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ callables.set("getSeqSymbols", (data) => {

let curSeqSymbol: string;
let renderer: Audio.SequenceRenderer;
let activeTracks: number = 0xffff;

callables.set("loadSeq", (data) => {
curSeqSymbol = data.name;
Expand All @@ -93,7 +94,8 @@ callables.set("loadSeq", (data) => {
sink(buffer) {
postMessage({ type: "pcm", data: buffer });
},
bufferLength: 1024 * 16
bufferLength: 1024 * 16,
activeTracks: activeTracks
});
});

Expand All @@ -115,6 +117,30 @@ callables.set("tickSeconds", (data) => {
return states;
});

callables.set("setTrackActive", (data) => {
if (data.active) {
activeTracks |= 1 << data.track;
} else {
activeTracks &= ~(1 << data.track);
}

if (renderer && renderer.tracks[data.track]) {
// This should probably be part of the renderer itself
renderer.activeTracks = activeTracks;
renderer.tracks[data.track].active = data.active;
}
});

callables.set("findAllocatedTracks", (data) => {
let tracks = 0xffff;
const cmd = renderer.commands[0];
if (cmd instanceof Audio.Commands.AllocateTracks) {
tracks = cmd.tracks;
}

return tracks;
});

let exportRenderer: Audio.SequenceRenderer;
let exportBuffer: Float32Array[] | null = null;

Expand Down
52 changes: 50 additions & 2 deletions src/core/Renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ let topTime = 1.5;
let bottomTime = -1;
let bottomSameSpeed = true;

let topChannels = 0xffff;
let pianoChannels = 0xffff;
let bottomChannels = 0xffff;

export function init() {
PianoRenderer.init();

Expand Down Expand Up @@ -71,13 +75,23 @@ export function resize() {

function render() {
const time = AudioPlayer.getTime();
topTimeline.draw(colors, time, noteRange, [0, topTime]);
bottomTimeline.draw(colors, time, noteRange, [bottomTime, 0]);
topTimeline.draw(colors, time, noteRange, [0, topTime], topChannels);
bottomTimeline.draw(
colors,
time,
noteRange,
[bottomTime, 0],
bottomChannels
);

const state = StateManager.getState(time);
PianoRenderer.clearNotes();
if (state) {
for (let i = 0; i < state.channels.length; i++) {
if ((pianoChannels & (1 << i)) === 0) {
continue;
}

const channel = state.channels[i];
for (const note of channel.playing) {
if (note.state === Audio.EnvelopeState.Release) {
Expand Down Expand Up @@ -137,3 +151,37 @@ export function setPianoRange(value: [number, number]) {
noteRange = value;
PianoRenderer.drawKeys(noteRange[0], noteRange[1]);
}

export function showChannel(
place: "top" | "piano" | "bottom",
channel: number
) {
switch (place) {
case "top":
topChannels |= 1 << channel;
break;
case "piano":
pianoChannels |= 1 << channel;
break;
case "bottom":
bottomChannels |= 1 << channel;
break;
}
}

export function hideChannel(
place: "top" | "piano" | "bottom",
channel: number
) {
switch (place) {
case "top":
topChannels &= ~(1 << channel);
break;
case "piano":
pianoChannels &= ~(1 << channel);
break;
case "bottom":
bottomChannels &= ~(1 << channel);
break;
}
}
7 changes: 6 additions & 1 deletion src/core/TimelineRenderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ export class TimelineRenderer {
colors: string[],
time: number,
noteRange: [Audio.Note, Audio.Note],
timeRange: [number, number]
timeRange: [number, number],
shownChannels: number
) {
if (this.canvas.height === 0) {
return;
Expand Down Expand Up @@ -50,6 +51,10 @@ export class TimelineRenderer {
}

for (let i = 0; i < s.channels.length; i++) {
if ((shownChannels & (1 << i)) === 0) {
continue;
}

const channel = s.channels[i];

this.ctx.fillStyle = colors[i];
Expand Down
143 changes: 143 additions & 0 deletions src/ui/ChannelsSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import { useEffect } from "react";
import { repeat, useStorage } from "./Helpers";
import * as classes from "./styles/ChannelsSection.module.css";
import * as AudioWorkerComms from "../core/AudioWorkerComms";
import * as Renderer from "../core/Renderer";
import { Color, ColorPicker, HSVtoRGB, roundColor } from "./ColorPicker";

// TODO: Make some nice icons for this instead of text
export function ChannelsSection({ allocatedTracks }) {
return (
<div className={classes.container}>
<div>Some of these settings may take a few seconds to apply.</div>
<div className={classes.grid}>
<div>Channel</div>
<div className={classes.rightAlign}>Color</div>
<div className={classes.rightAlign}>Sound</div>
<div className={classes.rightAlign}>Top</div>
<div className={classes.rightAlign}>Piano</div>
<div className={classes.rightAlign}>Bottom</div>
<div></div>
{repeat(16, (i) => (
<ChannelRow
key={i}
id={i}
disabled={((1 << i) & allocatedTracks) === 0}
/>
))}
</div>
</div>
);
}

function ChannelRow({ id, disabled }) {
const [color, setColor] = useStorage<Color>(
`channel_${id}_color`,
roundColor(HSVtoRGB((id * 360) / 16, 1, 1))
);
const [active, setActive] = useStorage<boolean>(
`channel_${id}_active`,
true
);
const [showTop, setShowTop] = useStorage<boolean>(
`channel_${id}_showTop`,
true
);
const [showPiano, setShowPiano] = useStorage<boolean>(
`channel_${id}_showPiano`,
true
);
const [showBottom, setShowBottom] = useStorage<boolean>(
`channel_${id}_showBottom`,
true
);

useEffect(() => {
AudioWorkerComms.call("setTrackActive", {
track: id,
active: active
});
}, [active]);

useEffect(() => {
if (showTop) {
Renderer.showChannel("top", id);
} else {
Renderer.hideChannel("top", id);
}
}, [showTop]);

useEffect(() => {
if (showPiano) {
Renderer.showChannel("piano", id);
} else {
Renderer.hideChannel("piano", id);
}
}, [showPiano]);

useEffect(() => {
if (showBottom) {
Renderer.showChannel("bottom", id);
} else {
Renderer.hideChannel("bottom", id);
}
}, [showBottom]);

return (
<>
<div>
{disabled ? (
<>
<del>{id + 1}</del>
🔇
</>
) : (
<>{id + 1}</>
)}
</div>
<ColorPicker color={color} onChange={(c) => setColor(c)} />
<input
type="checkbox"
className={classes.rightAlign}
checked={active}
onChange={(e) => setActive(e.target.checked)}
></input>
<input
type="checkbox"
className={classes.rightAlign}
checked={showTop}
onChange={(e) => {
setShowTop(e.target.checked);
}}
></input>
<input
type="checkbox"
className={classes.rightAlign}
checked={showPiano}
onChange={(e) => {
setShowPiano(e.target.checked);
}}
></input>
<input
type="checkbox"
className={classes.rightAlign}
checked={showBottom}
onChange={(e) => {
setShowBottom(e.target.checked);
}}
></input>
<button
className={classes.resetButton}
onClick={() => {
setColor(roundColor(HSVtoRGB((id * 360) / 16, 1, 1)));
setActive(true);
setShowTop(true);
setShowPiano(true);
setShowBottom(true);
}}
>
&#10226;
</button>
</>
);
}
Loading

0 comments on commit 1448ad2

Please sign in to comment.