Skip to content

Commit

Permalink
Refactor Korg exporter to support other formats
Browse files Browse the repository at this point in the history
  • Loading branch information
vsicurella committed Jul 8, 2023
1 parent 777c57d commit 6e0037d
Show file tree
Hide file tree
Showing 6 changed files with 257 additions and 163 deletions.
25 changes: 16 additions & 9 deletions src/components/ScaleBuilder.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { exportFile, type ExporterKey } from "@/exporters";
import Modal from "@/components/ModalDialog.vue";
import ReaperExportModal from "@/components/modals/export/ReaperExport.vue";
import MtsSysexExportModal from "@/components/modals/export/MtsSysexExport.vue";
import KorgExportModal from "@/components/modals/export/KorgExport.vue";
import ShareUrlModal from "@/components/modals/ShareUrl.vue";
import EqualTemperamentModal from "@/components/modals/generation/EqualTemperament.vue";
import HarmonicSeriesModal from "@/components/modals/generation/HarmonicSeries.vue";
Expand Down Expand Up @@ -137,6 +138,7 @@ function doExport(exporter: ExporterKey) {
exportFile(exporter, params);
}
const showKorgExportModal = ref(false);
const showReaperExportModal = ref(false);
const showMtsSysexExportModal = ref(false);
const showShareUrlModal = ref(false);
Expand Down Expand Up @@ -475,15 +477,10 @@ function copyToClipboard() {
<p><strong>Sytrus pitch map (.fnv)</strong></p>
<p>Envelope state file for the pitch envelope in Image-Line Sytrus</p>
</a>
<a href="#" class="btn" @click="doExport('mnlgtuns')">
<p><strong>Korg 'logue user scale (.mnlgtuns)</strong></p>
<p>Single scale for Korg 'logue Sound Librarian.</p>
<p>Full tuning of all MIDI notes</p>
</a>
<a href="#" class="btn" @click="doExport('mnlgtuno')">
<p><strong>Korg 'logue user octave (.mnlgtuno)</strong></p>
<p>Single scale for Korg 'logue Sound Librarian.</p>
<p>Only supports octave-repeating scales with 12 intervals</p>
<a href="#" class="btn" @click="showKorgExportModal = true">
<p><strong>Korg Sound Librarian scale (.mnlgtuns + others)</strong></p>
<p>Tuning formats for use with Monologue, Minilogue,</p>
<p>Minilogue XD, and Prologue synthesizers</p>
</a>
<a href="#" class="btn" @click="doExport('deflemask')">
<p><strong>Deflemask reference (.txt)</strong></p>
Expand Down Expand Up @@ -528,6 +525,16 @@ function copyToClipboard() {
/>

<Teleport to="body">
<KorgExportModal
:show="showKorgExportModal"
@confirm="showKorgExportModal = false"
@cancel="showKorgExportModal = false"
:newline="props.newline"
:scaleName="scaleName"
:baseMidiNote="baseMidiNote"
:scale="scale"
/>

<ReaperExportModal
:show="showReaperExportModal"
@confirm="showReaperExportModal = false"
Expand Down
84 changes: 84 additions & 0 deletions src/components/modals/export/KorgExport.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<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 useScaleFormat = ref(true);
const fileTypePreview = computed(() => {
const format = getKorgModelInfo(modelName.value);
return useScaleFormat.value ? format.scale : format.octave;
});
function doExport() {
const params = {
newline: props.newline,
scale: props.scale,
filename: sanitizeFilename(props.scaleName),
baseMidiNote: props.baseMidiNote,
};
const exporter = new KorgExporter(
params,
modelName.value,
useScaleFormat.value
);
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="true" v-model="useScaleFormat" />
&nbsp;Scale (128-note table)
</label>
<label>
<input type="radio" :value="false" v-model="useScaleFormat" />
&nbsp;Octave (12-note table, octave repeating with fixed C)
</label>
</div>
<p>
<label>Export Format: </label>
{{ fileTypePreview }}
</p>
</div>
</template>
</Modal>
</template>
12 changes: 0 additions & 12 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,5 @@ export const WINDOWS_NEWLINE = "\r\n";

export const NUMBER_OF_NOTES = 128;

// Korg specific constants for exporters and importers
export const KORG = {
programmer: "ScaleWorkshop",
mnlg: {
octaveSize: 12,
scaleSize: 128,
maxCents: 12800,
refA: { val: 6900, ind: 69, freq: 440.0 },
refC: { val: 6000, ind: 60, freq: 261.6255653 },
},
};

// Browser interaction
export const LEFT_MOUSE_BTN = 0;
23 changes: 12 additions & 11 deletions src/exporters/__tests__/korg.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { DEFAULT_NUMBER_OF_COMPONENTS } from "../../constants";
import { Scale } from "scale-workshop-core";
import { describe, it, expect } from "vitest";

import { MnlgtunsExporter, MnlgtunoExporter } from "../korg";
import { KorgExporter, KorgModels } from "../korg";

import { getTestData } from "./test-data";

Expand All @@ -19,7 +19,7 @@ describe("Korg exporters", () => {
256
);

const exporter = new MnlgtunsExporter(params);
const exporter = new KorgExporter(params, KorgModels.MINILOGUE, true);
const [zip, fileType] = exporter.getFileContents();

expect(fileType).toBe(".mnlgtuns");
Expand All @@ -36,7 +36,7 @@ describe("Korg exporters", () => {
if (path.endsWith("bin")) {
const content = await file.async("uint8array");
expect(createHash("sha256").update(content).digest("base64")).toBe(
"/st0f/90q1FNXxNnw2S+SCFeu9TkbXIydn85+qrqnrg="
"O6YaWtzo33MdIBcMRYlVq7PnzuoMd5Yyp6sBT/3oDnc="
);
}
// Other contents didn't seem to have issues so we ignore them here.
Expand All @@ -45,7 +45,8 @@ describe("Korg exporters", () => {

it("can handle all line types (mnlgtuns)", async () => {
const params = getTestData("Korg 'logue exporter unit test v0.0.0");
const exporter = new MnlgtunsExporter(params);

const exporter = new KorgExporter(params, KorgModels.MINILOGUE, true);
const [zip, fileType] = exporter.getFileContents();

expect(fileType).toBe(".mnlgtuns");
Expand All @@ -62,17 +63,17 @@ describe("Korg exporters", () => {
if (path.endsWith("bin")) {
const content = await file.async("uint8array");
expect(createHash("sha256").update(content).digest("base64")).toBe(
"nuHoVQKeaJlIHrNsaAcxFfoepmtzy+NN48LcfoU4fqE="
"Ps5Ddp9lBYZgCn7Y8aSBnhXOcfIm+sh9AcnybiLX4Zg="
);
} else {
const content = await file.async("string");
if (path === "TunS_000.TunS_info") {
expect(content).toBe(
"<minilogue_TuneScaleInformation><Programmer>ScaleWorkshop</Programmer><Comment>Test Scale</Comment></minilogue_TuneScaleInformation>"
'<?xml version="1.0" encoding="UTF-8"?>\n\n<minilogue_TuneScaleInformation>\n <Programmer>ScaleWorkshop</Programmer>\n <Comment>Test Scale</Comment>\n</minilogue_TuneScaleInformation>\n'
);
} else {
expect(content).toBe(
'<KorgMSLibrarian_Data><Product>minilogue</Product><Contents NumProgramData="0" NumPresetInformation="0" NumTuneScaleData="1" NumTuneOctData="0"><TuneScaleData><Information>TunS_000.TunS_info</Information><TuneScaleBinary>TunS_000.TunS_bin</TuneScaleBinary></TuneScaleData></Contents></KorgMSLibrarian_Data>'
'<?xml version="1.0" encoding="UTF-8"?>\n\n<KorgMSLibrarian_Data>\n <Product>minilogue</Product>\n <Contents NumProgramData="0" NumPresetInformation="0" NumTuneScaleData="1"\n NumTuneOctData="0">\n <TuneScaleData>\n <Information>TunS_000.TunS_info</Information>\n <TuneScaleBinary>TunS_000.TunS_bin</TuneScaleBinary>\n </TuneScaleData>\n </Contents>\n</KorgMSLibrarian_Data>\n'
);
}
}
Expand All @@ -83,7 +84,7 @@ describe("Korg exporters", () => {

it("can handle all line types (mnlgtuno)", async () => {
const params = getTestData("Korg 'logue exporter unit test v0.0.0");
const exporter = new MnlgtunoExporter(params);
const exporter = new KorgExporter(params, KorgModels.MINILOGUE, false);
const [zip, fileType] = exporter.getFileContents();

expect(fileType).toBe(".mnlgtuno");
Expand All @@ -100,17 +101,17 @@ describe("Korg exporters", () => {
if (path.endsWith("bin")) {
const content = await file.async("uint8array");
expect(createHash("sha256").update(content).digest("base64")).toBe(
"dQWlBBzfHE/LLvEhmAQqM1AppQg5YsoQ2GQbK6KTUeM="
"hnBNRPHvVHYkBfgM/ss+wTqd2Sy4UQ6bBk8aJqQWPzI="
);
} else {
const content = await file.async("string");
if (path === "TunO_000.TunO_info") {
expect(content).toBe(
"<minilogue_TuneOctInformation><Programmer>ScaleWorkshop</Programmer><Comment>Test Scale</Comment></minilogue_TuneOctInformation>"
'<?xml version="1.0" encoding="UTF-8"?>\n\n<minilogue_TuneOctInformation>\n <Programmer>ScaleWorkshop</Programmer>\n <Comment>Test Scale</Comment>\n</minilogue_TuneOctInformation>\n'
);
} else {
expect(content).toBe(
'<KorgMSLibrarian_Data><Product>minilogue</Product><Contents NumProgramData="0" NumPresetInformation="0" NumTuneScaleData="0" NumTuneOctData="1"><TuneOctData><Information>TunO_000.TunO_info</Information><TuneOctBinary>TunO_000.TunO_bin</TuneOctBinary></TuneOctData></Contents></KorgMSLibrarian_Data>'
'<?xml version="1.0" encoding="UTF-8"?>\n\n<KorgMSLibrarian_Data>\n <Product>minilogue</Product>\n <Contents NumProgramData="0" NumPresetInformation="0" NumTuneScaleData="0"\n NumTuneOctData="1">\n <TuneOctData>\n <Information>TunO_000.TunO_info</Information>\n <TuneOctBinary>TunO_000.TunO_bin</TuneOctBinary>\n </TuneOctData>\n </Contents>\n</KorgMSLibrarian_Data>\n'
);
}
}
Expand Down
5 changes: 0 additions & 5 deletions src/exporters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@ import { AnaMarkV1Exporter, AnaMarkV2Exporter } from "@/exporters/anamark";
import DeflemaskExporter from "@/exporters/deflemask";
import { HarmorExporter, SytrusExporter } from "@/exporters/image-line";
import KontaktExporter from "@/exporters/kontakt";
import { MnlgtunoExporter, MnlgtunsExporter } from "@/exporters/korg";
import MaxMSPExporter from "@/exporters/max-msp";
import PureDataExporter from "@/exporters/pure-data";
import { ScalaSclExporter, ScalaKbmExporter } from "@/exporters/scala";
import SoniccoutureExporter from "@/exporters/soniccouture";
import MtsSysexExporter from "@/exporters/mts-sysex";

const EXPORTERS = {
anamarkv1: AnaMarkV1Exporter,
Expand All @@ -21,9 +19,6 @@ const EXPORTERS = {
soniccouture: SoniccoutureExporter,
harmor: HarmorExporter,
sytrus: SytrusExporter,
mnlgtuns: MnlgtunsExporter,
mnlgtuno: MnlgtunoExporter,
mtsSysex: MtsSysexExporter,
deflemask: DeflemaskExporter,
};

Expand Down
Loading

0 comments on commit 6e0037d

Please sign in to comment.