-
-
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.
Add MTS exporter, add more Korg formats, comply with xen-dev-utils v0…
- Loading branch information
1 parent
04cf81a
commit 014dd8f
Showing
12 changed files
with
706 additions
and
169 deletions.
There are no files selected for viewing
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,109 @@ | ||
<script setup lang="ts"> | ||
import { KorgModels, KorgExporter, getKorgModelInfo } from "@/exporters/korg"; | ||
import { sanitizeFilename } from "@/utils"; | ||
import { computed, ref } from "vue"; | ||
import Modal from "@/components/ModalDialog.vue"; | ||
import type { Scale } from "scale-workshop-core"; | ||
const props = defineProps<{ | ||
newline: string; | ||
scaleName: string; | ||
baseMidiNote: number; | ||
scale: Scale; | ||
}>(); | ||
const emit = defineEmits(["confirm", "cancel"]); | ||
const models = [ | ||
KorgModels.MONOLOGUE, | ||
KorgModels.MINILOGUE, | ||
KorgModels.MINILOGUE_XD, | ||
KorgModels.PROLOGUE, | ||
]; | ||
const modelName = ref("minilogue"); | ||
const useOctaveFormat = ref(false); | ||
const dialogErrorMessage = computed(() => { | ||
if (useOctaveFormat.value) { | ||
const message = KorgExporter.getOctaveFormatErrorMessage(props.scale); | ||
if (message.length > 0) return message; | ||
} | ||
// Can check for other errors here... | ||
return String(); | ||
}); | ||
const fileTypePreview = computed(() => { | ||
const format = getKorgModelInfo(modelName.value); | ||
return useOctaveFormat.value ? format.octave : format.scale; | ||
}); | ||
async function doExport() { | ||
const params = { | ||
newline: props.newline, | ||
scale: props.scale, | ||
filename: sanitizeFilename(props.scaleName), | ||
baseMidiNote: props.baseMidiNote, | ||
}; | ||
const exporter = new KorgExporter( | ||
params, | ||
modelName.value, | ||
useOctaveFormat.value | ||
); | ||
await exporter.saveFile(); | ||
emit("confirm"); | ||
} | ||
</script> | ||
|
||
<template> | ||
<Modal @confirm="doExport" @cancel="$emit('cancel')"> | ||
<template #header> | ||
<h2>Export Korg Sound Librarian scale</h2> | ||
</template> | ||
<template #body> | ||
<div class="control-group"> | ||
<div class="control"> | ||
<label for="modelName">Synth Model</label> | ||
<select id="modelName" v-model="modelName"> | ||
<option v-for="name of models" :key="name" :value="name"> | ||
{{ getKorgModelInfo(name).title }} | ||
</option> | ||
</select> | ||
</div> | ||
<div id="format" class="control radio-group"> | ||
<label for="format">Tuning Format</label> | ||
<label> | ||
<input type="radio" :value="false" v-model="useOctaveFormat" /> | ||
Scale (128-note table) | ||
</label> | ||
<label> | ||
<input type="radio" :value="true" v-model="useOctaveFormat" /> | ||
Octave (12-note table, octave repeating with fixed C) | ||
</label> | ||
</div> | ||
<p> | ||
<label>Export Format: </label> | ||
{{ fileTypePreview }} | ||
</p> | ||
<div class="alert-box-danger" v-if="dialogErrorMessage.length > 0"> | ||
<p class="alert-message-danger"> | ||
{{ dialogErrorMessage }} | ||
</p> | ||
</div> | ||
</div> | ||
</template> | ||
<template #footer> | ||
<div class="btn-group"> | ||
<button | ||
@click="$emit('confirm')" | ||
:disabled="dialogErrorMessage.length > 0" | ||
> | ||
OK | ||
</button> | ||
<button @click="$emit('cancel')">Cancel</button> | ||
</div> | ||
</template> | ||
</Modal> | ||
</template> |
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,105 @@ | ||
<script setup lang="ts"> | ||
import MtsSysexExporter from "@/exporters/mts-sysex"; | ||
import { sanitizeFilename } from "@/utils"; | ||
import { ref, watch } 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"]); | ||
// Rarely implemented parameters | ||
// const deviceId = ref(0); | ||
// const bank = ref(0); (only for message 0x0804) | ||
function clampName(name: string): string { | ||
return name.slice(0, 16); | ||
} | ||
const name = ref(clampName(props.scaleName)); | ||
function nameInputCallback(nameInput: string): void { | ||
name.value = clampName(nameInput); | ||
} | ||
watch( | ||
() => props.scaleName, | ||
(newName) => nameInputCallback(newName), | ||
{ immediate: true } | ||
); | ||
function formatPresetIndex(input: string): string { | ||
const number = parseInt(input.replace(/\D/g, "")); | ||
if (Number.isNaN(number)) return "0"; | ||
return String(clamp(0, 127, number)); | ||
} | ||
const presetIndex = ref("0"); | ||
function presetIndexInputCallback(indexInput: string): void { | ||
presetIndex.value = formatPresetIndex(indexInput); | ||
} | ||
function doExport() { | ||
const params = { | ||
newline: props.newline, | ||
scale: props.scale, | ||
filename: sanitizeFilename(props.scaleName), | ||
baseMidiNote: props.baseMidiNote, | ||
name: name.value, | ||
presetIndex: parseInt(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" | ||
@input="nameInputCallback(name)" | ||
/> | ||
</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" | ||
id="preset-index" | ||
type="text" | ||
v-model="presetIndex" | ||
@input="presetIndexInputCallback(presetIndex)" | ||
/> | ||
</div> | ||
</div> | ||
</template> | ||
</Modal> | ||
</template> |
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
Oops, something went wrong.