-
-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c75afb2
commit 777c57d
Showing
9 changed files
with
295 additions
and
26 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
<script setup lang="ts"> | ||
import MtsSysexExporter from "@/exporters/mts-sysex"; | ||
import { sanitizeFilename } from "@/utils"; | ||
import { ref } from "vue"; | ||
import Modal from "@/components/ModalDialog.vue"; | ||
import type { Scale } from "scale-workshop-core"; | ||
import { clamp } from "xen-dev-utils"; | ||
const props = defineProps<{ | ||
newline: string; | ||
scaleName: string; | ||
baseMidiNote: number; | ||
scale: Scale; | ||
}>(); | ||
const emit = defineEmits(["confirm", "cancel"]); | ||
function clampName(name: string): string { | ||
return name.slice(0, 16); | ||
} | ||
function formatPresetIndex(input: string | number): number { | ||
let number = | ||
typeof input === "string" ? parseInt(input.replace(/\D/g, "")) : input; | ||
if (Number.isNaN(number)) return 0; | ||
return clamp(0, 127, number); | ||
} | ||
// Rarely implemented parameters | ||
// const deviceId = ref(0); | ||
// const bank = ref(0); (only for message 0x0804) | ||
const name = ref(clampName(props.scaleName)); | ||
const presetIndex = ref(0); | ||
function doExport() { | ||
const params = { | ||
newline: props.newline, | ||
scale: props.scale, | ||
filename: sanitizeFilename(props.scaleName), | ||
baseMidiNote: props.baseMidiNote, | ||
name: name.value, | ||
presetIndex: presetIndex.value, | ||
}; | ||
const exporter = new MtsSysexExporter(params); | ||
exporter.saveFile(); | ||
emit("confirm"); | ||
} | ||
</script> | ||
|
||
<template> | ||
<Modal @confirm="doExport" @cancel="$emit('cancel')"> | ||
<template #header> | ||
<h2>Export MTS Bulk Tuning Dump</h2> | ||
</template> | ||
<template #body> | ||
<div class="control-group"> | ||
<div class="control"> | ||
<label for="name">Name (16-character limit)</label> | ||
<input | ||
class="half" | ||
type="text" | ||
id="name" | ||
v-model="name" | ||
maxlength="16" | ||
/> | ||
</div> | ||
<div class="control"> | ||
<label for="preset-index"> | ||
Preset Index | ||
<span | ||
@click="$event.preventDefault()" | ||
class="info-question" | ||
title="Refer to your synth's manual for a valid range" | ||
> | ||
? | ||
</span> | ||
</label> | ||
<input | ||
class="half" | ||
type="number" | ||
id="preset-index" | ||
v-model="presetIndex" | ||
@input="presetIndex = formatPresetIndex(presetIndex)" | ||
/> | ||
</div> | ||
</div> | ||
</template> | ||
</Modal> | ||
</template> | ||
|
||
<style> | ||
input.half { | ||
flex-grow: 0.25 !important; | ||
} | ||
span.info-question { | ||
border-radius: 50%; | ||
border-width: 2px; | ||
border-style: solid; | ||
padding-left: 4px; | ||
padding-right: 4px; | ||
font-size: smaller; | ||
transition: 0.3s ease; | ||
} | ||
span.info-question:hover { | ||
background: white; | ||
color: black; | ||
border-color: white; | ||
transition: all 0.3s ease; | ||
} | ||
</style> |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { createHash } from "crypto"; | ||
import { describe, it, expect } from "vitest"; | ||
|
||
import { getTestData } from "./test-data"; | ||
import MtsSysexExporter from "../mts-sysex"; | ||
|
||
describe("MTS exporter", () => { | ||
it("can handle all line types", async () => { | ||
const params = getTestData( | ||
"MTS Sysex Bulk Tuning Dump exporter unit test v0.0.0" | ||
); | ||
params.presetIndex = 1; | ||
|
||
const exporter = new MtsSysexExporter(params); | ||
|
||
const scaleData = exporter.getBulkTuningData(); | ||
expect(createHash("sha256").update(scaleData).digest("base64")).toBe( | ||
"Ps5Ddp9lBYZgCn7Y8aSBnhXOcfIm+sh9AcnybiLX4Zg=" | ||
); | ||
|
||
// Name is padded with spaces | ||
const nameData = exporter.getNameData(); | ||
expect(nameData).toEqual([ | ||
84, 101, 115, 116, 32, 83, 99, 97, 108, 101, 32, 32, 32, 32, 32, 32, | ||
]); | ||
|
||
const sysExMsg = exporter.buildSysExDump(); | ||
expect(createHash("sha256").update(sysExMsg).digest("base64")).toBe( | ||
"Dx+z9IBMNqBrj7/g4EJ3XQxMPKbtQqmpfjLdoPPrV48=" | ||
); | ||
}); | ||
|
||
it("can gracefully handle invalid parameters", async () => { | ||
const params = getTestData( | ||
"MTS Sysex Bulk Tuning Dump exporter unit test v0.0.0" | ||
); | ||
params.name = "Super Special Test Scale"; | ||
params.presetIndex = -1; | ||
|
||
const exporter = new MtsSysexExporter(params); | ||
|
||
const scaleData = exporter.getBulkTuningData(); | ||
expect(createHash("sha256").update(scaleData).digest("base64")).toBe( | ||
"Ps5Ddp9lBYZgCn7Y8aSBnhXOcfIm+sh9AcnybiLX4Zg=" | ||
); | ||
|
||
// Name is truncated | ||
const nameData = exporter.getNameData(); | ||
expect(nameData).toEqual([ | ||
83, 117, 112, 101, 114, 32, 83, 112, 101, 99, 105, 97, 108, 32, 84, 101, | ||
]); | ||
|
||
const sysExMsg = exporter.buildSysExDump(); | ||
expect(createHash("sha256").update(sysExMsg).digest("base64")).toBe( | ||
"8TgBDEn+mTm/xar39zeO9NBCcRn6KymbO/ZeMfa8rq0=" | ||
); | ||
}); | ||
|
||
return; | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.