Unified way of reading/writing sysex (and support of sysex chain that contains performance data)

pull/1/head
asb2m10 9 years ago
parent b2517b47dd
commit f89e26caef
  1. 5223
      Builds/MacOSX/Dexed.xcodeproj/project.pbxproj
  2. BIN
      Builds/MacOSX/Dexed.xcodeproj/project.xcworkspace/xcuserdata/asb2m10.xcuserdatad/UserInterfaceState.xcuserstate
  3. 22
      Builds/MacOSX/Dexed.xcodeproj/xcuserdata/asb2m10.xcuserdatad/xcschemes/Dexed.xcscheme
  4. 91
      Builds/MacOSX/Info.plist
  5. 60
      Source/CartManager.cpp
  6. 12
      Source/DXComponents.cpp
  7. 4
      Source/DXComponents.h
  8. 4
      Source/Dexed.h
  9. 2
      Source/GlobalEditor.cpp
  10. 139
      Source/PluginData.cpp
  11. 185
      Source/PluginData.h
  12. 64
      Source/PluginEditor.cpp
  13. 2
      Source/PluginParam.cpp
  14. 12
      Source/PluginProcessor.cpp
  15. 12
      Source/PluginProcessor.h
  16. 13
      Source/ProgramListBox.cpp
  17. 19
      Source/ProgramListBox.h
  18. 5
      Source/msfa/dx7note.cc
  19. 4
      Source/msfa/dx7note.h
  20. 2
      Source/msfa/lfo.cc
  21. 2
      Source/msfa/lfo.h

File diff suppressed because it is too large Load Diff

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0460"
LastUpgradeVersion = "0700"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@ -23,30 +23,42 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "CC364D6AF074DD367C3061CC"
BuildableName = "Dexed.component"
BlueprintName = "Dexed"
ReferencedContainer = "container:Dexed.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction

@ -1,46 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist>
<dict>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>com.digitalsuburban.Dexed</string>
<key>CFBundleName</key>
<string>Dexed</string>
<key>CFBundlePackageType</key>
<string>TDMw</string>
<key>CFBundleSignature</key>
<string>PTul</string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<key>CFBundleVersion</key>
<string>1.0.0</string>
<key>NSHumanReadableCopyright</key>
<string>Digital Suburban</string>
<key>NSHighResolutionCapable</key>
<true/>
<key>AudioComponents</key>
<array>
<dict>
<key>name</key>
<string>Digital Suburban: Dexed</string>
<key>description</key>
<string>Dexed FM Synth</string>
<key>factoryFunction</key>
<string>DexedAUFactory</string>
<key>manufacturer</key>
<string>DGSB</string>
<key>type</key>
<string>aumu</string>
<key>subtype</key>
<string>Dexd</string>
<key>version</key>
<integer>65536</integer>
</dict>
</array>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>AudioComponents</key>
<array>
<dict>
<key>description</key>
<string>Dexed FM Synth</string>
<key>factoryFunction</key>
<string>DexedAUFactory</string>
<key>manufacturer</key>
<string>DGSB</string>
<key>name</key>
<string>Digital Suburban: Dexed</string>
<key>subtype</key>
<string>Dexd</string>
<key>type</key>
<string>aumu</string>
<key>version</key>
<integer>65536</integer>
</dict>
</array>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleName</key>
<string>Dexed</string>
<key>CFBundlePackageType</key>
<string>TDMw</string>
<key>CFBundleShortVersionString</key>
<string>1.0.0</string>
<key>CFBundleSignature</key>
<string>PTul</string>
<key>CFBundleVersion</key>
<string>1.0.0</string>
<key>NSHighResolutionCapable</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>Digital Suburban</string>
</dict>
</plist>

@ -115,10 +115,8 @@ void CartManager::programSelected(ProgramListBox *source, int pos) {
mainWindow->processor->setCurrentProgram(pos);
mainWindow->processor->updateHostDisplay();
} else {
if ( source->getCurrentCart() == nullptr )
return;
char unpackPgm[161];
unpackProgramFromSysex(unpackPgm, source->getCurrentCart(), pos);
uint8_t unpackPgm[161];
source->getCurrentCart().unpackProgram(unpackPgm, pos);
activeCart->setSelected(-1);
browserCart->setSelected(pos);
repaint();
@ -177,7 +175,7 @@ void CartManager::fileDoubleClicked(const File& file) {
if ( file.isDirectory() )
return;
mainWindow->loadCart(file);
activeCart->setCartridge(mainWindow->processor->sysex);
activeCart->setCartridge(mainWindow->processor->currentCart);
}
void CartManager::fileClicked(const File& file, const MouseEvent& e) {
@ -215,7 +213,7 @@ void CartManager::setActiveProgram(int idx, String activeName) {
}
void CartManager::resetActiveSysex() {
activeCart->setCartridge(mainWindow->processor->sysex);
activeCart->setCartridge(mainWindow->processor->currentCart);
}
void CartManager::selectionChanged() {
@ -227,21 +225,14 @@ void CartManager::selectionChanged() {
if ( file.isDirectory() )
return;
String f = file.getFullPathName();
uint8_t syx_data[4104];
ifstream fp_in(f.toRawUTF8(), ios::binary);
if (fp_in.fail()) {
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, "Error", "Unable to open: " + f);
Cartridge browserSysex;
int rc = browserSysex.load(file);
if ( rc < 0 ) {
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, "Error", "Unable to open file");
return;
}
fp_in.read((char *)syx_data, 4104);
fp_in.close();
char browserSysex[4104];
memcpy(browserSysex, syx_data+6, 4096);
int checksum = sysexChecksum(((char *) &browserSysex), 4096);
if ( checksum != syx_data[4102] ) {
if ( rc != 0 ) {
browserCart->readOnly = true;
} else {
browserCart->readOnly = false;
@ -260,15 +251,12 @@ void CartManager::programRightClicked(ProgramListBox *source, int pos) {
switch(menu.show()) {
case 1000:
char unpackPgm[161];
uint8_t unpackPgm[161];
if ( source == activeCart ) {
unpackProgramFromSysex(unpackPgm, mainWindow->processor->sysex, pos);
mainWindow->processor->currentCart.unpackProgram(unpackPgm, pos);
} else {
char *sysex = source->getCurrentCart();
if ( sysex == nullptr )
return;
unpackProgramFromSysex(unpackPgm, sysex, pos);
source->getCurrentCart().unpackProgram(unpackPgm, pos);
}
if ( mainWindow->processor->sysexComm.isOutputActive() )
@ -284,7 +272,7 @@ void CartManager::programRightClicked(ProgramListBox *source, int pos) {
void CartManager::programDragged(ProgramListBox *destListBox, int dest, char *packedPgm) {
if ( destListBox == activeCart ) {
char *sysex = mainWindow->processor->sysex;
char *sysex = mainWindow->processor->currentCart.getRawVoice();
memcpy(sysex+(dest*128), packedPgm, 128);
mainWindow->updateUI();
} else {
@ -295,22 +283,14 @@ void CartManager::programDragged(ProgramListBox *destListBox, int dest, char *pa
if ( file.isDirectory() )
return;
if ( file.getSize() > 5000 )
return;
MemoryBlock block;
file.loadFileAsData(block);
if ( block.getSize() < 4104 )
if ( file.getSize() != 4104 )
return;
char *sysex = ((char *) block.getData()) + 6;
memcpy(sysex+(dest*128), packedPgm, 128);
char exported[4104];
exportSysexCart(exported, sysex, 0);
file.replaceWithData(exported, 4104);
browserCart->setCartridge(sysex);
Cartridge cart;
cart.load(file);
memcpy(cart.getRawVoice()+(dest*128), packedPgm, 128);
cart.saveVoice(file);
browserCart->setCartridge(cart);
}
}

@ -157,13 +157,13 @@ static double getDuration(int p_rate, int p_level_l, int p_level_r) {
}
EnvDisplay::EnvDisplay() {
pvalues = (char *) &TMP_LEVEL_PTR;
pvalues = (uint8_t *) &TMP_LEVEL_PTR;
}
void EnvDisplay::paint(Graphics &g) {
int h = getHeight();
char *rates = pvalues;
char *levels = pvalues + 4;
uint8_t *rates = pvalues;
uint8_t *levels = pvalues + 4;
double d[4];
double keyoff = 0.0;
@ -250,15 +250,15 @@ void EnvDisplay::paint(Graphics &g) {
}
PitchEnvDisplay::PitchEnvDisplay() {
pvalues = (char *) &TMP_LEVEL_PTR;
pvalues = (uint8_t *) &TMP_LEVEL_PTR;
vPos = 0;
}
void PitchEnvDisplay::paint(Graphics &g) {
g.setColour(Colours::white);
char *levels = pvalues + 4;
char *rates = pvalues;
uint8_t *levels = pvalues + 4;
uint8_t *rates = pvalues;
float dist[4];
float total = 0;

@ -26,7 +26,7 @@
class EnvDisplay : public Component {
public:
EnvDisplay();
char *pvalues;
uint8_t *pvalues;
char vPos;
void paint(Graphics &g);
};
@ -35,7 +35,7 @@ class PitchEnvDisplay : public Component {
char rvalues[8];
public:
PitchEnvDisplay();
char *pvalues;
uint8_t *pvalues;
char vPos;
void paint(Graphics &g);
};

@ -24,14 +24,14 @@
void dexed_trace(const char *source, const char *fmt, ...);
#ifdef DEBUG
#define DEXED_VERSION "0.9.0 DEBUG"
#define DEXED_VERSION "0.9.1 DEBUG"
#ifdef _MSC_VER
#define TRACE(fmt, ...) dexed_trace(__FUNCTION__,fmt,##__VA_ARGS__)
#else
#define TRACE(fmt, ...) dexed_trace(__PRETTY_FUNCTION__,fmt,##__VA_ARGS__)
#endif
#else
#define DEXED_VERSION "0.9.0"
#define DEXED_VERSION "0.9.1"
#define TRACE(fmt, ...)
#endif

@ -542,7 +542,7 @@ void GlobalEditor::bind(DexedAudioProcessorEditor *edit) {
processor->fxCutoff->bind(cutoff);
processor->fxReso->bind(reso);
processor->output->bind(output);
algoDisplay->algo = &(processor->data[134]);
algoDisplay->algo = (char *) &(processor->data[134]);
pitchEnvDisplay->pvalues = &(processor->data[126]);
editor = edit;

@ -28,7 +28,7 @@
#include <fstream>
using namespace ::std;
uint8_t sysexChecksum(const char *sysex, int size) {
uint8_t sysexChecksum(const uint8_t *sysex, int size) {
int sum = 0;
int i;
@ -36,64 +36,9 @@ uint8_t sysexChecksum(const char *sysex, int size) {
return sum & 0x7F;
}
String normalizeSysexName(const char *sysexName) {
char buffer[11];
memcpy(buffer, sysexName, 10);
for (int j = 0; j < 10; j++) {
char c = (unsigned char) buffer[j];
switch (c) {
case 92:
c = 'Y';
break; /* yen */
case 126:
c = '>';
break; /* >> */
case 127:
c = '<';
break; /* << */
default:
if (c < 32 || c > 127)
c = 32;
break;
}
buffer[j] = c;
}
buffer[10] = 0;
return String(buffer);
}
void extractProgramNames(const char *block, StringArray &dest) {
dest.clear();
for (int i = 0; i < 32; i++) {
dest.add(String(normalizeSysexName(block + ((i * 128) + 118))));
}
}
void exportSysexCart(char *dest, char *src, char sysexChl) {
uint8_t header[] = { 0xF0, 0x43, 0x00, 0x09, 0x20, 0x00 };
header[2] = sysexChl;
memcpy(dest, header, 6);
// copy 32 voices
memcpy(dest+6, src, 4096);
// make checksum for dump
uint8_t footer[] = { sysexChecksum(src, 4096), 0xF7 };
memcpy(dest+4102, footer, 2);
}
void exportSysexPgm(char *dest, char *src, char sysexChl) {
void exportSysexPgm(uint8_t *dest, uint8_t *src) {
uint8_t header[] = { 0xF0, 0x43, 0x00, 0x00, 0x01, 0x1B };
header[2] = sysexChl;
memcpy(dest, header, 6);
// copy 1 unpacked voices
@ -110,8 +55,8 @@ void exportSysexPgm(char *dest, char *src, char sysexChl) {
/**
* Pack a program into a 32 packed sysex
*/
void packProgram(uint8_t *dest, uint8_t *src, int idx, String name) {
uint8_t *bulk = dest + (idx * 128);
void Cartridge::packProgram(uint8_t *src, int idx, String name) {
uint8_t *bulk = voiceData + 6 + (idx * 128);
for(int op = 0; op < 6; op++) {
// eg rate and level, brk pt, depth, scaling
@ -171,8 +116,9 @@ char normparm(char value, char max, int id) {
return v;
}
void unpackProgramFromSysex(char *unpackPgm, char *sysexCart, int idx) {
char *bulk = sysexCart + (idx * 128);
void Cartridge::unpackProgram(uint8_t *unpackPgm, int idx) {
// TODO put this in uint8_t :D
char *bulk = (char *)voiceData + 6 + (idx * 128);
for (int op = 0; op < 6; op++) {
// eg rate and level, brk pt, depth, scaling
@ -220,53 +166,33 @@ void unpackProgramFromSysex(char *unpackPgm, char *sysexCart, int idx) {
unpackPgm[160] = 1;
}
void DexedAudioProcessor::unpackProgram(int idx) {
unpackProgramFromSysex(data, sysex, idx);
}
int DexedAudioProcessor::importSysex(const char *imported) {
memcpy(sysex, imported + 6, 4096);
uint8_t checksum = sysexChecksum(((char *) &sysex), 4096);
extractProgramNames(sysex, programNames);
if ( checksum != imported[4102] ) {
TRACE("sysex import checksum doesnt match %d != %d", checksum, imported[4102]);
return 1;
}
return 0;
void DexedAudioProcessor::loadCartridge(Cartridge &sysex) {
currentCart = sysex;
currentCart.getProgramNames(programNames);
}
void DexedAudioProcessor::updateProgramFromSysex(const uint8 *rawdata) {
void DexedAudioProcessor::updateProgramFromSysex(const uint8_t *rawdata) {
memcpy(data, rawdata, 161);
triggerAsyncUpdate();
}
void DexedAudioProcessor::setupStartupCart() {
char syx_data[4104];
memset(&syx_data, 0, 4104);
File startup = dexedCartDir.getChildFile("Dexed_01.syx");
if ( currentCart.load(startup) != -1 )
return;
if ( startup.exists() ) {
FileInputStream *fis = startup.createInputStream();
if ( fis == nullptr ) {
TRACE("unable to open default cartridge");
return;
}
fis->read(syx_data, 4104);
delete fis;
} else {
// The user deleted the file :/, load from the builtin zip file.
MemoryInputStream *mis = new MemoryInputStream(BinaryData::builtin_pgm_zip, BinaryData::builtin_pgm_zipSize, false);
ZipFile *builtin_pgm = new ZipFile(mis, true);
InputStream *is = builtin_pgm->createStreamForEntry(builtin_pgm->getIndexOfFileName(("Dexed_01.syx")));
is->read(syx_data, 4104);
delete is;
delete builtin_pgm;
}
importSysex((char *) &syx_data);
// The user deleted the file :/, load from the builtin zip file.
MemoryInputStream *mis = new MemoryInputStream(BinaryData::builtin_pgm_zip, BinaryData::builtin_pgm_zipSize, false);
ZipFile *builtin_pgm = new ZipFile(mis, true);
InputStream *is = builtin_pgm->createStreamForEntry(builtin_pgm->getIndexOfFileName(("Dexed_01.syx")));
Cartridge init;
if ( init.load(*is) != -1 )
loadCartridge(init);
delete is;
delete builtin_pgm;
}
void DexedAudioProcessor::resetToInitVoice() {
@ -305,7 +231,7 @@ void DexedAudioProcessor::pasteEnvFromClipboard(int destOp) {
void DexedAudioProcessor::sendCurrentSysexProgram() {
uint8_t raw[167];
exportSysexPgm((char *) raw, data, sysexComm.getChl());
exportSysexPgm(raw, data);
if ( sysexComm.isOutputActive() ) {
sysexComm.send(MidiMessage(raw, 163));
}
@ -314,7 +240,7 @@ void DexedAudioProcessor::sendCurrentSysexProgram() {
void DexedAudioProcessor::sendCurrentSysexCartridge() {
uint8_t raw[4104];
exportSysexCart((char *) raw, (char *) &sysex, sysexComm.getChl());
currentCart.saveVoice(raw);
if ( sysexComm.isOutputActive() ) {
sysexComm.send(MidiMessage(raw, 4104));
}
@ -363,11 +289,8 @@ void DexedAudioProcessor::getStateInformation(MemoryBlock& destData) {
if ( activeFileCartridge.exists() )
dexedState.setAttribute("activeFileCartridge", activeFileCartridge.getFullPathName());
char sysex_blob[4104];
exportSysexCart((char *) &sysex_blob, (char *) sysex, 0);
NamedValueSet blobSet;
blobSet.set("sysex", var((void *) &sysex_blob, 4104));
blobSet.set("sysex", var((void *) currentCart.getVoiceSysex(), 4104));
blobSet.set("program", var((void *) &data, 161));
blobSet.copyToXmlAttributes(*dexedBlob);
@ -415,7 +338,9 @@ void DexedAudioProcessor::setStateInformation(const void* source, int sizeInByte
return;
}
importSysex((char *) sysex_blob.getBinaryData()->getData());
Cartridge cart;
cart.load((uint8 *)sysex_blob.getBinaryData()->getData(), 4104);
loadCartridge(cart);
memcpy(data, program.getBinaryData()->getData(), 161);
lastStateSave = (long) time(NULL);

@ -25,46 +25,155 @@
#define SYSEX_SIZE 4104
#include <stdint.h>
#include "Dexed.h"
enum UnpackedOffset {
egRate,
egLevel = 4,
breakpoint = 8,
lScaleDepth,
rScaleDepth,
lKeyScale,
rKeyScale,
rateScaling,
keyVelocity,
outputLevel,
mode,
fCoarse,
fFine,
oscDetune,
uint8_t sysexChecksum(const uint8_t *sysex, int size);
// Global values
pitchEgRate = 126,
pitchEgLevel = 130,
algorythm = 134,
feedback,
oscKeySync,
lfoSpeed,
lfoDelay,
lfoPmDepth,
lfoAmDepth,
lfoKeySync,
lfoWave,
middleC,
pModeSens,
osc6state
};
#define SYSEX_HEADER { 0xF0, 0x43, 0x00, 0x00, 0x20, 0x00 }
class Cartridge {
uint8_t voiceData[SYSEX_SIZE];
uint8_t perfData[SYSEX_SIZE];
void setHeader() {
uint8 voiceHeader[] = SYSEX_HEADER;
memcpy(voiceData, voiceHeader, 6);
voiceData[4102] = sysexChecksum(voiceData+6, 4096);
voiceData[4103] = 0xF7;
}
public:
Cartridge() { }
Cartridge(const Cartridge &cpy) {
memcpy(voiceData, cpy.voiceData, SYSEX_SIZE);
memcpy(perfData, cpy.perfData, SYSEX_SIZE);
}
static String normalizePgmName(const char *sysexName) {
char buffer[11];
memcpy(buffer, sysexName, 10);
for (int j = 0; j < 10; j++) {
char c = (unsigned char) buffer[j];
switch (c) {
case 92:
c = 'Y';
break; /* yen */
case 126:
c = '>';
break; /* >> */
case 127:
c = '<';
break; /* << */
default:
if (c < 32 || c > 127)
c = 32;
break;
}
buffer[j] = c;
}
buffer[10] = 0;
return String(buffer);
}
int load(File f) {
FileInputStream *fis = f.createInputStream();
if ( fis == NULL )
return -1;
int rc = load(*fis);
delete fis;
return rc;
}
int load(InputStream &fis) {
uint8 buffer[65535];
int sz = fis.read(buffer, 65535);
if ( sz == 0 )
return -1;
return load(buffer, sz);
}
int load(const uint8_t *stream, int size) {
uint8 voiceHeader[] = SYSEX_HEADER;
uint8 tmp[65535];
uint8 *pos = tmp;
int status = 3;
if ( size > 65535 )
size = 65535;
memcpy(tmp, stream, size);
while(size >= 4104) {
// random data
if ( pos[0] != 0xF0 ) {
if ( status != 0 )
return status;
memcpy(voiceData, pos+6, 4096);
return 2;
}
pos[3] = 0;
if ( memcmp(pos, voiceHeader, 6) == 0 ) {
memcpy(voiceData, pos, SYSEX_SIZE);
if ( sysexChecksum(voiceData + 6, 4096) == pos[4102] )
status = 0;
else
status = 1;
size -= 4104;
pos += 4104;
continue;
}
String normalizeSysexName(const char *sysexName);
uint8_t sysexChecksum(const char *sysex, int size);
void extractProgramNames(const char *block, StringArray &dest);
void exportSysexCart(char *dest, char *src, char sysexChl);
void exportSysexPgm(char *dest, char *src, char sysexChl);
void packProgram(uint8_t *dest, uint8_t *src, int idx, String name);
void unpackProgramFromSysex(char *unpackPgm, char *sysexCart, int idx);
// other sysex
int i;
for(i=0;i<size-1;i++) {
if ( pos[i] == 0xF7 )
break;
}
size -= i;
stream += i;
}
return status;
}
int saveVoice(File f) {
setHeader();
return f.replaceWithData(voiceData, SYSEX_SIZE);
}
void saveVoice(uint8_t *sysex) {
setHeader();
memcpy(sysex, voiceData, SYSEX_SIZE);
}
char *getRawVoice() {
return (char *) voiceData + 6;
}
char *getVoiceSysex() {
setHeader();
return (char *) voiceData;
}
void getProgramNames(StringArray &dest) {
dest.clear();
for (int i = 0; i < 32; i++)
dest.add( normalizePgmName(getRawVoice() + ((i * 128) + 118)) );
}
Cartridge operator =(const Cartridge other) {
memcpy(voiceData, other.voiceData, SYSEX_SIZE);
memcpy(perfData, other.perfData, SYSEX_SIZE);
return *this;
}
void unpackProgram(uint8_t *unpackPgm, int idx);
void packProgram(uint8_t *src, int idx, String name);
};
#endif // PLUGINDATA_H_INCLUDED

@ -140,22 +140,18 @@ void DexedAudioProcessorEditor::cartShow() {
void DexedAudioProcessorEditor::loadCart(File file) {
String f = file.getFullPathName();
uint8_t syx_data[4104];
ifstream fp_in(f.toRawUTF8(), ios::binary);
if (fp_in.fail()) {
Cartridge cart;
if ( cart.load(file) < 0 ) {
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
"Error",
"Unable to open: " + f);
"Unable to open: " + file.getFullPathName());
return;
}
fp_in.read((char *)syx_data, 4104);
fp_in.close();
if ( processor->importSysex((char *) &syx_data) ) {
global.setSystemMessage(String("Unkown sysex format !?"));
}
processor->setCurrentProgram(0);
processor->loadCartridge(cart);
rebuildProgramCombobox();
processor->setCurrentProgram(0);
global.programs->setSelectedId(processor->getCurrentProgram()+1, dontSendNotification);
processor->updateHostDisplay();
@ -167,19 +163,10 @@ void DexedAudioProcessorEditor::saveCart() {
FileChooser fc ("Export DX sysex...", processor->dexedCartDir, "*.syx", 1);
if ( fc.browseForFileToSave(true) ) {
String f = fc.getResults().getReference(0).getFullPathName();
char syx_data[4104];
exportSysexCart((char *) syx_data, (char *) &processor->sysex, 0);
ofstream fp_out(f.toRawUTF8(), ios::binary);
fp_out.write((char *)syx_data, 4104);
fp_out.close();
if (fp_out.fail()) {
if ( ! processor->currentCart.saveVoice(fc.getResults().getReference(0)) ) {
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
"Error",
"Unable to write: " + f);
"Unable to write: " + fc.getResults().getReference(0).getFullPathName());
}
}
}
@ -250,6 +237,8 @@ void DexedAudioProcessorEditor::updateUI() {
void DexedAudioProcessorEditor::rebuildProgramCombobox() {
global.programs->clear(dontSendNotification);
processor->currentCart.getProgramNames(processor->programNames);
for(int i=0;i<processor->getNumPrograms();i++) {
String id;
id << (i+1) << ". " << processor->getProgramName(i);
@ -258,7 +247,7 @@ void DexedAudioProcessorEditor::rebuildProgramCombobox() {
global.programs->setSelectedId(processor->getCurrentProgram()+1, dontSendNotification);
String name = normalizeSysexName((const char *) processor->data+145);
String name = Cartridge::normalizePgmName((const char *) processor->data+145);
cartManager.setActiveProgram(processor->getCurrentProgram(), name);
if ( name != processor->getProgramName(processor->getCurrentProgram()) )
global.programs->setText("**. " + name, dontSendNotification);
@ -267,11 +256,9 @@ void DexedAudioProcessorEditor::rebuildProgramCombobox() {
}
void DexedAudioProcessorEditor::storeProgram() {
String currentName = normalizeSysexName((const char *) processor->data+145);
char destSysex[4096];
String currentName = Cartridge::normalizePgmName((const char *) processor->data+145);
Cartridge destSysex = processor->currentCart;
File *externalFile = NULL;
memcpy(&destSysex, processor->sysex, 4096);
bool activeCartridgeFound = processor->activeFileCartridge.exists();
@ -292,7 +279,7 @@ void DexedAudioProcessorEditor::storeProgram() {
// TODO: fix the name length to 10
StringArray programs;
extractProgramNames((char *) &destSysex, programs);
destSysex.getProgramNames(programs);
dialog.addComboBox("Dest", programs, "Program Destination");
@ -318,12 +305,9 @@ void DexedAudioProcessorEditor::storeProgram() {
if ( externalFile != NULL )
delete externalFile;
MemoryBlock block;
externalFile = new File(fc.getResults().getReference(0));
if ( externalFile->loadFileAsData(block) ) {
block.copyTo(destSysex, 6, 4096);
if ( destSysex.load(*externalFile) )
continue;
}
AlertWindow::showMessageBoxAsync(AlertWindow::WarningIcon, "Read error", "Unable to read file");
}
}
@ -340,8 +324,7 @@ void DexedAudioProcessorEditor::storeProgram() {
}
if ( externalFile == NULL ) {
packProgram((uint8_t *) processor->sysex, (uint8_t *) processor->data, programNum, programName);
processor->programNames.set(programNum, programName);
processor->currentCart.packProgram((uint8_t *) processor->data, programNum, programName);
rebuildProgramCombobox();
processor->setCurrentProgram(programNum);
processor->updateHostDisplay();
@ -355,18 +338,13 @@ void DexedAudioProcessorEditor::storeProgram() {
break;
destination = fc.getResult();
}
char sysexFile[4104];
exportSysexCart((char *) &sysexFile, (char *) &processor->sysex, 0);
if ( ! destination.replaceWithData(sysexFile, 4104) ) {
AlertWindow::showMessageBoxAsync(AlertWindow::WarningIcon, "Write error", "Unable to write file");
}
processor->currentCart.saveVoice(destination);
processor->activeFileCartridge = destination;
}
} else {
packProgram((uint8_t *) &destSysex, (uint8_t *) processor->data, programNum, programName);
char sysexFile[4104];
exportSysexCart((char *) &sysexFile, (char *) &destSysex, 0);
if ( ! externalFile->replaceWithData(sysexFile, 4104) ) {
destSysex.packProgram((uint8_t *) processor->data, programNum, programName);
if ( ! destSysex.saveVoice(*externalFile)) {
AlertWindow::showMessageBoxAsync(AlertWindow::WarningIcon, "Write error", "Unable to write file");
}
}

@ -512,7 +512,7 @@ void DexedAudioProcessor::setCurrentProgram(int index) {
panic();
index = index > 31 ? 31 : index;
unpackProgram(index);
currentCart.unpackProgram(data, index);
lfo.reset(data + 137);
currentProgram = index;
triggerAsyncUpdate();

@ -152,7 +152,7 @@ void DexedAudioProcessor::processBlock(AudioSampleBuffer& buffer, MidiBuffer& mi
MidiBuffer::Iterator it(midiMessages);
hasMidiMessage = it.getNextEvent(*nextMidi,midiEventPos);
float *channelData = buffer.getSampleData(0);
float *channelData = buffer.getWritePointer(0);
// flush first events
for (i=0; i < numSamples && i < extra_buf_size; i++) {
@ -443,13 +443,11 @@ void DexedAudioProcessor::handleIncomingMidiMessage(MidiInput* source, const Mid
// 32 voice dump
if ( buf[3] == 9 ) {
if ( sz < 4104 ) {
TRACE("wrong 32 voice datasize %d", sz);
return;
Cartridge received;
if ( received.load(buf, sz) ) {
loadCartridge(received);
setCurrentProgram(0);
}
TRACE("update 32bulk voice");
importSysex((const char *)buf);
setCurrentProgram(0);
}
updateHostDisplay();

@ -115,14 +115,14 @@ class DexedAudioProcessor : public AudioProcessor, public AsyncUpdater, public
char clipboardContent;
void resolvAppDir();
public :
// in MIDI units (0x4000 is neutral)
Controllers controllers;
StringArray programNames;
char sysex[4096];
char data[161];
StringArray programNames;
Cartridge currentCart;
uint8_t data[161];
//CartridgeManager cartManager;
SysexComm sysexComm;
VoiceStatus voiceStatus;
File activeFileCartridge;
@ -154,7 +154,8 @@ public :
ScopedPointer<CtrlFloat> fxReso;
ScopedPointer<CtrlFloat> output;
int importSysex(const char *imported);
//int importSysex(const char *imported);
void loadCartridge(Cartridge &cart);
void setDxValue(int offset, int v);
//==============================================================================
@ -184,7 +185,6 @@ public :
bool hasEditor() const;
void updateUI();
bool peekVoiceStatus();
void unpackProgram(int idx);
void updateProgramFromSysex(const uint8 *rawdata);
void setupStartupCart();

@ -30,6 +30,7 @@ ProgramListBox::ProgramListBox(const String name, int numCols) : Component(name)
hasContent = false;
dragCandidate = -1;
readOnly = false;
programNames.clear();
}
void ProgramListBox::paint(Graphics &g) {
@ -85,9 +86,9 @@ void ProgramListBox::resized() {
cellHeight = getHeight() / rows;
}
void ProgramListBox::setCartridge(char *sysex) {
extractProgramNames((const char *)sysex, programNames);
memcpy(cartContent, sysex, 4104);
void ProgramListBox::setCartridge(Cartridge &cart) {
cartContent = cart;
cartContent.getProgramNames(programNames);
hasContent = true;
repaint();
}
@ -138,7 +139,7 @@ void ProgramListBox::mouseDrag(const MouseEvent &event) {
g.fillRect(0,0,cellWidth, cellHeight);
g.setColour(Colours::white);
g.drawFittedText(programNames[position], 0, 0, cellWidth, cellHeight, Justification::centred, true);
void *src = cartContent + (position*128);
void *src = cartContent.getRawVoice() + (position*128);
var description = var(src, 128);
dragContainer->startDragging(description, this, snapshot, false);
}
@ -148,9 +149,7 @@ void ProgramListBox::setSelected(int idx) {
selectedPgm = idx;
}
char* ProgramListBox::getCurrentCart() {
if ( ! hasContent )
return nullptr;
Cartridge &ProgramListBox::getCurrentCart() {
return cartContent;
}

@ -22,6 +22,7 @@
#define PROGRAMLISTBOX_H_INCLUDED
#include "JuceHeader.h"
#include "PluginData.h"
class ProgramListBox;
class ProgramListBoxListener {
@ -41,8 +42,7 @@ class ProgramListBox : public Component, public DragAndDropTarget {
int programPosition(int x, int y);
int selectedPgm;
// TODO: this should be a pointer
char cartContent[4104];
Cartridge cartContent;
int dragCandidate;
public:
@ -52,14 +52,15 @@ public:
ProgramListBox(const String name, int numCols);
void addListener(ProgramListBoxListener *listener);
void paint(Graphics &g);
void setCartridge(char *sysex);
void resized();
void mouseDoubleClick(const MouseEvent &event);
void mouseDown(const MouseEvent &event);
void mouseDrag(const MouseEvent &event);
void paint(Graphics &g) override;
void resized() override;
void mouseDoubleClick(const MouseEvent &event) override;
void mouseDown(const MouseEvent &event) override;
void mouseDrag(const MouseEvent &event) override;
void setSelected(int idx);
char* getCurrentCart();
Cartridge &getCurrentCart();
void setCartridge(Cartridge &cart);
bool isInterestedInDragSource(const SourceDetails& dragSourceDetails) override;
void itemDragEnter(const SourceDetails &dragSourceDetails) override;

@ -139,7 +139,7 @@ Dx7Note::Dx7Note() {
}
}
void Dx7Note::init(const char patch[156], int midinote, int velocity) {
void Dx7Note::init(const uint8_t patch[156], int midinote, int velocity) {
int rates[4];
int levels[4];
for (int op = 0; op < 6; op++) {
@ -244,7 +244,7 @@ void Dx7Note::keyup() {
}
}
void Dx7Note::update(const char patch[156], int midinote) {
void Dx7Note::update(const uint8_t patch[156], int midinote) {
for (int op = 0; op < 6; op++) {
int off = op * 21;
int mode = patch[off + 17];
@ -285,7 +285,6 @@ void Dx7Note::transferSignal(Dx7Note &src) {
for (int i=0;i<6;i++) {
params_[i].gain_out = src.params_[i].gain_out;
params_[i].phase = src.params_[i].phase;
//params_[i].phase = 0;
}
}

@ -36,7 +36,7 @@ struct VoiceStatus {
class Dx7Note {
public:
Dx7Note();
void init(const char patch[156], int midinote, int velocity);
void init(const uint8_t patch[156], int midinote, int velocity);
// Note: this _adds_ to the buffer. Interesting question whether it's
// worth it...
@ -51,7 +51,7 @@ class Dx7Note {
// keyup, that won't work.
// PG:add the update
void update(const char patch[156], int midinote);
void update(const uint8_t patch[156], int midinote);
void peekVoiceStatus(VoiceStatus &status);
void transferState(Dx7Note& src);
void transferSignal(Dx7Note &src);

@ -28,7 +28,7 @@ void Lfo::init(double sample_rate) {
Lfo::unit_ = (int32_t)(N * 25190424 / sample_rate + 0.5);
}
void Lfo::reset(const char params[6]) {
void Lfo::reset(const uint8_t params[6]) {
int rate = params[0]; // 0..99
int sr = rate == 0 ? 1 : (165 * rate) >> 6;
sr *= sr < 160 ? 11 : (11 + ((sr - 160) >> 4));

@ -19,7 +19,7 @@
class Lfo {
public:
static void init(double sample_rate);
void reset(const char params[6]);
void reset(const uint8_t params[6]);
// result is 0..1 in Q24
int32_t getsample();

Loading…
Cancel
Save