From b41468f80a4bc9b5eda3161db53aad7204d14f80 Mon Sep 17 00:00:00 2001 From: "[poww10s]" <[theironminer@gmail.com]> Date: Sat, 28 Nov 2020 03:49:28 -0500 Subject: [PATCH] move parsing code over from master --- package-lock.json | 13 ++ package.json | 1 + src/features/io/ioParser.js | 251 ++++++++++++++++++++++++++++++++++++ src/features/menu/Menu.css | 9 ++ src/features/menu/Menu.js | 7 +- 5 files changed, 280 insertions(+), 1 deletion(-) create mode 100644 src/features/io/ioParser.js diff --git a/package-lock.json b/package-lock.json index 43dbbda..da9c641 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3764,6 +3764,14 @@ "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", "optional": true }, + "binary-parser-encoder": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/binary-parser-encoder/-/binary-parser-encoder-1.5.3.tgz", + "integrity": "sha512-yu3tdLBYqPIwGRaXyswLoLrhaffkuZkNuXveq/jYoyBHQbFMjamHCWPFOmI2Qz+Go0Rh6wE9f6tt0EAvsgDD0g==", + "requires": { + "smart-buffer": "^4.1.0" + } + }, "bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -14092,6 +14100,11 @@ "is-fullwidth-code-point": "^2.0.0" } }, + "smart-buffer": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.1.0.tgz", + "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==" + }, "snapdragon": { "version": "0.8.2", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", diff --git a/package.json b/package.json index 47cc1a7..a9fa2ea 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.5.0", "@testing-library/user-event": "^7.2.1", + "binary-parser-encoder": "^1.5.3", "rc-slider": "^9.6.3", "react": "^17.0.1", "react-dom": "^17.0.1", diff --git a/src/features/io/ioParser.js b/src/features/io/ioParser.js new file mode 100644 index 0000000..849fb4c --- /dev/null +++ b/src/features/io/ioParser.js @@ -0,0 +1,251 @@ +import { Parser } from 'binary-parser-encoder'; + +function parse(parser, binary) { + // check if the binary is a valid KORG-produced SYSEX file + if (binary.length !== 297) { + throw new Error('incorrect file length'); + } + if (binary[0] !== 0xf0) { + throw new Error('first byte is not SYSEX byte'); + } + if (binary[1] !== 0x42) { + throw new Error('manufacturer code is not KORG'); + } + if (binary[4] !== 0x40) { + throw new Error('not a program dump'); + } + if (binary[5] !== 0x00) { + // in all files found in the wild it's always zero + throw new Error('sixth byte is not zero'); + } + if (binary[binary.length - 1] !== 0xf7) { + throw new Error('last byte is does not end SYSEX message'); + } + + const trimmedBinary = binary.slice(5, -1); + // every eigth byte is padding, so we remove it + const unpaddedBinary = trimmedBinary.filter((_, idx) => idx % 8); + + const buffer = Buffer.from( + Buffer.from(unpaddedBinary).toString('hex'), + 'hex' + ); + + console.log(parser.parse(buffer)); + + // do stuff with the parsed object +} + +const timbre = new Parser() + .int8('midiChannel') // in 7 bits + .bit2('assignMode') + .bit1('eg2Reset') + .bit1('eg1Reset') + .bit1('triggerMode') + .bit2('keyPriority') + .uint8('unisonDetune') + .uint8('pitchTune') + .uint8('pitchBendRange') + .uint8('pitchTranspose') + .uint8('pitchVibratoInt') + .uint8('osc1Wave') + .uint8('osc1WaveCtrl1') + .uint8('osc1WaveCtrl2') + .uint8('osc1DWGSWave') + .skip(1) + .bit2('not-use1') + .bit2('osc2ModSelect') + .bit2('not-use2') + .bit2('osc2Wave') + .uint8('osc2Semitone') + .uint8('osc2Tune') + .bit1('not-use3') + .bit7('portamentoTime') + .uint8('osc1Level') + .uint8('osc2Level') + .uint8('noiseLevel') + .uint8('filterType') + .uint8('filterCutoff') + .uint8('filterResonance') + .uint8('filterEG1Intensity') + .uint8('filterVelocitySense') + .uint8('filterKeyboardTrack') + .uint8('ampLevel') + .uint8('ampPanpot') + .bit1('not-use4') + .bit1('ampSW') + .bit5('not-use5') + .bit1('ampDistortion') + .uint8('ampVelocitySense') + .uint8('ampKeyboardTrack') + .uint8('eg1Attack') + .uint8('eg1Decay') + .uint8('eg1Sustain') + .uint8('eg1Release') + .uint8('eg2Attack') + .uint8('eg2Decay') + .uint8('eg2Sustain') + .uint8('eg2Release') + .bit2('not-use6') + .bit2('lfo1KeySync') + .bit2('not-use7') + .bit2('lfo1Wave') + .uint8('lfo1Freq') + .bit1('lfo1TempoSync') + .bit2('not-use8') + .bit5('lfo1SyncNote') + .bit2('not-use9') + .bit2('lfo2KeySync') + .bit2('not-use10') + .bit2('lfo2Wave') + .uint8('lfo2Freq') + .bit1('lfo2TempoSync') + .bit2('not-use11') + .bit5('lfo2SyncNote') + .bit4('patch1Dest') + .bit4('patch1Src') + .uint8('patch1Intensity') + .bit4('patch2Dest') + .bit4('patch2Src') + .uint8('patch2Intensity') + .bit4('patch3Dest') + .bit4('patch3Src') + .uint8('patch3Intensity') + .bit4('patch4Dest') + .bit4('patch4Src') + .uint8('patch4Intensity'); + +const vocoder = new Parser() + .int8('midiChannel') // in 7 bits + .bit2('assignMode') + .bit1('eg2Reset') + .bit1('eg1Reset') + .bit1('triggerMode') + .bit2('keyPriority') + .uint8('unisonDetune') + .uint8('pitchTune') + .uint8('pitchBendRange') + .uint8('pitchTranspose') + .uint8('pitchVibratoInt') + .uint8('osc1Wave') + .uint8('osc1WaveCtrl1') + .uint8('osc1WaveCtrl2') + .uint8('osc1DWGSWave') + .skip(1) // dummy byte + .bit7('not-use17') + .bit1('HPF Gate') + .skip(1) + .bit1('not-use18') + .bit7('portamentoTime') + .uint8('osc1Level') + .uint8('ext1Level') + .uint8('noiseLevel') + .uint8('hpfLevel') + .uint8('gateSense') + .uint8('threshold') + .uint8('shift') + .uint8('cutoff') + .uint8('resonance') + .uint8('modSource') + .uint8('intensity') + .uint8('efSense') + .uint8('ampLevel') + .uint8('ampDirectLevel') + .bit7('not-use19') + .bit1('ampDistortion') + .uint8('velocitySense') + .uint8('keyTrack') + // always 0 + .uint8('eg1Attack') + // always 0 + .uint8('eg1Decay') + // always 127 + .uint8('eg1Sustain') + // always 0 + .uint8('eg1Release') + .uint8('eg2Attack') + .uint8('eg2Decay') + .uint8('eg2Sustain') + .uint8('eg2Release') + .bit2('not-use20') + .bit2('lfo1KeySync') + .bit2('not-use21') + .bit2('lfo1Wave') + .uint8('lfo1Freq') + .bit1('lfo1TempoSync') + .bit2('not-use22') + .bit5('lfo1SyncNote') + .bit2('not-use23') + .bit2('lfo2KeySync') + .bit2('not-use24') + .bit2('lfo2Wave') + .uint8('lfo2Freq') + .bit1('lfo2TempoSync') + .bit2('not-use25') + .bit5('lfo2SyncNote') + .array('levels', { + type: 'uint8', + length: 16, + }) + .array('pans', { + type: 'uint8', + length: 16, + }) + .array('efSenseLevels', { + type: 'uint8', + length: 16, + }); + +const parser = new Parser() + .endianess('big') + .string('name', { encoding: 'ASCII', length: 12 }) + .skip(2) + .bit5('not-use12') + .bit3('arpTriggerLength') + .bit8('arpTriggerPattern') + .bit2('not-use13') + .bit2('voiceMode') + .bit4('not-use14') + .bit4('scaleKey') + .bit4('scaleType') + .skip(1) + .bit1('delayFxSync') + .bit3('not-use15') + .bit4('delayFXTimeBase') + .uint8('delayFXDelayTime') + .uint8('delayFXDepth') + .uint8('delayFXType') + .uint8('modFXLFOSpeed') + .uint8('modFXDepth') + .uint8('modFXType') + .uint8('eqHiFreq') + .uint8('eqHiGain') + .uint8('eqLowFreq') + .uint8('eqLowGain') + .uint8('arpTempo') + .uint8('arpSeqTempo') + .bit1('arpOnOff') + .bit1('arpLatchOnOff') + .bit2('arpTarget') + .bit1('not-use16') + .bit1('arpKeySync') + .bit4('arpRange') + .bit4('arpType') + .uint8('arpGateTime') + .uint8('arpResolution') + .uint8('arpSwing') + .uint8('kbdOctave') + .nest('timbre1', { type: timbre }) + // dummy bytes *see documentation + .skip(56) + .nest('timbre2', { type: timbre }) + // dummy bytes *see documentation + .skip(56) + .nest('vocoder', { type: vocoder }) + // dummy bytes *see documentation + .skip(111); + +// converts patch object to dump format the system uses +function serialise(parser, object) { + console.log(parser.encode(object)); +} diff --git a/src/features/menu/Menu.css b/src/features/menu/Menu.css index 63119c4..169be4a 100644 --- a/src/features/menu/Menu.css +++ b/src/features/menu/Menu.css @@ -86,6 +86,15 @@ height: 40vmin; pointer-events: none; padding: 0.5em; + -webkit-user-drag: none; + -khtml-user-drag: none; + -moz-user-drag: none; + -o-user-drag: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -o-user-select: none; + user-select: none; } .menu-title { diff --git a/src/features/menu/Menu.js b/src/features/menu/Menu.js index fdb44ac..17b3e69 100644 --- a/src/features/menu/Menu.js +++ b/src/features/menu/Menu.js @@ -110,7 +110,12 @@ export default function MainMenu() {
- logo + logo

Alapatch

A microKORG Patch Editor