Skip to content

Commit

Permalink
Merge pull request #366 from xenharmonic-devs/xen-midi
Browse files Browse the repository at this point in the history
Move MIDI classes to a separate package
  • Loading branch information
frostburn authored Nov 26, 2023
2 parents cf56de8 + 32e862a commit 3707b7f
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 258 deletions.
58 changes: 36 additions & 22 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@
"temperaments": "^0.4.5",
"vue": "^3.2.33",
"vue-router": "^4.1.5",
"webmidi": "^3.0.21",
"xen-dev-utils": "^0.1.4"
"webmidi": "^3.1.7",
"xen-dev-utils": "^0.1.4",
"xen-midi": "^0.1.0"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.2.0",
Expand Down
46 changes: 17 additions & 29 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,8 @@ import {
} from "@/constants";
import { ScaleWorkshopOneData } from "@/scale-workshop-one";
import type { Input, Output } from "webmidi";
import {
bendRangeInSemitones,
computeWhiteIndices,
MidiIn,
midiNoteInfo,
MidiOut,
} from "@/midi";
import { computeWhiteIndices } from "@/midi";
import { MidiIn, midiKeyInfo, MidiOut } from "xen-midi";
import { Keyboard, type CoordinateKeyboardEvent } from "@/keyboard";
import { decodeQuery, encodeQuery, type DecodedState } from "@/url-encode";
import { debounce } from "@/utils";
Expand Down Expand Up @@ -349,9 +344,9 @@ function getFrequency(index: number) {
}
}
const midiOut = computed(() => {
return new MidiOut(midiOutput.value as Output, midiOutputChannels.value);
});
const midiOut = computed(
() => new MidiOut(midiOutput.value as Output, midiOutputChannels.value)
);
function sendNoteOn(frequency: number, rawAttack: number) {
const midiOff = midiOut.value.sendNoteOn(frequency, rawAttack);
Expand Down Expand Up @@ -394,14 +389,17 @@ function sendNoteOn(frequency: number, rawAttack: number) {
// Offset such that default base MIDI note doesn't move
const WHITE_MODE_OFFSET = 69 - 40;
function midiNoteOn(index: number, rawAttack: number) {
function midiNoteOn(index: number, rawAttack?: number) {
if (rawAttack === undefined) {
rawAttack = 80;
}
let frequency = frequencies.value[index];
if (!midiVelocityOn.value) {
rawAttack = 80;
}
// Store state to ensure consistent note off.
const info = midiNoteInfo(index);
const info = midiKeyInfo(index);
const whiteMode = midiWhiteMode.value;
const indices = whiteIndices.value;
Expand Down Expand Up @@ -453,11 +451,14 @@ function midiNoteOn(index: number, rawAttack: number) {
if (isNaN(frequency)) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
return (rawRelease: number) => {};
return (rawRelease?: number) => {};
}
const noteOff = sendNoteOn(frequency, rawAttack);
return (rawRelease: number) => {
return (rawRelease?: number) => {
if (rawRelease === undefined) {
rawRelease = 80;
}
if (!midiVelocityOn.value) {
rawRelease = 80;
}
Expand Down Expand Up @@ -485,11 +486,10 @@ const RESERVED_MESSAGES = ["noteon", "noteoff", "pitchbend"];
watch(midiInput, (newValue, oldValue) => {
if (oldValue !== null) {
oldValue.removeListener();
midiIn.unlisten(oldValue as Input);
}
if (newValue !== null) {
newValue.addListener("noteon", midiIn.noteOn.bind(midiIn));
newValue.addListener("noteoff", midiIn.noteOff.bind(midiIn));
midiIn.listen(newValue as Input);
// Pass everything else through and distrubute among the channels
newValue.addListener("midimessage", (event) => {
Expand All @@ -515,15 +515,6 @@ watch(midiInput, (newValue, oldValue) => {
}
});
function sendPitchBendRange() {
const output = midiOutput.value;
if (output !== null) {
midiOutputChannels.value.forEach((channel) => {
output.channels[channel].sendPitchBendRange(bendRangeInSemitones, 0);
});
}
}
// === Virtual and typing keyboard ===
function keyboardNoteOn(index: number) {
tuningTableKeyOn(index);
Expand Down Expand Up @@ -812,9 +803,6 @@ watch(mainVolume, (newValue) => {
);
});
watch(midiOutput, sendPitchBendRange);
watch(midiOutputChannels, sendPitchBendRange);
function updateMidiInputChannels(newValue: Set<number>) {
midiInputChannels.clear();
newValue.forEach((channel) => midiInputChannels.add(channel));
Expand Down
7 changes: 4 additions & 3 deletions src/__tests__/midi.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { describe, it, expect } from "vitest";
import { midiKeyInfo } from "xen-midi";

import { computeWhiteIndices, midiNoteInfo } from "../midi";
import { computeWhiteIndices } from "../midi";

describe("White key to white color mapper", () => {
it("reproduces a chromatic scale in the default (A minor) configuration", () => {
Expand All @@ -20,7 +21,7 @@ describe("White key to white color mapper", () => {
]);

for (let index = 69; index < 69 + 12; index++) {
const info = midiNoteInfo(index);
const info = midiKeyInfo(index);
if (info.whiteNumber === undefined) {
expect(map[info.sharpOf] + 1).toBe(index);
} else {
Expand All @@ -46,7 +47,7 @@ describe("White key to white color mapper", () => {
]);

for (let index = 60; index < 60 + 12; index++) {
const info = midiNoteInfo(index);
const info = midiKeyInfo(index);
if (info.whiteNumber === undefined) {
expect(map[info.sharpOf] + 1).toBe(index);
} else {
Expand Down
Loading

0 comments on commit 3707b7f

Please sign in to comment.