Added master-tune parameter.

pull/1/head
Holger Wirtz 7 years ago
parent 3dd5e5a224
commit 3d5ec67038
  1. 9
      src/Dexed.ttl
  2. 7
      src/dexed.cpp
  3. 6
      src/dexed.h
  4. 379
      src/trash/AlgoDisplay.cpp
  5. 33
      src/trash/AlgoDisplay.h
  6. 359
      src/trash/CartManager.cpp
  7. 77
      src/trash/CartManager.h
  8. 442
      src/trash/DXComponents.cpp
  9. 78
      src/trash/DXComponents.h
  10. 255
      src/trash/DXLookNFeel.cpp
  11. 63
      src/trash/DXLookNFeel.h
  12. 788
      src/trash/GlobalEditor.cpp
  13. 126
      src/trash/GlobalEditor.h
  14. 660
      src/trash/OperatorEditor.cpp
  15. 110
      src/trash/OperatorEditor.h
  16. 703
      src/trash/ParamDialog.cpp
  17. 100
      src/trash/ParamDialog.h
  18. 452
      src/trash/PluginData.cpp
  19. 247
      src/trash/PluginData.h
  20. 341
      src/trash/PluginEditor.cpp
  21. 61
      src/trash/PluginEditor.h
  22. 705
      src/trash/PluginParam.cpp
  23. 127
      src/trash/PluginParam.h
  24. 616
      src/trash/PluginProcessor.cpp
  25. 235
      src/trash/PluginProcessor.h
  26. 203
      src/trash/ProgramListBox.cpp
  27. 74
      src/trash/ProgramListBox.h
  28. 155
      src/trash/SysexComm.cpp
  29. 60
      src/trash/SysexComm.h
  30. 76
      src/trash/ringbuffer.cc
  31. 44
      src/trash/ringbuffer.h

@ -1866,6 +1866,15 @@
lv2:minimum 0 ;
lv2:maximum 12 ;
lv2:portProperty lv2:integer ;
] ,
[
a lv2:InputPort, lv2:ControlPort ;
lv2:index 156 ;
lv2:symbol "master_tune" ;
lv2:name "MASTER TUNE" ;
lv2:default 0 ;
lv2:minimum -100.0 ;
lv2:maximum 100.0 ;
] ;
doap:name "Dexed" ;

@ -324,6 +324,7 @@ void Dexed::set_params(void)
onParam(157,*p(p_pitch_bend_step));
onParam(158,*p(p_mod_wheel_range));
onParam(159,*p(p_mod_wheel_step));
onParam(160,*p(p_master_tune));
if(_param_change_counter>PARAM_CHANGE_LEVEL)
panic();
@ -679,6 +680,12 @@ void Dexed::onParam(uint8_t param_num,float param_val)
_param_change_counter++;
if(param_num==160)
{
controllers.masterTune=param_val;
return;
}
if(param_num==144 || param_num==134)
panic();

@ -121,9 +121,9 @@ class Dexed : public lvtk::Synth<DexedVoice, Dexed>
double _rate;
uint8_t _param_counter;
uint8_t _param_change_counter;
float data_float[160];
float data_float[161];
//uint8_t data[160];
uint8_t data[160]={
uint8_t data[161]={
95, 29, 20, 50, 99, 95, 00, 00, 41, 00, 19, 00, 00, 03, 00, 06, 79, 00, 01, 00, 14,
95, 20, 20, 50, 99, 95, 00, 00, 00, 00, 00, 00, 00, 03, 00, 00, 99, 00, 01, 00, 00,
95, 29, 20, 50, 99, 95, 00, 00, 00, 00, 00, 00, 00, 03, 00, 06, 89, 00, 01, 00, 07,
@ -136,7 +136,7 @@ class Dexed : public lvtk::Synth<DexedVoice, Dexed>
03, 24,
00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
63,
12, 12, 12, 12};
12, 12, 12, 12, 00};
};
#endif // PLUGINPROCESSOR_H_INCLUDED

@ -1,379 +0,0 @@
/**
*
* Copyright (c) 2014, 2015 Pascal Gauthier.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "AlgoDisplay.h"
#include "DXLookNFeel.h"
#include "Dexed.h"
AlgoDisplay::AlgoDisplay() {
static char tmpAlgo = 0;
algo = &tmpAlgo;
}
inline void displayOp(Graphics &g, char id, int x, int y, char link, char fb) {
const int LINE_SZ = 3;
String t(id);
x *= 25;
x += 3;
y *= 21;
y += 5;
g.setColour(Colours::white);
g.drawText(t, x, y, 16, 12, Justification::centred, true);
g.setColour(DXLookNFeel::fillColour);
switch(link) {
case 0 : // LINE DOWN
g.drawLine(x+8, y+12, x+8, y+21, LINE_SZ);
break;
case 1: // ARROW TO RIGHT
g.drawLine(x+8, y+12, x+8, y+18, LINE_SZ);
g.drawLine(x+7, y+18, x+34, y+18, LINE_SZ);
break;
case 2: // ARROW TO RIGHT JOIN
g.drawLine(x+8, y+12, x+8, y+19, LINE_SZ);
break;
case 3: // ARROW TO RIGHT AND DOWN
g.drawLine(x+8, y+12, x+8, y+21, LINE_SZ);
g.drawLine(x+7, y+18, x+34, y+18, LINE_SZ);
g.drawLine(x+34, y+17, x+34, y+21, LINE_SZ);
break;
case 4: // ARROW TO RIGHT+LEFT AND DOWN
g.drawLine(x+8, y+12, x+8, y+21, LINE_SZ);
g.drawLine(x+7, y+18, x+34, y+18, LINE_SZ);
g.drawLine(x+34, y+17, x+34, y+21, LINE_SZ);
g.drawLine(x-17, y+18, x+8, y+18, LINE_SZ);
g.drawLine(x-17, y+17, x-17, y+21, LINE_SZ);
break;
case 6:
g.drawLine(x+8, y+12, x+8, y+18, LINE_SZ);
g.drawLine(x+7, y+18, x+58, y+18, LINE_SZ);
break;
case 7: // ARROW TO LEFT
g.drawLine(x+8, y+12, x+8, y+19, LINE_SZ);
g.drawLine(x-17, y+18, x+9, y+18, LINE_SZ);
break;
}
switch(fb) {
case 0:
break;
case 1:
g.drawLine(x+7, y, x+8, y-5, LINE_SZ);
g.drawLine(x+8, y-4, x+21, y-4, LINE_SZ);
g.drawLine(x+20, y-4, x+20, y+15, LINE_SZ);
g.drawLine(x+19, y+15, x+20, y+16, LINE_SZ);
g.drawLine(x+8, y+15, x+20, y+15, LINE_SZ);
break;
case 2: // ALGO 4
g.drawLine(x+7, y, x+8, y-5, LINE_SZ);
g.drawLine(x+8, y-4, x+20, y-4, LINE_SZ);
g.drawLine(x+19, y-4, x+19, y+59, LINE_SZ);
g.drawLine(x+8, y+58, x+19, y+58, LINE_SZ);
break;
case 3: // ALGO 6
g.drawLine(x+7, y, x+8, y-5, LINE_SZ);
g.drawLine(x+8, y-4, x+20, y-4, LINE_SZ);
g.drawLine(x+19, y-4, x+19, y+37, LINE_SZ);
g.drawLine(x+8, y+36, x+19, y+36, LINE_SZ);
break;
case 4:
g.drawLine(x+7, y, x+8, y-5, LINE_SZ);
g.drawLine(x+8, y-4, x-4, y-4, LINE_SZ);
g.drawLine(x-3, y-4, x-3, y+15, LINE_SZ);
g.drawLine(x-3, y+15, x+8, y+15, LINE_SZ);
g.drawLine(x+8, y+15, x+8, y+12, LINE_SZ);
break;
}
}
void AlgoDisplay::paint(Graphics &g) {
g.setColour(DXLookNFeel::fillColour);
g.fillRect(1, 3, 20, 15);
String n = String(*algo +1);
g.setColour(Colours::white);
g.drawText(n, 1, 3, 20, 15, Justification::centred, true);
switch(*algo) {
case 0:
displayOp(g, 6, 3, 0, 0, 1);
displayOp(g, 5, 3, 1, 0, 0);
displayOp(g, 4, 3, 2, 0, 0);
displayOp(g, 3, 3, 3, 2, 0);
displayOp(g, 2, 2, 2, 0, 0);
displayOp(g, 1, 2, 3, 1, 0);
break;
case 1:
displayOp(g, 6, 3, 0, 0, 0);
displayOp(g, 5, 3, 1, 0, 0);
displayOp(g, 4, 3, 2, 0, 0);
displayOp(g, 3, 3, 3, 2, 0);
displayOp(g, 2, 2, 2, 0, 1);
displayOp(g, 1, 2, 3, 1, 0);
break;
case 2:
displayOp(g, 6, 3, 1, 0, 1);
displayOp(g, 5, 3, 2, 0, 0);
displayOp(g, 4, 3, 3, 2, 0);
displayOp(g, 3, 2, 1, 0, 0);
displayOp(g, 2, 2, 2, 0, 0);
displayOp(g, 1, 2, 3, 1, 0);
break;
case 3: //
displayOp(g, 6, 3, 1, 0, 2);
displayOp(g, 5, 3, 2, 0, 0);
displayOp(g, 4, 3, 3, 2, 0);
displayOp(g, 3, 2, 1, 0, 0);
displayOp(g, 2, 2, 2, 0, 0);
displayOp(g, 1, 2, 3, 1, 0);
break;
case 4:
displayOp(g, 6, 4, 2, 0, 1);
displayOp(g, 5, 4, 3, 2, 0);
displayOp(g, 4, 3, 2, 0, 0);
displayOp(g, 3, 3, 3, 1, 0);
displayOp(g, 2, 2, 2, 0, 0);
displayOp(g, 1, 2, 3, 1, 0);
break;
case 5: //
displayOp(g, 6, 4, 2, 0, 3);
displayOp(g, 5, 4, 3, 2, 0);
displayOp(g, 4, 3, 2, 0, 0);
displayOp(g, 3, 3, 3, 1, 0);
displayOp(g, 2, 2, 2, 0, 0);
displayOp(g, 1, 2, 3, 1, 0);
break;
case 6:
displayOp(g, 6, 4, 1, 0, 1);
displayOp(g, 5, 4, 2, 7, 0);
displayOp(g, 4, 3, 2, 0, 0);
displayOp(g, 3, 3, 3, 2, 0);
displayOp(g, 2, 2, 2, 0, 0);
displayOp(g, 1, 2, 3, 1, 0);
break;
case 7:
displayOp(g, 6, 4, 1, 0, 0);
displayOp(g, 5, 4, 2, 7, 0);
displayOp(g, 4, 3, 2, 0, 4);
displayOp(g, 3, 3, 3, 2, 0);
displayOp(g, 2, 2, 2, 0, 0);
displayOp(g, 1, 2, 3, 1, 0);
break;
case 8:
displayOp(g, 6, 4, 1, 0, 0);
displayOp(g, 5, 4, 2, 7, 0);
displayOp(g, 4, 3, 2, 0, 0);
displayOp(g, 3, 3, 3, 2, 0);
displayOp(g, 2, 2, 2, 0, 1);
displayOp(g, 1, 2, 3, 1, 0);
break;
case 9:
displayOp(g, 6, 2, 2, 0, 0);
displayOp(g, 5, 1, 2, 1, 0);
displayOp(g, 4, 2, 3, 1, 0);
displayOp(g, 3, 3, 1, 0, 1);
displayOp(g, 2, 3, 2, 0, 0);
displayOp(g, 1, 3, 3, 2, 0);
break;
case 10:
displayOp(g, 6, 2, 2, 0, 1);
displayOp(g, 5, 1, 2, 1, 0);
displayOp(g, 4, 2, 3, 1, 0);
displayOp(g, 3, 3, 1, 0, 0);
displayOp(g, 2, 3, 2, 0, 0);
displayOp(g, 1, 3, 3, 2, 0);
break;
case 11:
displayOp(g, 6, 3, 2, 7, 0);
displayOp(g, 5, 2, 2, 0, 0);
displayOp(g, 4, 1, 2, 1, 0);
displayOp(g, 3, 2, 3, 6, 0);
displayOp(g, 2, 4, 2, 0, 1);
displayOp(g, 1, 4, 3, 2, 0);
break;
case 12:
displayOp(g, 6, 3, 2, 7, 1);
displayOp(g, 5, 2, 2, 0, 0);
displayOp(g, 4, 1, 2, 1, 0);
displayOp(g, 3, 2, 3, 6, 0);
displayOp(g, 2, 4, 2, 0, 0);
displayOp(g, 1, 4, 3, 2, 0);
break;
case 13:
displayOp(g, 6, 3, 1, 0, 1);
displayOp(g, 5, 2, 1, 1, 0);
displayOp(g, 4, 3, 2, 0, 0);
displayOp(g, 3, 3, 3, 2, 0);
displayOp(g, 2, 2, 2, 0, 0);
displayOp(g, 1, 2, 3, 1, 0);
break;
case 14:
displayOp(g, 6, 3, 1, 0, 0);
displayOp(g, 5, 2, 1, 1, 0);
displayOp(g, 4, 3, 2, 0, 0);
displayOp(g, 3, 3, 3, 2, 0);
displayOp(g, 2, 2, 2, 0, 4);
displayOp(g, 1, 2, 3, 1, 0);
break;
case 15:
displayOp(g, 6, 4, 1, 0, 1);
displayOp(g, 5, 4, 2, 7, 0);
displayOp(g, 4, 3, 1, 0, 0);
displayOp(g, 3, 3, 2, 0, 0);
displayOp(g, 2, 2, 2, 1, 0);
displayOp(g, 1, 3, 3, 0, 0);
break;
case 16:
displayOp(g, 6, 4, 1, 0, 0);
displayOp(g, 5, 4, 2, 7, 0);
displayOp(g, 4, 3, 1, 0, 0);
displayOp(g, 3, 3, 2, 0, 0);
displayOp(g, 2, 2, 2, 1, 4);
displayOp(g, 1, 3, 3, 0, 0);
break;
case 17:
displayOp(g, 6, 4, 0, 0, 0);
displayOp(g, 5, 4, 1, 0, 0);
displayOp(g, 4, 4, 2, 7, 0);
displayOp(g, 3, 3, 2, 0, 4);
displayOp(g, 2, 2, 2, 1, 0);
displayOp(g, 1, 3, 3, 0, 0);
break;
case 18:
displayOp(g, 6, 3, 2, 3, 1);
displayOp(g, 5, 4, 3, 2, 0);
displayOp(g, 4, 3, 3, 1, 0);
displayOp(g, 3, 2, 1, 0, 0);
displayOp(g, 2, 2, 2, 0, 0);
displayOp(g, 1, 2, 3, 1, 0);
break;
case 19:
displayOp(g, 6, 4, 2, 0, 0);
displayOp(g, 5, 3, 2, 1, 0);
displayOp(g, 4, 4, 3, 2, 0);
displayOp(g, 3, 1, 2, 3, 1);
displayOp(g, 2, 2, 3, 6, 0);
displayOp(g, 1, 1, 3, 1, 0);
break;
case 20:
displayOp(g, 6, 3, 2, 3, 0);
displayOp(g, 5, 4, 3, 2, 0);
displayOp(g, 4, 3, 3, 1, 0);
displayOp(g, 3, 1, 2, 3, 1);
displayOp(g, 2, 2, 3, 1, 0);
displayOp(g, 1, 1, 3, 1, 0);
break;
case 21:
displayOp(g, 6, 3, 2, 4, 1);
displayOp(g, 5, 4, 3, 2, 0);
displayOp(g, 4, 3, 3, 1, 0);
displayOp(g, 3, 2, 3, 1, 0);
displayOp(g, 2, 1, 2, 0, 0);
displayOp(g, 1, 1, 3, 1, 0);
break;
case 22: // CC
displayOp(g, 6, 3, 2, 3, 1);
displayOp(g, 5, 4, 3, 2, 0);
displayOp(g, 4, 3, 3, 1, 0);
displayOp(g, 3, 2, 2, 0, 0);
displayOp(g, 2, 2, 3, 1, 0);
displayOp(g, 1, 1, 3, 1, 0);
break;
case 23: // CC
displayOp(g, 6, 3, 2, 4, 1);
displayOp(g, 5, 4, 3, 2, 0);
displayOp(g, 4, 3, 3, 1, 0);
displayOp(g, 3, 2, 3, 1, 0);
displayOp(g, 2, 1, 3, 1, 0);
displayOp(g, 1, 0, 3, 1, 0);
break;
case 24: // CC
displayOp(g, 6, 3, 2, 3, 1);
displayOp(g, 5, 4, 3, 2, 0);
displayOp(g, 4, 3, 3, 1, 0);
displayOp(g, 3, 2, 3, 1, 0);
displayOp(g, 2, 1, 3, 1, 0);
displayOp(g, 1, 0, 3, 1, 0);
break;
case 25:
displayOp(g, 6, 4, 2, 0, 1);
displayOp(g, 5, 3, 2, 1, 0);
displayOp(g, 4, 4, 3, 2, 0);
displayOp(g, 3, 2, 2, 0, 0);
displayOp(g, 2, 2, 3, 6, 0);
displayOp(g, 1, 1, 3, 1, 0);
break;
case 26:
displayOp(g, 6, 4, 2, 0, 0);
displayOp(g, 5, 3, 2, 1, 0);
displayOp(g, 4, 4, 3, 2, 0);
displayOp(g, 3, 2, 2, 0, 1);
displayOp(g, 2, 2, 3, 6, 0);
displayOp(g, 1, 1, 3, 1, 0);
break;
case 27:
displayOp(g, 6, 4, 3, 2, 0);
displayOp(g, 5, 3, 1, 0, 1);
displayOp(g, 4, 3, 2, 0, 0);
displayOp(g, 3, 3, 3, 1, 0);
displayOp(g, 2, 2, 2, 0, 0);
displayOp(g, 1, 2, 3, 1, 0);
break;
case 28:
displayOp(g, 6, 4, 2, 0, 1);
displayOp(g, 5, 4, 3, 2, 0);
displayOp(g, 4, 3, 2, 0, 0);
displayOp(g, 3, 3, 3, 1, 0);
displayOp(g, 2, 2, 3, 1, 0);
displayOp(g, 1, 1, 3, 1, 0);
break;
case 29:
displayOp(g, 6, 4, 3, 2, 0);
displayOp(g, 5, 3, 1, 0, 1);
displayOp(g, 4, 3, 2, 0, 0);
displayOp(g, 3, 3, 3, 1, 0);
displayOp(g, 2, 2, 3, 1, 0);
displayOp(g, 1, 1, 3, 1, 0);
break;
case 30:
displayOp(g, 6, 4, 2, 0, 1);
displayOp(g, 5, 4, 3, 2, 0);
displayOp(g, 4, 3, 3, 1, 0);
displayOp(g, 3, 2, 3, 1, 0);
displayOp(g, 2, 1, 3, 1, 0);
displayOp(g, 1, 0, 3, 1, 0);
break;
case 31:
displayOp(g, 6, 5, 3, 2, 1);
displayOp(g, 5, 4, 3, 1, 0);
displayOp(g, 4, 3, 3, 1, 0);
displayOp(g, 3, 2, 3, 1, 0);
displayOp(g, 2, 1, 3, 1, 0);
displayOp(g, 1, 0, 3, 1, 0);
break;
default:
break;
}
}

@ -1,33 +0,0 @@
/**
*
* Copyright (c) 2014 Pascal Gauthier.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef ALGODISPLAY_H_INCLUDED
#define ALGODISPLAY_H_INCLUDED
#include "../JuceLibraryCode/JuceHeader.h"
class AlgoDisplay : public Component {
public:
AlgoDisplay();
char *algo;
void paint(Graphics &g);
};
#endif // ALGODISPLAY_H_INCLUDED

@ -1,359 +0,0 @@
/**
*
* Copyright (c) 2015 Pascal Gauthier.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "PluginProcessor.h"
#include "PluginEditor.h"
#include "CartManager.h"
#include "DXLookNFeel.h"
#include "PluginData.h"
#include <fstream>
using namespace ::std;
class SyxFileFilter : public FileFilter {
public:
SyxFileFilter() : FileFilter(".syx") {}
bool isFileSuitable(const File &file) const {
return file.getFileExtension().toLowerCase() == ".syx" && file.getSize() >= 4104;
}
bool isDirectorySuitable(const File &file) const {
return true;
};
};
class FileTreeDrop : public FileTreeComponent {
public :
FileTreeDrop(DirectoryContentsList &listToShow) : FileTreeComponent(listToShow) {}
bool isInterestedInFileDrag (const StringArray &files) override {
bool found = false;
for(int i=0; i<files.size(); i++) {
String filename = files[i].toLowerCase();
found |= filename.endsWith(".syx");
}
return found;
}
void filesDropped(const StringArray &files, int x, int y) override {
File targetDir = getSelectedFile();
if ( ! targetDir.exists() )
targetDir = DexedAudioProcessor::dexedCartDir;
if ( ! targetDir.isDirectory() )
targetDir = targetDir.getParentDirectory();
for(int i=0; i<files.size(); i++) {
if ( files[i].toLowerCase().endsWith(".syx") ) {
File src(files[i]);
File target = targetDir.getChildFile(src.getFileName());
src.copyFileTo(target);
}
}
fileList.refresh();
}
};
CartManager::CartManager(DexedAudioProcessorEditor *editor) : Component("CartManager") {
mainWindow = editor;
cartDir = DexedAudioProcessor::dexedCartDir;
addAndMakeVisible(activeCart = new ProgramListBox("activepgm", 8));
activeCart->setBounds(28, 441, 800, 96);
activeCart->addListener(this);
addAndMakeVisible(browserCart = new ProgramListBox("browserpgm", 2));
browserCart->setBounds(635, 18, 200, 384);
browserCart->addListener(this);
// -------------------------
syxFileFilter = new SyxFileFilter();
timeSliceThread = new TimeSliceThread("Cartridge Directory Scanner");
timeSliceThread->startThread();
cartBrowserList = new DirectoryContentsList(syxFileFilter, *timeSliceThread);
cartBrowserList->setDirectory(cartDir, true, true);
cartBrowser = new FileTreeDrop(*cartBrowserList);
cartBrowser->addKeyListener(this);
addAndMakeVisible(cartBrowser);
cartBrowser->setBounds(23, 18, 590, 384);
cartBrowser->setDragAndDropDescription("Sysex Browser");
cartBrowser->addListener(this);
addAndMakeVisible(closeButton = new TextButton("CLOSE"));
closeButton->setBounds(4, 545, 50, 30);
closeButton->addListener(this);
addAndMakeVisible(loadButton = new TextButton("LOAD"));
loadButton->setBounds(52, 545, 50, 30);
loadButton->addListener(this);
addAndMakeVisible(saveButton = new TextButton("SAVE"));
saveButton->setBounds(100, 545, 50, 30);
saveButton->addListener(this);
addAndMakeVisible(fileMgrButton = new TextButton("SHOW DIR"));
fileMgrButton->setBounds(148, 545, 70, 30);
fileMgrButton->addListener(this);
/*
*
* I've removed this since it only works on the DX7 II. TBC.
*
addAndMakeVisible(getDXPgmButton = new TextButton("GET DX7 PGM"));
getDXPgmButton->setBounds(656, 545, 100, 30);
getDXPgmButton->addListener(this);
addAndMakeVisible(getDXCartButton = new TextButton("GET DX7 CART"));
getDXCartButton->setBounds(755, 545, 100, 30);
getDXCartButton->addListener(this);
*/
}
CartManager::~CartManager() {
timeSliceThread->stopThread(500);
delete cartBrowser;
delete cartBrowserList;
delete timeSliceThread;
}
void CartManager::paint(Graphics &g) {
g.fillAll(DXLookNFeel::lightBackground);
g.setColour(DXLookNFeel::roundBackground);
g.fillRoundedRectangle(8, 418, 843, 126, 15);
g.setColour(Colours::whitesmoke);
g.drawText("currently loaded cartridge", 38, 410, 150, 40, Justification::left);
}
void CartManager::programSelected(ProgramListBox *source, int pos) {
if ( source == activeCart ) {
browserCart->setSelected(-1);
mainWindow->processor->setCurrentProgram(pos);
mainWindow->processor->updateHostDisplay();
} else {
uint8_t unpackPgm[161];
source->getCurrentCart().unpackProgram(unpackPgm, pos);
activeCart->setSelected(-1);
browserCart->setSelected(pos);
repaint();
mainWindow->processor->updateProgramFromSysex((uint8_t *) unpackPgm);
mainWindow->processor->updateHostDisplay();
}
}
void CartManager::buttonClicked(juce::Button *buttonThatWasClicked) {
if ( buttonThatWasClicked == closeButton ) {
mainWindow->startTimer(100);
setVisible(false);
return;
}
if ( buttonThatWasClicked == loadButton ) {
FileChooser fc ("Import original DX sysex...", File::nonexistent, "*.syx;*.SYX;*.*", 1);
if ( fc.browseForFileToOpen())
mainWindow->loadCart(fc.getResult());
return;
}
if ( buttonThatWasClicked == saveButton ) {
mainWindow->saveCart();
}
if ( buttonThatWasClicked == fileMgrButton ) {
cartDir.revealToUser();
return;
}
// THIS IS NOT USED
if ( buttonThatWasClicked == getDXPgmButton ) {
if ( mainWindow->processor->sysexComm.isInputActive() && mainWindow->processor->sysexComm.isOutputActive() ) {
unsigned char msg[] = { 0xF0, 0x43, 0x20, 0x09, 0xF7 };
mainWindow->processor->sysexComm.send(MidiMessage(msg, 5));
} else {
showSysexConfigMsg();
}
return;
}
if ( buttonThatWasClicked == getDXCartButton ) {
if ( mainWindow->processor->sysexComm.isInputActive() && mainWindow->processor->sysexComm.isOutputActive() ) {
unsigned char msg[] = { 0xF0, 0x43, 0x20, 0x00, 0xF7 };
mainWindow->processor->sysexComm.send(MidiMessage(msg, 5));
} else {
showSysexConfigMsg();
}
return;
}
}
void CartManager::fileDoubleClicked(const File& file) {
if ( file.isDirectory() )
return;
mainWindow->loadCart(file);
activeCart->setCartridge(mainWindow->processor->currentCart);
}
void CartManager::fileClicked(const File& file, const MouseEvent& e) {
if ( e.mods.isRightButtonDown() ) {
PopupMenu menu;
menu.addItem(1000, "Open location");
if ( ! file.isDirectory() ) {
menu.addItem(1010, "Send sysex cartridge to DX7");
}
menu.addSeparator();
menu.addItem(1020, "Refresh");
switch(menu.show()) {
case 1000:
file.revealToUser();
break;
case 1010 :
mainWindow->processor->sendSysexCartridge(file);
break;
case 1020:
cartBrowserList->refresh();
break;
}
return;
}
}
void CartManager::setActiveProgram(int idx, String activeName) {
if ( activeCart->programNames[idx] == activeName ) {
activeCart->setSelected(idx);
browserCart->setSelected(-1);
}
activeCart->repaint();
}
void CartManager::resetActiveSysex() {
activeCart->setCartridge(mainWindow->processor->currentCart);
}
void CartManager::selectionChanged() {
File file = cartBrowser->getSelectedFile();
if ( ! file.exists() )
return;
if ( file.isDirectory() )
return;
Cartridge browserSysex;
int rc = browserSysex.load(file);
if ( rc < 0 ) {
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, "Error", "Unable to open file");
return;
}
if ( rc != 0 ) {
browserCart->readOnly = true;
} else {
browserCart->readOnly = false;
}
browserCart->setSelected(-1);
browserCart->setCartridge(browserSysex);
}
void CartManager::programRightClicked(ProgramListBox *source, int pos) {
PopupMenu menu;
menu.addItem(1000, "Send program '" + source->programNames[pos] + "' to DX7");
if ( source == activeCart )
menu.addItem(1010, "Send current sysex cartridge to DX7");
switch(menu.show()) {
case 1000:
uint8_t unpackPgm[161];
if ( source == activeCart ) {
mainWindow->processor->currentCart.unpackProgram(unpackPgm, pos);
} else {
source->getCurrentCart().unpackProgram(unpackPgm, pos);
}
if ( mainWindow->processor->sysexComm.isOutputActive() ) {
uint8_t msg[163];
exportSysexPgm(msg, unpackPgm);
mainWindow->processor->sysexComm.send(MidiMessage(msg, 163));
}
break;
case 1010:
mainWindow->processor->sendCurrentSysexCartridge();
break;
}
}
void CartManager::programDragged(ProgramListBox *destListBox, int dest, char *packedPgm) {
if ( destListBox == activeCart ) {
char *sysex = mainWindow->processor->currentCart.getRawVoice();
memcpy(sysex+(dest*128), packedPgm, 128);
mainWindow->updateUI();
} else {
File file = cartBrowser->getSelectedFile();
if ( ! file.exists() )
return;
if ( file.isDirectory() )
return;
if ( file.getSize() != 4104 )
return;
Cartridge cart;
cart.load(file);
memcpy(cart.getRawVoice()+(dest*128), packedPgm, 128);
cart.saveVoice(file);
browserCart->setCartridge(cart);
}
}
void CartManager::initialFocus() {
cartBrowser->grabKeyboardFocus();
}
bool CartManager::keyPressed(const KeyPress& key, Component* originatingComponent) {
if ( key.getKeyCode() == 13 ) {
File file = cartBrowser->getSelectedFile();
if ( file.isDirectory() )
return true;
mainWindow->loadCart(file);
activeCart->setCartridge(mainWindow->processor->currentCart);
return true;
}
return false;
}
void CartManager::showSysexConfigMsg() {
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon, "Warning", "The DX7 midi interface is not configured correctly.\n\n"
"These buttons are used to 'ask' the DX7 to send the current program/cartridge.\n\n"
"In order to use this correctly, you need to connect your midi in and midi out of your DX7 to a midi interface and configure this midi interface with the [PARM] dialog. THIS ONLY WORKS ON A DX7-II");
}
// unused stuff from FileBrowserListener
void CartManager::browserRootChanged (const File& newRoot) {}

@ -1,77 +0,0 @@
/**
*
* Copyright (c) 2015 Pascal Gauthier.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef CARTMANAGER_H_INCLUDED
#define CARTMANAGER_H_INCLUDED
#include "../JuceLibraryCode/JuceHeader.h"
#include "PluginData.h"
#include "ProgramListBox.h"
#include "PluginData.h"
class CartManager : public Component, public ButtonListener, public DragAndDropContainer, public FileBrowserListener
, public ProgramListBoxListener, public KeyListener {
ScopedPointer<TextButton> newButton;
ScopedPointer<TextButton> loadButton;
ScopedPointer<TextButton> saveButton;
ScopedPointer<TextButton> closeButton;
ScopedPointer<TextButton> fileMgrButton;
ScopedPointer<TextButton> getDXPgmButton;
ScopedPointer<TextButton> getDXCartButton;
ScopedPointer<ProgramListBox> activeCart;
ScopedPointer<ProgramListBox> browserCart;
ScopedPointer<FileFilter> syxFileFilter;
FileTreeComponent *cartBrowser;
TimeSliceThread *timeSliceThread;
DirectoryContentsList *cartBrowserList;
File cartDir;
DexedAudioProcessorEditor *mainWindow;
void showSysexConfigMsg();
public:
CartManager(DexedAudioProcessorEditor *editor);
virtual ~CartManager();
void paint(Graphics& g) override;
void buttonClicked (Button* buttonThatWasClicked) override;
void selectionChanged() override;
void fileClicked (const File& file, const MouseEvent& e) override;
void fileDoubleClicked (const File& file) override;
void browserRootChanged (const File& newRoot) override;
void setActiveProgram(int idx, String activeName);
void resetActiveSysex();
virtual void programSelected(ProgramListBox *source, int pos) override;
virtual void programRightClicked(ProgramListBox *source, int pos) override;
virtual void programDragged(ProgramListBox *destListBox, int dest, char *packedPgm) override;
virtual bool keyPressed(const KeyPress& key, Component* originatingComponent) override;
void initialFocus();
};
#endif // CARTMANAGER_H_INCLUDED

@ -1,442 +0,0 @@
/**
*
* Copyright (c) 2014 Pascal Gauthier.
*
* DX7 Envelope Tables from legasynth-0.4.1 / DX7 Patch Editor
* Copyright (C) 2002 Juan Linietsky <coding@reduz.com.ar>
* Copyright (C) 2006 Mark-André Hopf <mhopf@mark13.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "Dexed.h"
#include "DXComponents.h"
#include "DXLookNFeel.h"
#include "PluginProcessor.h"
#include "msfa/pitchenv.h"
static char TMP_LEVEL_PTR[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
static float EG_rate_rise_duration[128] = {
38.00000 ,34.96000 ,31.92000 ,28.88000 ,25.84000 ,
22.80000 ,20.64000 ,18.48000 ,16.32000 ,14.16000 ,
12.00000 ,11.10000 ,10.20000 ,9.30000 ,8.40000 ,
7.50000 ,6.96000 ,6.42000 ,5.88000 ,5.34000 ,
4.80000 ,4.38000 ,3.96000 ,3.54000 ,3.12000 ,
2.70000 ,2.52000 ,2.34000 ,2.16000 ,1.98000 ,
1.80000 ,1.70000 ,1.60000 ,1.50000 ,1.40000 ,
1.30000 ,1.22962 ,1.15925 ,1.08887 ,1.01850 ,
0.94813 ,0.87775 ,0.80737 ,0.73700 ,0.69633 ,
0.65567 ,0.61500 ,0.57833 ,0.54167 ,0.50500 ,
0.47300 ,0.44100 ,0.40900 ,0.37967 ,0.35033 ,
0.32100 ,0.28083 ,0.24067 ,0.20050 ,0.16033 ,
0.12017 ,0.08000 ,0.07583 ,0.07167 ,0.06750 ,
0.06333 ,0.05917 ,0.05500 ,0.04350 ,0.03200 ,
0.02933 ,0.02667 ,0.02400 ,0.02200 ,0.02000 ,
0.01800 ,0.01667 ,0.01533 ,0.01400 ,0.01300 ,
0.01200 ,0.01100 ,0.01000 ,0.00900 ,0.00800 ,
0.00800 ,0.00800 ,0.00800 ,0.00767 ,0.00733 ,
0.00700 ,0.00633 ,0.00567 ,0.00500 ,0.00433 ,
0.00367 ,0.00300 ,0.00300 ,0.00300 ,0.00300 ,
0.00300 ,0.00300 ,0.00300 ,0.00300 ,0.00300 ,
0.00300 ,0.00300 ,0.00300 ,0.00300 ,0.00300 ,
0.00300 ,0.00300 ,0.00300 ,0.00300 ,0.00300 ,
0.00300 ,0.00300 ,0.00300 ,0.00300 ,0.00300 ,
0.00300 ,0.00300 ,0.00300 ,0.00300 ,0.00300 ,
0.00300 ,0.00300 ,0.00300
};
static float EG_rate_decay_duration[128] = {
318.00000 ,283.75000 ,249.50000 ,215.25000 ,181.00000 ,
167.80000 ,154.60001 ,141.39999 ,128.20000 ,115.00000 ,
104.60000 ,94.20000 ,83.80000 ,73.40000 ,63.00000 ,
58.34000 ,53.68000 ,49.02000 ,44.36000 ,39.70000 ,
35.76000 ,31.82000 ,27.88000 ,23.94000 ,20.00000 ,
18.24000 ,16.48000 ,14.72000 ,12.96000 ,11.20000 ,
10.36000 ,9.52000 ,8.68000 ,7.84000 ,7.00000 ,
6.83250 ,6.66500 ,6.49750 ,6.33000 ,6.16250 ,
5.99500 ,5.82750 ,5.66000 ,5.10000 ,4.54000 ,
3.98000 ,3.64833 ,3.31667 ,2.98500 ,2.65333 ,
2.32167 ,1.99000 ,1.77333 ,1.55667 ,1.34000 ,
1.22333 ,1.10667 ,0.99000 ,0.89667 ,0.80333 ,
0.71000 ,0.65000 ,0.59000 ,0.53000 ,0.47000 ,
0.41000 ,0.32333 ,0.23667 ,0.15000 ,0.12700 ,
0.10400 ,0.08100 ,0.07667 ,0.07233 ,0.06800 ,
0.06100 ,0.05400 ,0.04700 ,0.04367 ,0.04033 ,
0.03700 ,0.03300 ,0.02900 ,0.02500 ,0.02333 ,
0.02167 ,0.02000 ,0.01767 ,0.01533 ,0.01300 ,
0.01133 ,0.00967 ,0.00800 ,0.00800 ,0.00800 ,
0.00800 ,0.00800 ,0.00800 ,0.00800 ,0.00800 ,
0.00800 ,0.00800 ,0.00800 ,0.00800 ,0.00800 ,
0.00800 ,0.00800 ,0.00800 ,0.00800 ,0.00800 ,
0.00800 ,0.00800 ,0.00800 ,0.00800 ,0.00800 ,
0.00800 ,0.00800 ,0.00800 ,0.00800 ,0.00800 ,
0.00800 ,0.00800 ,0.00800 ,0.00800 ,0.00800 ,
0.00800 ,0.00800 ,0.00800
};
static float EG_rate_decay_percent[128] = {
0.00001 ,0.00001 ,0.00001 ,0.00001 ,0.00001 ,
0.00001 ,0.00001 ,0.00001 ,0.00001 ,0.00001 ,
0.00001 ,0.00001 ,0.00001 ,0.00001 ,0.00001 ,
0.00001 ,0.00001 ,0.00001 ,0.00001 ,0.00001 ,
0.00001 ,0.00001 ,0.00001 ,0.00001 ,0.00001 ,
0.00001 ,0.00001 ,0.00001 ,0.00001 ,0.00001 ,
0.00001 ,0.00001 ,0.00501 ,0.01001 ,0.01500 ,
0.02000 ,0.02800 ,0.03600 ,0.04400 ,0.05200 ,
0.06000 ,0.06800 ,0.07600 ,0.08400 ,0.09200 ,
0.10000 ,0.10800 ,0.11600 ,0.12400 ,0.13200 ,
0.14000 ,0.15000 ,0.16000 ,0.17000 ,0.18000 ,
0.19000 ,0.20000 ,0.21000 ,0.22000 ,0.23000 ,
0.24000 ,0.25100 ,0.26200 ,0.27300 ,0.28400 ,
0.29500 ,0.30600 ,0.31700 ,0.32800 ,0.33900 ,
0.35000 ,0.36500 ,0.38000 ,0.39500 ,0.41000 ,
0.42500 ,0.44000 ,0.45500 ,0.47000 ,0.48500 ,
0.50000 ,0.52000 ,0.54000 ,0.56000 ,0.58000 ,
0.60000 ,0.62000 ,0.64000 ,0.66000 ,0.68000 ,
0.70000 ,0.73200 ,0.76400 ,0.79600 ,0.82800 ,
0.86000 ,0.89500 ,0.93000 ,0.96500 ,1.00000 ,
1.00000 ,1.00000 ,1.00000 ,1.00000 ,1.00000 ,
1.00000 ,1.00000 ,1.00000 ,1.00000 ,1.00000 ,
1.00000 ,1.00000 ,1.00000 ,1.00000 ,1.00000 ,
1.00000 ,1.00000 ,1.00000 ,1.00000 ,1.00000 ,
1.00000 ,1.00000 ,1.00000 ,1.00000 ,1.00000 ,
1.00000 ,1.00000 ,1.00000
};
static float EG_rate_rise_percent[128] = {
0.00001 ,0.00001 ,0.00001 ,0.00001 ,0.00001 ,
0.00001 ,0.00001 ,0.00001 ,0.00001 ,0.00001 ,
0.00001 ,0.00001 ,0.00001 ,0.00001 ,0.00001 ,
0.00001 ,0.00001 ,0.00001 ,0.00001 ,0.00001 ,
0.00001 ,0.00001 ,0.00001 ,0.00001 ,0.00001 ,
0.00001 ,0.00001 ,0.00001 ,0.00001 ,0.00001 ,
0.00001 ,0.00001 ,0.00501 ,0.01001 ,0.01500 ,
0.02000 ,0.02800 ,0.03600 ,0.04400 ,0.05200 ,
0.06000 ,0.06800 ,0.07600 ,0.08400 ,0.09200 ,
0.10000 ,0.10800 ,0.11600 ,0.12400 ,0.13200 ,
0.14000 ,0.15000 ,0.16000 ,0.17000 ,0.18000 ,
0.19000 ,0.20000 ,0.21000 ,0.22000 ,0.23000 ,
0.24000 ,0.25100 ,0.26200 ,0.27300 ,0.28400 ,
0.29500 ,0.30600 ,0.31700 ,0.32800 ,0.33900 ,
0.35000 ,0.36500 ,0.38000 ,0.39500 ,0.41000 ,
0.42500 ,0.44000 ,0.45500 ,0.47000 ,0.48500 ,
0.50000 ,0.52000 ,0.54000 ,0.56000 ,0.58000 ,
0.60000 ,0.62000 ,0.64000 ,0.66000 ,0.68000 ,
0.70000 ,0.73200 ,0.76400 ,0.79600 ,0.82800 ,
0.86000 ,0.89500 ,0.93000 ,0.96500 ,1.00000 ,
1.00000 ,1.00000 ,1.00000 ,1.00000 ,1.00000 ,
1.00000 ,1.00000 ,1.00000 ,1.00000 ,1.00000 ,
1.00000 ,1.00000 ,1.00000 ,1.00000 ,1.00000 ,
1.00000 ,1.00000 ,1.00000 ,1.00000 ,1.00000 ,
1.00000 ,1.00000 ,1.00000 ,1.00000 ,1.00000 ,
1.00000 ,1.00000 ,1.00000
};
static double getDuration(int p_rate, int p_level_l, int p_level_r) {
float *duration_table=(p_level_r>p_level_l) ? EG_rate_rise_duration : EG_rate_decay_duration;
double duration=duration_table[p_rate];
float* percent_table =(p_level_r>p_level_l) ? EG_rate_rise_percent : EG_rate_decay_percent;
duration *= fabs(percent_table[p_level_r]-percent_table[p_level_l]);
return duration;
}
EnvDisplay::EnvDisplay() {
pvalues = (uint8_t *) &TMP_LEVEL_PTR;
}
void EnvDisplay::paint(Graphics &g) {
int h = getHeight();
uint8_t *rates = pvalues;
uint8_t *levels = pvalues + 4;
double d[4];
double keyoff = 0.0;
double release = 0.0;
d[0] = getDuration(rates[0], levels[3], levels[0]);
d[1] = getDuration(rates[1], levels[0], levels[1]);
d[2] = getDuration(rates[2], levels[1], levels[2]);
double ko = 0.0;
for(int j=0; j<3; ++j)
ko += d[j];
if (ko>keyoff)
keyoff=ko;
d[3] = getDuration(rates[3], levels[2], levels[3]);
if ( d[3]>release ) {
release = d[3];
}
keyoff += 10.0;
double w = getWidth() / (keyoff + release);
g.setColour(Colour(0xF0000000));
g.fillRoundedRectangle (keyoff*w, 0.0f, (float) getWidth(), (float) getHeight(), 1.0f);
g.setColour(Colours::white);
int x, y;
Path p;
p.startNewSubPath(0, 32);
// 0
x = 0;
y = h - h / 99.0 * levels[3];
p.lineTo(x, y);
if ( vPos == 0 || vPos == 1 ) {
g.fillEllipse(x-2, y-2, 4, 4);
}
// 1
x = d[0]*w;
y = h - h / 99.0 * levels[0];
p.lineTo( x, y );
if ( vPos == 1 || vPos == 2 ) {
g.fillEllipse(x-2, y-2, 4, 4);
}
// 2
x = (d[0]+d[1])*w;
y = h - h / 99.0 * levels[1];
p.lineTo( x, y );
if ( vPos == 2 || vPos == 3 ) {
g.fillEllipse(x-2, y-2, 4, 4);
}
// 3
x = (d[0]+d[1]+d[2])*w;
y = h - h / 99.0 * levels[2];
p.lineTo( x, y );
if ( vPos == 3 || vPos == 4) {
g.fillEllipse(x-2, y-2, 4, 4);
}
// 4
x = keyoff*w;
y = h - h / 99.0 * levels[2];
p.lineTo( x, y );
if ( vPos == 4 ) {
g.fillEllipse(x-2, y-2, 4, 4);
}
// 5
p.lineTo( (d[0]+d[1]+d[2]+keyoff+d[3])*w, h - h / 99.0 * levels[3] );
p.lineTo(96,32);
p.lineTo(0, 32);
g.setColour(DXLookNFeel::fillColour);
g.fillPath(p);
g.setColour(Colour(0xFFFFFFFF));
String len;
len << ((int) vPos);
g.drawText(len, 5, 1, 72, 14, Justification::left, true);
}
PitchEnvDisplay::PitchEnvDisplay() {
pvalues = (uint8_t *) &TMP_LEVEL_PTR;
vPos = 0;
}
void PitchEnvDisplay::paint(Graphics &g) {
g.setColour(Colours::white);
uint8_t *levels = pvalues + 4;
uint8_t *rates = pvalues;
float dist[4];
float total = 0;
int old = pitchenv_tab[levels[3]] + 128;
// find the scale
for(int i=0;i<4;i++) {
int nw = pitchenv_tab[levels[i]] + 128;
dist[i] = ((float)abs(nw - old)) / pitchenv_rate[rates[i]];
total += dist[i];
old = nw;
}
if ( total < 0.00001 ) {
dist[0] = dist[1] = dist[2] = dist[3] = 1;
total = 4;
}
float ratio = 96 / total;
Path p;
p.startNewSubPath(0, 32);
int x = 0;
int y = 25 - (pitchenv_tab[levels[3]] + 128) / 10;
p.lineTo(0,y);
int dx = x;
int dy = y;
int i;
for(i=0;i<4;i++) {
if ( vPos == i ) {
dx = x;
dy = y;
}
x = dist[i] * ratio + x;
y = 25 - (pitchenv_tab[levels[i]] + 128) / 10;
p.lineTo(x, y);
}
if ( vPos == i ) {
dx = x;
dy = y;
}
p.lineTo(96,32);
p.lineTo(0, 32);
g.setColour(DXLookNFeel::fillColour);
g.fillPath(p);
g.setColour(Colours::white);
g.fillEllipse(dx-2, dy-2, 4, 4);
}
void VuMeter::paint(Graphics &g) {
Image myStrip = ImageCache::getFromMemory(BinaryData::Meter_140x8_png, BinaryData::Meter_140x8_pngSize);
g.drawImage(myStrip, 0, 0, 140, 8, 0, 0, 140, 8);
if ( v <= 0 )
return;
const int totalBlocks = 46;
int numBlocks = roundToInt(totalBlocks * v);
if ( numBlocks > 46 )
numBlocks = totalBlocks;
int brkpoint = numBlocks * 3 + 2;
g.drawImage(myStrip, 0, 0, brkpoint, 8, 0, 8, brkpoint, 8);
}
LcdDisplay::LcdDisplay() {
paramMsg = "DEXED " DEXED_VERSION;
}
void LcdDisplay::setSystemMsg(String msg) {
paramMsg = msg;
}
void LcdDisplay::paint(Graphics &g) {
g.setColour (Colours::white);
g.drawText (paramMsg,
0, 0, 140, 14,
Justification::centred, true);
}
void ComboBoxImage::paint(Graphics &g) {
int idx = getSelectedItemIndex();
if ( itemPos[0] != -1 ) {
if ( idx < 4 )
idx = itemPos[idx];
}
g.drawImage(items, 0, 0, items.getWidth(), itemHeight, 0, idx * itemHeight, items.getWidth(), itemHeight);
}
ComboBoxImage::ComboBoxImage() {
itemPos[0] = -1;
}
static void comboBoxPopupMenuFinishedCallback (int result, ComboBoxImage* combo) {
if (combo != nullptr) {
combo->hidePopup();
if (result != 0)
combo->setSelectedId (result);
}
}
void ComboBoxImage::showPopup() {
popup.showMenuAsync (PopupMenu::Options().withTargetComponent (this)
.withItemThatMustBeVisible(getSelectedId())
.withMinimumWidth(getWidth())
.withMaximumNumColumns(1)
.withStandardItemHeight(itemHeight),
ModalCallbackFunction::forComponent(comboBoxPopupMenuFinishedCallback, this));
}
void ComboBoxImage::setImage(Image image) {
items = image;
int numItems = getNumItems();
itemHeight = image.getHeight() / numItems;
for(int i=0;i<numItems;i++) {
Image tmp = image.getClippedImage(Rectangle<int>(0,itemHeight*i, image.getWidth(), itemHeight));
popup.addItem(i+1, getItemText(i), true, false, tmp);
}
}
void ComboBoxImage::setImage(Image image, int pos[]) {
items = image;
int numItems = getNumItems();
itemHeight = 26;
for(int i=0;i<numItems;i++) {
Image tmp = image.getClippedImage(Rectangle<int>(0,itemHeight*pos[i], image.getWidth(), itemHeight));
popup.addItem(i+1, getItemText(i), true, false, tmp);
}
for(int i=0;i<4;i++)
itemPos[i] = pos[i];
}
void ProgramSelector::mouseDown(const MouseEvent &event) {
if ( event.x < getWidth() - 8) {
ComboBox::mouseDown(event);
return;
}
int cur = getSelectedItemIndex();
if ( event.y < getHeight() / 2 ) {
if ( cur == 0 )
cur = 31;
else
cur--;
} else {
if ( cur == 31 )
cur = 0;
else
cur++;
}
setSelectedItemIndex(cur);
}
void ProgramSelector::paint(Graphics &g) {
int x = getWidth();
int y = getHeight();
Path path;
path.addTriangle(x-8, y/2-1, x-4, 2, x, y/2-1);
path.addTriangle(x-8, y/2+1, x-4, y-2, x, y/2+1);
g.setColour(Colours::white);
g.fillPath(path);
}

@ -1,78 +0,0 @@
/**
*
* Copyright (c) 2014 Pascal Gauthier.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef DXCOMPONENTS_H_INCLUDED
#define DXCOMPONENTS_H_INCLUDED
#include "../JuceLibraryCode/JuceHeader.h"
#include <stdint.h>
class EnvDisplay : public Component {
public:
EnvDisplay();
uint8_t *pvalues;
char vPos;
void paint(Graphics &g);
};
class PitchEnvDisplay : public Component {
char rvalues[8];
public:
PitchEnvDisplay();
uint8_t *pvalues;
char vPos;
void paint(Graphics &g);
};
class VuMeter: public Component {
void paint(Graphics &g);
public :
float v;
};
class LcdDisplay : public Component {
public:
LcdDisplay();
void setSystemMsg(String msg);
String paramMsg;
void paint(Graphics &g);
};
class ComboBoxImage : public ComboBox {
Image items;
int itemHeight;
PopupMenu popup;
int itemPos[4];
public:
ComboBoxImage();
virtual void paint(Graphics &g) override;
virtual void showPopup() override;
void setImage(Image image);
void setImage(Image image, int pos[]);
};
class ProgramSelector : public ComboBox {
public:
void mouseDown(const MouseEvent &event) override;
virtual void paint(Graphics &g) override;
};
#endif // DXCOMPONENTS_H_INCLUDED

@ -1,255 +0,0 @@
/**
*
* Copyright (c) 2013-2016 Pascal Gauthier.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*/
#include "DXLookNFeel.h"
#include "DXComponents.h"
#include "Dexed.h"
#include "PluginProcessor.h"
#define REG_COLOUR(id, value) setColour(id, value); colourMap.set(#id, id)
Image findImage(String path) {
Image img;
if ( path.length() <= 3 )
return img;
File imgFile(path);
img = ImageCache::getFromFile(imgFile);
return img;
}
DXLookNFeel::DXLookNFeel() {
Colour ctrlBackground;
DexedAudioProcessor::dexedAppDir.setAsCurrentWorkingDirectory();
ctrlBackground = Colour(20,18,18);
REG_COLOUR(TextButton::buttonColourId,Colour(0xFF0FC00F));
REG_COLOUR(TextButton::textColourOnId, Colours::white);
REG_COLOUR(TextButton::textColourOffId, Colours::white);
REG_COLOUR(Slider::rotarySliderOutlineColourId,Colour(0xFF0FC00F));
REG_COLOUR(Slider::rotarySliderFillColourId,Colour(0xFFFFFFFF));
REG_COLOUR(AlertWindow::backgroundColourId,lightBackground);
REG_COLOUR(AlertWindow::textColourId, Colours::white);
REG_COLOUR(TextEditor::backgroundColourId,ctrlBackground);
REG_COLOUR(TextEditor::textColourId, Colours::white);
REG_COLOUR(TextEditor::highlightColourId, fillColour);
REG_COLOUR(TextEditor::outlineColourId, Colours::transparentBlack);
REG_COLOUR(ComboBox::backgroundColourId, ctrlBackground);
REG_COLOUR(ComboBox::textColourId, Colours::white);
REG_COLOUR(ComboBox::buttonColourId, Colours::white);
REG_COLOUR(PopupMenu::backgroundColourId, background);
REG_COLOUR(PopupMenu::textColourId, Colours::white);
REG_COLOUR(PopupMenu::highlightedTextColourId, Colours::white);
REG_COLOUR(PopupMenu::highlightedBackgroundColourId, fillColour);
REG_COLOUR(TreeView::backgroundColourId, background);
REG_COLOUR(DirectoryContentsDisplayComponent::highlightColourId, fillColour);
REG_COLOUR(DirectoryContentsDisplayComponent::textColourId, Colours::white);
imageKnob = ImageCache::getFromMemory(BinaryData::Knob_34x34_png, BinaryData::Knob_34x34_pngSize);
imageSwitch = ImageCache::getFromMemory(BinaryData::Switch_48x26_png, BinaryData::Switch_48x26_pngSize);
imageSwitchOperator = ImageCache::getFromMemory(BinaryData::Switch_32x32_png, BinaryData::Switch_32x32_pngSize);
imageButton = ImageCache::getFromMemory(BinaryData::ButtonUnlabeled_50x30_png, BinaryData::ButtonUnlabeled_50x30_pngSize);
imageSlider = ImageCache::getFromMemory(BinaryData::Slider_26x26_png, BinaryData::Slider_26x26_pngSize);
imageScaling = ImageCache::getFromMemory(BinaryData::Scaling_36_26_png, BinaryData::Scaling_36_26_pngSize);;
imageLight = ImageCache::getFromMemory(BinaryData::Light_14x14_png, BinaryData::Light_14x14_pngSize);
imageLFO = ImageCache::getFromMemory(BinaryData::LFO_36_26_png, BinaryData::LFO_36_26_pngSize);
imageOperator = ImageCache::getFromMemory(BinaryData::OperatorEditor_287x218_png, BinaryData::OperatorEditor_287x218_pngSize);
imageGlobal = ImageCache::getFromMemory (BinaryData::GlobalEditor_864x144_png, BinaryData::GlobalEditor_864x144_pngSize);
defaultFont = Typeface::createSystemTypefaceFor(BinaryData::NotoSansRegular_ttf, BinaryData::NotoSansRegular_ttfSize);
defaultFontBold = Typeface::createSystemTypefaceFor(BinaryData::NotoSansBold_ttf, BinaryData::NotoSansBold_ttfSize);
File dexedTheme = DexedAudioProcessor::dexedAppDir.getChildFile("DexedTheme.xml");
if ( ! dexedTheme.existsAsFile() )
return;
XmlElement *root = XmlDocument::parse(dexedTheme);
if ( root == NULL )
return;
forEachXmlChildElementWithTagName(*root, colour, "colour") {
String name = colour->getStringAttribute("id", "");
if ( name == "" )
continue;
String value = colour->getStringAttribute("value", "");
if ( value == "" )
continue;
if ( value.length() < 8 )
continue;
int conv = strtol(value.toRawUTF8(), NULL, 16);
if ( colourMap.contains(name) ) {
setColour(colourMap[name], Colour(conv));
} else {
if ( name == "Dexed::backgroundId" ) {
background = Colour(conv);
continue;
}
if ( name == "Dexed::fillColourId" ) {
fillColour = Colour(conv);
continue;
}
}
}
forEachXmlChildElementWithTagName(*root, image, "image") {
String name = image->getStringAttribute("id", "");
String path = image->getStringAttribute("path", "");
if ( name == "Knob_34x34.png" ) {
imageKnob = findImage(path);
continue;
}
if ( name == "Switch_48x26.png" ) {
imageSwitch = findImage(path);
continue;
}
if ( name == "Switch_32x64.png" ) {
imageSwitchOperator = findImage(path);
continue;
}
if ( name == "ButtonUnlabeled_50x30.png" ) {
imageButton = findImage(path);
continue;
}
if ( name == "Slider_26x26.png" ) {
imageSlider = findImage(path);
continue;
}
if ( name == "Scaling_36_26.png" ) {
imageScaling = findImage(path);
continue;
}
if ( name == "Light_14x14.png" ) {
imageLight = findImage(path);
continue;
}
if ( name == "LFO_36_26.png" ) {
imageLFO = findImage(path);
continue;
}
if ( name == "OperatorEditor_287x218.png" ) {
imageOperator = findImage(path);
continue;
}
if ( name == "GlobalEditor_864x144.png" ) {
imageGlobal = findImage(path);
continue;
}
}
delete root;
}
Typeface::Ptr DXLookNFeel::getTypefaceForFont(const Font &) {
return defaultFont;
}
void DXLookNFeel::drawRotarySlider( Graphics &g, int x, int y, int width, int height, float sliderPosProportional,
float rotaryStartAngle, float rotaryEndAngle, Slider &slider ) {
if ( imageKnob.isNull() ) {
LookAndFeel_V3::drawRotarySlider(g, x, y, width, height, sliderPosProportional, rotaryStartAngle, rotaryEndAngle, slider);
return;
}
const double fractRotation = (slider.getValue() - slider.getMinimum()) / (slider.getMaximum() - slider.getMinimum()); //value between 0 and 1 for current amount of rotation
const int nFrames = imageKnob.getHeight()/imageKnob.getWidth(); // number of frames for vertical film strip
const int frameIdx = (int)ceil(fractRotation * ((double)nFrames-1.0) ); // current index from 0 --> nFrames-1
const float radius = jmin (width / 2.0f, height / 2.0f) ;
const float centreX = x + width * 0.5f;
const float centreY = y + height * 0.5f;
const float rx = centreX - radius - 1.0f;
const float ry = centreY - radius - 1.0f;
g.drawImage(imageKnob, (int)rx, (int)ry, 2*(int)radius, 2*(int)radius, 0, frameIdx*imageKnob.getWidth(), imageKnob.getWidth(), imageKnob.getWidth());
};
void DXLookNFeel::drawToggleButton(Graphics& g, ToggleButton& button, bool isMouseOverButton, bool isButtonDown) {
if ( imageSwitch.isNull() ) {
LookAndFeel_V3::drawToggleButton(g, button, isMouseOverButton, isButtonDown);
return;
}
g.drawImage(imageSwitch, 0, 0, 48, 26, 0, button.getToggleState() ? 0 : 26, 48, 26);
}
void DXLookNFeel::drawButtonBackground(Graphics &g, Button &button, const Colour& backgroundColour, bool isMouseOverButton, bool isButtonDown) {
if ( imageButton.isNull() ) {
LookAndFeel_V3::drawButtonBackground(g, button, backgroundColour, isMouseOverButton, isButtonDown);
return;
}
int w = button.getWidth();
// dx, dy, dw, dl, sx, sy, sw, sl
g.drawImage(imageButton, 0, 0, 3, 30, 0, isButtonDown ? 30 : 0, 3, 30);
g.drawImage(imageButton, 3, 0, w-6, 30, 3, isButtonDown ? 30 : 0, 44, 30);
g.drawImage(imageButton, w-3, 0, 3, 30, 47, isButtonDown ? 30 : 0, 47, 30);
}
void DXLookNFeel::drawLinearSliderBackground (Graphics&, int x, int y, int width, int height,
float sliderPos, float minSliderPos, float maxSliderPos,
const Slider::SliderStyle st, Slider& s) {
// NOP
}
void DXLookNFeel::drawLinearSliderThumb (Graphics& g, int x, int y, int width, int height,
float sliderPos, float minSliderPos, float maxSliderPos,
const Slider::SliderStyle st, Slider& s) {
if ( imageSlider.isNull() ) {
LookAndFeel_V3::drawLinearSliderThumb(g, x, y, width, height, sliderPos, minSliderPos, maxSliderPos, st, s);
return;
}
int p = sliderPos - minSliderPos;
p -= 6;
g.drawImage(imageSlider, p, 0, 26, 26, 0, 0, 26, 26);
}
Font DXLookNFeel::getTextButtonFont(TextButton& button, int buttonHeight) {
return Font(defaultFontBold);
}
void DXLookNFeel::positionComboBoxText(ComboBox& box, Label& label) {
ComboBox *src = &box;
// I'm not proud of this one, but really... it must be another way to do this....
ComboBoxImage* img = dynamic_cast<ComboBoxImage*>(src);
if( img != 0 ) {
return;
}
LookAndFeel_V3::positionComboBoxText(box, label);
}
CriticalSection DXLookNFeel::lock;
DXLookNFeel * DXLookNFeel::ins = NULL;
Colour DXLookNFeel::fillColour = Colour(77,159,151);
Colour DXLookNFeel::lightBackground = Colour(78,72,63);
Colour DXLookNFeel::background = Colour(60,50,47);
Colour DXLookNFeel::roundBackground = Colour(58,52,48);
DXLookNFeel *DXLookNFeel::getLookAndFeel() {
const ScopedLock locker(lock);
if ( ins != NULL )
return ins;
ins = new DXLookNFeel();
return ins;
}

@ -1,63 +0,0 @@
/**
*
* Copyright (c) 2013-2016 Pascal Gauthier.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef DXLOOKNFEEL_H_INCLUDED
#define DXLOOKNFEEL_H_INCLUDED
#include "../JuceLibraryCode/JuceHeader.h"
class DXLookNFeel : public LookAndFeel_V3 {
static CriticalSection lock;
static DXLookNFeel *ins;
DXLookNFeel();
HashMap<String, int> colourMap;
public:
Typeface::Ptr defaultFont;
Typeface::Ptr defaultFontBold;
Image imageKnob, imageSwitch, imageButton, imageSlider, imageScaling, imageLight, imageLFO;
Image imageSwitchOperator;
Image imageOperator, imageGlobal;
/* overriden methods */
virtual void drawRotarySlider(Graphics &g, int x, int y, int width, int height, float sliderPosProportional, float rotaryStartAngle, float rotaryEndAngle, Slider &slider ) override;
virtual void drawToggleButton(Graphics& g, ToggleButton& button, bool isMouseOverButton, bool isButtonDown) override;
virtual void drawLinearSliderBackground (Graphics&, int x, int y, int width, int height,
float sliderPos, float minSliderPos, float maxSliderPos,
const Slider::SliderStyle, Slider&) override;
virtual void drawLinearSliderThumb (Graphics&, int x, int y, int width, int height,
float sliderPos, float minSliderPos, float maxSliderPos,
const Slider::SliderStyle, Slider&) override;
virtual void drawButtonBackground (Graphics&, Button&, const Colour& backgroundColour,
bool isMouseOverButton, bool isButtonDown) override;
virtual Font getTextButtonFont(TextButton&, int buttonHeight) override;
virtual Typeface::Ptr getTypefaceForFont(const Font &) override;
virtual void positionComboBoxText (ComboBox& box, Label& label) override;
static DXLookNFeel *getLookAndFeel();
static Colour fillColour;
static Colour lightBackground;
static Colour background;
static Colour roundBackground;
};
#endif // DXLOOKNFEEL_H_INCLUDED

@ -1,788 +0,0 @@
/*
==============================================================================
This is an automatically generated GUI class created by the Introjucer!
Be careful when adding custom code to these files, as only the code within
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
and re-saved.
Created with Introjucer version: 3.2.0
------------------------------------------------------------------------------
The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright (c) 2015 - ROLI Ltd.
==============================================================================
*/
//[Headers] You can add your own extra header files here...
#include "PluginEditor.h"
#include "DXLookNFeel.h"
//[/Headers]
#include "GlobalEditor.h"
//[MiscUserDefs] You can add your own user definitions and misc code here...
/**
* 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;
Image light;
public:
MidiMonitor(SysexComm *sysexComm) {
midi = sysexComm;
light = DXLookNFeel::getLookAndFeel()->imageLight;
}
void paint(Graphics &g) {
if ( ! (midi->isInputActive() || midi->isOutputActive() ) )
return;
g.setColour(Colours::white);
if ( midi->isInputActive() ) {
g.drawSingleLineText("DX7 IN", 17,14);
g.drawImage(light, 0, 3, 14, 14, 0, midi->inActivity ? 14 : 0, 14, 14);
midi->inActivity = false;
}
if ( midi->isOutputActive() ) {
g.drawSingleLineText("DX7 OUT", 17, 28);
g.drawImage(light, 0, 17, 14, 14, 0, midi->outActivity ? 14 : 0, 14, 14);
midi->outActivity = false;
}
}
};
class AboutBox : public DialogWindow {
public:
Image about_png;
AboutBox(Component *parent) : DialogWindow("About", Colour(0xFF000000), true) {
setUsingNativeTitleBar(false);
setAlwaysOnTop(true);
about_png = ImageCache::getFromMemory(BinaryData::about_png, BinaryData::about_pngSize);
setSize(about_png.getWidth(), about_png.getHeight());
centreAroundComponent (parent, getWidth(), getHeight());
}
void closeButtonPressed() {
setVisible (false);
}
void paint(Graphics &g) {
g.drawImage (about_png, 0, 0, about_png.getWidth(), about_png.getHeight(),
0, 0, about_png.getWidth(), about_png.getHeight());
g.setColour(Colour(0xFF000000));
String ver("Version " DEXED_VERSION " ; build date " __DATE__ );
g.drawSingleLineText(ver, 18, 130);
}
};
//[/MiscUserDefs]
//==============================================================================
GlobalEditor::GlobalEditor ()
{
//[Constructor_pre] You can add your own custom stuff here..
//[/Constructor_pre]
addAndMakeVisible (lfoSpeed = new Slider ("lfoSpeed"));
lfoSpeed->setRange (0, 99, 1);
lfoSpeed->setSliderStyle (Slider::RotaryVerticalDrag);
lfoSpeed->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
lfoSpeed->addListener (this);
addAndMakeVisible (lfoAmDepth = new Slider ("lfoAmDepth"));
lfoAmDepth->setRange (0, 99, 1);
lfoAmDepth->setSliderStyle (Slider::RotaryVerticalDrag);
lfoAmDepth->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
lfoAmDepth->addListener (this);
addAndMakeVisible (lfoPitchDepth = new Slider ("lfoPitchDepth"));
lfoPitchDepth->setRange (0, 99, 1);
lfoPitchDepth->setSliderStyle (Slider::RotaryVerticalDrag);
lfoPitchDepth->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
lfoPitchDepth->addListener (this);
addAndMakeVisible (lfoDelay = new Slider ("lfoDelay"));
lfoDelay->setRange (0, 99, 1);
lfoDelay->setSliderStyle (Slider::RotaryVerticalDrag);
lfoDelay->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
lfoDelay->addListener (this);
addAndMakeVisible (cutoff = new Slider ("cutoff"));
cutoff->setRange (0, 1, 0);
cutoff->setSliderStyle (Slider::RotaryVerticalDrag);
cutoff->setTextBoxStyle (Slider::NoTextBox, true, 80, 20);
cutoff->addListener (this);
addAndMakeVisible (reso = new Slider ("reso"));
reso->setRange (0, 1, 0);
reso->setSliderStyle (Slider::RotaryVerticalDrag);
reso->setTextBoxStyle (Slider::NoTextBox, true, 80, 20);
reso->addListener (this);
addAndMakeVisible (pitchRate2 = new Slider ("pitchRate2"));
pitchRate2->setRange (0, 99, 1);
pitchRate2->setSliderStyle (Slider::RotaryVerticalDrag);
pitchRate2->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
pitchRate2->addListener (this);
addAndMakeVisible (pitchRate3 = new Slider ("pitchRate3"));
pitchRate3->setRange (0, 99, 1);
pitchRate3->setSliderStyle (Slider::RotaryVerticalDrag);
pitchRate3->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
pitchRate3->addListener (this);
addAndMakeVisible (pitchRate4 = new Slider ("pitchRate4"));
pitchRate4->setRange (0, 99, 1);
pitchRate4->setSliderStyle (Slider::RotaryVerticalDrag);
pitchRate4->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
pitchRate4->addListener (this);
addAndMakeVisible (pitchRate1 = new Slider ("pitchRate1"));
pitchRate1->setRange (0, 99, 1);
pitchRate1->setSliderStyle (Slider::RotaryVerticalDrag);
pitchRate1->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
pitchRate1->addListener (this);
addAndMakeVisible (pitchLevel2 = new Slider ("pitchLevel2"));
pitchLevel2->setRange (0, 99, 1);
pitchLevel2->setSliderStyle (Slider::RotaryVerticalDrag);
pitchLevel2->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
pitchLevel2->addListener (this);
addAndMakeVisible (pitchLevel3 = new Slider ("pitchLevel3"));
pitchLevel3->setRange (0, 99, 1);
pitchLevel3->setSliderStyle (Slider::RotaryVerticalDrag);
pitchLevel3->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
pitchLevel3->addListener (this);
addAndMakeVisible (pitchLevel4 = new Slider ("pitchLevel4"));
pitchLevel4->setRange (0, 99, 1);
pitchLevel4->setSliderStyle (Slider::RotaryVerticalDrag);
pitchLevel4->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
pitchLevel4->addListener (this);
addAndMakeVisible (pitchLevel1 = new Slider ("pitchLevel1"));
pitchLevel1->setRange (0, 99, 1);
pitchLevel1->setSliderStyle (Slider::RotaryVerticalDrag);
pitchLevel1->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
pitchLevel1->addListener (this);
addAndMakeVisible (transpose = new Slider ("transpose"));
transpose->setRange (0, 48, 1);
transpose->setSliderStyle (Slider::RotaryVerticalDrag);
transpose->setTextBoxStyle (Slider::NoTextBox, true, 80, 20);
transpose->addListener (this);
addAndMakeVisible (oscSync = new ToggleButton ("oscSync"));
oscSync->setButtonText (String::empty);
oscSync->addListener (this);
addAndMakeVisible (pitchModSens = new Slider ("pitchModSens"));
pitchModSens->setRange (0, 7, 1);
pitchModSens->setSliderStyle (Slider::RotaryVerticalDrag);
pitchModSens->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
pitchModSens->addListener (this);
addAndMakeVisible (lfoSync = new ToggleButton ("lfoSync"));
lfoSync->setButtonText (String::empty);
lfoSync->addListener (this);
addAndMakeVisible (pitchEnvDisplay = new PitchEnvDisplay());
pitchEnvDisplay->setName ("pitchEnvDisplay");
addAndMakeVisible (algoDisplay = new AlgoDisplay());
algoDisplay->setName ("algoDisplay");
addAndMakeVisible (feedback = new Slider ("feedback"));
feedback->setRange (0, 7, 1);
feedback->setSliderStyle (Slider::RotaryVerticalDrag);
feedback->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
feedback->addListener (this);
addAndMakeVisible (algo = new Slider ("algo"));
algo->setRange (1, 32, 1);
algo->setSliderStyle (Slider::RotaryVerticalDrag);
algo->setTextBoxStyle (Slider::NoTextBox, true, 80, 20);
algo->addListener (this);
addAndMakeVisible (lcdDisplay = new LcdDisplay());
lcdDisplay->setName ("lcdDisplay");
addAndMakeVisible (output = new Slider ("output"));
output->setRange (0, 1, 0);
output->setSliderStyle (Slider::RotaryVerticalDrag);
output->setTextBoxStyle (Slider::NoTextBox, true, 80, 20);
output->addListener (this);
addAndMakeVisible (vuOutput = new VuMeter());
vuOutput->setName ("vuOutput");
addAndMakeVisible (initButton = new TextButton ("initButton"));
initButton->setButtonText (TRANS("INIT"));
initButton->addListener (this);
addAndMakeVisible (parmButton = new TextButton ("parmButton"));
parmButton->setButtonText (TRANS("PARM"));
parmButton->addListener (this);
addAndMakeVisible (cartButton = new TextButton ("cartButton"));
cartButton->setButtonText (TRANS("CART"));
cartButton->addListener (this);
addAndMakeVisible (storeButton = new TextButton ("storeButton"));
storeButton->setButtonText (TRANS("STORE"));
storeButton->addListener (this);
addAndMakeVisible (monoMode = new ToggleButton ("monoMode"));
monoMode->setButtonText (String::empty);
monoMode->addListener (this);
addAndMakeVisible (lfoType = new ComboBoxImage());
lfoType->setName ("lfoType");
addAndMakeVisible (programSelector = new ProgramSelector());
programSelector->setName ("programSelector");
addAndMakeVisible (aboutButton = new ImageButton ("aboutButton"));
aboutButton->setButtonText (String::empty);
aboutButton->addListener (this);
aboutButton->setImages (false, true, false,
Image(), 1.000f, Colour (0x00000000),
Image(), 1.000f, Colour (0x00000000),
Image(), 1.000f, Colour (0x00000000));
addAndMakeVisible (tune = new Slider ("tune"));
tune->setRange (0, 1, 0);
tune->setSliderStyle (Slider::RotaryVerticalDrag);
tune->setTextBoxStyle (Slider::NoTextBox, true, 80, 20);
tune->addListener (this);
//[UserPreSize]
//[/UserPreSize]
setSize (864, 144);
//[Constructor] You can add your own custom stuff here..
lfoType->addItem("TRIANGLE", 1);
lfoType->addItem("SAW DOWN", 2);
lfoType->addItem("SAW UP", 3);
lfoType->addItem("SQUARE", 4);
lfoType->addItem("SINE", 5);
lfoType->addItem("S&HOLD", 6);
lfoType->setImage(DXLookNFeel::getLookAndFeel()->imageLFO);
programs = programSelector;
background = DXLookNFeel::getLookAndFeel()->imageGlobal;
imageLight = DXLookNFeel::getLookAndFeel()->imageLight;
//[/Constructor]
}
GlobalEditor::~GlobalEditor()
{
//[Destructor_pre]. You can add your own custom destruction code here..
//[/Destructor_pre]
lfoSpeed = nullptr;
lfoAmDepth = nullptr;
lfoPitchDepth = nullptr;
lfoDelay = nullptr;
cutoff = nullptr;
reso = nullptr;
pitchRate2 = nullptr;
pitchRate3 = nullptr;
pitchRate4 = nullptr;
pitchRate1 = nullptr;
pitchLevel2 = nullptr;
pitchLevel3 = nullptr;
pitchLevel4 = nullptr;
pitchLevel1 = nullptr;
transpose = nullptr;
oscSync = nullptr;
pitchModSens = nullptr;
lfoSync = nullptr;
pitchEnvDisplay = nullptr;
algoDisplay = nullptr;
feedback = nullptr;
algo = nullptr;
lcdDisplay = nullptr;
output = nullptr;
vuOutput = nullptr;
initButton = nullptr;
parmButton = nullptr;
cartButton = nullptr;
storeButton = nullptr;
monoMode = nullptr;
lfoType = nullptr;
programSelector = nullptr;
aboutButton = nullptr;
tune = nullptr;
//[Destructor]. You can add your own custom destruction code here..
//[/Destructor]
}
//==============================================================================
void GlobalEditor::paint (Graphics& g)
{
//[UserPrePaint] Add your own custom painting code here..
g.drawImage(background, 0, 0, 864, 144, 0, 0, 864, 144);
//[/UserPrePaint]
//[UserPaint] Add your own custom painting code here..
g.drawImage(imageLight, 300, 70, 14, 14, 0, monoMode->getToggleState() ? 14 : 0, 14, 14);
g.drawImage(imageLight, 619, 102, 14, 14, 0, lfoSync->getToggleState() ? 14 : 0, 14, 14);
g.drawImage(imageLight, 705, 102, 14, 14, 0, oscSync->getToggleState() ? 14 : 0, 14, 14);
//[/UserPaint]
}
void GlobalEditor::resized()
{
//[UserPreResize] Add your own custom resize code here..
//[/UserPreResize]
lfoSpeed->setBounds (564, 50, 34, 34);
lfoAmDepth->setBounds (686, 50, 34, 34);
lfoPitchDepth->setBounds (646, 50, 34, 34);
lfoDelay->setBounds (603, 50, 34, 34);
cutoff->setBounds (234, 9, 34, 34);
reso->setBounds (278, 9, 34, 34);
pitchRate2->setBounds (767, 96, 34, 34);
pitchRate3->setBounds (795, 96, 35, 34);
pitchRate4->setBounds (823, 96, 34, 34);
pitchRate1->setBounds (739, 96, 34, 34);
pitchLevel2->setBounds (767, 57, 34, 34);
pitchLevel3->setBounds (795, 56, 34, 34);
pitchLevel4->setBounds (823, 56, 34, 34);
pitchLevel1->setBounds (739, 57, 34, 34);
transpose->setBounds (202, 60, 34, 34);
oscSync->setBounds (650, 96, 48, 26);
pitchModSens->setBounds (666, 5, 34, 34);
lfoSync->setBounds (565, 96, 48, 26);
pitchEnvDisplay->setBounds (751, 10, 93, 30);
algoDisplay->setBounds (335, 30, 152, 91);
feedback->setBounds (501, 81, 34, 34);
algo->setBounds (501, 22, 34, 34);
lcdDisplay->setBounds (6, 87, 140, 13);
output->setBounds (157, 60, 34, 34);
vuOutput->setBounds (6, 103, 140, 8);
initButton->setBounds (100, 111, 50, 30);
parmButton->setBounds (52, 111, 50, 30);
cartButton->setBounds (3, 111, 50, 30);
storeButton->setBounds (270, 109, 50, 30);
monoMode->setBounds (249, 65, 48, 26);
lfoType->setBounds (583, 8, 36, 26);
programSelector->setBounds (153, 115, 112, 18);
aboutButton->setBounds (8, 11, 135, 46);
tune->setBounds (190, 9, 34, 34);
//[UserResized] Add your own custom resize handling here..
//[/UserResized]
}
void GlobalEditor::sliderValueChanged (Slider* sliderThatWasMoved)
{
//[UsersliderValueChanged_Pre]
//[/UsersliderValueChanged_Pre]
if (sliderThatWasMoved == lfoSpeed)
{
//[UserSliderCode_lfoSpeed] -- add your slider handling code here..
//[/UserSliderCode_lfoSpeed]
}
else if (sliderThatWasMoved == lfoAmDepth)
{
//[UserSliderCode_lfoAmDepth] -- add your slider handling code here..
//[/UserSliderCode_lfoAmDepth]
}
else if (sliderThatWasMoved == lfoPitchDepth)
{
//[UserSliderCode_lfoPitchDepth] -- add your slider handling code here..
//[/UserSliderCode_lfoPitchDepth]
}
else if (sliderThatWasMoved == lfoDelay)
{
//[UserSliderCode_lfoDelay] -- add your slider handling code here..
//[/UserSliderCode_lfoDelay]
}
else if (sliderThatWasMoved == cutoff)
{
//[UserSliderCode_cutoff] -- add your slider handling code here..
//[/UserSliderCode_cutoff]
}
else if (sliderThatWasMoved == reso)
{
//[UserSliderCode_reso] -- add your slider handling code here..
//[/UserSliderCode_reso]
}
else if (sliderThatWasMoved == pitchRate2)
{
//[UserSliderCode_pitchRate2] -- add your slider handling code here..
pitchEnvDisplay->repaint();
//[/UserSliderCode_pitchRate2]
}
else if (sliderThatWasMoved == pitchRate3)
{
//[UserSliderCode_pitchRate3] -- add your slider handling code here..
pitchEnvDisplay->repaint();
//[/UserSliderCode_pitchRate3]
}
else if (sliderThatWasMoved == pitchRate4)
{
//[UserSliderCode_pitchRate4] -- add your slider handling code here..
pitchEnvDisplay->repaint();
//[/UserSliderCode_pitchRate4]
}
else if (sliderThatWasMoved == pitchRate1)
{
//[UserSliderCode_pitchRate1] -- add your slider handling code here..
pitchEnvDisplay->repaint();
//[/UserSliderCode_pitchRate1]
}
else if (sliderThatWasMoved == pitchLevel2)
{
//[UserSliderCode_pitchLevel2] -- add your slider handling code here..
pitchEnvDisplay->repaint();
//[/UserSliderCode_pitchLevel2]
}
else if (sliderThatWasMoved == pitchLevel3)
{
//[UserSliderCode_pitchLevel3] -- add your slider handling code here..
pitchEnvDisplay->repaint();
//[/UserSliderCode_pitchLevel3]
}
else if (sliderThatWasMoved == pitchLevel4)
{
//[UserSliderCode_pitchLevel4] -- add your slider handling code here..
pitchEnvDisplay->repaint();
//[/UserSliderCode_pitchLevel4]
}
else if (sliderThatWasMoved == pitchLevel1)
{
//[UserSliderCode_pitchLevel1] -- add your slider handling code here..
pitchEnvDisplay->repaint();
//[/UserSliderCode_pitchLevel1]
}
else if (sliderThatWasMoved == transpose)
{
//[UserSliderCode_transpose] -- add your slider handling code here..
//[/UserSliderCode_transpose]
}
else if (sliderThatWasMoved == pitchModSens)
{
//[UserSliderCode_pitchModSens] -- add your slider handling code here..
//[/UserSliderCode_pitchModSens]
}
else if (sliderThatWasMoved == feedback)
{
//[UserSliderCode_feedback] -- add your slider handling code here..
//[/UserSliderCode_feedback]
}
else if (sliderThatWasMoved == algo)
{
//[UserSliderCode_algo] -- add your slider handling code here..
//[/UserSliderCode_algo]
}
else if (sliderThatWasMoved == output)
{
//[UserSliderCode_output] -- add your slider handling code here..
//[/UserSliderCode_output]
}
else if (sliderThatWasMoved == tune)
{
//[UserSliderCode_tune] -- add your slider handling code here..
//[/UserSliderCode_tune]
}
//[UsersliderValueChanged_Post]
//[/UsersliderValueChanged_Post]
}
void GlobalEditor::buttonClicked (Button* buttonThatWasClicked)
{
//[UserbuttonClicked_Pre]
//[/UserbuttonClicked_Pre]
if (buttonThatWasClicked == oscSync)
{
//[UserButtonCode_oscSync] -- add your button handler code here..
repaint();
//[/UserButtonCode_oscSync]
}
else if (buttonThatWasClicked == lfoSync)
{
//[UserButtonCode_lfoSync] -- add your button handler code here..
repaint();
//[/UserButtonCode_lfoSync]
}
else if (buttonThatWasClicked == initButton)
{
//[UserButtonCode_initButton] -- add your button handler code here..
editor->initProgram();
//[/UserButtonCode_initButton]
}
else if (buttonThatWasClicked == parmButton)
{
//[UserButtonCode_parmButton] -- add your button handler code here..
editor->parmShow();
//[/UserButtonCode_parmButton]
}
else if (buttonThatWasClicked == cartButton)
{
//[UserButtonCode_cartButton] -- add your button handler code here..
editor->cartShow();
//[/UserButtonCode_cartButton]
}
else if (buttonThatWasClicked == storeButton)
{
//[UserButtonCode_storeButton] -- add your button handler code here..
editor->storeProgram();
//[/UserButtonCode_storeButton]
}
else if (buttonThatWasClicked == monoMode)
{
//[UserButtonCode_monoMode] -- add your button handler code here..
editor->processor->setMonoMode(monoMode->getToggleState());
repaint();
//[/UserButtonCode_monoMode]
}
else if (buttonThatWasClicked == aboutButton)
{
//[UserButtonCode_aboutButton] -- add your button handler code here..
AboutBox about(this->getParentComponent());
about.runModalLoop();
//[/UserButtonCode_aboutButton]
}
//[UserbuttonClicked_Post]
//[/UserbuttonClicked_Post]
}
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
void GlobalEditor::bind(DexedAudioProcessorEditor *edit) {
processor = edit->processor;
processor->algo->bind(algo);
processor->lfoRate->bind(lfoSpeed);
processor->lfoDelay->bind(lfoDelay);
processor->lfoWaveform->bind(lfoType);
processor->lfoAmpDepth->bind(lfoAmDepth);
processor->lfoPitchDepth->bind(lfoPitchDepth);
processor->lfoSync->bind(lfoSync);
processor->oscSync->bind(oscSync);
processor->transpose->bind(transpose);
processor->feedback->bind(feedback);
processor->pitchModSens->bind(pitchModSens);
processor->pitchEgLevel[0]->bind(pitchLevel1);
processor->pitchEgLevel[1]->bind(pitchLevel2);
processor->pitchEgLevel[2]->bind(pitchLevel3);
processor->pitchEgLevel[3]->bind(pitchLevel4);
processor->pitchEgRate[0]->bind(pitchRate1);
processor->pitchEgRate[1]->bind(pitchRate2);
processor->pitchEgRate[2]->bind(pitchRate3);
processor->pitchEgRate[3]->bind(pitchRate4);
processor->fxCutoff->bind(cutoff);
processor->fxReso->bind(reso);
processor->output->bind(output);
processor->tune->bind(tune);
algoDisplay->algo = (char *) &(processor->data[134]);
pitchEnvDisplay->pvalues = &(processor->data[126]);
editor = edit;
midiMonitor = new MidiMonitor(&(processor->sysexComm));
//addAndMakeVisible(midiMonitor);
//midiMonitor->setBounds(155, 21, 80, 45);
repaint();
}
void GlobalEditor::setSystemMessage(String msg) {
lcdDisplay->setSystemMsg(msg);
}
void GlobalEditor::setParamMessage(String msg) {
lcdDisplay->paramMsg = msg;
}
void GlobalEditor::updateDisplay() {
repaint();
}
void GlobalEditor::updatePitchPos(int pos) {
pitchEnvDisplay->vPos = pos;
pitchEnvDisplay->repaint();
}
void GlobalEditor::updateVu(float f) {
vuOutput->v = f;
vuOutput->repaint();
midiMonitor->repaint();
}
void GlobalEditor::setMonoState(bool state) {
monoMode->setToggleState(state ? Button::buttonDown : Button::buttonNormal, dontSendNotification);
}
//[/MiscUserCode]
//==============================================================================
#if 0
/* -- Introjucer information section --
This is where the Introjucer stores the metadata that describe this GUI layout, so
make changes in here at your peril!
BEGIN_JUCER_METADATA
<JUCER_COMPONENT documentType="Component" className="GlobalEditor" componentName=""
parentClasses="public Component" constructorParams="" variableInitialisers=""
snapPixels="8" snapActive="0" snapShown="1" overlayOpacity="0.330"
fixedSize="1" initialWidth="864" initialHeight="144">
<BACKGROUND backgroundColour="ffffff"/>
<SLIDER name="lfoSpeed" id="b10eaf327ab3bff5" memberName="lfoSpeed" virtualName=""
explicitFocusOrder="0" pos="564 50 34 34" min="0" max="99" int="1"
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="lfoAmDepth" id="3e95a6206fa4a891" memberName="lfoAmDepth"
virtualName="" explicitFocusOrder="0" pos="686 50 34 34" min="0"
max="99" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox"
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="lfoPitchDepth" id="6ead769ca786c813" memberName="lfoPitchDepth"
virtualName="" explicitFocusOrder="0" pos="646 50 34 34" min="0"
max="99" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox"
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="lfoDelay" id="1fce68dc81619ef5" memberName="lfoDelay" virtualName=""
explicitFocusOrder="0" pos="603 50 34 34" min="0" max="99" int="1"
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="cutoff" id="40531f16bb0bd225" memberName="cutoff" virtualName=""
explicitFocusOrder="0" pos="234 9 34 34" min="0" max="1" int="0"
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="0"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="reso" id="c8c13464e81a8d83" memberName="reso" virtualName=""
explicitFocusOrder="0" pos="278 9 34 34" min="0" max="1" int="0"
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="0"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="pitchRate2" id="73f386b3c91d3de4" memberName="pitchRate2"
virtualName="" explicitFocusOrder="0" pos="767 96 34 34" min="0"
max="99" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox"
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="pitchRate3" id="187c25b24413fccf" memberName="pitchRate3"
virtualName="" explicitFocusOrder="0" pos="795 96 35 34" min="0"
max="99" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox"
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="pitchRate4" id="1aeb2a8fbbcbeaab" memberName="pitchRate4"
virtualName="" explicitFocusOrder="0" pos="823 96 34 34" min="0"
max="99" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox"
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="pitchRate1" id="419d613b3fb9604e" memberName="pitchRate1"
virtualName="" explicitFocusOrder="0" pos="739 96 34 34" min="0"
max="99" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox"
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="pitchLevel2" id="3a355ad2221887d9" memberName="pitchLevel2"
virtualName="" explicitFocusOrder="0" pos="767 57 34 34" min="0"
max="99" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox"
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="pitchLevel3" id="5c5d782e8a7f3ad7" memberName="pitchLevel3"
virtualName="" explicitFocusOrder="0" pos="795 56 34 34" min="0"
max="99" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox"
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="pitchLevel4" id="eb900b141fbad8ff" memberName="pitchLevel4"
virtualName="" explicitFocusOrder="0" pos="823 56 34 34" min="0"
max="99" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox"
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="pitchLevel1" id="344cbe26ec9fa128" memberName="pitchLevel1"
virtualName="" explicitFocusOrder="0" pos="739 57 34 34" min="0"
max="99" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox"
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="transpose" id="7d1266b1c1534947" memberName="transpose"
virtualName="" explicitFocusOrder="0" pos="202 60 34 34" min="0"
max="48" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox"
textBoxEditable="0" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<TOGGLEBUTTON name="oscSync" id="8f3fe641537cd00" memberName="oscSync" virtualName=""
explicitFocusOrder="0" pos="650 96 48 26" buttonText="" connectedEdges="0"
needsCallback="1" radioGroupId="0" state="0"/>
<SLIDER name="pitchModSens" id="904f73df85a9f886" memberName="pitchModSens"
virtualName="" explicitFocusOrder="0" pos="666 5 34 34" min="0"
max="7" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox"
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<TOGGLEBUTTON name="lfoSync" id="ff92bb0a5a4f7187" memberName="lfoSync" virtualName=""
explicitFocusOrder="0" pos="565 96 48 26" buttonText="" connectedEdges="0"
needsCallback="1" radioGroupId="0" state="0"/>
<GENERICCOMPONENT name="pitchEnvDisplay" id="9ddaae8ef924a038" memberName="pitchEnvDisplay"
virtualName="" explicitFocusOrder="0" pos="751 10 93 30" class="PitchEnvDisplay"
params=""/>
<GENERICCOMPONENT name="algoDisplay" id="b26fb9e3b5f0bc37" memberName="algoDisplay"
virtualName="" explicitFocusOrder="0" pos="335 30 152 91" class="AlgoDisplay"
params=""/>
<SLIDER name="feedback" id="4fac1940c29ab8c" memberName="feedback" virtualName=""
explicitFocusOrder="0" pos="501 81 34 34" min="0" max="7" int="1"
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="algo" id="8a226ddf9bbff752" memberName="algo" virtualName=""
explicitFocusOrder="0" pos="501 22 34 34" min="1" max="32" int="1"
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="0"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<GENERICCOMPONENT name="lcdDisplay" id="30c7bb8f114cbbe3" memberName="lcdDisplay"
virtualName="" explicitFocusOrder="0" pos="6 87 140 13" class="LcdDisplay"
params=""/>
<SLIDER name="output" id="7697fdd54fd1593e" memberName="output" virtualName=""
explicitFocusOrder="0" pos="157 60 34 34" min="0" max="1" int="0"
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="0"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<GENERICCOMPONENT name="vuOutput" id="dac75af912267f51" memberName="vuOutput" virtualName=""
explicitFocusOrder="0" pos="6 103 140 8" class="VuMeter" params=""/>
<TEXTBUTTON name="initButton" id="92b278163c42e21d" memberName="initButton"
virtualName="" explicitFocusOrder="0" pos="100 111 50 30" buttonText="INIT"
connectedEdges="0" needsCallback="1" radioGroupId="0"/>
<TEXTBUTTON name="parmButton" id="d5cd6260b34be817" memberName="parmButton"
virtualName="" explicitFocusOrder="0" pos="52 111 50 30" buttonText="PARM"
connectedEdges="0" needsCallback="1" radioGroupId="0"/>
<TEXTBUTTON name="cartButton" id="465a101c3a0e744" memberName="cartButton"
virtualName="" explicitFocusOrder="0" pos="3 111 50 30" buttonText="CART"
connectedEdges="0" needsCallback="1" radioGroupId="0"/>
<TEXTBUTTON name="storeButton" id="a94bec26832eb58b" memberName="storeButton"
virtualName="" explicitFocusOrder="0" pos="270 109 50 30" buttonText="STORE"
connectedEdges="0" needsCallback="1" radioGroupId="0"/>
<TOGGLEBUTTON name="monoMode" id="e683d8cbe286367b" memberName="monoMode" virtualName=""
explicitFocusOrder="0" pos="249 65 48 26" buttonText="" connectedEdges="0"
needsCallback="1" radioGroupId="0" state="0"/>
<GENERICCOMPONENT name="lfoType" id="62f61dda9f76c8f" memberName="lfoType" virtualName=""
explicitFocusOrder="0" pos="583 8 36 26" class="ComboBoxImage"
params=""/>
<GENERICCOMPONENT name="programSelector" id="990bbcccae72dbe6" memberName="programSelector"
virtualName="" explicitFocusOrder="0" pos="153 115 112 18" class="ProgramSelector"
params=""/>
<IMAGEBUTTON name="aboutButton" id="d195a60b29440aa1" memberName="aboutButton"
virtualName="" explicitFocusOrder="0" pos="8 11 135 46" buttonText=""
connectedEdges="0" needsCallback="1" radioGroupId="0" keepProportions="0"
resourceNormal="" opacityNormal="1" colourNormal="0" resourceOver=""
opacityOver="1" colourOver="0" resourceDown="" opacityDown="1"
colourDown="0"/>
<SLIDER name="tune" id="d22c34aa3363a28a" memberName="tune" virtualName=""
explicitFocusOrder="0" pos="190 9 34 34" min="0" max="1" int="0"
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="0"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
</JUCER_COMPONENT>
END_JUCER_METADATA
*/
#endif
//[EndFile] You can add extra defines here...
//[/EndFile]

@ -1,126 +0,0 @@
/*
==============================================================================
This is an automatically generated GUI class created by the Introjucer!
Be careful when adding custom code to these files, as only the code within
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
and re-saved.
Created with Introjucer version: 3.2.0
------------------------------------------------------------------------------
The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright (c) 2015 - ROLI Ltd.
==============================================================================
*/
#ifndef __JUCE_HEADER_10638A2B49B704D0__
#define __JUCE_HEADER_10638A2B49B704D0__
//[Headers] -- You can add your own extra header files here --
#include "JuceHeader.h"
#include "PluginProcessor.h"
#include "DXComponents.h"
#include "AlgoDisplay.h"
class DexedAudioProcessorEditor;
//[/Headers]
//==============================================================================
/**
//[Comments]
An auto-generated component, created by the Introjucer.
Describe your class and how it works here!
//[/Comments]
*/
class GlobalEditor : public Component,
public SliderListener,
public ButtonListener
{
public:
//==============================================================================
GlobalEditor ();
~GlobalEditor();
//==============================================================================
//[UserMethods] -- You can add your own custom methods in this section.
void bind(DexedAudioProcessorEditor *processor);
void setSystemMessage(String msg);
void setParamMessage(String msg);
void updatePitchPos(int pos);
void updateVu(float v);
void updateDisplay();
void repaintMsg();
void setMonoState(bool state);
ProgramSelector *programs;
ScopedPointer<Component> midiMonitor;
//[/UserMethods]
void paint (Graphics& g);
void resized();
void sliderValueChanged (Slider* sliderThatWasMoved);
void buttonClicked (Button* buttonThatWasClicked);
private:
//[UserVariables] -- You can add your own custom variables in this section.
DexedAudioProcessorEditor *editor;
DexedAudioProcessor *processor;
Image background;
Image imageLight;
//[/UserVariables]
//==============================================================================
ScopedPointer<Slider> lfoSpeed;
ScopedPointer<Slider> lfoAmDepth;
ScopedPointer<Slider> lfoPitchDepth;
ScopedPointer<Slider> lfoDelay;
ScopedPointer<Slider> cutoff;
ScopedPointer<Slider> reso;
ScopedPointer<Slider> pitchRate2;
ScopedPointer<Slider> pitchRate3;
ScopedPointer<Slider> pitchRate4;
ScopedPointer<Slider> pitchRate1;
ScopedPointer<Slider> pitchLevel2;
ScopedPointer<Slider> pitchLevel3;
ScopedPointer<Slider> pitchLevel4;
ScopedPointer<Slider> pitchLevel1;
ScopedPointer<Slider> transpose;
ScopedPointer<ToggleButton> oscSync;
ScopedPointer<Slider> pitchModSens;
ScopedPointer<ToggleButton> lfoSync;
ScopedPointer<PitchEnvDisplay> pitchEnvDisplay;
ScopedPointer<AlgoDisplay> algoDisplay;
ScopedPointer<Slider> feedback;
ScopedPointer<Slider> algo;
ScopedPointer<LcdDisplay> lcdDisplay;
ScopedPointer<Slider> output;
ScopedPointer<VuMeter> vuOutput;
ScopedPointer<TextButton> initButton;
ScopedPointer<TextButton> parmButton;
ScopedPointer<TextButton> cartButton;
ScopedPointer<TextButton> storeButton;
ScopedPointer<ToggleButton> monoMode;
ScopedPointer<ComboBoxImage> lfoType;
ScopedPointer<ProgramSelector> programSelector;
ScopedPointer<ImageButton> aboutButton;
ScopedPointer<Slider> tune;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GlobalEditor)
};
//[EndFile] You can add extra defines here...
//[/EndFile]
#endif // __JUCE_HEADER_10638A2B49B704D0__

@ -1,660 +0,0 @@
/*
==============================================================================
This is an automatically generated GUI class created by the Introjucer!
Be careful when adding custom code to these files, as only the code within
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
and re-saved.
Created with Introjucer version: 3.2.0
------------------------------------------------------------------------------
The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright (c) 2015 - ROLI Ltd.
==============================================================================
*/
//[Headers] You can add your own extra header files here...
//[/Headers]
#include "OperatorEditor.h"
//[MiscUserDefs] You can add your own user definitions and misc code here...
#ifndef M_LN10
#define M_LN10 2.30258509299404568402
#endif
class OperatorSwitch : public ToggleButton {
Image image;
public :
OperatorSwitch() : ToggleButton("opSwitch") {
image = DXLookNFeel::getLookAndFeel()->imageSwitchOperator;
setSize(32, 32);
}
void paintButton (Graphics& g, bool isMouseOverButton, bool isButtonDown) {
g.drawImage(image, 0, 0, 32, 32, 0, getToggleState() ? 0 : 32, 32, 32);
}
};
//[/MiscUserDefs]
//==============================================================================
OperatorEditor::OperatorEditor ()
{
//[Constructor_pre] You can add your own custom stuff here..
//[/Constructor_pre]
addAndMakeVisible (s_egl1 = new Slider ("egl1"));
s_egl1->setRange (0, 99, 1);
s_egl1->setSliderStyle (Slider::RotaryVerticalDrag);
s_egl1->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
s_egl1->addListener (this);
addAndMakeVisible (s_egl2 = new Slider ("egl2"));
s_egl2->setRange (0, 99, 1);
s_egl2->setSliderStyle (Slider::RotaryVerticalDrag);
s_egl2->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
s_egl2->addListener (this);
addAndMakeVisible (s_egl3 = new Slider ("egl3"));
s_egl3->setRange (0, 99, 1);
s_egl3->setSliderStyle (Slider::RotaryVerticalDrag);
s_egl3->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
s_egl3->addListener (this);
addAndMakeVisible (s_egl4 = new Slider ("egl4"));
s_egl4->setRange (0, 99, 1);
s_egl4->setSliderStyle (Slider::RotaryVerticalDrag);
s_egl4->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
s_egl4->addListener (this);
addAndMakeVisible (s_egv1 = new Slider ("egr1"));
s_egv1->setRange (0, 99, 1);
s_egv1->setSliderStyle (Slider::RotaryVerticalDrag);
s_egv1->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
s_egv1->addListener (this);
addAndMakeVisible (s_egv2 = new Slider ("egr3"));
s_egv2->setRange (0, 99, 1);
s_egv2->setSliderStyle (Slider::RotaryVerticalDrag);
s_egv2->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
s_egv2->addListener (this);
addAndMakeVisible (s_egv3 = new Slider ("egr3"));
s_egv3->setRange (0, 99, 1);
s_egv3->setSliderStyle (Slider::RotaryVerticalDrag);
s_egv3->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
s_egv3->addListener (this);
addAndMakeVisible (s_egv4 = new Slider ("egr4"));
s_egv4->setRange (0, 99, 1);
s_egv4->setSliderStyle (Slider::RotaryVerticalDrag);
s_egv4->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
s_egv4->addListener (this);
addAndMakeVisible (opLevel = new Slider ("opLevel"));
opLevel->setRange (0, 99, 1);
opLevel->setSliderStyle (Slider::RotaryVerticalDrag);
opLevel->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
opLevel->addListener (this);
addAndMakeVisible (opFine = new Slider ("opFine"));
opFine->setRange (0, 99, 1);
opFine->setSliderStyle (Slider::RotaryVerticalDrag);
opFine->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
opFine->addListener (this);
addAndMakeVisible (opCoarse = new Slider ("opCoarse"));
opCoarse->setRange (0, 31, 1);
opCoarse->setSliderStyle (Slider::RotaryVerticalDrag);
opCoarse->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
opCoarse->addListener (this);
addAndMakeVisible (khzDisplay = new Label ("khz",
TRANS("1,000 kHz")));
khzDisplay->setFont (Font (12.60f, Font::plain));
khzDisplay->setJustificationType (Justification::centred);
khzDisplay->setEditable (false, false, false);
khzDisplay->setColour (Label::backgroundColourId, Colour (0x6a000000));
khzDisplay->setColour (Label::textColourId, Colours::white);
khzDisplay->setColour (Label::outlineColourId, Colour (0x00000000));
khzDisplay->setColour (TextEditor::textColourId, Colours::black);
khzDisplay->setColour (TextEditor::backgroundColourId, Colour (0x00000000));
addAndMakeVisible (detune = new Slider ("detune"));
detune->setRange (-7, 7, 1);
detune->setSliderStyle (Slider::RotaryVerticalDrag);
detune->setTextBoxStyle (Slider::NoTextBox, true, 80, 20);
detune->addListener (this);
addAndMakeVisible (envDisplay = new EnvDisplay());
envDisplay->setName ("envDisplay");
addAndMakeVisible (sclLeftLevel = new Slider ("sclLeftLevel"));
sclLeftLevel->setTooltip (TRANS("Keyboard Scale Level Left Depth "));
sclLeftLevel->setRange (0, 99, 1);
sclLeftLevel->setSliderStyle (Slider::RotaryVerticalDrag);
sclLeftLevel->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
sclLeftLevel->addListener (this);
addAndMakeVisible (sclRightLevel = new Slider ("sclRightLevel"));
sclRightLevel->setTooltip (TRANS("Keyboard Scale Level Right Depth "));
sclRightLevel->setRange (0, 99, 1);
sclRightLevel->setSliderStyle (Slider::RotaryVerticalDrag);
sclRightLevel->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
sclRightLevel->addListener (this);
addAndMakeVisible (sclLvlBrkPt = new Slider ("sclLvlBrkPt"));
sclLvlBrkPt->setTooltip (TRANS("Scale Level Breakpoint"));
sclLvlBrkPt->setRange (0, 99, 1);
sclLvlBrkPt->setSliderStyle (Slider::LinearHorizontal);
sclLvlBrkPt->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
sclLvlBrkPt->addListener (this);
addAndMakeVisible (sclRateScaling = new Slider ("sclRateScaling"));
sclRateScaling->setTooltip (TRANS("Keyboard Rate Scaling"));
sclRateScaling->setRange (0, 7, 1);
sclRateScaling->setSliderStyle (Slider::RotaryVerticalDrag);
sclRateScaling->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
sclRateScaling->addListener (this);
addAndMakeVisible (keyVelSens = new Slider ("keyVelSens"));
keyVelSens->setRange (0, 7, 1);
keyVelSens->setSliderStyle (Slider::RotaryVerticalDrag);
keyVelSens->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
keyVelSens->addListener (this);
addAndMakeVisible (ampModSens = new Slider ("ampModSens"));
ampModSens->setRange (0, 3, 1);
ampModSens->setSliderStyle (Slider::RotaryVerticalDrag);
ampModSens->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
ampModSens->addListener (this);
addAndMakeVisible (vu = new VuMeter());
vu->setName ("vu");
addAndMakeVisible (opMode = new ToggleButton ("opMode"));
opMode->setButtonText (String::empty);
opMode->addListener (this);
addAndMakeVisible (kbdLeftCurve = new ComboBoxImage());
kbdLeftCurve->setName ("kbdLeftCurve");
addAndMakeVisible (kbdRightCurve = new ComboBoxImage());
kbdRightCurve->setName ("kbdRightCurve");
//[UserPreSize]
addAndMakeVisible(opSwitch = new OperatorSwitch());
//[/UserPreSize]
setSize (287, 218);
//[Constructor] You can add your own custom stuff here..
light = DXLookNFeel::getLookAndFeel()->imageLight;
Image tmp = DXLookNFeel::getLookAndFeel()->imageScaling;
kbdLeftCurve->addItem("-LN", 1);
kbdLeftCurve->addItem("-EX", 2);
kbdLeftCurve->addItem("+EX", 3);
kbdLeftCurve->addItem("+LN", 4);
int posLeft[] = {0,5,4,3};
kbdLeftCurve->setImage(tmp, posLeft);
kbdRightCurve->addItem("-LN", 1);
kbdRightCurve->addItem("-EX", 2);
kbdRightCurve->addItem("+EX", 3);
kbdRightCurve->addItem("+LN", 4);
int posRight[] = {3,2,1,0};
kbdRightCurve->setImage(tmp, posRight);
background = DXLookNFeel::getLookAndFeel()->imageOperator;
//[/Constructor]
}
OperatorEditor::~OperatorEditor()
{
//[Destructor_pre]. You can add your own custom destruction code here..
//[/Destructor_pre]
s_egl1 = nullptr;
s_egl2 = nullptr;
s_egl3 = nullptr;
s_egl4 = nullptr;
s_egv1 = nullptr;
s_egv2 = nullptr;
s_egv3 = nullptr;
s_egv4 = nullptr;
opLevel = nullptr;
opFine = nullptr;
opCoarse = nullptr;
khzDisplay = nullptr;
detune = nullptr;
envDisplay = nullptr;
sclLeftLevel = nullptr;
sclRightLevel = nullptr;
sclLvlBrkPt = nullptr;
sclRateScaling = nullptr;
keyVelSens = nullptr;
ampModSens = nullptr;
vu = nullptr;
opMode = nullptr;
kbdLeftCurve = nullptr;
kbdRightCurve = nullptr;
//[Destructor]. You can add your own custom destruction code here..
opSwitch = nullptr;
//[/Destructor]
}
//==============================================================================
void OperatorEditor::paint (Graphics& g)
{
//[UserPrePaint] Add your own custom painting code here..
g.drawImage(background, 0, 0, 287, 218, 0, 0, 287, 218);
//[/UserPrePaint]
//[UserPaint] Add your own custom painting code here..
g.setColour (Colours::white);
g.setFont(Font (30.00f, Font::plain));
g.drawText(opNum, 250, 14, 30, 30, Justification::centred, true);
bool state = opMode->getToggleState();
// 129 x 24
g.drawImage(light, 127, 24, 14, 14, 0, state ? 0 : 14, 14, 14);
// 199 x 24
g.drawImage(light, 198, 24, 14, 14, 0, !state ? 0 : 14, 14, 14);
//[/UserPaint]
}
void OperatorEditor::resized()
{
//[UserPreResize] Add your own custom resize code here..
//[/UserPreResize]
s_egl1->setBounds (5, 128, 34, 34);
s_egl2->setBounds (33, 129, 34, 34);
s_egl3->setBounds (61, 128, 34, 34);
s_egl4->setBounds (89, 128, 34, 34);
s_egv1->setBounds (5, 169, 34, 34);
s_egv2->setBounds (33, 169, 34, 34);
s_egv3->setBounds (61, 169, 34, 34);
s_egv4->setBounds (89, 169, 34, 34);
opLevel->setBounds (245, 76, 34, 34);
opFine->setBounds (78, 24, 34, 34);
opCoarse->setBounds (43, 24, 34, 34);
khzDisplay->setBounds (15, 10, 95, 10);
detune->setBounds (6, 24, 34, 34);
envDisplay->setBounds (16, 83, 94, 30);
sclLeftLevel->setBounds (131, 115, 34, 34);
sclRightLevel->setBounds (241, 115, 34, 34);
sclLvlBrkPt->setBounds (178, 130, 54, 24);
sclRateScaling->setBounds (186, 179, 34, 34);
keyVelSens->setBounds (204, 76, 34, 34);
ampModSens->setBounds (140, 76, 34, 34);
vu->setBounds (132, 52, 140, 8);
opMode->setBounds (146, 19, 48, 26);
kbdLeftCurve->setBounds (128, 170, 36, 26);
kbdRightCurve->setBounds (240, 170, 36, 26);
//[UserResized] Add your own custom resize handling here..
opSwitch->setBounds(226, 13, 64, 32);
//[/UserResized]
}
void OperatorEditor::sliderValueChanged (Slider* sliderThatWasMoved)
{
//[UsersliderValueChanged_Pre]
//[/UsersliderValueChanged_Pre]
if (sliderThatWasMoved == s_egl1)
{
//[UserSliderCode_s_egl1] -- add your slider handling code here..
envDisplay->repaint();
//[/UserSliderCode_s_egl1]
}
else if (sliderThatWasMoved == s_egl2)
{
//[UserSliderCode_s_egl2] -- add your slider handling code here..
envDisplay->repaint();
//[/UserSliderCode_s_egl2]
}
else if (sliderThatWasMoved == s_egl3)
{
//[UserSliderCode_s_egl3] -- add your slider handling code here..
envDisplay->repaint();
//[/UserSliderCode_s_egl3]
}
else if (sliderThatWasMoved == s_egl4)
{
//[UserSliderCode_s_egl4] -- add your slider handling code here..
envDisplay->repaint();
//[/UserSliderCode_s_egl4]
}
else if (sliderThatWasMoved == s_egv1)
{
//[UserSliderCode_s_egv1] -- add your slider handling code here..
envDisplay->repaint();
//[/UserSliderCode_s_egv1]
}
else if (sliderThatWasMoved == s_egv2)
{
//[UserSliderCode_s_egv2] -- add your slider handling code here..
envDisplay->repaint();
//[/UserSliderCode_s_egv2]
}
else if (sliderThatWasMoved == s_egv3)
{
//[UserSliderCode_s_egv3] -- add your slider handling code here..
envDisplay->repaint();
//[/UserSliderCode_s_egv3]
}
else if (sliderThatWasMoved == s_egv4)
{
//[UserSliderCode_s_egv4] -- add your slider handling code here..
envDisplay->repaint();
//[/UserSliderCode_s_egv4]
}
else if (sliderThatWasMoved == opLevel)
{
//[UserSliderCode_opLevel] -- add your slider handling code here..
//[/UserSliderCode_opLevel]
}
else if (sliderThatWasMoved == opFine)
{
//[UserSliderCode_opFine] -- add your slider handling code here..
updateDisplay();
//[/UserSliderCode_opFine]
}
else if (sliderThatWasMoved == opCoarse)
{
//[UserSliderCode_opCoarse] -- add your slider handling code here..
updateDisplay();
//[/UserSliderCode_opCoarse]
}
else if (sliderThatWasMoved == detune)
{
//[UserSliderCode_detune] -- add your slider handling code here..
updateDisplay();
//[/UserSliderCode_detune]
}
else if (sliderThatWasMoved == sclLeftLevel)
{
//[UserSliderCode_sclLeftLevel] -- add your slider handling code here..
//[/UserSliderCode_sclLeftLevel]
}
else if (sliderThatWasMoved == sclRightLevel)
{
//[UserSliderCode_sclRightLevel] -- add your slider handling code here..
//[/UserSliderCode_sclRightLevel]
}
else if (sliderThatWasMoved == sclLvlBrkPt)
{
//[UserSliderCode_sclLvlBrkPt] -- add your slider handling code here..
//[/UserSliderCode_sclLvlBrkPt]
}
else if (sliderThatWasMoved == sclRateScaling)
{
//[UserSliderCode_sclRateScaling] -- add your slider handling code here..
//[/UserSliderCode_sclRateScaling]
}
else if (sliderThatWasMoved == keyVelSens)
{
//[UserSliderCode_keyVelSens] -- add your slider handling code here..
//[/UserSliderCode_keyVelSens]
}
else if (sliderThatWasMoved == ampModSens)
{
//[UserSliderCode_ampModSens] -- add your slider handling code here..
//[/UserSliderCode_ampModSens]
}
//[UsersliderValueChanged_Post]
//[/UsersliderValueChanged_Post]
}
void OperatorEditor::buttonClicked (Button* buttonThatWasClicked)
{
//[UserbuttonClicked_Pre]
//[/UserbuttonClicked_Pre]
if (buttonThatWasClicked == opMode)
{
//[UserButtonCode_opMode] -- add your button handler code here..
repaint();
//[/UserButtonCode_opMode]
}
//[UserbuttonClicked_Post]
//[/UserbuttonClicked_Post]
}
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
void OperatorEditor::bind(DexedAudioProcessor *parent, int op) {
parent->opCtrl[op].egLevel[0]->bind(s_egl1);
parent->opCtrl[op].egLevel[1]->bind(s_egl2);
parent->opCtrl[op].egLevel[2]->bind(s_egl3);
parent->opCtrl[op].egLevel[3]->bind(s_egl4);
parent->opCtrl[op].egRate[0]->bind(s_egv1);
parent->opCtrl[op].egRate[1]->bind(s_egv2);
parent->opCtrl[op].egRate[2]->bind(s_egv3);
parent->opCtrl[op].egRate[3]->bind(s_egv4);
parent->opCtrl[op].level->bind(opLevel);
parent->opCtrl[op].opMode->bind(opMode);
parent->opCtrl[op].fine->bind(opFine);
parent->opCtrl[op].coarse->bind(opCoarse);
parent->opCtrl[op].detune->bind(detune);
parent->opCtrl[op].sclBrkPt->bind(sclLvlBrkPt);
parent->opCtrl[op].sclLeftCurve->bind(kbdLeftCurve);
parent->opCtrl[op].sclRightCurve->bind(kbdRightCurve);
parent->opCtrl[op].sclLeftDepth->bind(sclLeftLevel);
parent->opCtrl[op].sclRightDepth->bind(sclRightLevel);
parent->opCtrl[op].sclRate->bind(sclRateScaling);
parent->opCtrl[op].ampModSens->bind(ampModSens);
parent->opCtrl[op].velModSens->bind(keyVelSens);
parent->opCtrl[op].opSwitch->bind(opSwitch);
int offset = parent->opCtrl[op].egRate[0]->getOffset();
envDisplay->pvalues = &(parent->data[offset]);
processor = parent;
opNum << op + 1;
internalOp = 5-op;
}
void OperatorEditor::updateGain(float v) {
vu->v = v;
vu->repaint();
}
void OperatorEditor::updateDisplay() {
float freq = opCoarse->getValue();
float fine = opFine->getValue();
String txtFreq;
if (opMode->getToggleState() == 0) {
if ( freq == 0 )
freq = 0.5;
txtFreq << "f = " << (freq + (freq * (fine/100)));
} else {
freq = pow(10,((int)freq)&3);
freq = freq * exp(M_LN10*(fine/100));
txtFreq << freq << " Hz";
}
int det = detune->getValue();
if ( det != 0 ) {
if ( det > 0 )
txtFreq << " +" << det;
else
txtFreq << " " << det;
}
khzDisplay->setText(txtFreq, dontSendNotification);
repaint();
}
void OperatorEditor::updateEnvPos(char pos) {
envDisplay->vPos = pos;
envDisplay->repaint();
}
void OperatorEditor::mouseDown(const MouseEvent &event) {
if ( event.mods.isRightButtonDown() ) {
PopupMenu popup;
popup.addItem(1, "Copy Operator Values");
popup.addItem(2, "Paste Envelope Values", processor->hasClipboardContent());
popup.addItem(3, "Paste Operator Values", processor->hasClipboardContent());
popup.addSeparator();
popup.addItem(4, "Send current program to DX7");
switch(popup.show()) {
case 1:
processor->copyToClipboard(internalOp);
break;
case 2:
processor->pasteEnvFromClipboard(internalOp);
break;
case 3:
processor->pasteOpFromClipboard(internalOp);
break;
case 4:
processor->sendCurrentSysexProgram();
break;
}
}
}
//[/MiscUserCode]
//==============================================================================
#if 0
/* -- Introjucer information section --
This is where the Introjucer stores the metadata that describe this GUI layout, so
make changes in here at your peril!
BEGIN_JUCER_METADATA
<JUCER_COMPONENT documentType="Component" className="OperatorEditor" componentName=""
parentClasses="public Component" constructorParams="" variableInitialisers=""
snapPixels="2" snapActive="0" snapShown="1" overlayOpacity="0.330"
fixedSize="1" initialWidth="287" initialHeight="218">
<BACKGROUND backgroundColour="ffffff"/>
<SLIDER name="egl1" id="dc070cc41347df47" memberName="s_egl1" virtualName=""
explicitFocusOrder="0" pos="5 128 34 34" min="0" max="99" int="1"
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="egl2" id="66f5195e9c374029" memberName="s_egl2" virtualName=""
explicitFocusOrder="0" pos="33 129 34 34" min="0" max="99" int="1"
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="egl3" id="9d57bd53203dcdb4" memberName="s_egl3" virtualName=""
explicitFocusOrder="0" pos="61 128 34 34" min="0" max="99" int="1"
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="egl4" id="4f7c3ece3ea2cf9c" memberName="s_egl4" virtualName=""
explicitFocusOrder="0" pos="89 128 34 34" min="0" max="99" int="1"
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="egr1" id="2ca8137d80da46fb" memberName="s_egv1" virtualName=""
explicitFocusOrder="0" pos="5 169 34 34" min="0" max="99" int="1"
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="egr3" id="4ad6d0c532d15973" memberName="s_egv2" virtualName=""
explicitFocusOrder="0" pos="33 169 34 34" min="0" max="99" int="1"
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="egr3" id="8a2027f9ede16b4f" memberName="s_egv3" virtualName=""
explicitFocusOrder="0" pos="61 169 34 34" min="0" max="99" int="1"
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="egr4" id="8c04f1c943d837e8" memberName="s_egv4" virtualName=""
explicitFocusOrder="0" pos="89 169 34 34" min="0" max="99" int="1"
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="opLevel" id="f8521c8214fb8993" memberName="opLevel" virtualName=""
explicitFocusOrder="0" pos="245 76 34 34" min="0" max="99" int="1"
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="opFine" id="e445aa61bd6cddcb" memberName="opFine" virtualName=""
explicitFocusOrder="0" pos="78 24 34 34" min="0" max="99" int="1"
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="opCoarse" id="4eec63d30d7488d2" memberName="opCoarse" virtualName=""
explicitFocusOrder="0" pos="43 24 34 34" min="0" max="31" int="1"
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="1"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<LABEL name="khz" id="eb961eed8902a6fc" memberName="khzDisplay" virtualName=""
explicitFocusOrder="0" pos="15 10 95 10" bkgCol="6a000000" textCol="ffffffff"
outlineCol="0" edTextCol="ff000000" edBkgCol="0" labelText="1,000 kHz"
editableSingleClick="0" editableDoubleClick="0" focusDiscardsChanges="0"
fontname="Default font" fontsize="12.599999999999999645" bold="0"
italic="0" justification="36"/>
<SLIDER name="detune" id="f093ec8defca2fc2" memberName="detune" virtualName=""
explicitFocusOrder="0" pos="6 24 34 34" min="-7" max="7" int="1"
style="RotaryVerticalDrag" textBoxPos="NoTextBox" textBoxEditable="0"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<GENERICCOMPONENT name="envDisplay" id="b18856de924c6340" memberName="envDisplay"
virtualName="" explicitFocusOrder="0" pos="16 83 94 30" class="EnvDisplay"
params=""/>
<SLIDER name="sclLeftLevel" id="bd6f338ae68e454f" memberName="sclLeftLevel"
virtualName="" explicitFocusOrder="0" pos="131 115 34 34" tooltip="Keyboard Scale Level Left Depth "
min="0" max="99" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox"
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="sclRightLevel" id="b9e23ed5187fc7e5" memberName="sclRightLevel"
virtualName="" explicitFocusOrder="0" pos="241 115 34 34" tooltip="Keyboard Scale Level Right Depth "
min="0" max="99" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox"
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="sclLvlBrkPt" id="c563ac3116923bbc" memberName="sclLvlBrkPt"
virtualName="" explicitFocusOrder="0" pos="178 130 54 24" tooltip="Scale Level Breakpoint"
min="0" max="99" int="1" style="LinearHorizontal" textBoxPos="NoTextBox"
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="sclRateScaling" id="f0d17c8e09aa4c49" memberName="sclRateScaling"
virtualName="" explicitFocusOrder="0" pos="186 179 34 34" tooltip="Keyboard Rate Scaling"
min="0" max="7" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox"
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="keyVelSens" id="21795d045d07602b" memberName="keyVelSens"
virtualName="" explicitFocusOrder="0" pos="204 76 34 34" min="0"
max="7" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox"
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="ampModSens" id="634ceaa7b0f81a6c" memberName="ampModSens"
virtualName="" explicitFocusOrder="0" pos="140 76 34 34" min="0"
max="3" int="1" style="RotaryVerticalDrag" textBoxPos="NoTextBox"
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<GENERICCOMPONENT name="vu" id="6f952594ea99dc1e" memberName="vu" virtualName=""
explicitFocusOrder="0" pos="132 52 140 8" class="VuMeter" params=""/>
<TOGGLEBUTTON name="opMode" id="15db8e5c9dd13966" memberName="opMode" virtualName=""
explicitFocusOrder="0" pos="146 19 48 26" buttonText="" connectedEdges="0"
needsCallback="1" radioGroupId="0" state="0"/>
<GENERICCOMPONENT name="kbdLeftCurve" id="ee4e60dfcd6cb790" memberName="kbdLeftCurve"
virtualName="" explicitFocusOrder="0" pos="128 170 36 26" class="ComboBoxImage"
params=""/>
<GENERICCOMPONENT name="kbdRightCurve" id="f5ca44d67593488a" memberName="kbdRightCurve"
virtualName="" explicitFocusOrder="0" pos="240 170 36 26" class="ComboBoxImage"
params=""/>
</JUCER_COMPONENT>
END_JUCER_METADATA
*/
#endif
//[EndFile] You can add extra defines here...
//[/EndFile]

@ -1,110 +0,0 @@
/*
==============================================================================
This is an automatically generated GUI class created by the Introjucer!
Be careful when adding custom code to these files, as only the code within
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
and re-saved.
Created with Introjucer version: 3.2.0
------------------------------------------------------------------------------
The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright (c) 2015 - ROLI Ltd.
==============================================================================
*/
#ifndef __JUCE_HEADER_F21C2CC3FAD5D98E__
#define __JUCE_HEADER_F21C2CC3FAD5D98E__
//[Headers] -- You can add your own extra header files here --
#include "JuceHeader.h"
#include "PluginProcessor.h"
#include "DXComponents.h"
#include "DXLookNFeel.h"
//[/Headers]
//==============================================================================
/**
//[Comments]
An auto-generated component, created by the Introjucer.
Describe your class and how it works here!
//[/Comments]
*/
class OperatorEditor : public Component,
public SliderListener,
public ButtonListener
{
public:
//==============================================================================
OperatorEditor ();
~OperatorEditor();
//==============================================================================
//[UserMethods] -- You can add your own custom methods in this section.
void bind(DexedAudioProcessor *processor, int num);
void updateGain(float v);
void updateDisplay();
void updateEnvPos(char pos);
void mouseDown(const MouseEvent& e) override;
//[/UserMethods]
void paint (Graphics& g) override;
void resized() override;
void sliderValueChanged (Slider* sliderThatWasMoved) override;
void buttonClicked (Button* buttonThatWasClicked) override;
private:
//[UserVariables] -- You can add your own custom variables in this section.
String opNum;
int internalOp;
Image light;
DexedAudioProcessor *processor;
Image background;
ScopedPointer<ToggleButton> opSwitch;
//[/UserVariables]
//==============================================================================
ScopedPointer<Slider> s_egl1;
ScopedPointer<Slider> s_egl2;
ScopedPointer<Slider> s_egl3;
ScopedPointer<Slider> s_egl4;
ScopedPointer<Slider> s_egv1;
ScopedPointer<Slider> s_egv2;
ScopedPointer<Slider> s_egv3;
ScopedPointer<Slider> s_egv4;
ScopedPointer<Slider> opLevel;
ScopedPointer<Slider> opFine;
ScopedPointer<Slider> opCoarse;
ScopedPointer<Label> khzDisplay;
ScopedPointer<Slider> detune;
ScopedPointer<EnvDisplay> envDisplay;
ScopedPointer<Slider> sclLeftLevel;
ScopedPointer<Slider> sclRightLevel;
ScopedPointer<Slider> sclLvlBrkPt;
ScopedPointer<Slider> sclRateScaling;
ScopedPointer<Slider> keyVelSens;
ScopedPointer<Slider> ampModSens;
ScopedPointer<VuMeter> vu;
ScopedPointer<ToggleButton> opMode;
ScopedPointer<ComboBoxImage> kbdLeftCurve;
ScopedPointer<ComboBoxImage> kbdRightCurve;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OperatorEditor)
};
//[EndFile] You can add extra defines here...
//[/EndFile]
#endif // __JUCE_HEADER_F21C2CC3FAD5D98E__

@ -1,703 +0,0 @@
/*
==============================================================================
This is an automatically generated GUI class created by the Introjucer!
Be careful when adding custom code to these files, as only the code within
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
and re-saved.
Created with Introjucer version: 3.2.0
------------------------------------------------------------------------------
The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright (c) 2015 - ROLI Ltd.
==============================================================================
*/
//[Headers] You can add your own extra header files here...
#include "Dexed.h"
//[/Headers]
#include "ParamDialog.h"
//[MiscUserDefs] You can add your own user definitions and misc code here...
//[/MiscUserDefs]
//==============================================================================
ParamDialog::ParamDialog ()
{
//[Constructor_pre] You can add your own custom stuff here..
//[/Constructor_pre]
addAndMakeVisible (pitchRange = new Slider ("pitchRange"));
pitchRange->setRange (0, 12, 1);
pitchRange->setSliderStyle (Slider::RotaryVerticalDrag);
pitchRange->setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20);
pitchRange->addListener (this);
addAndMakeVisible (pitchStep = new Slider ("pitchStep"));
pitchStep->setRange (0, 12, 1);
pitchStep->setSliderStyle (Slider::RotaryVerticalDrag);
pitchStep->setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20);
pitchStep->addListener (this);
addAndMakeVisible (sysexIn = new ComboBox ("sysexIn"));
sysexIn->setEditableText (false);
sysexIn->setJustificationType (Justification::centredLeft);
sysexIn->setTextWhenNothingSelected (String::empty);
sysexIn->setTextWhenNoChoicesAvailable (TRANS("(no choices)"));
sysexIn->addListener (this);
addAndMakeVisible (sysexOut = new ComboBox ("sysexOut"));
sysexOut->setEditableText (false);
sysexOut->setJustificationType (Justification::centredLeft);
sysexOut->setTextWhenNothingSelected (String::empty);
sysexOut->setTextWhenNoChoicesAvailable (TRANS("(no choices)"));
sysexOut->addListener (this);
addAndMakeVisible (sysexChl = new Slider ("sysexChl"));
sysexChl->setRange (1, 16, 1);
sysexChl->setSliderStyle (Slider::RotaryVerticalDrag);
sysexChl->setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20);
sysexChl->addListener (this);
addAndMakeVisible (engineReso = new ComboBox ("new combo box"));
engineReso->setEditableText (false);
engineReso->setJustificationType (Justification::centredLeft);
engineReso->setTextWhenNothingSelected (String::empty);
engineReso->setTextWhenNoChoicesAvailable (TRANS("(no choices)"));
engineReso->addItem (TRANS("Modern (24-bit)"), 1);
engineReso->addItem (TRANS("Mark I"), 2);
engineReso->addItem (TRANS("OPL Series"), 3);
engineReso->addListener (this);
addAndMakeVisible (showKeyboard = new ToggleButton ("showKeyboard"));
showKeyboard->setButtonText (String::empty);
addAndMakeVisible (whlRange = new Slider ("whlRange"));
whlRange->setRange (0, 99, 1);
whlRange->setSliderStyle (Slider::RotaryVerticalDrag);
whlRange->setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20);
whlRange->addListener (this);
addAndMakeVisible (ftRange = new Slider ("ftRange"));
ftRange->setRange (0, 99, 1);
ftRange->setSliderStyle (Slider::RotaryVerticalDrag);
ftRange->setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20);
ftRange->addListener (this);
addAndMakeVisible (brRange = new Slider ("brRange"));
brRange->setRange (0, 99, 1);
brRange->setSliderStyle (Slider::RotaryVerticalDrag);
brRange->setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20);
brRange->addListener (this);
addAndMakeVisible (atRange = new Slider ("atRange"));
atRange->setRange (0, 99, 1);
atRange->setSliderStyle (Slider::RotaryVerticalDrag);
atRange->setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20);
atRange->addListener (this);
addAndMakeVisible (whlEg = new ToggleButton ("whlEg"));
whlEg->setButtonText (String::empty);
whlEg->addListener (this);
addAndMakeVisible (ftEg = new ToggleButton ("ftEg"));
ftEg->setButtonText (String::empty);
ftEg->addListener (this);
addAndMakeVisible (brEg = new ToggleButton ("brEg"));
brEg->setButtonText (String::empty);
brEg->addListener (this);
addAndMakeVisible (atEg = new ToggleButton ("atEg"));
atEg->setButtonText (String::empty);
atEg->addListener (this);
addAndMakeVisible (whlAmp = new ToggleButton ("whlAmp"));
whlAmp->setButtonText (String::empty);
whlAmp->addListener (this);
addAndMakeVisible (ftAmp = new ToggleButton ("ftAmp"));
ftAmp->setButtonText (String::empty);
ftAmp->addListener (this);
addAndMakeVisible (brAmp = new ToggleButton ("brAmp"));
brAmp->setButtonText (String::empty);
brAmp->addListener (this);
addAndMakeVisible (atAmp = new ToggleButton ("atAmp"));
atAmp->setButtonText (String::empty);
atAmp->addListener (this);
addAndMakeVisible (whlPitch = new ToggleButton ("whlPitch"));
whlPitch->setButtonText (String::empty);
whlPitch->addListener (this);
addAndMakeVisible (ftPitch = new ToggleButton ("ftPitch"));
ftPitch->setButtonText (String::empty);
ftPitch->addListener (this);
addAndMakeVisible (brPitch = new ToggleButton ("brPitch"));
brPitch->setButtonText (String::empty);
brPitch->addListener (this);
addAndMakeVisible (atPitch = new ToggleButton ("atPitch"));
atPitch->setButtonText (String::empty);
atPitch->addListener (this);
//[UserPreSize]
//[/UserPreSize]
setSize (710, 350);
//[Constructor] You can add your own custom stuff here..
pitchRange->setEnabled(pitchStep->getValue() == 0);
StringArray input;
input.add("None");
input.addArray(MidiInput::getDevices());
sysexIn->addItemList(input, 2);
StringArray output;
output.add("None");
output.addArray(MidiOutput::getDevices());
sysexOut->addItemList(output, 2);
//[/Constructor]
}
ParamDialog::~ParamDialog()
{
//[Destructor_pre]. You can add your own custom destruction code here..
//[/Destructor_pre]
pitchRange = nullptr;
pitchStep = nullptr;
sysexIn = nullptr;
sysexOut = nullptr;
sysexChl = nullptr;
engineReso = nullptr;
showKeyboard = nullptr;
whlRange = nullptr;
ftRange = nullptr;
brRange = nullptr;
atRange = nullptr;
whlEg = nullptr;
ftEg = nullptr;
brEg = nullptr;
atEg = nullptr;
whlAmp = nullptr;
ftAmp = nullptr;
brAmp = nullptr;
atAmp = nullptr;
whlPitch = nullptr;
ftPitch = nullptr;
brPitch = nullptr;
atPitch = nullptr;
//[Destructor]. You can add your own custom destruction code here..
//[/Destructor]
}
//==============================================================================
void ParamDialog::paint (Graphics& g)
{
//[UserPrePaint] Add your own custom painting code here..
//[/UserPrePaint]
g.fillAll (Colour (0xff3c322f));
g.setColour (Colours::white);
g.setFont (Font (15.00f, Font::plain));
g.drawText (TRANS("Pitch Bend Range"),
20, 16, 276, 23,
Justification::centredLeft, true);
g.setColour (Colours::white);
g.setFont (Font (15.00f, Font::plain));
g.drawText (TRANS("Pitch Bend Step"),
20, 56, 276, 23,
Justification::centredLeft, true);
g.setColour (Colours::white);
g.setFont (Font (15.00f, Font::plain));
g.drawText (TRANS("DX7 In"),
20, 224, 131, 23,
Justification::centredLeft, true);
g.setColour (Colours::white);
g.setFont (Font (15.00f, Font::plain));
g.drawText (TRANS("DX7 Out"),
20, 264, 131, 23,
Justification::centredLeft, true);
g.setColour (Colours::white);
g.setFont (Font (15.00f, Font::plain));
g.drawText (TRANS("DX7 Channel"),
20, 304, 245, 23,
Justification::centredLeft, true);
g.setColour (Colours::white);
g.setFont (Font (15.00f, Font::plain));
g.drawText (TRANS("Engine Resolution"),
20, 156, 276, 23,
Justification::centredLeft, true);
g.setColour (Colours::black);
g.fillRect (22, 138, 306, 1);
g.setColour (Colours::black);
g.fillRect (22, 195, 306, 1);
g.setColour (Colours::white);
g.setFont (Font (15.00f, Font::plain));
g.drawText (TRANS("Show Keyboard"),
20, 96, 276, 23,
Justification::centredLeft, true);
g.setColour (Colours::black);
g.fillRect (352, 11, 1, 325);
g.setColour (Colours::white);
g.setFont (Font (15.00f, Font::plain));
g.drawText (TRANS("Wheel"),
368, 16, 276, 23,
Justification::centredLeft, true);
g.setColour (Colours::white);
g.setFont (Font (15.00f, Font::plain));
g.drawText (TRANS("Foot"),
368, 96, 276, 23,
Justification::centredLeft, true);
g.setColour (Colours::white);
g.setFont (Font (15.00f, Font::plain));
g.drawText (TRANS("Breath"),
368, 56, 276, 23,
Justification::centredLeft, true);
g.setColour (Colours::white);
g.setFont (Font (15.00f, Font::plain));
g.drawText (TRANS("After Touch"),
368, 136, 276, 23,
Justification::centredLeft, true);
g.setColour (Colours::white);
g.setFont (Font (15.00f, Font::plain));
g.drawText (TRANS("PITCH"),
533, 163, 48, 23,
Justification::centredLeft, true);
g.setColour (Colours::white);
g.setFont (Font (15.00f, Font::plain));
g.drawText (TRANS("AMP"),
589, 163, 48, 23,
Justification::centredLeft, true);
g.setColour (Colours::white);
g.setFont (Font (15.00f, Font::plain));
g.drawText (TRANS("EG BIAS"),
645, 163, 48, 23,
Justification::centredLeft, true);
//[UserPaint] Add your own custom painting code here..
//[/UserPaint]
}
void ParamDialog::resized()
{
//[UserPreResize] Add your own custom resize code here..
//[/UserPreResize]
pitchRange->setBounds (264, 16, 72, 24);
pitchStep->setBounds (264, 56, 72, 24);
sysexIn->setBounds (104, 224, 224, 24);
sysexOut->setBounds (104, 264, 224, 24);
sysexChl->setBounds (264, 304, 72, 24);
engineReso->setBounds (160, 156, 168, 24);
showKeyboard->setBounds (264, 96, 56, 24);
whlRange->setBounds (448, 16, 72, 24);
ftRange->setBounds (448, 56, 72, 24);
brRange->setBounds (448, 96, 72, 24);
atRange->setBounds (448, 136, 72, 24);
whlEg->setBounds (640, 16, 56, 24);
ftEg->setBounds (640, 56, 56, 24);
brEg->setBounds (640, 96, 56, 24);
atEg->setBounds (640, 136, 56, 24);
whlAmp->setBounds (584, 16, 56, 24);
ftAmp->setBounds (584, 56, 56, 24);
brAmp->setBounds (584, 96, 56, 24);
atAmp->setBounds (584, 136, 56, 24);
whlPitch->setBounds (528, 16, 56, 24);
ftPitch->setBounds (528, 56, 56, 24);
brPitch->setBounds (528, 96, 56, 24);
atPitch->setBounds (528, 136, 56, 24);
//[UserResized] Add your own custom resize handling here..
//[/UserResized]
}
void ParamDialog::sliderValueChanged (Slider* sliderThatWasMoved)
{
//[UsersliderValueChanged_Pre]
//[/UsersliderValueChanged_Pre]
if (sliderThatWasMoved == pitchRange)
{
//[UserSliderCode_pitchRange] -- add your slider handling code here..
//[/UserSliderCode_pitchRange]
}
else if (sliderThatWasMoved == pitchStep)
{
//[UserSliderCode_pitchStep] -- add your slider handling code here..
pitchRange->setEnabled(pitchStep->getValue() == 0);
//[/UserSliderCode_pitchStep]
}
else if (sliderThatWasMoved == sysexChl)
{
//[UserSliderCode_sysexChl] -- add your slider handling code here..
//[/UserSliderCode_sysexChl]
}
else if (sliderThatWasMoved == whlRange)
{
//[UserSliderCode_whlRange] -- add your slider handling code here..
//[/UserSliderCode_whlRange]
}
else if (sliderThatWasMoved == ftRange)
{
//[UserSliderCode_ftRange] -- add your slider handling code here..
//[/UserSliderCode_ftRange]
}
else if (sliderThatWasMoved == brRange)
{
//[UserSliderCode_brRange] -- add your slider handling code here..
//[/UserSliderCode_brRange]
}
else if (sliderThatWasMoved == atRange)
{
//[UserSliderCode_atRange] -- add your slider handling code here..
//[/UserSliderCode_atRange]
}
//[UsersliderValueChanged_Post]
//[/UsersliderValueChanged_Post]
}
void ParamDialog::comboBoxChanged (ComboBox* comboBoxThatHasChanged)
{
//[UsercomboBoxChanged_Pre]
//[/UsercomboBoxChanged_Pre]
if (comboBoxThatHasChanged == sysexIn)
{
//[UserComboBoxCode_sysexIn] -- add your combo box handling code here..
//[/UserComboBoxCode_sysexIn]
}
else if (comboBoxThatHasChanged == sysexOut)
{
//[UserComboBoxCode_sysexOut] -- add your combo box handling code here..
//[/UserComboBoxCode_sysexOut]
}
else if (comboBoxThatHasChanged == engineReso)
{
//[UserComboBoxCode_engineReso] -- add your combo box handling code here..
//[/UserComboBoxCode_engineReso]
}
//[UsercomboBoxChanged_Post]
//[/UsercomboBoxChanged_Post]
}
void ParamDialog::buttonClicked (Button* buttonThatWasClicked)
{
//[UserbuttonClicked_Pre]
//[/UserbuttonClicked_Pre]
if (buttonThatWasClicked == whlEg)
{
//[UserButtonCode_whlEg] -- add your button handler code here..
//[/UserButtonCode_whlEg]
}
else if (buttonThatWasClicked == ftEg)
{
//[UserButtonCode_ftEg] -- add your button handler code here..
//[/UserButtonCode_ftEg]
}
else if (buttonThatWasClicked == brEg)
{
//[UserButtonCode_brEg] -- add your button handler code here..
//[/UserButtonCode_brEg]
}
else if (buttonThatWasClicked == atEg)
{
//[UserButtonCode_atEg] -- add your button handler code here..
//[/UserButtonCode_atEg]
}
else if (buttonThatWasClicked == whlAmp)
{
//[UserButtonCode_whlAmp] -- add your button handler code here..
//[/UserButtonCode_whlAmp]
}
else if (buttonThatWasClicked == ftAmp)
{
//[UserButtonCode_ftAmp] -- add your button handler code here..
//[/UserButtonCode_ftAmp]
}
else if (buttonThatWasClicked == brAmp)
{
//[UserButtonCode_brAmp] -- add your button handler code here..
//[/UserButtonCode_brAmp]
}
else if (buttonThatWasClicked == atAmp)
{
//[UserButtonCode_atAmp] -- add your button handler code here..
//[/UserButtonCode_atAmp]
}
else if (buttonThatWasClicked == whlPitch)
{
//[UserButtonCode_whlPitch] -- add your button handler code here..
//[/UserButtonCode_whlPitch]
}
else if (buttonThatWasClicked == ftPitch)
{
//[UserButtonCode_ftPitch] -- add your button handler code here..
//[/UserButtonCode_ftPitch]
}
else if (buttonThatWasClicked == brPitch)
{
//[UserButtonCode_brPitch] -- add your button handler code here..
//[/UserButtonCode_brPitch]
}
else if (buttonThatWasClicked == atPitch)
{
//[UserButtonCode_atPitch] -- add your button handler code here..
//[/UserButtonCode_atPitch]
}
//[UserbuttonClicked_Post]
//[/UserbuttonClicked_Post]
}
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
void ParamDialog::setDialogValues(Controllers &c, SysexComm &mgr, int reso, bool showKey) {
pitchRange->setValue(c.values_[kControllerPitchRange]);
pitchStep->setValue(c.values_[kControllerPitchStep]);
sysexChl->setValue(mgr.getChl() + 1);
whlRange->setValue(c.wheel.range);
whlPitch->setToggleState(c.wheel.pitch, dontSendNotification);
whlPitch->setToggleState(c.wheel.pitch, dontSendNotification);
whlAmp->setToggleState(c.wheel.amp, dontSendNotification);
whlEg->setToggleState(c.wheel.eg, dontSendNotification);
ftRange->setValue(c.foot.range);
ftPitch->setToggleState(c.foot.pitch, dontSendNotification);
ftAmp->setToggleState(c.foot.amp, dontSendNotification);
ftEg->setToggleState(c.foot.eg, dontSendNotification);
brRange->setValue(c.breath.range);
brPitch->setToggleState(c.breath.pitch, dontSendNotification);
brAmp->setToggleState(c.breath.amp, dontSendNotification);
brEg->setToggleState(c.breath.eg, dontSendNotification);
atRange->setValue(c.at.range);
atPitch->setToggleState(c.at.pitch, dontSendNotification);
atAmp->setToggleState(c.at.amp, dontSendNotification);
atEg->setToggleState(c.at.eg, dontSendNotification);
StringArray inputs = MidiInput::getDevices();
int idx = inputs.indexOf(mgr.getInput());
idx = idx == -1 ? 0 : idx + 1;
sysexIn->setSelectedItemIndex(idx);
StringArray outputs = MidiOutput::getDevices();
idx = outputs.indexOf(mgr.getOutput());
idx = idx == -1 ? 0 : idx + 1;
sysexOut->setSelectedItemIndex(idx);
engineReso->setSelectedItemIndex(reso);
showKeyboard->setToggleState(showKey, false);
}
bool ParamDialog::getDialogValues(Controllers &c, SysexComm &mgr, int *reso, bool *showKey) {
bool ret = true;
c.values_[kControllerPitchRange] = pitchRange->getValue();
c.values_[kControllerPitchStep] = pitchStep->getValue();
c.wheel.range = whlRange->getValue();
c.wheel.pitch = whlPitch->getToggleState();
c.wheel.amp = whlAmp->getToggleState();
c.wheel.eg = whlEg->getToggleState();
c.foot.range = ftRange->getValue();
c.foot.pitch = ftPitch->getToggleState();
c.foot.amp = ftAmp->getToggleState();
c.foot.eg = ftEg->getToggleState();
c.breath.range = brRange->getValue();
c.breath.pitch = brPitch->getToggleState();
c.breath.amp = brAmp->getToggleState();
c.breath.eg = brEg->getToggleState();
c.at.range = atRange->getValue();
c.at.pitch = atPitch->getToggleState();
c.at.amp = atAmp->getToggleState();
c.at.eg = atEg->getToggleState();
c.refresh();
ret &= mgr.setInput(sysexIn->getItemText(sysexIn->getSelectedItemIndex()));
ret &= mgr.setOutput(sysexOut->getItemText(sysexOut->getSelectedItemIndex()));
mgr.setChl(sysexChl->getValue() - 1);
*reso = engineReso->getSelectedItemIndex();
*showKey = showKeyboard->getToggleState();
return ret;
}
//[/MiscUserCode]
//==============================================================================
#if 0
/* -- Introjucer information section --
This is where the Introjucer stores the metadata that describe this GUI layout, so
make changes in here at your peril!
BEGIN_JUCER_METADATA
<JUCER_COMPONENT documentType="Component" className="ParamDialog" componentName=""
parentClasses="public Component" constructorParams="" variableInitialisers=""
snapPixels="8" snapActive="1" snapShown="1" overlayOpacity="0.330"
fixedSize="1" initialWidth="710" initialHeight="350">
<BACKGROUND backgroundColour="ff3c322f">
<TEXT pos="20 16 276 23" fill="solid: ffffffff" hasStroke="0" text="Pitch Bend Range"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="20 56 276 23" fill="solid: ffffffff" hasStroke="0" text="Pitch Bend Step"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="20 224 131 23" fill="solid: ffffffff" hasStroke="0" text="DX7 In"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="20 264 131 23" fill="solid: ffffffff" hasStroke="0" text="DX7 Out"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="20 304 245 23" fill="solid: ffffffff" hasStroke="0" text="DX7 Channel"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="20 156 276 23" fill="solid: ffffffff" hasStroke="0" text="Engine Resolution"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<RECT pos="22 138 306 1" fill="solid: ff000000" hasStroke="0"/>
<RECT pos="22 195 306 1" fill="solid: ff000000" hasStroke="0"/>
<TEXT pos="20 96 276 23" fill="solid: ffffffff" hasStroke="0" text="Show Keyboard"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<RECT pos="352 11 1 325" fill="solid: ff000000" hasStroke="0"/>
<TEXT pos="368 16 276 23" fill="solid: ffffffff" hasStroke="0" text="Wheel"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="368 96 276 23" fill="solid: ffffffff" hasStroke="0" text="Foot"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="368 56 276 23" fill="solid: ffffffff" hasStroke="0" text="Breath"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="368 136 276 23" fill="solid: ffffffff" hasStroke="0" text="After Touch"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="533 163 48 23" fill="solid: ffffffff" hasStroke="0" text="PITCH"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="589 163 48 23" fill="solid: ffffffff" hasStroke="0" text="AMP"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="645 163 48 23" fill="solid: ffffffff" hasStroke="0" text="EG BIAS"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
</BACKGROUND>
<SLIDER name="pitchRange" id="7409be5a8dfaa91" memberName="pitchRange"
virtualName="" explicitFocusOrder="0" pos="264 16 72 24" min="0"
max="12" int="1" style="RotaryVerticalDrag" textBoxPos="TextBoxLeft"
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="pitchStep" id="b86af4b792e768ca" memberName="pitchStep"
virtualName="" explicitFocusOrder="0" pos="264 56 72 24" min="0"
max="12" int="1" style="RotaryVerticalDrag" textBoxPos="TextBoxLeft"
textBoxEditable="1" textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<COMBOBOX name="sysexIn" id="3750642d8b5be11" memberName="sysexIn" virtualName=""
explicitFocusOrder="0" pos="104 224 224 24" editable="0" layout="33"
items="" textWhenNonSelected="" textWhenNoItems="(no choices)"/>
<COMBOBOX name="sysexOut" id="44730115841c2214" memberName="sysexOut" virtualName=""
explicitFocusOrder="0" pos="104 264 224 24" editable="0" layout="33"
items="" textWhenNonSelected="" textWhenNoItems="(no choices)"/>
<SLIDER name="sysexChl" id="7fdc8830f90a7c86" memberName="sysexChl" virtualName=""
explicitFocusOrder="0" pos="264 304 72 24" min="1" max="16" int="1"
style="RotaryVerticalDrag" textBoxPos="TextBoxLeft" textBoxEditable="1"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<COMBOBOX name="new combo box" id="4087ff978c3d9e8d" memberName="engineReso"
virtualName="" explicitFocusOrder="0" pos="160 156 168 24" editable="0"
layout="33" items="Modern (24-bit)&#10;Mark I&#10;OPL Series"
textWhenNonSelected="" textWhenNoItems="(no choices)"/>
<TOGGLEBUTTON name="showKeyboard" id="c963d2cb8e49ffd7" memberName="showKeyboard"
virtualName="" explicitFocusOrder="0" pos="264 96 56 24" buttonText=""
connectedEdges="0" needsCallback="0" radioGroupId="0" state="0"/>
<SLIDER name="whlRange" id="3d6522f5f581e580" memberName="whlRange" virtualName=""
explicitFocusOrder="0" pos="448 16 72 24" min="0" max="99" int="1"
style="RotaryVerticalDrag" textBoxPos="TextBoxLeft" textBoxEditable="1"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="ftRange" id="cf553f74c3fb0d12" memberName="ftRange" virtualName=""
explicitFocusOrder="0" pos="448 56 72 24" min="0" max="99" int="1"
style="RotaryVerticalDrag" textBoxPos="TextBoxLeft" textBoxEditable="1"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="brRange" id="c4aa6814f75016a7" memberName="brRange" virtualName=""
explicitFocusOrder="0" pos="448 96 72 24" min="0" max="99" int="1"
style="RotaryVerticalDrag" textBoxPos="TextBoxLeft" textBoxEditable="1"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="atRange" id="d0aa1ebb24284577" memberName="atRange" virtualName=""
explicitFocusOrder="0" pos="448 136 72 24" min="0" max="99" int="1"
style="RotaryVerticalDrag" textBoxPos="TextBoxLeft" textBoxEditable="1"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<TOGGLEBUTTON name="whlEg" id="d8242ae592c912a" memberName="whlEg" virtualName=""
explicitFocusOrder="0" pos="640 16 56 24" buttonText="" connectedEdges="0"
needsCallback="1" radioGroupId="0" state="0"/>
<TOGGLEBUTTON name="ftEg" id="69d816607bd71cb0" memberName="ftEg" virtualName=""
explicitFocusOrder="0" pos="640 56 56 24" buttonText="" connectedEdges="0"
needsCallback="1" radioGroupId="0" state="0"/>
<TOGGLEBUTTON name="brEg" id="ba89ae54d676983f" memberName="brEg" virtualName=""
explicitFocusOrder="0" pos="640 96 56 24" buttonText="" connectedEdges="0"
needsCallback="1" radioGroupId="0" state="0"/>
<TOGGLEBUTTON name="atEg" id="371934a58ce5f1bc" memberName="atEg" virtualName=""
explicitFocusOrder="0" pos="640 136 56 24" buttonText="" connectedEdges="0"
needsCallback="1" radioGroupId="0" state="0"/>
<TOGGLEBUTTON name="whlAmp" id="3d4e46e63c3ddd86" memberName="whlAmp" virtualName=""
explicitFocusOrder="0" pos="584 16 56 24" buttonText="" connectedEdges="0"
needsCallback="1" radioGroupId="0" state="0"/>
<TOGGLEBUTTON name="ftAmp" id="f631892e209b094a" memberName="ftAmp" virtualName=""
explicitFocusOrder="0" pos="584 56 56 24" buttonText="" connectedEdges="0"
needsCallback="1" radioGroupId="0" state="0"/>
<TOGGLEBUTTON name="brAmp" id="d0a68d37220638f1" memberName="brAmp" virtualName=""
explicitFocusOrder="0" pos="584 96 56 24" buttonText="" connectedEdges="0"
needsCallback="1" radioGroupId="0" state="0"/>
<TOGGLEBUTTON name="atAmp" id="4220c7b22e7845ea" memberName="atAmp" virtualName=""
explicitFocusOrder="0" pos="584 136 56 24" buttonText="" connectedEdges="0"
needsCallback="1" radioGroupId="0" state="0"/>
<TOGGLEBUTTON name="whlPitch" id="b7a626ec1e45af16" memberName="whlPitch" virtualName=""
explicitFocusOrder="0" pos="528 16 56 24" buttonText="" connectedEdges="0"
needsCallback="1" radioGroupId="0" state="0"/>
<TOGGLEBUTTON name="ftPitch" id="1acedf6f16a5a3" memberName="ftPitch" virtualName=""
explicitFocusOrder="0" pos="528 56 56 24" buttonText="" connectedEdges="0"
needsCallback="1" radioGroupId="0" state="0"/>
<TOGGLEBUTTON name="brPitch" id="23fa82533e004b96" memberName="brPitch" virtualName=""
explicitFocusOrder="0" pos="528 96 56 24" buttonText="" connectedEdges="0"
needsCallback="1" radioGroupId="0" state="0"/>
<TOGGLEBUTTON name="atPitch" id="43805c6a4673e291" memberName="atPitch" virtualName=""
explicitFocusOrder="0" pos="528 136 56 24" buttonText="" connectedEdges="0"
needsCallback="1" radioGroupId="0" state="0"/>
</JUCER_COMPONENT>
END_JUCER_METADATA
*/
#endif
//[EndFile] You can add extra defines here...
//[/EndFile]

@ -1,100 +0,0 @@
/*
==============================================================================
This is an automatically generated GUI class created by the Introjucer!
Be careful when adding custom code to these files, as only the code within
the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded
and re-saved.
Created with Introjucer version: 3.2.0
------------------------------------------------------------------------------
The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright (c) 2015 - ROLI Ltd.
==============================================================================
*/
#ifndef __JUCE_HEADER_D00F97AD887A66__
#define __JUCE_HEADER_D00F97AD887A66__
//[Headers] -- You can add your own extra header files here --
#include "JuceHeader.h"
#include "msfa/controllers.h"
#include "SysexComm.h"
//[/Headers]
//==============================================================================
/**
//[Comments]
An auto-generated component, created by the Introjucer.
Describe your class and how it works here!
//[/Comments]
*/
class ParamDialog : public Component,
public SliderListener,
public ComboBoxListener,
public ButtonListener
{
public:
//==============================================================================
ParamDialog ();
~ParamDialog();
//==============================================================================
//[UserMethods] -- You can add your own custom methods in this section.
void setDialogValues(Controllers &c, SysexComm &mgr, int reso, bool showKeyboard);
bool getDialogValues(Controllers &c, SysexComm &mgr, int *reso, bool *showKeyboard);
//[/UserMethods]
void paint (Graphics& g);
void resized();
void sliderValueChanged (Slider* sliderThatWasMoved);
void comboBoxChanged (ComboBox* comboBoxThatHasChanged);
void buttonClicked (Button* buttonThatWasClicked);
private:
//[UserVariables] -- You can add your own custom variables in this section.
//[/UserVariables]
//==============================================================================
ScopedPointer<Slider> pitchRange;
ScopedPointer<Slider> pitchStep;
ScopedPointer<ComboBox> sysexIn;
ScopedPointer<ComboBox> sysexOut;
ScopedPointer<Slider> sysexChl;
ScopedPointer<ComboBox> engineReso;
ScopedPointer<ToggleButton> showKeyboard;
ScopedPointer<Slider> whlRange;
ScopedPointer<Slider> ftRange;
ScopedPointer<Slider> brRange;
ScopedPointer<Slider> atRange;
ScopedPointer<ToggleButton> whlEg;
ScopedPointer<ToggleButton> ftEg;
ScopedPointer<ToggleButton> brEg;
ScopedPointer<ToggleButton> atEg;
ScopedPointer<ToggleButton> whlAmp;
ScopedPointer<ToggleButton> ftAmp;
ScopedPointer<ToggleButton> brAmp;
ScopedPointer<ToggleButton> atAmp;
ScopedPointer<ToggleButton> whlPitch;
ScopedPointer<ToggleButton> ftPitch;
ScopedPointer<ToggleButton> brPitch;
ScopedPointer<ToggleButton> atPitch;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ParamDialog)
};
//[EndFile] You can add extra defines here...
//[/EndFile]
#endif // __JUCE_HEADER_D00F97AD887A66__

@ -1,452 +0,0 @@
/**
*
* Copyright (c) 2014-2016 Pascal Gauthier.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <time.h>
#include "PluginParam.h"
#include "PluginProcessor.h"
#include "PluginData.h"
#include "Dexed.h"
#include <fstream>
using namespace ::std;
uint8_t sysexChecksum(const uint8_t *sysex, int size) {
int sum = 0;
int i;
for (i = 0; i < size; sum -= sysex[i++]);
return sum & 0x7F;
}
void exportSysexPgm(uint8_t *dest, uint8_t *src) {
uint8_t header[] = { 0xF0, 0x43, 0x00, 0x00, 0x01, 0x1B };
memcpy(dest, header, 6);
// copy 1 unpacked voices
memcpy(dest+6, src, 155);
// put some logic to "mute" an operator if the level is 0
// make checksum for dump
uint8_t footer[] = { sysexChecksum(src, 155), 0xF7 };
memcpy(dest+161, footer, 2);
}
/**
* Pack a program into a 32 packed sysex
*/
void Cartridge::packProgram(uint8_t *src, int idx, String name, char *opSwitch) {
uint8_t *bulk = voiceData + 6 + (idx * 128);
for(int op = 0; op < 6; op++) {
// eg rate and level, brk pt, depth, scaling
memcpy(bulk + op * 17, src + op * 21, 11);
int pp = op*17;
int up = op*21;
// left curves
bulk[pp+11] = (src[up+11]&0x03) | ((src[up+12]&0x03) << 2);
bulk[pp+12] = (src[up+13]&0x07) | ((src[up+20]&0x0f) << 3);
// kvs_ams
bulk[pp+13] = (src[up+14]&0x03) | ((src[up+15]&0x07) << 2);
// output lvl
if ( opSwitch[op] == '0' )
bulk[pp+14] = 0;
else
bulk[pp+14] = src[up+16];
// fcoarse_mode
bulk[pp+15] = (src[up+17]&0x01) | ((src[up+18]&0x1f) << 1);
// fine freq
bulk[pp+16] = src[up+19];
}
memcpy(bulk + 102, src + 126, 9); // pitch env, algo
bulk[111] = (src[135]&0x07) | ((src[136]&0x01) << 3);
memcpy(bulk + 112, src + 137, 4); // lfo
bulk[116] = (src[141]&0x01) | (((src[142]&0x07) << 1) | ((src[143]&0x07) << 4));
bulk[117] = src[144];
int eos = 0;
for(int i=0; i < 10; i++) {
char c = (char) name[i];
if ( c == 0 )
eos = 1;
if ( eos ) {
bulk[118+i] = ' ';
continue;
}
c = c < 32 ? ' ' : c;
c = c > 127 ? ' ' : c;
bulk[118+i] = c;
}
}
/**
* This function normalize data that comes from corrupted sysex.
* It used to avoid engine crashing upon extrem values
*/
char normparm(char value, char max, int id) {
if ( value <= max && value >= 0 )
return value;
// if this is beyond the max, we expect a 0-255 range, normalize this
// to the expected return value; and this value as a random data.
value = abs(value);
char v = ((float)value)/255 * max;
return v;
}
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
for(int i=0; i<11; i++) {
unpackPgm[op * 21 + i] = normparm(bulk[op * 17 + i], 99, i);
}
memcpy(unpackPgm + op * 21, bulk + op * 17, 11);
char leftrightcurves = bulk[op * 17 + 11];
unpackPgm[op * 21 + 11] = leftrightcurves & 3;
unpackPgm[op * 21 + 12] = (leftrightcurves >> 2) & 3;
char detune_rs = bulk[op * 17 + 12];
unpackPgm[op * 21 + 13] = detune_rs & 7;
char kvs_ams = bulk[op * 17 + 13];
unpackPgm[op * 21 + 14] = kvs_ams & 3;
unpackPgm[op * 21 + 15] = kvs_ams >> 2;
unpackPgm[op * 21 + 16] = bulk[op * 17 + 14]; // output level
char fcoarse_mode = bulk[op * 17 + 15];
unpackPgm[op * 21 + 17] = fcoarse_mode & 1;
unpackPgm[op * 21 + 18] = fcoarse_mode >> 1;
unpackPgm[op * 21 + 19] = bulk[op * 17 + 16]; // fine freq
unpackPgm[op * 21 + 20] = detune_rs >> 3;
}
for (int i=0; i<8; i++) {
unpackPgm[126+i] = normparm(bulk[102+i], 99, 126+i);
}
unpackPgm[134] = normparm(bulk[110], 31, 134);
char oks_fb = bulk[111];
unpackPgm[135] = oks_fb & 7;
unpackPgm[136] = oks_fb >> 3;
memcpy(unpackPgm + 137, bulk + 112, 4); // lfo
char lpms_lfw_lks = bulk[116];
unpackPgm[141] = lpms_lfw_lks & 1;
unpackPgm[142] = (lpms_lfw_lks >> 1) & 7;
unpackPgm[143] = lpms_lfw_lks >> 4;
memcpy(unpackPgm + 144, bulk + 117, 11); // transpose, name
unpackPgm[155] = 1; // operator on/off (DEPRECATED)
unpackPgm[156] = 1;
unpackPgm[157] = 1;
unpackPgm[158] = 1;
unpackPgm[159] = 1;
unpackPgm[160] = 1;
}
void DexedAudioProcessor::loadCartridge(Cartridge &sysex) {
currentCart = sysex;
currentCart.getProgramNames(programNames);
}
void DexedAudioProcessor::updateProgramFromSysex(const uint8_t *rawdata) {
memcpy(data, rawdata, 161);
lfo.reset(data + 137);
triggerAsyncUpdate();
}
void DexedAudioProcessor::setupStartupCart() {
File startup = dexedCartDir.getChildFile("Dexed_01.syx");
if ( currentCart.load(startup) != -1 )
return;
// 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() {
const char init_voice[] =
{ 99, 99, 99, 99, 99, 99, 99, 00, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 7,
99, 99, 99, 99, 99, 99, 99, 00, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 7,
99, 99, 99, 99, 99, 99, 99, 00, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 7,
99, 99, 99, 99, 99, 99, 99, 00, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 7,
99, 99, 99, 99, 99, 99, 99, 00, 39, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 7,
99, 99, 99, 99, 99, 99, 99, 00, 39, 0, 0, 0, 0, 0, 0, 0, 99, 0, 1, 0, 7,
99, 99, 99, 99, 50, 50, 50, 50, 0, 0, 1, 35, 0, 0, 0, 1, 0, 3, 24,
73, 78, 73, 84, 32, 86, 79, 73, 67, 69 };
for(int i=0;i<sizeof(init_voice);i++) {
data[i] = init_voice[i];
}
panic();
triggerAsyncUpdate();
}
void DexedAudioProcessor::copyToClipboard(int srcOp) {
memcpy(clipboard, data, 161);
clipboardContent = srcOp;
}
void DexedAudioProcessor::pasteOpFromClipboard(int destOp) {
memcpy(data+(destOp*21), clipboard+(clipboardContent*21), 21);
triggerAsyncUpdate();
}
void DexedAudioProcessor::pasteEnvFromClipboard(int destOp) {
memcpy(data+(destOp*21), clipboard+(clipboardContent*21), 8);
triggerAsyncUpdate();
}
void DexedAudioProcessor::sendCurrentSysexProgram() {
uint8_t raw[163];
exportSysexPgm(raw, data);
if ( sysexComm.isOutputActive() ) {
sysexComm.send(MidiMessage(raw, 163));
}
}
void DexedAudioProcessor::sendCurrentSysexCartridge() {
uint8_t raw[4104];
currentCart.saveVoice(raw);
if ( sysexComm.isOutputActive() ) {
sysexComm.send(MidiMessage(raw, 4104));
}
}
void DexedAudioProcessor::sendSysexCartridge(File cart) {
if ( ! sysexComm.isOutputActive() )
return;
FileInputStream *fis = cart.createInputStream();
if ( fis == NULL ) {
String f = cart.getFullPathName();
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
"Error",
"Unable to open: " + f);
}
uint8 syx_data[65535];
int sz = fis->read(syx_data, 65535);
delete fis;
if (syx_data[0] != 0xF0) {
String f = cart.getFullPathName();
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
"Error",
"File: " + f + " doesn't seems to contain any sysex data");
return;
}
sysexComm.send(MidiMessage(syx_data, sz));
}
bool DexedAudioProcessor::hasClipboardContent() {
return clipboardContent != -1;
}
//==============================================================================
void DexedAudioProcessor::getStateInformation(MemoryBlock& destData) {
// You should use this method to store your parameters in the memory block.
// You could do that either as raw data, or use the XML or ValueTree classes
// as intermediaries to make it easy to save and load complex data.
// used to SAVE plugin state
XmlElement dexedState("dexedState");
XmlElement *dexedBlob = dexedState.createNewChildElement("dexedBlob");
dexedState.setAttribute("cutoff", fx.uiCutoff);
dexedState.setAttribute("reso", fx.uiReso);
dexedState.setAttribute("gain", fx.uiGain);
dexedState.setAttribute("currentProgram", currentProgram);
dexedState.setAttribute("monoMode", monoMode);
dexedState.setAttribute("engineType", (int) engineType);
dexedState.setAttribute("masterTune", controllers.masterTune);
dexedState.setAttribute("opSwitch", controllers.opSwitch);
char mod_cfg[15];
controllers.wheel.setConfig(mod_cfg);
dexedState.setAttribute("wheelMod", mod_cfg);
controllers.foot.setConfig(mod_cfg);
dexedState.setAttribute("footMod", mod_cfg);
controllers.breath.setConfig(mod_cfg);
dexedState.setAttribute("breathMod", mod_cfg);
controllers.at.setConfig(mod_cfg);
dexedState.setAttribute("aftertouchMod", mod_cfg);
if ( activeFileCartridge.exists() )
dexedState.setAttribute("activeFileCartridge", activeFileCartridge.getFullPathName());
NamedValueSet blobSet;
blobSet.set("sysex", var((void *) currentCart.getVoiceSysex(), 4104));
blobSet.set("program", var((void *) &data, 161));
blobSet.copyToXmlAttributes(*dexedBlob);
copyXmlToBinary(dexedState, destData);
}
void DexedAudioProcessor::setStateInformation(const void* source, int sizeInBytes) {
// You should use this method to restore your parameters from this memory block,
// whose contents will have been created by the getStateInformation() call.
// used to LOAD plugin state
ScopedPointer<XmlElement> root(getXmlFromBinary(source, sizeInBytes));
if (root == nullptr) {
TRACE("unkown state format");
return;
}
fx.uiCutoff = root->getDoubleAttribute("cutoff");
fx.uiReso = root->getDoubleAttribute("reso");
fx.uiGain = root->getDoubleAttribute("gain");
currentProgram = root->getIntAttribute("currentProgram");
String opSwitchValue = root->getStringAttribute("opSwitch");
if ( opSwitchValue.length() != 6 ) {
strcpy(controllers.opSwitch, "111111");
} else {
strncpy(controllers.opSwitch, opSwitchValue.toRawUTF8(), 6);
}
controllers.wheel.parseConfig(root->getStringAttribute("wheelMod").toRawUTF8());
controllers.foot.parseConfig(root->getStringAttribute("footMod").toRawUTF8());
controllers.breath.parseConfig(root->getStringAttribute("breathMod").toRawUTF8());
controllers.at.parseConfig(root->getStringAttribute("aftertouchMod").toRawUTF8());
setEngineType(root->getIntAttribute("engineType", 1));
monoMode = root->getIntAttribute("monoMode", 0);
controllers.masterTune = root->getIntAttribute("masterTune", 0);
File possibleCartridge = File(root->getStringAttribute("activeFileCartridge"));
if ( possibleCartridge.exists() )
activeFileCartridge = possibleCartridge;
XmlElement *dexedBlob = root->getChildByName("dexedBlob");
if ( dexedBlob == NULL ) {
TRACE("dexedBlob element not found");
return;
}
NamedValueSet blobSet;
blobSet.setFromXmlAttributes(*dexedBlob);
var sysex_blob = blobSet["sysex"];
var program = blobSet["program"];
if ( sysex_blob.isVoid() || program.isVoid() ) {
TRACE("unkown serialized blob data");
return;
}
Cartridge cart;
cart.load((uint8 *)sysex_blob.getBinaryData()->getData(), 4104);
loadCartridge(cart);
memcpy(data, program.getBinaryData()->getData(), 161);
lastStateSave = (long) time(NULL);
TRACE("setting VST STATE");
updateUI();
}
File DexedAudioProcessor::dexedAppDir;
File DexedAudioProcessor::dexedCartDir;
void DexedAudioProcessor::resolvAppDir() {
#if JUCE_MAC || JUCE_IOS
File parent = File::getSpecialLocation(File::currentExecutableFile).getParentDirectory().getParentDirectory().getParentDirectory().getSiblingFile("Dexed");
if ( parent.isDirectory() ) {
dexedAppDir = parent;
} else {
dexedAppDir = File("~/Library/Application Support/DigitalSuburban/Dexed");
}
#elif JUCE_WINDOWS
if ( File::getSpecialLocation(File::currentExecutableFile).getSiblingFile("Dexed").isDirectory() ) {
dexedAppDir = File::getSpecialLocation(File::currentExecutableFile).getSiblingFile("Dexed");
} else {
dexedAppDir = File::getSpecialLocation(File::userApplicationDataDirectory).getChildFile("DigitalSuburban").getChildFile("Dexed");
}
#else
if ( File::getSpecialLocation(File::currentExecutableFile).getSiblingFile("Dexed").isDirectory() ) {
dexedAppDir = File::getSpecialLocation(File::currentExecutableFile).getSiblingFile("Dexed");
} else {
char *xdgHome = getenv("XDG_DATA_HOME");
if ( xdgHome == nullptr ) {
dexedAppDir = File("~/.local/share").getChildFile("DigitalSuburban").getChildFile("Dexed");
} else {
dexedAppDir = File(xdgHome).getChildFile("DigitalSuburban").getChildFile("Dexed");
}
}
#endif
if ( ! dexedAppDir.exists() ) {
dexedAppDir.createDirectory();
// ==========================================================================
// For older versions, we move the Dexed.xml config file
// This code will be removed in 0.9.0
File cfgFile = dexedAppDir.getParentDirectory().getChildFile("Dexed.xml");
if ( cfgFile.exists() )
cfgFile.moveFileTo(dexedAppDir.getChildFile("Dexed.xml"));
// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
// ==========================================================================
}
dexedCartDir = dexedAppDir.getChildFile("Cartridges");
if ( ! dexedCartDir.exists() ) {
// Initial setup, we unzip the built-in cartridges
dexedCartDir.createDirectory();
File synprezFmDir = dexedCartDir.getChildFile("SynprezFM");
synprezFmDir.createDirectory();
MemoryInputStream *mis = new MemoryInputStream(BinaryData::builtin_pgm_zip, BinaryData::builtin_pgm_zipSize, false);
ZipFile *builtin_pgm = new ZipFile(mis, true);
for(int i=0;i<builtin_pgm->getNumEntries();i++) {
if ( builtin_pgm->getEntry(i)->filename == "Dexed_01.syx" ) {
builtin_pgm->uncompressEntry(i, dexedCartDir);
} else {
builtin_pgm->uncompressEntry(i, synprezFmDir);
}
}
delete builtin_pgm;
}
}

@ -1,247 +0,0 @@
/**
*
* Copyright (c) 2014-2016 Pascal Gauthier.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef PLUGINDATA_H_INCLUDED
#define PLUGINDATA_H_INCLUDED
#include "../JuceLibraryCode/JuceHeader.h"
#include <stdint.h>
#include <string.h>
#include "Dexed.h"
uint8_t sysexChecksum(const uint8_t *sysex, int size);
void exportSysexPgm(uint8_t *dest, uint8_t *src);
#define SYSEX_HEADER { 0xF0, 0x43, 0x00, 0x09, 0x20, 0x00 }
#define SYSEX_SIZE 4104
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;
}
/**
* Loads sysex stream
* Returns 0 if it was parsed sucessfully
* Returns -1 if it cannot open the stream
*/
int load(InputStream &fis) {
uint8 buffer[65535];
int sz = fis.read(buffer, 65535);
if ( sz == 0 )
return -1;
return load(buffer, sz);
}
/**
* Loads sysex buffer
* Returns 0 if it was parsed sucessfully
* Returns 1 if sysex checksum didn't match
* Returns 2 if no sysex data found, probably random data
*/
int load(const uint8_t *stream, int size) {
const uint8 voiceHeaderBroken[] = { 0xF0, 0x43, 0x00, 0x00, 0x20, 0x00 };
// I've added a stupid bug that saved the wrong sysex data for dx7 sysex (0.9.1)
// This is there to support this version. One day we will be able to remove this. :(
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 != 3 )
return status;
memcpy(voiceData, pos+6, 4096);
return 2;
}
pos[3] = 0;
if ( memcmp(pos, voiceHeader, 6) == 0 || memcmp(pos, voiceHeaderBroken, 6) == 0) {
memcpy(voiceData, pos, SYSEX_SIZE);
if ( sysexChecksum(voiceData + 6, 4096) == pos[4102] )
status = 0;
else
status = 1;
size -= 4104;
pos += 4104;
continue;
}
// other sysex
int i;
for(i=0;i<size-1;i++) {
if ( pos[i] == 0xF7 )
break;
}
size -= i;
stream += i;
}
// nothing good has been found, map it then to random data
if ( status > 1 ) {
memcpy(voiceData, pos+6, 4096);
return 2;
}
return status;
}
int saveVoice(File f) {
setHeader();
if ( ! f.existsAsFile() ) {
// file doesn't exists, create it
return f.replaceWithData(voiceData, SYSEX_SIZE);
}
FileInputStream *fis = f.createInputStream();
if ( fis == NULL )
return -1;
uint8 buffer[65535];
int sz = fis->read(buffer, 65535);
delete fis;
// if the file is smaller than 4104, it probably needs to be overriden.
if ( sz <= 4104 ) {
return f.replaceWithData(voiceData, SYSEX_SIZE);
}
// To avoid to erase the performance data, we skip the sysex stream until
// we see the header 0xF0, 0x43, 0x00, 0x09, 0x20, 0x00
int pos = 0;
bool found = 0;
while(pos < sz) {
// corrupted sysex, erase everything :
if ( buffer[pos] != 0xF0 )
return f.replaceWithData(voiceData, SYSEX_SIZE);
uint8_t header[] = SYSEX_HEADER;
if ( memcmp(buffer+pos, header, 6) ) {
found = true;
memcpy(buffer+pos, voiceData, SYSEX_SIZE);
break;
} else {
for(;pos<sz;pos++) {
if ( buffer[pos] == 0xF7 )
break;
}
}
}
if ( ! found )
return -1;
return f.replaceWithData(buffer, sz);
}
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, char *opSwitch);
};
#endif // PLUGINDATA_H_INCLUDED

@ -1,341 +0,0 @@
/**
*
* Copyright (c) 2013-2015 Pascal Gauthier.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "PluginProcessor.h"
#include "PluginEditor.h"
#include "GlobalEditor.h"
#include "ParamDialog.h"
#include "SysexComm.h"
#include "Dexed.h"
#include "math.h"
#include "DXLookNFeel.h"
#include <fstream>
#include "msfa/fm_op_kernel.h"
//==============================================================================
DexedAudioProcessorEditor::DexedAudioProcessorEditor (DexedAudioProcessor* ownerFilter)
: AudioProcessorEditor (ownerFilter),
midiKeyboard (ownerFilter->keyboardState, MidiKeyboardComponent::horizontalKeyboard),
cartManager(this)
{
LookAndFeel::setDefaultLookAndFeel(DXLookNFeel::getLookAndFeel());
setSize(866, ownerFilter->showKeyboard ? 674 : 581);
processor = ownerFilter;
background = DXLookNFeel::getLookAndFeel()->background;
// OPERATORS
addAndMakeVisible(&(operators[0]));
operators[0].setBounds(2, 1, 287, 218);
operators[0].bind(processor, 0);
addAndMakeVisible(&(operators[1]));
operators[1].setBounds(290, 1, 287, 218);
operators[1].bind(processor, 1);
addAndMakeVisible(&(operators[2]));
operators[2].setBounds(578, 1, 287, 218);
operators[2].bind(processor, 2);
addAndMakeVisible(&(operators[3]));
operators[3].setBounds(2, 219, 287, 218);
operators[3].bind(processor, 3);
addAndMakeVisible(&(operators[4]));
operators[4].setBounds(290, 219, 287, 218);
operators[4].bind(processor, 4);
addAndMakeVisible(&(operators[5]));
operators[5].setBounds(578, 219, 287, 218);
operators[5].bind(processor, 5);
// add the midi keyboard component..
addAndMakeVisible (&midiKeyboard);
// The DX7 is a badass on the bass, keep it that way
midiKeyboard.setLowestVisibleKey(24);
midiKeyboard.setBounds(4, 581, getWidth() - 8, 90);
addAndMakeVisible(&global);
global.setBounds(2,436,864,144);
global.bind(this);
global.setMonoState(processor->isMonoMode());
rebuildProgramCombobox();
global.programs->addListener(this);
addChildComponent(&cartManager);
updateUI();
startTimer(100);
}
DexedAudioProcessorEditor::~DexedAudioProcessorEditor() {
stopTimer();
processor->unbindUI();
}
//==============================================================================
void DexedAudioProcessorEditor::paint (Graphics& g) {
g.setColour(background);
g.fillRoundedRectangle(0.0f, 0.0f, (float) getWidth(), (float) getHeight(), 0);
}
void DexedAudioProcessorEditor::cartShow() {
stopTimer();
cartManager.resetActiveSysex();
cartManager.setBounds(4, 2, 859, 576);
cartManager.setVisible(true);
cartManager.initialFocus();
}
void DexedAudioProcessorEditor::loadCart(File file) {
Cartridge cart;
int rc = cart.load(file);
if ( rc < 0 ) {
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
"Error",
"Unable to open: " + file.getFullPathName());
return;
}
if ( rc != 0 ) {
rc = AlertWindow::showOkCancelBox(AlertWindow::QuestionIcon, "Unable to find DX7 sysex cartridge in file",
"This sysex file is not for the DX7 or it is corrupted. "
"Do you still want to load this file as random data ?");
if ( rc == 0 )
return;
}
processor->loadCartridge(cart);
rebuildProgramCombobox();
processor->setCurrentProgram(0);
global.programs->setSelectedId(processor->getCurrentProgram()+1, dontSendNotification);
processor->updateHostDisplay();
processor->activeFileCartridge = file;
}
void DexedAudioProcessorEditor::saveCart() {
File startFileName = processor->activeFileCartridge.exists() ? processor->activeFileCartridge : processor->dexedCartDir;
FileChooser fc ("Export DX sysex...", processor->dexedCartDir, "*.syx", 1);
if ( fc.browseForFileToSave(true) ) {
if ( ! processor->currentCart.saveVoice(fc.getResults().getReference(0)) ) {
AlertWindow::showMessageBoxAsync (AlertWindow::WarningIcon,
"Error",
"Unable to write: " + fc.getResults().getReference(0).getFullPathName());
}
}
}
void DexedAudioProcessorEditor::parmShow() {
int tp = processor->getEngineType();
AlertWindow window("","", AlertWindow::NoIcon, this);
ParamDialog param;
param.setColour(AlertWindow::backgroundColourId, Colour(0x32FFFFFF));
param.setDialogValues(processor->controllers, processor->sysexComm, tp, processor->showKeyboard);
window.addCustomComponent(&param);
window.addButton("OK", 0);
window.addButton("Cancel" ,1);
if ( window.runModalLoop() != 0 )
return;
bool ret = param.getDialogValues(processor->controllers, processor->sysexComm, &tp, &processor->showKeyboard);
processor->setEngineType(tp);
processor->savePreference();
setSize(866, processor->showKeyboard ? 674 : 581);
midiKeyboard.repaint();
if ( ret == false ) {
AlertWindow::showMessageBoxAsync(AlertWindow::WarningIcon, "Midi Interface", "Error opening midi ports");
}
}
void DexedAudioProcessorEditor::initProgram() {
processor->resetToInitVoice();
}
void DexedAudioProcessorEditor::comboBoxChanged (ComboBox* comboBoxThatHasChanged) {
processor->setCurrentProgram(global.programs->getSelectedId()-1);
processor->updateHostDisplay();
}
void DexedAudioProcessorEditor::timerCallback() {
if ( processor->forceRefreshUI ) {
processor->forceRefreshUI = false;
updateUI();
}
if ( ! processor->peekVoiceStatus() )
return;
for(int i=0;i<6;i++) {
operators[i].updateGain(sqrt(processor->voiceStatus.amp[5 - i]) / 8196); // TODO: FUGLY !!!! change this sqrt nonsens
operators[i].updateEnvPos(processor->voiceStatus.ampStep[5 - i]);
}
global.updatePitchPos(processor->voiceStatus.pitchStep);
global.updateVu(processor->vuSignal);
}
void DexedAudioProcessorEditor::updateUI() {
for(int i=0;i<processor->ctrl.size();i++) {
processor->ctrl[i]->updateComponent();
}
for(int i=0;i<6;i++) {
operators[i].updateDisplay();
}
rebuildProgramCombobox();
global.updateDisplay();
}
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);
global.programs->addItem(id, i+1);
}
global.programs->setSelectedId(processor->getCurrentProgram()+1, dontSendNotification);
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);
cartManager.resetActiveSysex();
}
void DexedAudioProcessorEditor::storeProgram() {
String currentName = Cartridge::normalizePgmName((const char *) processor->data+145);
Cartridge destSysex = processor->currentCart;
File *externalFile = NULL;
bool activeCartridgeFound = processor->activeFileCartridge.exists();
while (true) {
String msg;
if ( externalFile == NULL ) {
if ( activeCartridgeFound )
msg = "Store program to current (" + processor->activeFileCartridge.getFileName() + ") / new cartridge";
else
msg = "Store program to current / new cartridge";
} else {
msg = "Store program to " + externalFile->getFileName();
}
AlertWindow dialog("Store Program", msg, AlertWindow::NoIcon, this);
dialog.addTextEditor("Name", currentName, String("Name"), false);
// TODO: fix the name length to 10
StringArray programs;
destSysex.getProgramNames(programs);
dialog.addComboBox("Dest", programs, "Program Destination");
if ( externalFile == NULL ) {
StringArray saveAction;
saveAction.add("Store program to DAW plugin song state");
saveAction.add("Store program and create a new copy of the .syx cartridge");
if ( activeCartridgeFound )
saveAction.add("Store program and overwrite current .syx cartridge");
dialog.addComboBox("SaveAction", saveAction, "Store Action");
}
dialog.addButton("OK", 0, KeyPress(KeyPress::returnKey));
dialog.addButton("CANCEL", 1, KeyPress(KeyPress::escapeKey));
dialog.addButton("EXTERNAL FILE", 2, KeyPress());
int response = dialog.runModalLoop();
if ( response == 2 ) {
FileChooser fc("Destination Sysex", processor->dexedCartDir, "*.syx;*.SYX;*.*", 1);
if ( fc.browseForFileToOpen() ) {
if ( externalFile != NULL )
delete externalFile;
externalFile = new File(fc.getResults().getReference(0));
if ( destSysex.load(*externalFile) )
continue;
AlertWindow::showMessageBoxAsync(AlertWindow::WarningIcon, "Read error", "Unable to read file");
}
}
if ( response == 0 ) {
TextEditor *name = dialog.getTextEditor("Name");
ComboBox *dest = dialog.getComboBoxComponent("Dest");
int programNum = dest->getSelectedItemIndex();
String programName(name->getText());
if ( programName.length() > 10 ) {
int toStrip = programName.length() - 10;
programName = programName.dropLastCharacters(toStrip);
}
if ( externalFile == NULL ) {
processor->currentCart.packProgram((uint8_t *) processor->data, programNum, programName, processor->controllers.opSwitch);
rebuildProgramCombobox();
processor->setCurrentProgram(programNum);
processor->updateHostDisplay();
int action = dialog.getComboBoxComponent("SaveAction")->getSelectedItemIndex();
if ( action > 0 ) {
File destination = processor->activeFileCartridge;
if ( ! destination.exists() ) {
FileChooser fc("Destination Sysex", processor->dexedCartDir, "*.syx", 1);
if ( ! fc.browseForFileToSave(true) )
break;
destination = fc.getResult();
}
processor->currentCart.saveVoice(destination);
processor->activeFileCartridge = destination;
}
} else {
destSysex.packProgram((uint8_t *) processor->data, programNum, programName, processor->controllers.opSwitch);
if ( ! destSysex.saveVoice(*externalFile)) {
AlertWindow::showMessageBoxAsync(AlertWindow::WarningIcon, "Write error", "Unable to write file");
}
}
}
break;
}
if ( externalFile != NULL )
delete externalFile;
cartManager.resetActiveSysex();
}

@ -1,61 +0,0 @@
/**
*
* Copyright (c) 2013-2016 Pascal Gauthier.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#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"
#include "CartManager.h"
//==============================================================================
/**
*/
class DexedAudioProcessorEditor : public AudioProcessorEditor, public ComboBoxListener, public Timer {
MidiKeyboardComponent midiKeyboard;
OperatorEditor operators[6];
Colour background;
CartManager cartManager;
public:
DexedAudioProcessor *processor;
GlobalEditor global;
DexedAudioProcessorEditor (DexedAudioProcessor* ownerFilter);
~DexedAudioProcessorEditor();
void timerCallback();
void paint (Graphics& g);
void comboBoxChanged (ComboBox* comboBoxThatHasChanged);
void updateUI();
void rebuildProgramCombobox();
void loadCart(File file);
void saveCart();
void initProgram();
void storeProgram();
void cartShow();
void parmShow();
};
#endif // PLUGINEDITOR_H_INCLUDED

@ -1,705 +0,0 @@
/**
*
* Copyright (c) 2013-2016 Pascal Gauthier.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include <time.h>
#include <stdlib.h>
#include "PluginParam.h"
#include "PluginProcessor.h"
#include "PluginEditor.h"
#include "Dexed.h"
// ************************************************************************
// Custom displays
class CtrlDXLabel : public CtrlDX {
StringArray labels;
public:
CtrlDXLabel(String name, int steps, int offset, StringArray &labels) : CtrlDX(name, steps, offset, 0) {
this->labels = labels;
};
String getValueDisplay() {
return labels[getValue()];
}
};
class CtrlDXTranspose : public CtrlDX {
public:
CtrlDXTranspose(String name, int steps, int offset) : CtrlDX(name, steps, offset, 0) {
};
String getValueDisplay() {
String ret;
int value = getValue();
switch(value % 12) {
case 0: ret << "C"; break;
case 1: ret << "C#"; break;
case 2: ret << "D"; break;
case 3: ret << "D#"; break;
case 4: ret << "E"; break;
case 5: ret << "F"; break;
case 6: ret << "F#"; break;
case 7: ret << "G"; break;
case 8: ret << "G#"; break;
case 9: ret << "A"; break;
case 10: ret << "A#"; break;
case 11: ret << "B"; break;
}
return ret << (value/12+1);
}
};
class CtrlTune : public Ctrl {
public:
DexedAudioProcessor *processor;
CtrlTune(String name, DexedAudioProcessor *owner) : Ctrl(name) {
processor = owner;
}
float getValueHost() {
// meh. good enough for now
int32_t tune = processor->controllers.masterTune / (1.0/12);
tune = (tune >> 11) + 0x2000;
return (float)tune / 0x4000;
}
void setValueHost(float v) {
int32_t tune = (v * 0x4000) - 0x2000;
processor->controllers.masterTune = ((float) (tune << 11)) * (1.0/12);
}
String getValueDisplay() {
String display;
display << (getValueHost() * 2) -1;
return display;
}
void updateComponent() {
if (slider != NULL) {
slider->setValue(getValueHost(), dontSendNotification);
}
}
};
class CtrlOpSwitch : public Ctrl {
char *value;
public :
CtrlOpSwitch(String name, char *switchValue) : Ctrl(name) {
value = switchValue;
}
void setValueHost(float f) {
if ( f == 0 )
*value = '0';
else
*value = '1';
}
float getValueHost() {
if ( *value == '0' )
return 0;
else
return 1;
}
String getValueDisplay() {
String ret;
ret << label << " " << (*value == '0' ? "OFF" : "ON");
return ret;
}
void updateComponent() {
if (button != NULL) {
if (*value == '0') {
button->setToggleState(false, dontSendNotification);
} else {
button->setToggleState(true, dontSendNotification);
}
}
}
};
// ************************************************************************
//
Ctrl::Ctrl(String name) {
label << name;
slider = NULL;
button = NULL;
comboBox = NULL;
}
void Ctrl::bind(Slider *s) {
slider = s;
updateComponent();
s->addListener(this);
s->addMouseListener(this, true);
}
void Ctrl::bind(Button *b) {
button = b;
updateComponent();
b->addListener(this);
b->addMouseListener(this, true);
}
void Ctrl::bind(ComboBox *c) {
comboBox = c;
updateComponent();
c->addListener(this);
c->addMouseListener(this, true);
}
void Ctrl::unbind() {
if (slider != NULL) {
slider->removeListener(this);
slider->removeMouseListener(this);
slider = NULL;
}
if (button != NULL) {
button->removeListener(this);
button->removeMouseListener(this);
button = NULL;
}
if (comboBox != NULL) {
comboBox->removeListener(this);
comboBox->removeMouseListener(this);
comboBox = NULL;
}
}
void Ctrl::publishValue(float value) {
parent->beginParameterChangeGesture(idx);
parent->setParameterNotifyingHost(idx, value);
parent->endParameterChangeGesture(idx);
}
void Ctrl::sliderValueChanged(Slider* moved) {
publishValue(moved->getValue());
}
void Ctrl::buttonClicked(Button* clicked) {
publishValue(clicked->getToggleState());
}
void Ctrl::comboBoxChanged(ComboBox* combo) {
publishValue((combo->getSelectedId() - 1) / combo->getNumItems());
}
void Ctrl::mouseEnter(const juce::MouseEvent &event) {
updateDisplayName();
}
void Ctrl::updateDisplayName() {
}
// ************************************************************************
// CtrlDX - control DX mapping
CtrlFloat::CtrlFloat(String name, float *storageValue) : Ctrl(name) {
vPointer = storageValue;
}
float CtrlFloat::getValueHost() {
return *vPointer;
}
void CtrlFloat::setValueHost(float v) {
*vPointer = v;
}
String CtrlFloat::getValueDisplay() {
String display;
display << *vPointer;
return display;
}
void CtrlFloat::updateComponent() {
if (slider != NULL) {
slider->setValue(*vPointer, dontSendNotification);
}
}
// ************************************************************************
// CtrlDX - control DX mapping
CtrlDX::CtrlDX(String name, int steps, int offset, int displayValue) : Ctrl(name) {
this->displayValue = displayValue;
this->steps = steps;
dxValue = 0;
dxOffset = offset;
}
float CtrlDX::getValueHost() {
return getValue() / (float) steps;
}
void CtrlDX::setValueHost(float f) {
setValue(roundToInt(f * steps));
}
void CtrlDX::setValue(int v) {
TRACE("setting value %d %d", dxOffset, v);
dxValue = v;
if (dxOffset >= 0) {
if (parent != NULL)
parent->setDxValue(dxOffset, dxValue);
}
}
int CtrlDX::getValue() {
if (dxOffset >= 0)
dxValue = parent->data[dxOffset];
return dxValue;
}
int CtrlDX::getOffset() {
return dxOffset;
}
String CtrlDX::getValueDisplay() {
String ret;
ret << ( getValue() + displayValue );
return ret;
}
void CtrlDX::updateDisplayName() {
DexedAudioProcessorEditor *editor = (DexedAudioProcessorEditor *) parent->getActiveEditor();
if ( editor == NULL ) {
return;
}
String msg;
msg << label << " = " << getValueDisplay();
editor->global.setParamMessage(msg);
editor->global.repaint();
}
void CtrlDX::publishValue(float value) {
Ctrl::publishValue(value / steps);
updateDisplayName();
}
void CtrlDX::sliderValueChanged(Slider* moved) {
publishValue(((int) moved->getValue() - displayValue));
}
void CtrlDX::comboBoxChanged(ComboBox* combo) {
publishValue(combo->getSelectedId() - 1);
}
void CtrlDX::buttonClicked(Button *button) {
publishValue((int) button->getToggleState());
}
void CtrlDX::updateComponent() {
if (slider != NULL) {
slider->setValue(getValue() + displayValue,
dontSendNotification);
}
if (button != NULL) {
if (getValue() == 0) {
button->setToggleState(false, dontSendNotification);
} else {
button->setToggleState(true, dontSendNotification);
}
}
if (comboBox != NULL) {
int cvalue = getValue() + 1;
if (comboBox->getNumItems() <= cvalue) {
cvalue = comboBox->getNumItems();
}
comboBox->setSelectedId(cvalue, dontSendNotification);
}
}
/***************************************************************
*
*/
void DexedAudioProcessor::initCtrl() {
setupStartupCart();
currentProgram = 0;
fxCutoff = new CtrlFloat("Cutoff", &fx.uiCutoff);
ctrl.add(fxCutoff);
fxReso = new CtrlFloat("Resonance", &fx.uiReso);
ctrl.add(fxReso);
output = new CtrlFloat("Output", &fx.uiGain);
ctrl.add(output);
tune = new CtrlTune("MASTER TUNE ADJ", this);
ctrl.add(tune);
algo = new CtrlDX("ALGORITHM", 31, 134, 1);
ctrl.add(algo);
feedback = new CtrlDX("FEEDBACK", 7, 135);
ctrl.add(feedback);
oscSync = new CtrlDX("OSC KEY SYNC", 1, 136);
ctrl.add(oscSync);
lfoRate = new CtrlDX("LFO SPEED", 99, 137);
ctrl.add(lfoRate);
lfoDelay = new CtrlDX("LFO DELAY", 99, 138);
ctrl.add(lfoDelay);
lfoPitchDepth = new CtrlDX("LFO PM DEPTH", 99, 139);
ctrl.add(lfoPitchDepth);
lfoAmpDepth = new CtrlDX("LFO AM DEPTH", 99, 140);
ctrl.add(lfoAmpDepth);
lfoSync = new CtrlDX("LFO KEY SYNC", 1, 141);
ctrl.add(lfoSync);
StringArray lbl;
lbl.add("TRIANGE");
lbl.add("SAW DOWN");
lbl.add("SAW UP");
lbl.add("SQUARE");
lbl.add("SINE");
lbl.add("S&HOLD");
lfoWaveform = new CtrlDXLabel("LFO WAVE", 5, 142, lbl);
ctrl.add(lfoWaveform);
transpose = new CtrlDXTranspose("MIDDLE C", 48, 144);
ctrl.add(transpose);
pitchModSens = new CtrlDX("P MODE SENS.", 7, 143);
ctrl.add(pitchModSens);
for (int i=0;i<4;i++) {
String rate;
rate << "PITCH EG RATE " << (i+1);
pitchEgRate[i] = new CtrlDX(rate, 99, 126+i);
ctrl.add(pitchEgRate[i]);
}
for (int i=0;i<4;i++) {
String level;
level << "PITCH EG LEVEL " << (i+1);
pitchEgLevel[i] = new CtrlDX(level, 99, 130+i);
ctrl.add(pitchEgLevel[i]);
}
StringArray keyScaleLabels;
keyScaleLabels.add("-LN");
keyScaleLabels.add("-EX");
keyScaleLabels.add("+EX");
keyScaleLabels.add("+LN");
// fill operator values;
for (int i = 0; i < 6; i++) {
//// In the Sysex, OP6 comes first, then OP5...
int opTarget = (5-i) * 21;
int opVal = i;
String opName;
opName << "OP" << (opVal + 1);
for (int j = 0; j < 4; j++) {
String opRate;
opRate << opName << " EG RATE " << (j + 1);
opCtrl[opVal].egRate[j] = new CtrlDX(opRate, 99, opTarget + j);
ctrl.add(opCtrl[opVal].egRate[j]);
}
for (int j = 0; j < 4; j++) {
String opLevel;
opLevel << opName << " EG LEVEL " << (j + 1);
opCtrl[opVal].egLevel[j] = new CtrlDX(opLevel, 99, opTarget + j + 4);
ctrl.add(opCtrl[opVal].egLevel[j]);
}
String opVol;
opVol << opName << " OUTPUT LEVEL";
opCtrl[opVal].level = new CtrlDX(opVol, 99, opTarget + 16);
ctrl.add(opCtrl[opVal].level);
String opMode;
opMode << opName << " MODE";
opCtrl[opVal].opMode = new CtrlDX(opMode, 1, opTarget + 17);
ctrl.add(opCtrl[opVal].opMode);
String coarse;
coarse << opName << " F COARSE";
opCtrl[opVal].coarse = new CtrlDX(coarse, 31, opTarget + 18);
ctrl.add(opCtrl[opVal].coarse);
String fine;
fine << opName << " F FINE";
opCtrl[opVal].fine = new CtrlDX(fine, 99, opTarget + 19);
ctrl.add(opCtrl[opVal].fine);
String detune;
detune << opName << " OSC DETUNE";
opCtrl[opVal].detune = new CtrlDX(detune, 14, opTarget + 20, -7);
ctrl.add(opCtrl[opVal].detune);
String sclBrkPt;
sclBrkPt << opName << " BREAK POINT";
opCtrl[opVal].sclBrkPt = new CtrlDX(sclBrkPt, 99, opTarget + 8);
ctrl.add(opCtrl[opVal].sclBrkPt);
String sclLeftDepth;
sclLeftDepth << opName << " L SCALE DEPTH";
opCtrl[opVal].sclLeftDepth = new CtrlDX(sclLeftDepth, 99, opTarget + 9);
ctrl.add(opCtrl[opVal].sclLeftDepth);
String sclRightDepth;
sclRightDepth << opName << " R SCALE DEPTH";
opCtrl[opVal].sclRightDepth = new CtrlDX(sclRightDepth, 99, opTarget + 10);
ctrl.add(opCtrl[opVal].sclRightDepth);
String sclLeftCurve;
sclLeftCurve << opName << " L KEY SCALE";
opCtrl[opVal].sclLeftCurve = new CtrlDXLabel(sclLeftCurve, 3, opTarget + 11, keyScaleLabels);
ctrl.add(opCtrl[opVal].sclLeftCurve);
String sclRightCurve;
sclRightCurve << opName << " R KEY SCALE";
opCtrl[opVal].sclRightCurve = new CtrlDXLabel(sclRightCurve, 3, opTarget + 12, keyScaleLabels);
ctrl.add(opCtrl[opVal].sclRightCurve);
String sclRate;
sclRate << opName << " RATE SCALING";
opCtrl[opVal].sclRate = new CtrlDX(sclRate, 7, opTarget + 13);
ctrl.add(opCtrl[opVal].sclRate);
String ampModSens;
ampModSens << opName << " A MOD SENS.";
opCtrl[opVal].ampModSens = new CtrlDX(ampModSens, 3, opTarget + 14);
ctrl.add(opCtrl[opVal].ampModSens);
String velModSens;
velModSens << opName << " KEY VELOCITY";
opCtrl[opVal].velModSens = new CtrlDX(velModSens, 7, opTarget + 15);
ctrl.add(opCtrl[opVal].velModSens);
String opSwitchLabel;
opSwitchLabel << opName << " SWITCH";
opCtrl[opVal].opSwitch = new CtrlOpSwitch(opSwitchLabel, (char *)&(controllers.opSwitch)+(5-i));
ctrl.add(opCtrl[opVal].opSwitch);
}
for (int i=0; i < ctrl.size(); i++) {
ctrl[i]->idx = i;
ctrl[i]->parent = this;
}
}
void DexedAudioProcessor::setDxValue(int offset, int v) {
if (offset < 0)
return;
if ( data[offset] != v ) {
TRACE("setting dx %d %d", offset, v);
data[offset] = v;
} else {
TRACE("ignoring dx7 same values %d %d", offset, v);
return;
}
refreshVoice = true;
// MIDDLE C (transpose)
if (offset == 144)
panic();
if (!sendSysexChange)
return;
uint8 msg[7] = { 0xF0, 0x43, 0x10, offset > 127, 0, (uint8) v, 0xF7 };
msg[2] = 0x10 | sysexComm.getChl();
msg[4] = offset & 0x7F;
if ( sysexComm.isOutputActive() ) {
sysexComm.send(MidiMessage(msg,7));
}
}
void DexedAudioProcessor::unbindUI() {
for (int i = 0; i < ctrl.size(); i++) {
ctrl[i]->unbind();
}
}
//==============================================================================
int DexedAudioProcessor::getNumParameters() {
return ctrl.size();
}
float DexedAudioProcessor::getParameter(int index) {
return ctrl[index]->getValueHost();
}
void DexedAudioProcessor::setParameter(int index, float newValue) {
ctrl[index]->setValueHost(newValue);
forceRefreshUI = true;
}
int DexedAudioProcessor::getNumPrograms() {
return 32;
}
int DexedAudioProcessor::getCurrentProgram() {
return currentProgram;
}
void DexedAudioProcessor::setCurrentProgram(int index) {
TRACE("setting program %d state", index);
if ( lastStateSave + 2 > time(NULL) ) {
TRACE("skipping save, storage recall to close");
return;
}
panic();
index = index > 31 ? 31 : index;
currentCart.unpackProgram(data, index);
strcpy(controllers.opSwitch, "111111");
lfo.reset(data + 137);
currentProgram = index;
triggerAsyncUpdate();
// reset parameter display
DexedAudioProcessorEditor *editor = (DexedAudioProcessorEditor *) getActiveEditor();
if ( editor == NULL ) {
return;
}
editor->global.setParamMessage("");
panic();
}
const String DexedAudioProcessor::getProgramName(int index) {
if (index >= 32)
index = 31;
return programNames[index];
}
void DexedAudioProcessor::changeProgramName(int index, const String& newName) {
}
const String DexedAudioProcessor::getParameterName(int index) {
return ctrl[index]->label;
}
const String DexedAudioProcessor::getParameterText(int index) {
return ctrl[index]->getValueDisplay();
}
void DexedAudioProcessor::loadPreference() {
File propFile = DexedAudioProcessor::dexedAppDir.getChildFile("Dexed.xml");
PropertiesFile::Options prefOptions;
PropertiesFile prop(propFile, prefOptions);
if ( ! prop.isValidFile() ) {
return;
}
if ( prop.containsKey( String("normalizeDxVelocity") ) ) {
normalizeDxVelocity = prop.getIntValue( String("normalizeDxVelocity") );
}
if ( prop.containsKey( String("pitchRange") ) ) {
controllers.values_[kControllerPitchRange] = prop.getIntValue( String("pitchRange") );
}
if ( prop.containsKey( String("pitchStep") ) ) {
controllers.values_[kControllerPitchStep] = prop.getIntValue( String("pitchStep") );
}
if ( prop.containsKey( String("sysexIn") ) ) {
sysexComm.setInput( prop.getValue("sysexIn") );
}
if ( prop.containsKey( String("sysexOut") ) ) {
sysexComm.setOutput( prop.getValue("sysexOut") );
}
if ( prop.containsKey( String("sysexChl") ) ) {
sysexComm.setChl( prop.getIntValue( String("sysexChl") ) );
}
if ( prop.containsKey( String("engineType") ) ) {
setEngineType(prop.getIntValue(String("engineType")));
}
if ( prop.containsKey( String("showKeyboard") ) ) {
showKeyboard = prop.getIntValue( String("showKeyboard") );
}
if ( prop.containsKey( String("wheelMod") ) ) {
controllers.wheel.parseConfig(prop.getValue(String("wheelMod")).toRawUTF8());
}
if ( prop.containsKey( String("footMod") ) ) {
controllers.foot.parseConfig(prop.getValue(String("footMod")).toRawUTF8());
}
if ( prop.containsKey( String("breathMod") ) ) {
controllers.breath.parseConfig(prop.getValue(String("breathMod")).toRawUTF8());
}
if ( prop.containsKey( String("aftertouchMod") ) ) {
controllers.at.parseConfig(prop.getValue(String("aftertouchMod")).toRawUTF8());
}
}
void DexedAudioProcessor::savePreference() {
File propFile = DexedAudioProcessor::dexedAppDir.getChildFile("Dexed.xml");
PropertiesFile::Options prefOptions;
PropertiesFile prop(propFile, prefOptions);
prop.setValue(String("normalizeDxVelocity"), normalizeDxVelocity);
prop.setValue(String("pitchRange"), controllers.values_[kControllerPitchRange]);
prop.setValue(String("pitchStep"), controllers.values_[kControllerPitchStep]);
prop.setValue(String("sysexIn"), sysexComm.getInput());
prop.setValue(String("sysexOut"), sysexComm.getOutput());
prop.setValue(String("sysexChl"), sysexComm.getChl());
prop.setValue(String("showKeyboard"), showKeyboard);
char mod_cfg[15];
controllers.wheel.setConfig(mod_cfg);
prop.setValue(String("wheelMod"), mod_cfg);
controllers.foot.setConfig(mod_cfg);
prop.setValue(String("footMod"), mod_cfg);
controllers.breath.setConfig(mod_cfg);
prop.setValue(String("breathMod"), mod_cfg);
controllers.at.setConfig(mod_cfg);
prop.setValue(String("aftertouchMod"), mod_cfg);
prop.setValue(String("engineType"), (int) engineType);
prop.save();
}

@ -1,127 +0,0 @@
/**
*
* Copyright (c) 2013 Pascal Gauthier.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef PLUGINPARAM_H_INCLUDED
#define PLUGINPARAM_H_INCLUDED
#include "../JuceLibraryCode/JuceHeader.h"
class DexedAudioProcessor;
class Ctrl : public SliderListener, public ButtonListener, public ComboBoxListener, public MouseListener {
protected:
/**
* Binded components of the UI
*/
Slider *slider;
Button *button;
ComboBox *comboBox;
public:
String label;
Ctrl(String name);
void bind(Slider *s);
void bind(Button *b);
void bind(ComboBox *c);
void unbind();
// use this to signal a parameter change to the host
void publishValue(float value);
/**
* Host value is related 0.0 to 1.0 values
*/
virtual void setValueHost(float f) = 0;
virtual float getValueHost() = 0;
virtual String getValueDisplay() = 0;
virtual void updateComponent() = 0;
void comboBoxChanged (ComboBox* combo);
void sliderValueChanged (Slider* moved);
void buttonClicked (Button* buttonThatWasClicked);
void mouseEnter(const MouseEvent &event);
virtual void updateDisplayName();
/**
* Index of this parameter
*/
int idx;
DexedAudioProcessor *parent;
};
class CtrlFloat : public Ctrl {
float *vPointer;
public:
CtrlFloat(String name, float *storageValue);
void setValueHost(float f);
float getValueHost();
String getValueDisplay();
void updateComponent();
};
// CtrlDX is a controller that is related to DX parameters
class CtrlDX : public Ctrl {
int dxValue;
int steps;
int dxOffset;
int displayValue;
public:
CtrlDX(String name, int steps, int offset = -1, int displayValue = 0);
void setValueHost(float f);
float getValueHost();
void publishValue(float value);
void setValue(int value);
int getValue();
int getOffset();
String getValueDisplay();
void sliderValueChanged (Slider* moved);
void comboBoxChanged (ComboBox* combo);
void buttonClicked (Button* buttonThatWasClicked);
void updateComponent();
void updateDisplayName();
};
struct OperatorCtrl {
ScopedPointer<CtrlDX> egRate[4];
ScopedPointer<CtrlDX> egLevel[4];
ScopedPointer<CtrlDX> level;
ScopedPointer<CtrlDX> opMode;
ScopedPointer<CtrlDX> coarse;
ScopedPointer<CtrlDX> fine;
ScopedPointer<CtrlDX> detune;
ScopedPointer<CtrlDX> sclBrkPt;
ScopedPointer<CtrlDX> sclLeftDepth;
ScopedPointer<CtrlDX> sclRightDepth;
ScopedPointer<CtrlDX> sclLeftCurve;
ScopedPointer<CtrlDX> sclRightCurve;
ScopedPointer<CtrlDX> sclRate;
ScopedPointer<CtrlDX> ampModSens;
ScopedPointer<CtrlDX> velModSens;
ScopedPointer<Ctrl> opSwitch;
};
#endif // PLUGINPARAM_H_INCLUDED

@ -1,616 +0,0 @@
/**
*
* Copyright (c) 2013-2015 Pascal Gauthier.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "PluginProcessor.h"
#include "PluginEditor.h"
#include "Dexed.h"
#include "msfa/synth.h"
#include "msfa/freqlut.h"
#include "msfa/sin.h"
#include "msfa/exp2.h"
#include "msfa/env.h"
#include "msfa/pitchenv.h"
#include "msfa/aligned_buf.h"
#include "msfa/fm_op_kernel.h"
//==============================================================================
DexedAudioProcessor::DexedAudioProcessor() {
#ifdef DEBUG
Logger *tmp = Logger::getCurrentLogger();
if ( tmp == NULL ) {
Logger::setCurrentLogger(FileLogger::createDateStampedLogger("Dexed", "DebugSession-", "log", "DexedAudioProcessor Created"));
}
TRACE("Hi");
#endif
Exp2::init();
Tanh::init();
Sin::init();
lastStateSave = 0;
currentNote = -1;
engineType = -1;
vuSignal = 0;
monoMode = 0;
resolvAppDir();
TRACE("controler %s", controllers.opSwitch);
initCtrl();
sendSysexChange = true;
normalizeDxVelocity = false;
sysexComm.listener = this;
showKeyboard = true;
memset(&voiceStatus, 0, sizeof(VoiceStatus));
setEngineType(DEXED_ENGINE_MARKI);
controllers.values_[kControllerPitchRange] = 3;
controllers.values_[kControllerPitchStep] = 0;
controllers.masterTune = 0;
loadPreference();
for (int note = 0; note < MAX_ACTIVE_NOTES; ++note) {
voices[note].dx7_note = NULL;
}
setCurrentProgram(0);
nextMidi = NULL;
midiMsg = NULL;
clipboardContent = -1;
}
DexedAudioProcessor::~DexedAudioProcessor() {
TRACE("Bye");
}
//==============================================================================
void DexedAudioProcessor::prepareToPlay(double sampleRate, int samplesPerBlock) {
Freqlut::init(sampleRate);
Lfo::init(sampleRate);
PitchEnv::init(sampleRate);
Env::init_sr(sampleRate);
fx.init(sampleRate);
for (int note = 0; note < MAX_ACTIVE_NOTES; ++note) {
voices[note].dx7_note = new Dx7Note;
voices[note].keydown = false;
voices[note].sustained = false;
voices[note].live = false;
}
currentNote = 0;
controllers.values_[kControllerPitch] = 0x2000;
controllers.modwheel_cc = 0;
controllers.foot_cc = 0;
controllers.breath_cc = 0;
controllers.aftertouch_cc = 0;
sustain = false;
extra_buf_size = 0;
keyboardState.reset();
lfo.reset(data + 137);
nextMidi = new MidiMessage(0xF0);
midiMsg = new MidiMessage(0xF0);
}
void DexedAudioProcessor::releaseResources() {
currentNote = -1;
for (int note = 0; note < MAX_ACTIVE_NOTES; ++note) {
if ( voices[note].dx7_note != NULL ) {
delete voices[note].dx7_note;
voices[note].dx7_note = NULL;
}
voices[note].keydown = false;
voices[note].sustained = false;
voices[note].live = false;
}
keyboardState.reset();
if ( nextMidi != NULL ) {
delete nextMidi;
nextMidi = NULL;
}
if ( midiMsg != NULL ) {
delete midiMsg;
midiMsg = NULL;
}
}
void DexedAudioProcessor::processBlock(AudioSampleBuffer& buffer, MidiBuffer& midiMessages) {
int numSamples = buffer.getNumSamples();
int i;
if ( refreshVoice ) {
for(i=0;i < MAX_ACTIVE_NOTES;i++) {
if ( voices[i].live )
voices[i].dx7_note->update(data, voices[i].midi_note, feedback_bitdepth);
}
lfo.reset(data + 137);
refreshVoice = false;
}
keyboardState.processNextMidiBuffer(midiMessages, 0, numSamples, true);
MidiBuffer::Iterator it(midiMessages);
hasMidiMessage = it.getNextEvent(*nextMidi,midiEventPos);
float *channelData = buffer.getWritePointer(0);
// flush first events
for (i=0; i < numSamples && i < extra_buf_size; i++) {
channelData[i] = extra_buf[i];
}
// remaining buffer is still to be processed
if (extra_buf_size > numSamples) {
for (int j = 0; j < extra_buf_size - numSamples; j++) {
extra_buf[j] = extra_buf[j + numSamples];
}
extra_buf_size -= numSamples;
// flush the events, they will be process in the next cycle
while(getNextEvent(&it, numSamples)) {
processMidiMessage(midiMsg);
}
} else {
for (; i < numSamples; i += N) {
AlignedBuf<int32_t, N> audiobuf;
float sumbuf[N];
while(getNextEvent(&it, i)) {
processMidiMessage(midiMsg);
}
for (int j = 0; j < N; ++j) {
audiobuf.get()[j] = 0;
sumbuf[j] = 0;
}
int32_t lfovalue = lfo.getsample();
int32_t lfodelay = lfo.getdelay();
for (int note = 0; note < MAX_ACTIVE_NOTES; ++note) {
if (voices[note].live) {
voices[note].dx7_note->compute(audiobuf.get(), lfovalue, lfodelay, &controllers);
for (int j=0; j < N; ++j) {
int32_t val = audiobuf.get()[j];
val = val >> 4;
int clip_val = val < -(1 << 24) ? 0x8000 : val >= (1 << 24) ? 0x7fff : val >> 9;
float f = ((float) clip_val) / (float) 0x8000;
if( f > 1 ) f = 1;
if( f < -1 ) f = -1;
sumbuf[j] += f;
audiobuf.get()[j] = 0;
}
}
}
int jmax = numSamples - i;
for (int j = 0; j < N; ++j) {
if (j < jmax) {
channelData[i + j] = sumbuf[j];
} else {
extra_buf[j - jmax] = sumbuf[j];
}
}
}
extra_buf_size = i - numSamples;
}
while(getNextEvent(&it, numSamples)) {
processMidiMessage(midiMsg);
}
fx.process(channelData, numSamples);
for(i=0; i<numSamples; i++) {
float s = std::abs(channelData[i]);
const double decayFactor = 0.99992;
if (s > vuSignal)
vuSignal = s;
else if (vuSignal > 0.001f)
vuSignal *= decayFactor;
else
vuSignal = 0;
}
// DX7 is a mono synth
buffer.copyFrom(1, 0, channelData, numSamples, 1);
}
//==============================================================================
// This creates new instances of the plugin..
AudioProcessor* JUCE_CALLTYPE createPluginFilter() {
return new DexedAudioProcessor();
}
bool DexedAudioProcessor::getNextEvent(MidiBuffer::Iterator* iter,const int samplePos) {
if (hasMidiMessage && midiEventPos <= samplePos) {
*midiMsg = *nextMidi;
hasMidiMessage = iter->getNextEvent(*nextMidi, midiEventPos);
return true;
}
return false;
}
void DexedAudioProcessor::processMidiMessage(const MidiMessage *msg) {
const uint8 *buf = msg->getRawData();
uint8_t cmd = buf[0];
switch(cmd & 0xf0) {
case 0x80 :
keyup(buf[1]);
return;
case 0x90 :
keydown(buf[1], buf[2]);
return;
case 0xb0 : {
int ctrl = buf[1];
int value = buf[2];
switch(ctrl) {
case 1:
controllers.modwheel_cc = value;
controllers.refresh();
break;
case 2:
controllers.breath_cc = value;
controllers.refresh();
break;
case 4:
controllers.foot_cc = value;
controllers.refresh();
break;
case 64:
sustain = value > 63;
if (!sustain) {
for (int note = 0; note < MAX_ACTIVE_NOTES; note++) {
if (voices[note].sustained && !voices[note].keydown) {
voices[note].dx7_note->keyup();
voices[note].sustained = false;
}
}
}
break;
}
}
return;
case 0xc0 :
setCurrentProgram(buf[1]);
return;
// aftertouch
case 0xd0 :
controllers.aftertouch_cc = buf[1];
controllers.refresh();
return;
}
switch (cmd) {
case 0xe0 :
controllers.values_[kControllerPitch] = buf[1] | (buf[2] << 7);
break;
}
}
void DexedAudioProcessor::keydown(uint8_t pitch, uint8_t velo) {
if ( velo == 0 ) {
keyup(pitch);
return;
}
pitch += data[144] - 24;
if ( normalizeDxVelocity ) {
velo = ((float)velo) * 0.7874015; // 100/127
}
int note = currentNote;
for (int i=0; i<MAX_ACTIVE_NOTES; i++) {
if (!voices[note].keydown) {
currentNote = (note + 1) % MAX_ACTIVE_NOTES;
lfo.keydown(); // TODO: should only do this if # keys down was 0
voices[note].midi_note = pitch;
voices[note].sustained = sustain;
voices[note].keydown = true;
voices[note].dx7_note->init(data, pitch, velo, feedback_bitdepth);
if ( data[136] )
voices[note].dx7_note->oscSync();
break;
}
note = (note + 1) % MAX_ACTIVE_NOTES;
}
if ( monoMode ) {
for(int i=0; i<MAX_ACTIVE_NOTES; i++) {
if ( voices[i].live ) {
// all keys are up, only transfert signal
if ( ! voices[i].keydown ) {
voices[i].live = false;
voices[note].dx7_note->transferSignal(*voices[i].dx7_note);
break;
}
if ( voices[i].midi_note < pitch ) {
voices[i].live = false;
voices[note].dx7_note->transferState(*voices[i].dx7_note);
break;
}
return;
}
}
}
voices[note].live = true;
}
void DexedAudioProcessor::keyup(uint8_t pitch) {
pitch += data[144] - 24;
int note;
for (note=0; note<MAX_ACTIVE_NOTES; ++note) {
if ( voices[note].midi_note == pitch && voices[note].keydown ) {
voices[note].keydown = false;
break;
}
}
// note not found ?
if ( note >= MAX_ACTIVE_NOTES ) {
TRACE("note-off not found???");
return;
}
if ( monoMode ) {
int highNote = -1;
int target = 0;
for (int i=0; i<MAX_ACTIVE_NOTES;i++) {
if ( voices[i].keydown && voices[i].midi_note > highNote ) {
target = i;
highNote = voices[i].midi_note;
}
}
if ( highNote != -1 ) {
voices[note].live = false;
voices[target].live = true;
voices[target].dx7_note->transferState(*voices[note].dx7_note);
}
}
if ( sustain ) {
voices[note].sustained = true;
} else {
voices[note].dx7_note->keyup();
}
}
void DexedAudioProcessor::panic() {
for(int i=0;i<MAX_ACTIVE_NOTES;i++) {
voices[i].keydown = false;
voices[i].live = false;
if ( voices[i].dx7_note != NULL ) {
voices[i].dx7_note->oscSync();
}
}
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;
}
updateProgramFromSysex(buf+6);
}
// 32 voice dump
if ( buf[3] == 9 ) {
Cartridge received;
if ( received.load(buf, sz) ) {
loadCartridge(received);
setCurrentProgram(0);
}
}
updateHostDisplay();
forceRefreshUI = true;
}
int DexedAudioProcessor::getEngineType() {
return engineType;
}
void DexedAudioProcessor::setEngineType(int tp) {
TRACE("settings engine %d", tp);
switch (tp) {
case DEXED_ENGINE_MARKI:
controllers.core = &engineMkI;
feedback_bitdepth = 11;
break;
case DEXED_ENGINE_OPL:
controllers.core = &engineOpl;
feedback_bitdepth = 11;
break;
default:
controllers.core = &engineMsfa;
feedback_bitdepth = 8;
break;
}
engineType = tp;
}
void DexedAudioProcessor::setMonoMode(bool mode) {
panic();
monoMode = mode;
}
// ====================================================================
bool DexedAudioProcessor::peekVoiceStatus() {
if ( currentNote == -1 )
return false;
// we are trying to find the last "keydown" note
int note = currentNote;
for (int i = 0; i < MAX_ACTIVE_NOTES; i++) {
if (voices[note].keydown) {
voices[note].dx7_note->peekVoiceStatus(voiceStatus);
return true;
}
if ( --note < 0 )
note = MAX_ACTIVE_NOTES-1;
}
// not found; try a live note
note = currentNote;
for (int i = 0; i < MAX_ACTIVE_NOTES; i++) {
if (voices[note].live) {
voices[note].dx7_note->peekVoiceStatus(voiceStatus);
return true;
}
if ( --note < 0 )
note = MAX_ACTIVE_NOTES-1;
}
return true;
}
const String DexedAudioProcessor::getInputChannelName (int channelIndex) const {
return String (channelIndex + 1);
}
const String DexedAudioProcessor::getOutputChannelName (int channelIndex) const {
return String (channelIndex + 1);
}
bool DexedAudioProcessor::isInputChannelStereoPair (int index) const {
return true;
}
bool DexedAudioProcessor::isOutputChannelStereoPair (int index) const {
return true;
}
bool DexedAudioProcessor::acceptsMidi() const {
#if JucePlugin_WantsMidiInput
return true;
#else
return false;
#endif
}
bool DexedAudioProcessor::producesMidi() const {
#if JucePlugin_ProducesMidiOutput
return true;
#else
return false;
#endif
}
bool DexedAudioProcessor::silenceInProducesSilenceOut() const {
return false;
}
double DexedAudioProcessor::getTailLengthSeconds() const {
return 0.0;
}
const String DexedAudioProcessor::getName() const {
return JucePlugin_Name;
}
//==============================================================================
bool DexedAudioProcessor::hasEditor() const {
return true; // (change this to false if you choose to not supply an editor)
}
void DexedAudioProcessor::updateUI() {
// notify host something has changed
updateHostDisplay();
AudioProcessorEditor *editor = getActiveEditor();
if ( editor == NULL ) {
return;
}
DexedAudioProcessorEditor *dexedEditor = (DexedAudioProcessorEditor *) editor;
dexedEditor->updateUI();
}
AudioProcessorEditor* DexedAudioProcessor::createEditor() {
return new DexedAudioProcessorEditor (this);
}
void DexedAudioProcessor::handleAsyncUpdate() {
updateUI();
}
void dexed_trace(const char *source, const char *fmt, ...) {
char output[4096];
va_list argptr;
va_start(argptr, fmt);
vsnprintf(output, 4095, fmt, argptr);
va_end(argptr);
String dest;
dest << source << " " << output;
Logger::writeToLog(dest);
}

@ -1,235 +0,0 @@
/**
*
* Copyright (c) 2013-2015 Pascal Gauthier.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef PLUGINPROCESSOR_H_INCLUDED
#define PLUGINPROCESSOR_H_INCLUDED
#include "msfa/controllers.h"
#include "msfa/dx7note.h"
#include "msfa/lfo.h"
#include "msfa/synth.h"
#include "msfa/fm_core.h"
#include "PluginFx.h"
//#include "SysexComm.h"
#include "EngineMkI.h"
#include "EngineOpl.h"
struct ProcessorVoice {
int midi_note;
bool keydown;
bool sustained;
bool live;
Dx7Note *dx7_note;
};
enum DexedEngineResolution {
DEXED_ENGINE_MODERN,
DEXED_ENGINE_MARKI,
DEXED_ENGINE_OPL
};
//==============================================================================
/**
*/
class DexedAudioProcessor : public AudioProcessor, public AsyncUpdater, public MidiInputCallback
{
static const int MAX_ACTIVE_NOTES = 16;
ProcessorVoice voices[MAX_ACTIVE_NOTES];
int currentNote;
// The original DX7 had one single LFO. Later units had an LFO per note.
Lfo lfo;
bool sustain;
bool monoMode;
// Extra buffering for when GetSamples wants a buffer not a multiple of N
float extra_buf[N];
int extra_buf_size;
int currentProgram;
/**
* The last time the state was save, to be able to bypass a VST host bug.
*/
long lastStateSave;
/**
* Plugin fx (the filter)
*/
PluginFx fx;
/**
* This flag is used in the audio thread to know if the voice has changed
* and needs to be updated.
*/
bool refreshVoice;
bool normalizeDxVelocity;
bool sendSysexChange;
void processMidiMessage(const MidiMessage *msg);
void keydown(uint8_t pitch, uint8_t velo);
void keyup(uint8_t pitch);
/**
* this is called from the Audio thread to tell
* to update the UI / hostdata
*/
void handleAsyncUpdate();
void initCtrl();
MidiMessage* nextMidi,*midiMsg;
bool hasMidiMessage;
int midiEventPos;
bool getNextEvent(MidiBuffer::Iterator* iter,const int samplePos);
void handleIncomingMidiMessage(MidiInput* source, const MidiMessage& message);
uint32_t engineType;
FmCore engineMsfa;
EngineMkI engineMkI;
EngineOpl engineOpl;
char clipboard[161];
char clipboardContent;
void resolvAppDir();
int feedback_bitdepth;
public :
// in MIDI units (0x4000 is neutral)
Controllers controllers;
StringArray programNames;
Cartridge currentCart;
uint8_t data[161];
SysexComm sysexComm;
VoiceStatus voiceStatus;
File activeFileCartridge;
bool forceRefreshUI;
float vuSignal;
bool showKeyboard;
int getEngineType();
void setEngineType(int rs);
Array<Ctrl*> ctrl;
OperatorCtrl opCtrl[6];
ScopedPointer<CtrlDX> pitchEgRate[4];
ScopedPointer<CtrlDX> pitchEgLevel[4];
ScopedPointer<CtrlDX> pitchModSens;
ScopedPointer<CtrlDX> algo;
ScopedPointer<CtrlDX> oscSync;
ScopedPointer<CtrlDX> feedback;
ScopedPointer<CtrlDX> lfoRate;
ScopedPointer<CtrlDX> lfoDelay;
ScopedPointer<CtrlDX> lfoAmpDepth;
ScopedPointer<CtrlDX> lfoPitchDepth;
ScopedPointer<CtrlDX> lfoWaveform;
ScopedPointer<CtrlDX> lfoSync;
ScopedPointer<CtrlDX> transpose;
ScopedPointer<CtrlFloat> fxCutoff;
ScopedPointer<CtrlFloat> fxReso;
ScopedPointer<CtrlFloat> output;
ScopedPointer<Ctrl> tune;
void loadCartridge(Cartridge &cart);
void setDxValue(int offset, int v);
//==============================================================================
DexedAudioProcessor();
~DexedAudioProcessor();
//==============================================================================
void prepareToPlay (double sampleRate, int samplesPerBlock);
void releaseResources();
void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages);
void panic();
bool isMonoMode() {
return monoMode;
}
void setMonoMode(bool mode);
void copyToClipboard(int srcOp);
void pasteOpFromClipboard(int destOp);
void pasteEnvFromClipboard(int destOp);
void sendCurrentSysexProgram();
void sendCurrentSysexCartridge();
void sendSysexCartridge(File cart);
bool hasClipboardContent();
//==============================================================================
AudioProcessorEditor* createEditor();
bool hasEditor() const;
void updateUI();
bool peekVoiceStatus();
void updateProgramFromSysex(const uint8 *rawdata);
void setupStartupCart();
//==============================================================================
const String getName() const;
int getNumParameters();
float getParameter (int index);
void setParameter (int index, float newValue);
const String getParameterName (int index);
const String getParameterText (int index);
const String getInputChannelName (int channelIndex) const;
const String getOutputChannelName (int channelIndex) const;
bool isInputChannelStereoPair (int index) const;
bool isOutputChannelStereoPair (int index) const;
bool acceptsMidi() const;
bool producesMidi() const;
bool silenceInProducesSilenceOut() const;
double getTailLengthSeconds() const;
//==============================================================================
int getNumPrograms();
int getCurrentProgram();
void setCurrentProgram(int index);
const String getProgramName (int index);
void changeProgramName(int index, const String& newName);
void resetToInitVoice();
//==============================================================================
void getStateInformation (MemoryBlock& destData);
void setStateInformation (const void* data, int sizeInBytes);
// this is kept up to date with the midi messages that arrive, and the UI component
// registers with it so it can represent the incoming messages
MidiKeyboardState keyboardState;
void unbindUI();
void loadPreference();
void savePreference();
static File dexedAppDir;
static File dexedCartDir;
private:
//==============================================================================
DexedAudioProcessor;
};
#endif // PLUGINPROCESSOR_H_INCLUDED

@ -1,203 +0,0 @@
/**
*
* Copyright (c) 2015 Pascal Gauthier.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "ProgramListBox.h"
#include "PluginData.h"
#include "DXLookNFeel.h"
#include "Dexed.h"
ProgramListBox::ProgramListBox(const String name, int numCols) : Component(name) {
cols = numCols;
rows = 32 / numCols;
selectedPgm = -1;
hasContent = false;
dragCandidate = -1;
pgmCandidate = -1;
readOnly = false;
programNames.clear();
}
void ProgramListBox::paint(Graphics &g) {
int pgm = 0;
g.setColour(Colour(20,18,18));
g.fillRect(0,0,getWidth(), getHeight());
g.setColour(Colour(0,0,0));
g.drawLine(0,0,getWidth(), 0, 2);
g.setColour(Colour(3,3,1));
g.drawLine(0,0,0,getHeight(),2);
g.setColour(Colour(34,32,32));
g.drawLine(getWidth(), 3, getWidth(), getHeight(), 2);
g.setColour(Colour(75,73,73));
g.drawLine(0,getHeight(),getWidth(),getHeight(), 2);
const float dashLength[] = { 4, 4 };
g.setColour(Colour(83,76,69));
for(int i=1;i<cols;i++) {
Line<float> line(cellWidth*i,0,cellWidth*i,getHeight());
g.drawDashedLine(line, dashLength, 2);
}
for(int i=1;i<rows;i++) {
Line<float> line(2, cellHeight*i,getWidth(),cellHeight*i);
g.drawDashedLine(line, dashLength, 2);
}
for(int i=0;i<cols;i++) {
for(int j=0;j<rows;j++) {
if ( selectedPgm == pgm && dragCandidate == -1 ) {
g.setColour(DXLookNFeel::fillColour);
g.fillRoundedRectangle(cellWidth*i+2, cellHeight*j + 2, cellWidth - 4, cellHeight - 4, 0);
}
if ( hasContent == true ) {
if ( dragCandidate != pgm ) {
g.setColour(Colours::white);
g.drawFittedText(programNames[pgm], cellWidth * i , cellHeight * j, cellWidth, cellHeight, Justification::centred, true);
} else {
g.setColour(DXLookNFeel::fillColour);
g.fillRoundedRectangle(cellWidth*i+2, cellHeight*j + 2, cellWidth - 4, cellHeight - 4, 0);
}
}
pgm++;
}
}
}
void ProgramListBox::resized() {
cellWidth = getWidth() / cols;
cellHeight = getHeight() / rows;
}
void ProgramListBox::setCartridge(Cartridge &cart) {
cartContent = cart;
cartContent.getProgramNames(programNames);
hasContent = true;
repaint();
}
void ProgramListBox::addListener(ProgramListBoxListener *listener) {
this->listener = listener;
}
int ProgramListBox::programPosition(int x, int y) {
return (y / cellHeight) + ((x / cellWidth) * rows);
}
void ProgramListBox::mouseDown(const MouseEvent &event) {
pgmCandidate = -1;
if ( ! hasContent )
return;
if ( event.mods.isRightButtonDown() ) {
int pos = programPosition(event.getMouseDownX(), event.getMouseDownY());
if ( listener != nullptr )
listener->programRightClicked(this, pos);
return;
}
pgmCandidate = programPosition(event.getMouseDownX(), event.getMouseDownY());
}
void ProgramListBox::mouseUp(const MouseEvent &event) {
if ( pgmCandidate == -1 )
return;
int pos = programPosition(event.getMouseDownX(), event.getMouseDownY());
if ( pgmCandidate == pos) {
if ( listener != nullptr )
listener->programSelected(this, pgmCandidate);
pgmCandidate = -1;
}
}
void ProgramListBox::mouseDrag(const MouseEvent &event) {
pgmCandidate = -1;
if ( ! hasContent )
return;
if ( dragCandidate != -1 )
return;
if ( event.getDistanceFromDragStart() < 7 )
return;
if (DragAndDropContainer* const dragContainer = DragAndDropContainer::findParentDragContainerFor(this)) {
Image snapshot (Image::ARGB, cellWidth, cellHeight, true);
int position = programPosition(event.getMouseDownX(), event.getMouseDownY());
Graphics g(snapshot);
g.setColour(DXLookNFeel::lightBackground);
g.fillRect(0,0,cellWidth, cellHeight);
g.setColour(Colours::white);
g.drawFittedText(programNames[position], 0, 0, cellWidth, cellHeight, Justification::centred, true);
void *src = cartContent.getRawVoice() + (position*128);
var description = var(src, 128);
dragContainer->startDragging(description, this, snapshot, false);
}
}
void ProgramListBox::setSelected(int idx) {
selectedPgm = idx;
}
Cartridge &ProgramListBox::getCurrentCart() {
return cartContent;
}
bool ProgramListBox::isInterestedInDragSource (const SourceDetails& dragSourceDetail) {
if ( readOnly )
return false;
if ( ! hasContent )
return false;
Component *comp = dragSourceDetail.sourceComponent.get();
if ( comp == nullptr )
return false;
if ( dynamic_cast<ProgramListBox*>(comp) == nullptr )
return false;
return true;
}
void ProgramListBox::itemDropped(const SourceDetails& dragSourceDetails) {
dragCandidate = programPosition(dragSourceDetails.localPosition.x, dragSourceDetails.localPosition.y);
MemoryBlock* block = dragSourceDetails.description.getBinaryData();
if ( listener != nullptr )
listener->programDragged(this, dragCandidate, (char *)block->getData());
dragCandidate = -1;
repaint();
}
void ProgramListBox::itemDragEnter(const SourceDetails &dragSourceDetails) {
dragCandidate = programPosition(dragSourceDetails.localPosition.x, dragSourceDetails.localPosition.y);
repaint();
}
void ProgramListBox::itemDragMove(const SourceDetails &dragSourceDetails) {
dragCandidate = programPosition(dragSourceDetails.localPosition.x, dragSourceDetails.localPosition.y);
repaint();
}
void ProgramListBox::itemDragExit(const SourceDetails &dragSourceDetails) {
dragCandidate = -1;
repaint();
}

@ -1,74 +0,0 @@
/**
*
* Copyright (c) 2015 Pascal Gauthier.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef PROGRAMLISTBOX_H_INCLUDED
#define PROGRAMLISTBOX_H_INCLUDED
#include "JuceHeader.h"
#include "PluginData.h"
class ProgramListBox;
class ProgramListBoxListener {
public:
virtual ~ProgramListBoxListener() {}
virtual void programSelected(ProgramListBox *source, int pos) = 0;
virtual void programRightClicked(ProgramListBox *source, int pos) = 0;
virtual void programDragged(ProgramListBox *destListBox, int dest, char *packedPgm) = 0;
};
class ProgramListBox : public Component, public DragAndDropTarget {
ProgramListBoxListener *listener;
bool hasContent;
bool showPgmNumber;
int cols, rows;
int cellWidth, cellHeight;
int programPosition(int x, int y);
int selectedPgm;
Cartridge cartContent;
int dragCandidate;
int pgmCandidate;
public:
StringArray programNames;
bool readOnly;
ProgramListBox(const String name, int numCols);
void addListener(ProgramListBoxListener *listener);
void paint(Graphics &g) override;
void resized() override;
void mouseDown(const MouseEvent &event) override;
void mouseDrag(const MouseEvent &event) override;
void mouseUp(const MouseEvent &event) override;
void setSelected(int idx);
Cartridge &getCurrentCart();
void setCartridge(Cartridge &cart);
bool isInterestedInDragSource(const SourceDetails& dragSourceDetails) override;
void itemDragEnter(const SourceDetails &dragSourceDetails) override;
void itemDragMove(const SourceDetails &dragSourceDetails) override;
void itemDragExit(const SourceDetails &dragSourceDetails) override;
void itemDropped(const SourceDetails& dragSourceDetails) override;
};
#endif // PROGRAMLISTBOX_H_INCLUDED

@ -1,155 +0,0 @@
/**
*
* Copyright (c) 2014 Pascal Gauthier.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "SysexComm.h"
#include "Dexed.h"
SysexComm::SysexComm() {
sysexChl = 0;
listener = NULL; // this will get injected later
inputName = "";
outputName = "";
input = NULL;
output = NULL;
inputOutput = false;
}
SysexComm::~SysexComm() {
if ( input != NULL ) {
input->stop();
delete input;
}
if ( output != NULL )
delete output;
}
String SysexComm::getInput() {
return inputName;
}
bool SysexComm::setInput(String target) {
if ( input != NULL ) {
input->stop();
delete input;
input = NULL;
}
inputOutput = false;
if ( listener == NULL )
return true;
StringArray devices = MidiInput::getDevices();
int idx = devices.indexOf(target);
if ( idx == -1 ) {
TRACE("device %s not found", target.toRawUTF8());
inputName = "";
if ( target == "None" || target == "" )
return true;
return false;
}
input = MidiInput::openDevice(idx, listener);
if ( input == NULL ) {
TRACE("unable to open %s", target.toRawUTF8());
return false;
}
inputName = target;
TRACE("sysex %s opened", target.toRawUTF8());
input->start();
if ( output )
inputOutput = true;
return true;
}
String SysexComm::getOutput() {
return outputName;
}
bool SysexComm::setOutput(String target) {
if ( output != NULL ) {
delete output;
output = NULL;
}
inputOutput = false;
StringArray devices = MidiOutput::getDevices();
int idx = devices.indexOf(target);
if ( idx == -1 ) {
TRACE("device %s not found", target.toRawUTF8());
outputName = "";
if ( target == "None" || target == "" )
return true;
return false;
}
output = MidiOutput::openDevice(idx);
if ( output == NULL ) {
TRACE("unable to open %s", target.toRawUTF8());
return false;
}
outputName = target;
if ( input )
inputOutput = true;
TRACE("sysex %s opened", target.toRawUTF8());
return true;
}
bool SysexComm::isInputActive() {
return input != NULL;
}
bool SysexComm::isOutputActive() {
return output != NULL;
}
int SysexComm::getChl() {
return sysexChl;
}
void SysexComm::setChl(int chl) {
sysexChl = chl;
}
int SysexComm::send(const MidiMessage &message) {
if ( output == NULL )
return 2;
TRACE("send sysex");
outActivity = true;
output->sendMessageNow(message);
return 0;
}
void SysexComm::playBuffer(MidiBuffer &keyboardEvents, int numSamples ) {
noteOutput.addEvents(keyboardEvents, 0, numSamples, 0);
}

@ -1,60 +0,0 @@
/**
*
* Copyright (c) 2014 Pascal Gauthier.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifndef SYSEXCOMM_H_INCLUDED
#define SYSEXCOMM_H_INCLUDED
class SysexComm {
MidiInput *input;
MidiOutput *output;
String inputName;
String outputName;
int sysexChl;
bool inputOutput;
MidiBuffer noteOutput;
public :
MidiInputCallback *listener;
bool inActivity;
bool outActivity;
SysexComm();
~SysexComm();
bool setInput(String name);
bool setOutput(String name);
void setChl(int chl);
String getInput();
String getOutput();
int getChl();
bool isInputActive();
bool isOutputActive();
inline bool isInputOutputActive() {
return inputOutput;
}
int send(const MidiMessage& message);
void playBuffer(MidiBuffer &keyboardEvents, int numSamples);
};
#endif // SYSEXCOMM_H_INCLUDED

@ -1,76 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <time.h>
#include <string.h>
#include "synth.h"
#include "ringbuffer.h"
RingBuffer::RingBuffer() {
rd_ix_ = 0;
wr_ix_ = 0;
}
int RingBuffer::BytesAvailable() {
return (wr_ix_ - rd_ix_) & (kBufSize - 1);
}
int RingBuffer::WriteBytesAvailable() {
return (rd_ix_ - wr_ix_ - 1) & (kBufSize - 1);
}
int RingBuffer::Read(int size, uint8_t *bytes) {
int rd_ix = rd_ix_;
SynthMemoryBarrier(); // read barrier, make sure data is committed before ix
int fragment_size = min(size, kBufSize - rd_ix);
memcpy(bytes, buf_ + rd_ix, fragment_size);
if (size > fragment_size) {
memcpy(bytes + fragment_size, buf_, size - fragment_size);
}
SynthMemoryBarrier(); // full barrier, make sure read commits before updating
rd_ix_ = (rd_ix + size) & (kBufSize - 1);
return size;
}
int RingBuffer::Write(const uint8_t *bytes, int size) {
int remaining = size;
while (remaining > 0) {
int rd_ix = rd_ix_;
int wr_ix = wr_ix_;
int space_available = (rd_ix - wr_ix - 1) & (kBufSize - 1);
if (space_available == 0) {
struct timespec sleepTime;
sleepTime.tv_sec = 0;
sleepTime.tv_nsec = 1000000;
nanosleep(&sleepTime, NULL);
} else {
int wr_size = min(remaining, space_available);
int fragment_size = min(wr_size, kBufSize - wr_ix);
memcpy(buf_ + wr_ix, bytes, fragment_size);
if (wr_size > fragment_size) {
memcpy(buf_, bytes + fragment_size, wr_size - fragment_size);
}
SynthMemoryBarrier(); // write barrier, make sure data commits
wr_ix_ = (wr_ix + wr_size) & (kBufSize - 1);
remaining -= wr_size;
bytes += wr_size;
}
}
// JJK : defined as returning int
return 0;
}

@ -1,44 +0,0 @@
/*
* Copyright 2012 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SYNTH_RINGBUFFER_H_
#define SYNTH_RINGBUFFER_H_
class RingBuffer {
public:
RingBuffer();
// Returns number of bytes available for reading.
int BytesAvailable();
// Returns number of bytes that can be written without blocking.
int WriteBytesAvailable();
// Reads bytes. It is the caller's responsibility to make sure that
// size <= a previous value of BytesAvailable().
int Read(int size, uint8_t *bytes);
// Writes bytes into the buffer. If the buffer is full, the method will
// block until space is available.
int Write(const uint8_t *bytes, int size);
private:
static const int kBufSize = 8192;
uint8_t buf_[kBufSize];
volatile unsigned int rd_ix_;
volatile unsigned int wr_ix_;
};
#endif // SYNTH_RINGBUFFER_H_
Loading…
Cancel
Save