DX7 Editor : Tested with real DX7

pull/1/head
Pascal Gauthier 10 years ago
parent 052cc04ab7
commit a28b651a5f
  1. 1
      .gitignore
  2. BIN
      Builds/VisualStudio2012/Dexed.v11.suo
  3. 964
      Builds/VisualStudio2012/Dexed.vcxproj
  4. 92
      Builds/VisualStudio2012/Dexed.vcxproj.filters
  5. 33
      README.md
  6. 9
      Source/DXComponents.cpp
  7. 22
      Source/ParamDialog.cpp
  8. 2
      Source/ParamDialog.h
  9. 62
      Source/PluginData.cpp
  10. 1
      Source/PluginData.h
  11. 85
      Source/PluginEditor.cpp
  12. 4
      Source/PluginEditor.h
  13. 2
      Source/PluginParam.cpp
  14. 107
      Source/PluginProcessor.cpp
  15. 4
      Source/PluginProcessor.h
  16. 60
      Source/SysexComm.cpp
  17. 15
      Source/SysexComm.h

1
.gitignore vendored

@ -0,0 +1 @@
Builds/VisualStudio2012/Dexed.vcxproj.user

File diff suppressed because it is too large Load Diff

@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Dexed">
@ -385,9 +384,6 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_basics\synthesisers\juce_Synthesiser.cpp">
<Filter>Juce Modules\juce_audio_basics\synthesisers</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\AU\juce_AU_Wrapper.mm">
<Filter>Juce Modules\juce_audio_plugin_client\AU</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\RTAS\juce_RTAS_DigiCode1.cpp">
<Filter>Juce Modules\juce_audio_plugin_client\RTAS</Filter>
</ClCompile>
@ -403,27 +399,15 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\RTAS\juce_RTAS_Wrapper.cpp">
<Filter>Juce Modules\juce_audio_plugin_client\RTAS</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\RTAS\juce_RTAS_MacUtilities.mm">
<Filter>Juce Modules\juce_audio_plugin_client\RTAS</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST\juce_VST_Wrapper.cpp">
<Filter>Juce Modules\juce_audio_plugin_client\VST</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST\juce_VST_Wrapper.mm">
<Filter>Juce Modules\juce_audio_plugin_client\VST</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST3\juce_VST3_Wrapper.cpp">
<Filter>Juce Modules\juce_audio_plugin_client\VST3</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST3\juce_VST3_Wrapper.mm">
<Filter>Juce Modules\juce_audio_plugin_client\VST3</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\AAX\juce_AAX_Wrapper.cpp">
<Filter>Juce Modules\juce_audio_plugin_client\AAX</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\AAX\juce_AAX_Wrapper.mm">
<Filter>Juce Modules\juce_audio_plugin_client\AAX</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\utility\juce_PluginUtilities.cpp">
<Filter>Juce Modules\juce_audio_plugin_client\utility</Filter>
</ClCompile>
@ -448,9 +432,6 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format\juce_AudioPluginFormatManager.cpp">
<Filter>Juce Modules\juce_audio_processors\format</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_AudioUnitPluginFormat.mm">
<Filter>Juce Modules\juce_audio_processors\format_types</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_processors\format_types\juce_LADSPAPluginFormat.cpp">
<Filter>Juce Modules\juce_audio_processors\format_types</Filter>
</ClCompile>
@ -691,21 +672,6 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\native\juce_linux_Threads.cpp">
<Filter>Juce Modules\juce_core\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\native\juce_mac_Files.mm">
<Filter>Juce Modules\juce_core\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\native\juce_mac_Network.mm">
<Filter>Juce Modules\juce_core\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\native\juce_mac_Strings.mm">
<Filter>Juce Modules\juce_core\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\native\juce_mac_SystemStats.mm">
<Filter>Juce Modules\juce_core\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\native\juce_mac_Threads.mm">
<Filter>Juce Modules\juce_core\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_core\native\juce_posix_NamedPipe.cpp">
<Filter>Juce Modules\juce_core\native</Filter>
</ClCompile>
@ -778,15 +744,9 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_events\native\juce_android_Messaging.cpp">
<Filter>Juce Modules\juce_events\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_events\native\juce_ios_MessageManager.mm">
<Filter>Juce Modules\juce_events\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_events\native\juce_linux_Messaging.cpp">
<Filter>Juce Modules\juce_events\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_events\native\juce_mac_MessageManager.mm">
<Filter>Juce Modules\juce_events\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_events\native\juce_win32_Messaging.cpp">
<Filter>Juce Modules\juce_events\native</Filter>
</ClCompile>
@ -886,12 +846,6 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_graphics\native\juce_linux_Fonts.cpp">
<Filter>Juce Modules\juce_graphics\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_graphics\native\juce_mac_CoreGraphicsContext.mm">
<Filter>Juce Modules\juce_graphics\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_graphics\native\juce_mac_Fonts.mm">
<Filter>Juce Modules\juce_graphics\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_graphics\native\juce_win32_Direct2DGraphicsContext.cpp">
<Filter>Juce Modules\juce_graphics\native</Filter>
</ClCompile>
@ -1240,12 +1194,6 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\native\juce_android_Windowing.cpp">
<Filter>Juce Modules\juce_gui_basics\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\native\juce_ios_UIViewComponentPeer.mm">
<Filter>Juce Modules\juce_gui_basics\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\native\juce_ios_Windowing.mm">
<Filter>Juce Modules\juce_gui_basics\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\native\juce_linux_Clipboard.cpp">
<Filter>Juce Modules\juce_gui_basics\native</Filter>
</ClCompile>
@ -1255,21 +1203,6 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\native\juce_linux_Windowing.cpp">
<Filter>Juce Modules\juce_gui_basics\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\native\juce_mac_FileChooser.mm">
<Filter>Juce Modules\juce_gui_basics\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\native\juce_mac_MainMenu.mm">
<Filter>Juce Modules\juce_gui_basics\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\native\juce_mac_MouseCursor.mm">
<Filter>Juce Modules\juce_gui_basics\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\native\juce_mac_NSViewComponentPeer.mm">
<Filter>Juce Modules\juce_gui_basics\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\native\juce_mac_Windowing.mm">
<Filter>Juce Modules\juce_gui_basics\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_basics\native\juce_win32_DragAndDrop.cpp">
<Filter>Juce Modules\juce_gui_basics\native</Filter>
</ClCompile>
@ -1324,27 +1257,15 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\native\juce_android_WebBrowserComponent.cpp">
<Filter>Juce Modules\juce_gui_extra\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\native\juce_ios_UIViewComponent.mm">
<Filter>Juce Modules\juce_gui_extra\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\native\juce_linux_SystemTrayIcon.cpp">
<Filter>Juce Modules\juce_gui_extra\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\native\juce_linux_WebBrowserComponent.cpp">
<Filter>Juce Modules\juce_gui_extra\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\native\juce_mac_AppleRemote.mm">
<Filter>Juce Modules\juce_gui_extra\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\native\juce_mac_NSViewComponent.mm">
<Filter>Juce Modules\juce_gui_extra\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\native\juce_mac_SystemTrayIcon.cpp">
<Filter>Juce Modules\juce_gui_extra\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\native\juce_mac_WebBrowserComponent.mm">
<Filter>Juce Modules\juce_gui_extra\native</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_gui_extra\native\juce_win32_ActiveXComponent.cpp">
<Filter>Juce Modules\juce_gui_extra\native</Filter>
</ClCompile>
@ -1417,6 +1338,15 @@
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST\juce_VST_Wrapper.cpp">
<Filter>Juce Library Code</Filter>
</ClCompile>
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\AAX\juce_AAX_Wrapper.cpp" />
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\utility\juce_PluginUtilities.cpp" />
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\RTAS\juce_RTAS_DigiCode1.cpp" />
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\RTAS\juce_RTAS_DigiCode2.cpp" />
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\RTAS\juce_RTAS_DigiCode3.cpp" />
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\RTAS\juce_RTAS_WinUtilities.cpp" />
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\RTAS\juce_RTAS_Wrapper.cpp" />
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST3\juce_VST3_Wrapper.cpp" />
<ClCompile Include="..\..\JuceLibraryCode\modules\juce_audio_plugin_client\VST\juce_VST_Wrapper.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\Source\Dexed.h">
@ -2714,4 +2644,4 @@
<Filter>Juce Library Code</Filter>
</ResourceCompile>
</ItemGroup>
</Project>
</Project>

@ -25,7 +25,7 @@ Features
Changelog
---------
#### Version 0.6.0 (current sprint)
* Added external midi interface to send / receive sysex message
* Added external midi interface to send / receive sysex messages
* Fix Tracktion crash upon startup
* Middle C (transpose) now works
* Mouse over the interface controls now tells what it does without having to change it
@ -47,7 +47,9 @@ Changelog
Binary downloads
----------------
Dexed is not a finished product but it is stable enough to be used in a DAW environment:
in normal operation it shouldn't crash and the VST state saving works. If you don't see the new version here but you see it in the change log, it's because this version is in development (current sprint). Only officials (tested) builds are listed here.
in normal operation it shouldn't crash and the VST state saving works. If you don't see the
new version here but you see it in the change log, it's because this version is in development
(current sprint). Only officials (tested) builds are listed here.
* Version 0.5.1 [vst win32](http://le-son666.com/software/dexed/dexed-0.5.1-win32.zip) - [vst win64](http://le-son666.com/software/dexed/dexed-0.5.1-win64.zip) - [vst os x](http://le-son666.com/software/dexed/dexed-0.5.1-osx.vst.zip)
* Version 0.5.0 [vst win32](http://le-son666.com/software/dexed/dexed-0.5.0a-win32.zip) - [vst win64](http://le-son666.com/software/dexed/dexed-0.5.0a-win64.zip) - [vst os x](http://le-son666.com/software/dexed/dexed-0.5.0-osx.vst.zip)
@ -56,7 +58,32 @@ in normal operation it shouldn't crash and the VST state saving works. If you do
Using as a DX7 editor
---------------------
You can use this plugin to edit your real DX7 patch. Since sysex support on most DAW is missing, you might need to configure this plugin to send/receive sysex data to a specific midi port.
You can use this plugin to edit your real DX7 patchs. Since midi send/receive are quirky for the
majority of VST hosts, any sysex messages (editor messages) must be send or received with the external Dexed
midi interface, configurable in the "PARM" panel. By setting a DX7 in / DX7 out, Dexed will
listen to specific program/cartridge changes from your DX7 and send controller/program/cartridge
you edit.
### Prerequisite
* Before you use this interface, your DX7 must be configured to send or receive sysex messages. By hitting [FUNCTION] and [8] button :
* The first one is the midi channel. By reading some of DX7 literature, most DX7 are supposed to support only 1 channel. Unless you are running a cluster of DX7, you should keep this to 1.
* The second one (press [8] again) is "SYS INFO AVAIL" or "SYS INFO UNAVAIL". Keep it to "SYS INFO AVAIL" to be able to receive sysex messages.
* The third one, you need to remove MEMORY PROTECT on the internal or cartridge memory to be able to receive a Dexed 32 voice bulk dump.
### To send to your DX7
* If the midi port is configured, any parameter change will be sent to your DX7.
* Use the [SEND] button on Dexed to send program or cartridge changes to your DX7. Be sure you have set [MEMORY PROTECT] to off so the cartridge (internal et external one) on the DX7 can be overridden.
### To receive to your DX7
* Receive a program by simply using [MEMORY SELECT] then the program you want to change ([1] to [32]).
* Receive a cartridge by pressing [FUNCTION] then 3 times on [8] you should see " MIDI TRANSMIT ? ". If you hit yes, Dexed should receive the complete cartridge.
### Troubleshooting
* If the midi ports are opened correcly you should see a DX7 light flashing when you send or receive midi data from/to your DX7. If you don't see anything, or just the input, it because it was unable to open the output midi interface.
* If you play on your DX7 keyboard, the |DX7 In light| should be flashing. Use this to test the midi in communication.
* If you click/play on the Dexed virtual keyboard, it will send the correspoding midi note to the DX7 port; if configured. Use this to test the midi out communication.
* If the data sent is corrupted (wrong checksum, DX7 crash); it might be the midi interface implementation. Default Windows USB midi driver can send corrupt sysex data. If it is the case, use a third party device (like the midiman uno) that have his own USB driver.
* If you are unable to open the interface (error message after the [PARM] dialog), it might be because the midi driver doesn't support multiple clients (common on Windows). Be sure that there are no other applications that are using the same midi interface.
Randomized programs
-------------------

@ -457,11 +457,18 @@ void LcdDisplay::handleAsyncUpdate() {
startTimer(5000);
}
#ifdef _WIN32
const float LCD_FONTSIZE = 13.0f;
#else
const float LCD_FONTSIZE = 15.0f;
#endif
void LcdDisplay::paint(Graphics &g) {
g.setColour(Colours::black.withAlpha(0.4f));
g.fillRoundedRectangle (0.0f, 0.0f, (float) getWidth(), (float) getHeight(), 1.0f);
g.setColour (Colours::white);
g.setFont (Font (Font::getDefaultMonospacedFontName(), 15.00f, Font::plain));
g.setFont (Font (Font::getDefaultMonospacedFontName(), LCD_FONTSIZE, Font::plain));
g.drawText (systemMsg,
7, 4, 300, 8,
Justification::centredLeft, true);

@ -123,19 +123,19 @@ void ParamDialog::paint (Graphics& g)
g.setColour (Colours::white);
g.setFont (Font (15.00f, Font::plain));
g.drawText (TRANS("Sysex In"),
g.drawText (TRANS("DX7 In"),
19, 178, 131, 23,
Justification::centredLeft, true);
g.setColour (Colours::white);
g.setFont (Font (15.00f, Font::plain));
g.drawText (TRANS("Sysex Out"),
g.drawText (TRANS("DX7 Out"),
19, 218, 131, 23,
Justification::centredLeft, true);
g.setColour (Colours::white);
g.setFont (Font (15.00f, Font::plain));
g.drawText (TRANS("Sysex Channel"),
g.drawText (TRANS("DX7 Channel"),
19, 258, 245, 23,
Justification::centredLeft, true);
@ -221,12 +221,16 @@ void ParamDialog::setDialogValues(Controllers &c, SysexComm &mgr) {
sysexOut->setSelectedItemIndex(idx);
}
void ParamDialog::getDialogValues(Controllers &c, SysexComm &mgr) {
bool ParamDialog::getDialogValues(Controllers &c, SysexComm &mgr) {
bool ret = true;
c.values_[kControllerPitchRange] = pitchRange->getValue();
c.values_[kControllerPitchStep] = pitchStep->getValue();
mgr.setInput(sysexIn->getItemText(sysexIn->getSelectedItemIndex()));
mgr.setOutput(sysexOut->getItemText(sysexOut->getSelectedItemIndex()));
ret &= mgr.setInput(sysexIn->getItemText(sysexIn->getSelectedItemIndex()));
ret &= mgr.setOutput(sysexOut->getItemText(sysexOut->getSelectedItemIndex()));
mgr.setChl(sysexChl->getValue() - 1);
return ret;
}
//[/MiscUserCode]
@ -250,11 +254,11 @@ BEGIN_JUCER_METADATA
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="19 61 229 23" fill="solid: ffffffff" hasStroke="0" text="Pitch Bend Step"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="19 178 131 23" fill="solid: ffffffff" hasStroke="0" text="Sysex In"
<TEXT pos="19 178 131 23" fill="solid: ffffffff" hasStroke="0" text="DX7 In"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="19 218 131 23" fill="solid: ffffffff" hasStroke="0" text="Sysex Out"
<TEXT pos="19 218 131 23" fill="solid: ffffffff" hasStroke="0" text="DX7 Out"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="19 258 245 23" fill="solid: ffffffff" hasStroke="0" text="Sysex Channel"
<TEXT pos="19 258 245 23" fill="solid: ffffffff" hasStroke="0" text="DX7 Channel"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
</BACKGROUND>
<SLIDER name="pitchRange" id="7409be5a8dfaa91" memberName="pitchRange"

@ -48,7 +48,7 @@ public:
//==============================================================================
//[UserMethods] -- You can add your own custom methods in this section.
void setDialogValues(Controllers &c, SysexComm &mgr);
void getDialogValues(Controllers &c, SysexComm &mgr);
bool getDialogValues(Controllers &c, SysexComm &mgr);
//[/UserMethods]
void paint (Graphics& g);

@ -33,36 +33,41 @@ 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) {
char programName[11];
dest.clear();
for (int i = 0; i < 32; i++) {
memcpy(programName, block + ((i * 128) + 118), 11);
for (int j = 0; j < 10; j++) {
char c = (unsigned char) programName[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;
}
programName[j] = c;
}
programName[10] = 0;
dest.add(String(programName));
dest.add(String(normalizeSysexName(block + ((i * 128) + 118))));
}
}
@ -77,7 +82,7 @@ void exportSysexCart(char *dest, char *src, char sysexChl) {
// make checksum for dump
uint8_t footer[] = { sysexChecksum(src, 4096), 0xF7 };
memcpy(dest+4102, footer, 2);
}
@ -131,6 +136,7 @@ void packProgram(uint8_t *dest, uint8_t *src, int idx, String name) {
bulk[117] = src[144];
int eos = 0;
for(int i=0; i < 10; i++) {
char c = (char) name[i];
if ( c == 0 )
@ -227,7 +233,7 @@ int DexedAudioProcessor::importSysex(const char *imported) {
}
void DexedAudioProcessor::updateProgramFromSysex(const uint8 *rawdata) {
memcpy(data, rawdata, 160);
memcpy(data, rawdata, 161);
triggerAsyncUpdate();
}

@ -58,6 +58,7 @@ enum UnpackedOffset {
osc6state
};
String normalizeSysexName(const char *sysexName);
void extractProgramNames(const char *block, StringArray &dest);
void exportSysexCart(char *dest, char *src, char sysexChl);
void exportSysexPgm(char *dest, char *src, char sysexChl);

@ -22,6 +22,7 @@
#include "PluginEditor.h"
#include "GlobalEditor.h"
#include "ParamDialog.h"
#include "SysexComm.h"
#include "Dexed.h"
#include "math.h"
#include <fstream>
@ -55,6 +56,53 @@ public:
}
};
/**
* Ugly but usefull midi monitor to know if you are really sending/receiving something from the DX7
* If the midi is not configured this component wont show up
*/
class MidiMonitor : public Component {
SysexComm *midi;
public:
MidiMonitor(SysexComm *sysexComm) {
midi = sysexComm;
}
void paint(Graphics &g) {
if ( ! (midi->isInputActive() || midi->isOutputActive() ) )
return;
g.setColour(DXLookNFeel::dxDarkBrown);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColour(Colours::black);
g.drawSingleLineText("DX7 ", 0, 13);
if ( midi->isInputActive() ) {
g.drawSingleLineText("IN", 27,13);
if ( midi->inActivity ) {
g.setColour(Colours::red);
} else {
g.setColour(Colours::darkgrey);
}
g.fillRect(44, 4, 7, 9);
midi->inActivity = false;
}
if ( midi->isOutputActive() ) {
g.setColour(Colours::black);
g.drawSingleLineText("OUT", 55, 13);
if ( midi->outActivity ) {
g.setColour(Colours::red);
} else {
g.setColour(Colours::darkgrey);
}
g.fillRect(83, 4, 7, 9);
midi->outActivity = false;
}
}
};
//==============================================================================
DexedAudioProcessorEditor::DexedAudioProcessorEditor (DexedAudioProcessor* ownerFilter)
: AudioProcessorEditor (ownerFilter),
@ -98,10 +146,15 @@ DexedAudioProcessorEditor::DexedAudioProcessorEditor (DexedAudioProcessor* owner
storeButton->setBounds(331, 6, 50, 18);
addAndMakeVisible(sendButton = new TextButton("SEND"));
sendButton->setVisible(false);
sendButton->setButtonText("SEND");
sendButton->addListener(this);
sendButton->setBounds(385, 6, 50, 18);
sendButton->setVisible(processor->sysexComm.isOutputActive());
addAndMakeVisible(midiMonitor = new MidiMonitor(&processor->sysexComm));
midiMonitor->setBounds(645, 6, 110, 18);
addAndMakeVisible(settingsButton = new TextButton("PARMS"));
settingsButton->setButtonText("PARMS");
settingsButton->addListener(this);
@ -150,8 +203,8 @@ DexedAudioProcessorEditor::DexedAudioProcessorEditor (DexedAudioProcessor* owner
global.setBounds(5,235,855,90);
global.bind(processor);
sendPopup.addItem(1, "Send current program to DX7");
sendPopup.addItem(2, "Send current cartridge to DX7");
sendPopup.addItem(1, "Send program to DX7");
sendPopup.addItem(2, "Send cartridge to DX7");
updateUI();
startTimer(100);
@ -243,26 +296,24 @@ void DexedAudioProcessorEditor::buttonClicked(Button *buttonThatWasClicked) {
int result = sendPopup.show();
if ( result == 1 ) {
uint8_t raw[165];
uint8_t raw[167];
exportSysexPgm((char *) raw, processor->data, processor->sysexComm.getChl());
if ( processor->sysexComm.isOutputActive() ) {
processor->sysexComm.send(MidiMessage(raw, 165));
} else {
processor->midiOut.addEvent(raw, 165, 0);
processor->sysexComm.send(MidiMessage(raw, 163));
}
global.setSystemMessage(String("Done sending program"));
return;
}
if ( result == 2 ) {
uint8_t raw[4104];
exportSysexCart((char *) raw, processor->sysex, processor->sysexComm.getChl());
exportSysexCart((char *) raw, (char *) &processor->sysex, processor->sysexComm.getChl());
if ( processor->sysexComm.isOutputActive() ) {
processor->sysexComm.send(MidiMessage(raw, 4104));
} else {
processor->midiOut.addEvent(raw, 4104, 0);
}
global.setSystemMessage(String("Done sending cartridge"));
return;
}
@ -270,7 +321,6 @@ void DexedAudioProcessorEditor::buttonClicked(Button *buttonThatWasClicked) {
}
if (buttonThatWasClicked == settingsButton) {
AlertWindow window("","", AlertWindow::NoIcon, this);
ParamDialog param;
param.setColour(AlertWindow::backgroundColourId, Colour(0x32FFFFFF));
@ -282,9 +332,14 @@ void DexedAudioProcessorEditor::buttonClicked(Button *buttonThatWasClicked) {
if ( window.runModalLoop() != 0 )
return;
param.getDialogValues(processor->controllers, processor->sysexComm);
bool ret = param.getDialogValues(processor->controllers, processor->sysexComm);
processor->savePreference();
if ( ret == false ) {
AlertWindow::showMessageBoxAsync(AlertWindow::WarningIcon, "Midi Interface", "Error opening midi ports");
}
sendButton->setVisible(processor->sysexComm.isOutputActive());
return;
}
@ -317,6 +372,7 @@ void DexedAudioProcessorEditor::timerCallback() {
}
global.updatePitchPos(processor->voiceStatus.pitchStep);
global.updateVu(processor->vuSignal);
midiMonitor->repaint();
}
void DexedAudioProcessorEditor::updateUI() {
@ -326,10 +382,7 @@ void DexedAudioProcessorEditor::updateUI() {
for(int i=0;i<6;i++) {
operators[i].updateDisplay();
}
int id = processor->getCurrentProgram() + 1;
programs.setSelectedId(id, dontSendNotification);
rebuildProgramCombobox();
global.updateDisplay();
}

@ -21,11 +21,13 @@
#ifndef PLUGINEDITOR_H_INCLUDED
#define PLUGINEDITOR_H_INCLUDED
#include "../JuceLibraryCode/JuceHeader.h"
#include "PluginProcessor.h"
#include "OperatorEditor.h"
#include "GlobalEditor.h"
#include "DXComponents.h"
#include "DXLookNFeel.h"
//==============================================================================
/**
@ -49,7 +51,7 @@ class DexedAudioProcessorEditor : public AudioProcessorEditor,
ScopedPointer<TextButton> aboutButton;
ScopedPointer<TextButton> settingsButton;
ScopedPointer<TextButton> sendButton;
ScopedPointer<Component> midiMonitor;
void storeProgram();
public:

@ -407,8 +407,6 @@ void DexedAudioProcessor::setDxValue(int offset, int v) {
if ( sysexComm.isOutputActive() ) {
sysexComm.send(MidiMessage(msg,7));
} else {
midiOut.addEvent(msg, 7, 0);
}
}

@ -53,6 +53,7 @@ DexedAudioProcessor::DexedAudioProcessor() {
sendSysexChange = true;
normalizeDxVelocity = false;
sysexComm.listener = this;
keyboardState.addListener(&sysexComm);
memset(&voiceStatus, 0, sizeof(VoiceStatus));
@ -236,11 +237,6 @@ void DexedAudioProcessor::processBlock(AudioSampleBuffer& buffer, MidiBuffer& mi
for (int i = getNumInputChannels(); i < getNumOutputChannels(); ++i) {
buffer.clear (i, 0, buffer.getNumSamples());
}
midiMessages.clear();
if ( ! midiOut.isEmpty() ) {
midiMessages.swapWith(midiOut);
}
}
@ -260,46 +256,6 @@ bool DexedAudioProcessor::getNextEvent(MidiBuffer::Iterator* iter,const int samp
}
void DexedAudioProcessor::processMidiMessage(const MidiMessage *msg) {
if ( msg->isSysEx() ) {
const uint8 *buf = msg->getSysExData();
int sz = msg->getSysExDataSize();
TRACE("SYSEX RECEIVED %d", sz);
if ( sz < 3 )
return;
// test if it is a Yamaha Sysex
if ( buf[0] != 0x43 ) {
TRACE("not a yamaha sysex %d", buf[0]);
return;
}
// single voice dump
if ( buf[2] == 0 ) {
if ( sz < 155 ) {
TRACE("wrong single voice datasize %d", sz);
return;
}
TRACE("program update sysex");
updateProgramFromSysex(buf+4);
triggerAsyncUpdate();
return;
}
// 32 voice dump
if ( buf[2] == 9 ) {
if ( sz < 4016 ) {
TRACE("wrong 32 voice datasize %d", sz);
return;
}
TRACE("update 32bulk voice)");
importSysex((const char *)buf+4);
currentProgram = 0;
triggerAsyncUpdate();
}
return;
}
const uint8 *buf = msg->getRawData();
uint8_t cmd = buf[0];
@ -351,12 +307,6 @@ void DexedAudioProcessor::processMidiMessage(const MidiMessage *msg) {
}
void DexedAudioProcessor::handleIncomingMidiMessage(MidiInput* source, const MidiMessage& message) {
if ( ! message.isSysEx() )
return;
processMidiMessage(&message);
}
void DexedAudioProcessor::keydown(uint8_t pitch, uint8_t velo) {
if ( velo == 0 ) {
keyup(pitch);
@ -408,6 +358,59 @@ void DexedAudioProcessor::panic() {
keyboardState.reset();
}
void DexedAudioProcessor::handleIncomingMidiMessage(MidiInput* source, const MidiMessage& message) {
if ( message.isActiveSense() )
return;
sysexComm.inActivity = true;
if ( ! message.isSysEx() )
return;
//const uint8 *buf = msg->getSysExData();
const uint8 *buf = message.getRawData();
int sz = message.getRawDataSize();
if ( sz < 3 )
return;
TRACE("SYSEX RECEIVED %d", sz);
// test if it is a Yamaha Sysex
if ( buf[1] != 0x43 ) {
TRACE("not a yamaha sysex %d", buf[0]);
return;
}
// single voice dump
if ( buf[3] == 0 ) {
if ( sz < 155 ) {
TRACE("wrong single voice datasize %d", sz);
return;
}
TRACE("program update sysex");
updateProgramFromSysex(buf+6);
String name = normalizeSysexName((const char *) buf+151);
packProgram((uint8_t *) sysex, (uint8_t *) data, currentProgram, name);
programNames.set(currentProgram, name);
}
// 32 voice dump
if ( buf[3] == 9 ) {
if ( sz < 4104 ) {
TRACE("wrong 32 voice datasize %d", sz);
return;
}
TRACE("update 32bulk voice");
importSysex((const char *)buf);
setCurrentProgram(0);
}
updateHostDisplay();
forceRefreshUI = true;
}
// ====================================================================
bool DexedAudioProcessor::peekVoiceStatus() {
if ( currentNote == -1 )
@ -490,7 +493,7 @@ bool DexedAudioProcessor::hasEditor() const {
void DexedAudioProcessor::updateUI() {
// notify host something has changed
updateHostDisplay();
AudioProcessorEditor *editor = getActiveEditor();
if ( editor == NULL ) {
return;

@ -75,7 +75,7 @@ class DexedAudioProcessor : public AudioProcessor, public AsyncUpdater, public
* and needs to be updated.
*/
bool refreshVoice;
bool normalizeDxVelocity;
bool sendSysexChange;
@ -108,7 +108,6 @@ public :
CartridgeManager cartManager;
SysexComm sysexComm;
MidiBuffer midiOut;
VoiceStatus voiceStatus;
@ -155,7 +154,6 @@ public :
bool hasEditor() const;
void updateUI();
bool peekVoiceStatus();
void packProgram(int idx, const char *name);
void unpackProgram(int idx);
void updateProgramFromSysex(const uint8 *rawdata);
void loadBuiltin(int idx);

@ -22,7 +22,7 @@
#include "Dexed.h"
SysexComm::SysexComm() {
sysexChl = 1;
sysexChl = 0;
listener = NULL; // this will get injected later
inputName = "";
@ -46,7 +46,7 @@ String SysexComm::getInput() {
return inputName;
}
void SysexComm::setInput(String target) {
bool SysexComm::setInput(String target) {
if ( input != NULL ) {
input->stop();
delete input;
@ -54,7 +54,7 @@ void SysexComm::setInput(String target) {
}
if ( listener == NULL )
return;
return true;
StringArray devices = MidiInput::getDevices();
int idx = devices.indexOf(target);
@ -62,24 +62,28 @@ void SysexComm::setInput(String target) {
if ( idx == -1 ) {
TRACE("device %s not found", target.toRawUTF8());
inputName = "";
return;
if ( target == "None" || target == "" )
return true;
return false;
}
input = MidiInput::openDevice(idx, listener);
if ( input != NULL ) {
inputName = target;
input->start();
TRACE("sysex %s opened", target.toRawUTF8());
} else {
if ( input == NULL ) {
TRACE("unable to open %s", target.toRawUTF8());
return false;
}
inputName = target;
TRACE("sysex %s opened", target.toRawUTF8());
input->start();
return true;
}
String SysexComm::getOutput() {
return outputName;
}
void SysexComm::setOutput(String target) {
bool SysexComm::setOutput(String target) {
if ( output != NULL ) {
delete output;
output = NULL;
@ -91,16 +95,20 @@ void SysexComm::setOutput(String target) {
if ( idx == -1 ) {
TRACE("device %s not found", target.toRawUTF8());
outputName = "";
return;
if ( target == "None" || target == "" )
return true;
return false;
}
output = MidiOutput::openDevice(idx);
if ( output != NULL ) {
outputName = target;
TRACE("sysex %s opened", target.toRawUTF8());
} else {
if ( output == NULL ) {
TRACE("unable to open %s", target.toRawUTF8());
return false;
}
outputName = target;
TRACE("sysex %s opened", target.toRawUTF8());
return true;
}
bool SysexComm::isInputActive() {
@ -119,10 +127,26 @@ void SysexComm::setChl(int chl) {
sysexChl = chl;
}
void SysexComm::send(const juce::MidiMessage &message) {
int SysexComm::send(const MidiMessage &message) {
if ( output == NULL )
return;
return 2;
TRACE("sending sysex...");
outActivity = true;
output->sendMessageNow(message);
return 0;
}
// This is called from the UI Keyboard...
void SysexComm::handleNoteOn(MidiKeyboardState*, int, int midiNoteNumber, float velocity) {
if ( output == NULL )
return;
outActivity = true;
char iVelo = velocity * 100;
MidiMessage msg(0x90 + sysexChl, midiNoteNumber, iVelo);
output->sendMessageNow(msg);
}
void SysexComm::handleNoteOff(MidiKeyboardState* source, int midiChannel, int midiNoteNumber) {
handleNoteOn(source, midiChannel, midiNoteNumber, 0);
}

@ -23,20 +23,21 @@
#include "../JuceLibraryCode/JuceHeader.h"
class SysexComm {
class SysexComm : public MidiKeyboardStateListener {
MidiInput *input;
MidiOutput *output;
String inputName;
String outputName;
int sysexChl;
public :
MidiInputCallback *listener;
SysexComm();
~SysexComm();
void setInput(String name);
void setOutput(String name);
bool setInput(String name);
bool setOutput(String name);
void setChl(int chl);
String getInput();
@ -46,7 +47,13 @@ public :
bool isInputActive();
bool isOutputActive();
void send(const MidiMessage& message);
int send(const MidiMessage& message);
void handleNoteOn(MidiKeyboardState* source, int midiChannel, int midiNoteNumber, float velocity);
void handleNoteOff(MidiKeyboardState* source, int midiChannel, int midiNoteNumber);
bool inActivity;
bool outActivity;
};
#endif // SYSEXCOMM_H_INCLUDED
Loading…
Cancel
Save