Pitch bend range + display env

pull/1/head
asb2m10 11 years ago
parent fec88d7287
commit 06c3d842a3
  1. 6
      Builds/MacOSX/Dexed.xcodeproj/project.pbxproj
  2. BIN
      Builds/MacOSX/Dexed.xcodeproj/project.xcworkspace/xcuserdata/asb2m10.xcuserdatad/UserInterfaceState.xcuserstate
  3. 2
      Builds/VisualStudio2012/Dexed.vcxproj
  4. 6
      Builds/VisualStudio2012/Dexed.vcxproj.filters
  5. 2
      Builds/VisualStudio2013/Dexed.vcxproj
  6. 6
      Builds/VisualStudio2013/Dexed.vcxproj.filters
  7. 2
      Dexed.jucer
  8. 223
      Source/DXComponents.cpp
  9. 2
      Source/DXLookNFeel.cpp
  10. 172
      Source/ParamDialog.cpp
  11. 75
      Source/ParamDialog.h
  12. 20
      Source/PluginEditor.cpp
  13. 12
      Source/PluginParam.cpp
  14. 13
      Source/PluginProcessor.cpp
  15. 4
      Source/PluginProcessor.h
  16. 6
      Source/msfa/controllers.h
  17. 14
      Source/msfa/dx7note.cc

@ -31,6 +31,7 @@
0D3132A8B412AE9E63024927 = {isa = PBXBuildFile; fileRef = B0230FCCA099E6430411DFC9; }; 0D3132A8B412AE9E63024927 = {isa = PBXBuildFile; fileRef = B0230FCCA099E6430411DFC9; };
478699B4EF80A1A1C0D34C10 = {isa = PBXBuildFile; fileRef = 018D0FB9E97B68D2EB3E3F72; }; 478699B4EF80A1A1C0D34C10 = {isa = PBXBuildFile; fileRef = 018D0FB9E97B68D2EB3E3F72; };
C510246D7D5E162C9DE63DDE = {isa = PBXBuildFile; fileRef = 19CEF599CB23958AC63D427E; }; C510246D7D5E162C9DE63DDE = {isa = PBXBuildFile; fileRef = 19CEF599CB23958AC63D427E; };
CD1CF0C6B4AB9F4C8175FE08 = {isa = PBXBuildFile; fileRef = F221CF21582EE0B8FE774583; };
082D6FF34EFF195C3A3B0CFB = {isa = PBXBuildFile; fileRef = 838E63F5800CA577B92EF6AE; }; 082D6FF34EFF195C3A3B0CFB = {isa = PBXBuildFile; fileRef = 838E63F5800CA577B92EF6AE; };
D5A4D43A16EA4C71D53E96CD = {isa = PBXBuildFile; fileRef = A02775EA788AD4BF7DD1B1A1; }; D5A4D43A16EA4C71D53E96CD = {isa = PBXBuildFile; fileRef = A02775EA788AD4BF7DD1B1A1; };
8121E10419E2D99645EA254E = {isa = PBXBuildFile; fileRef = D984CE634945077E682B48F3; }; 8121E10419E2D99645EA254E = {isa = PBXBuildFile; fileRef = D984CE634945077E682B48F3; };
@ -543,6 +544,7 @@
99D8CB814600E509F918CFC5 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_DrawableButton.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/buttons/juce_DrawableButton.h"; sourceTree = "SOURCE_ROOT"; }; 99D8CB814600E509F918CFC5 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_DrawableButton.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/buttons/juce_DrawableButton.h"; sourceTree = "SOURCE_ROOT"; };
99FFA4AC86A982F68CE03ED3 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Uuid.cpp"; path = "../../JuceLibraryCode/modules/juce_core/misc/juce_Uuid.cpp"; sourceTree = "SOURCE_ROOT"; }; 99FFA4AC86A982F68CE03ED3 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Uuid.cpp"; path = "../../JuceLibraryCode/modules/juce_core/misc/juce_Uuid.cpp"; sourceTree = "SOURCE_ROOT"; };
9A68431EDA5B8D2023A10A02 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Viewport.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_Viewport.h"; sourceTree = "SOURCE_ROOT"; }; 9A68431EDA5B8D2023A10A02 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Viewport.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/layout/juce_Viewport.h"; sourceTree = "SOURCE_ROOT"; };
9AAC5E6C1A21F8FE2F66F0E0 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ParamDialog.h; path = ../../Source/ParamDialog.h; sourceTree = "SOURCE_ROOT"; };
9ADD55269807C198F51001F4 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_audio_utils.h"; path = "../../../JUCE/modules/juce_audio_utils/juce_audio_utils.h"; sourceTree = "SOURCE_ROOT"; }; 9ADD55269807C198F51001F4 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_audio_utils.h"; path = "../../../JUCE/modules/juce_audio_utils/juce_audio_utils.h"; sourceTree = "SOURCE_ROOT"; };
9B103127E2063BAFD4A4FD33 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Thread.h"; path = "../../JuceLibraryCode/modules/juce_core/threads/juce_Thread.h"; sourceTree = "SOURCE_ROOT"; }; 9B103127E2063BAFD4A4FD33 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Thread.h"; path = "../../JuceLibraryCode/modules/juce_core/threads/juce_Thread.h"; sourceTree = "SOURCE_ROOT"; };
9B36F7CC7A136C2AEB4E5E53 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_WindowsRegistry.h"; path = "../../JuceLibraryCode/modules/juce_core/misc/juce_WindowsRegistry.h"; sourceTree = "SOURCE_ROOT"; }; 9B36F7CC7A136C2AEB4E5E53 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_WindowsRegistry.h"; path = "../../JuceLibraryCode/modules/juce_core/misc/juce_WindowsRegistry.h"; sourceTree = "SOURCE_ROOT"; };
@ -822,6 +824,7 @@
F1B87A9524CB1BFD0A3CDC47 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Justification.h"; path = "../../JuceLibraryCode/modules/juce_graphics/placement/juce_Justification.h"; sourceTree = "SOURCE_ROOT"; }; F1B87A9524CB1BFD0A3CDC47 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Justification.h"; path = "../../JuceLibraryCode/modules/juce_graphics/placement/juce_Justification.h"; sourceTree = "SOURCE_ROOT"; };
F1D186A91AC8D4E99EA16650 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_MemoryOutputStream.cpp"; path = "../../JuceLibraryCode/modules/juce_core/streams/juce_MemoryOutputStream.cpp"; sourceTree = "SOURCE_ROOT"; }; F1D186A91AC8D4E99EA16650 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_MemoryOutputStream.cpp"; path = "../../JuceLibraryCode/modules/juce_core/streams/juce_MemoryOutputStream.cpp"; sourceTree = "SOURCE_ROOT"; };
F213F6D6186ABA1FD60ADC42 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_PathIterator.h"; path = "../../JuceLibraryCode/modules/juce_graphics/geometry/juce_PathIterator.h"; sourceTree = "SOURCE_ROOT"; }; F213F6D6186ABA1FD60ADC42 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_PathIterator.h"; path = "../../JuceLibraryCode/modules/juce_graphics/geometry/juce_PathIterator.h"; sourceTree = "SOURCE_ROOT"; };
F221CF21582EE0B8FE774583 = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ParamDialog.cpp; path = ../../Source/ParamDialog.cpp; sourceTree = "SOURCE_ROOT"; };
F273ED17232368EBFAFC820B = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_DropShadowEffect.cpp"; path = "../../JuceLibraryCode/modules/juce_graphics/effects/juce_DropShadowEffect.cpp"; sourceTree = "SOURCE_ROOT"; }; F273ED17232368EBFAFC820B = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_DropShadowEffect.cpp"; path = "../../JuceLibraryCode/modules/juce_graphics/effects/juce_DropShadowEffect.cpp"; sourceTree = "SOURCE_ROOT"; };
F27DB431B9ECEE07B84281E8 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TextButton.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/buttons/juce_TextButton.h"; sourceTree = "SOURCE_ROOT"; }; F27DB431B9ECEE07B84281E8 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_TextButton.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/buttons/juce_TextButton.h"; sourceTree = "SOURCE_ROOT"; };
F2A26292713BB459A7AE5780 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ImageCache.h"; path = "../../JuceLibraryCode/modules/juce_graphics/images/juce_ImageCache.h"; sourceTree = "SOURCE_ROOT"; }; F2A26292713BB459A7AE5780 = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ImageCache.h"; path = "../../JuceLibraryCode/modules/juce_graphics/images/juce_ImageCache.h"; sourceTree = "SOURCE_ROOT"; };
@ -909,6 +912,8 @@
BD25F7AC4728A7875B6AE9D5, BD25F7AC4728A7875B6AE9D5,
19CEF599CB23958AC63D427E, 19CEF599CB23958AC63D427E,
4B70CBF4DB4E571EDF5D3114, 4B70CBF4DB4E571EDF5D3114,
F221CF21582EE0B8FE774583,
9AAC5E6C1A21F8FE2F66F0E0,
838E63F5800CA577B92EF6AE, 838E63F5800CA577B92EF6AE,
C2AA393651CBC37DCD7718BD, C2AA393651CBC37DCD7718BD,
A02775EA788AD4BF7DD1B1A1, A02775EA788AD4BF7DD1B1A1,
@ -1988,6 +1993,7 @@
0D3132A8B412AE9E63024927, 0D3132A8B412AE9E63024927,
478699B4EF80A1A1C0D34C10, 478699B4EF80A1A1C0D34C10,
C510246D7D5E162C9DE63DDE, C510246D7D5E162C9DE63DDE,
CD1CF0C6B4AB9F4C8175FE08,
082D6FF34EFF195C3A3B0CFB, 082D6FF34EFF195C3A3B0CFB,
D5A4D43A16EA4C71D53E96CD, D5A4D43A16EA4C71D53E96CD,
8121E10419E2D99645EA254E, 8121E10419E2D99645EA254E,

@ -153,6 +153,7 @@
<ClCompile Include="..\..\Source\msfa\sin.cc"/> <ClCompile Include="..\..\Source\msfa\sin.cc"/>
<ClCompile Include="..\..\Source\PluginEditor.cpp"/> <ClCompile Include="..\..\Source\PluginEditor.cpp"/>
<ClCompile Include="..\..\Source\GlobalEditor.cpp"/> <ClCompile Include="..\..\Source\GlobalEditor.cpp"/>
<ClCompile Include="..\..\Source\ParamDialog.cpp"/>
<ClCompile Include="..\..\Source\OperatorEditor.cpp"/> <ClCompile Include="..\..\Source\OperatorEditor.cpp"/>
<ClCompile Include="..\..\Source\DXLookNFeel.cpp"/> <ClCompile Include="..\..\Source\DXLookNFeel.cpp"/>
<ClCompile Include="..\..\Source\DXComponents.cpp"/> <ClCompile Include="..\..\Source\DXComponents.cpp"/>
@ -1153,6 +1154,7 @@
<ClInclude Include="..\..\Source\msfa\synth.h"/> <ClInclude Include="..\..\Source\msfa\synth.h"/>
<ClInclude Include="..\..\Source\PluginEditor.h"/> <ClInclude Include="..\..\Source\PluginEditor.h"/>
<ClInclude Include="..\..\Source\GlobalEditor.h"/> <ClInclude Include="..\..\Source\GlobalEditor.h"/>
<ClInclude Include="..\..\Source\ParamDialog.h"/>
<ClInclude Include="..\..\Source\OperatorEditor.h"/> <ClInclude Include="..\..\Source\OperatorEditor.h"/>
<ClInclude Include="..\..\Source\DXLookNFeel.h"/> <ClInclude Include="..\..\Source\DXLookNFeel.h"/>
<ClInclude Include="..\..\Source\DXComponents.h"/> <ClInclude Include="..\..\Source\DXComponents.h"/>

@ -313,6 +313,9 @@
<ClCompile Include="..\..\Source\GlobalEditor.cpp"> <ClCompile Include="..\..\Source\GlobalEditor.cpp">
<Filter>Dexed\Source</Filter> <Filter>Dexed\Source</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\Source\ParamDialog.cpp">
<Filter>Dexed\Source</Filter>
</ClCompile>
<ClCompile Include="..\..\Source\OperatorEditor.cpp"> <ClCompile Include="..\..\Source\OperatorEditor.cpp">
<Filter>Dexed\Source</Filter> <Filter>Dexed\Source</Filter>
</ClCompile> </ClCompile>
@ -1467,6 +1470,9 @@
<ClInclude Include="..\..\Source\GlobalEditor.h"> <ClInclude Include="..\..\Source\GlobalEditor.h">
<Filter>Dexed\Source</Filter> <Filter>Dexed\Source</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\Source\ParamDialog.h">
<Filter>Dexed\Source</Filter>
</ClInclude>
<ClInclude Include="..\..\Source\OperatorEditor.h"> <ClInclude Include="..\..\Source\OperatorEditor.h">
<Filter>Dexed\Source</Filter> <Filter>Dexed\Source</Filter>
</ClInclude> </ClInclude>

@ -152,6 +152,7 @@
<ClCompile Include="..\..\Source\msfa\sin.cc"/> <ClCompile Include="..\..\Source\msfa\sin.cc"/>
<ClCompile Include="..\..\Source\PluginEditor.cpp"/> <ClCompile Include="..\..\Source\PluginEditor.cpp"/>
<ClCompile Include="..\..\Source\GlobalEditor.cpp"/> <ClCompile Include="..\..\Source\GlobalEditor.cpp"/>
<ClCompile Include="..\..\Source\ParamDialog.cpp"/>
<ClCompile Include="..\..\Source\OperatorEditor.cpp"/> <ClCompile Include="..\..\Source\OperatorEditor.cpp"/>
<ClCompile Include="..\..\Source\DXLookNFeel.cpp"/> <ClCompile Include="..\..\Source\DXLookNFeel.cpp"/>
<ClCompile Include="..\..\Source\DXComponents.cpp"/> <ClCompile Include="..\..\Source\DXComponents.cpp"/>
@ -1152,6 +1153,7 @@
<ClInclude Include="..\..\Source\msfa\synth.h"/> <ClInclude Include="..\..\Source\msfa\synth.h"/>
<ClInclude Include="..\..\Source\PluginEditor.h"/> <ClInclude Include="..\..\Source\PluginEditor.h"/>
<ClInclude Include="..\..\Source\GlobalEditor.h"/> <ClInclude Include="..\..\Source\GlobalEditor.h"/>
<ClInclude Include="..\..\Source\ParamDialog.h"/>
<ClInclude Include="..\..\Source\OperatorEditor.h"/> <ClInclude Include="..\..\Source\OperatorEditor.h"/>
<ClInclude Include="..\..\Source\DXLookNFeel.h"/> <ClInclude Include="..\..\Source\DXLookNFeel.h"/>
<ClInclude Include="..\..\Source\DXComponents.h"/> <ClInclude Include="..\..\Source\DXComponents.h"/>

@ -313,6 +313,9 @@
<ClCompile Include="..\..\Source\GlobalEditor.cpp"> <ClCompile Include="..\..\Source\GlobalEditor.cpp">
<Filter>Dexed\Source</Filter> <Filter>Dexed\Source</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\Source\ParamDialog.cpp">
<Filter>Dexed\Source</Filter>
</ClCompile>
<ClCompile Include="..\..\Source\OperatorEditor.cpp"> <ClCompile Include="..\..\Source\OperatorEditor.cpp">
<Filter>Dexed\Source</Filter> <Filter>Dexed\Source</Filter>
</ClCompile> </ClCompile>
@ -1467,6 +1470,9 @@
<ClInclude Include="..\..\Source\GlobalEditor.h"> <ClInclude Include="..\..\Source\GlobalEditor.h">
<Filter>Dexed\Source</Filter> <Filter>Dexed\Source</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\Source\ParamDialog.h">
<Filter>Dexed\Source</Filter>
</ClInclude>
<ClInclude Include="..\..\Source\OperatorEditor.h"> <ClInclude Include="..\..\Source\OperatorEditor.h">
<Filter>Dexed\Source</Filter> <Filter>Dexed\Source</Filter>
</ClInclude> </ClInclude>

@ -53,6 +53,8 @@
<FILE id="thAIGQ" name="GlobalEditor.cpp" compile="1" resource="0" <FILE id="thAIGQ" name="GlobalEditor.cpp" compile="1" resource="0"
file="Source/GlobalEditor.cpp"/> file="Source/GlobalEditor.cpp"/>
<FILE id="CxMFcr" name="GlobalEditor.h" compile="0" resource="0" file="Source/GlobalEditor.h"/> <FILE id="CxMFcr" name="GlobalEditor.h" compile="0" resource="0" file="Source/GlobalEditor.h"/>
<FILE id="eZN5P2" name="ParamDialog.cpp" compile="1" resource="0" file="Source/ParamDialog.cpp"/>
<FILE id="fijjBN" name="ParamDialog.h" compile="0" resource="0" file="Source/ParamDialog.h"/>
<FILE id="oUObPG" name="OperatorEditor.cpp" compile="1" resource="0" <FILE id="oUObPG" name="OperatorEditor.cpp" compile="1" resource="0"
file="Source/OperatorEditor.cpp"/> file="Source/OperatorEditor.cpp"/>
<FILE id="ChJDca" name="OperatorEditor.h" compile="0" resource="0" <FILE id="ChJDca" name="OperatorEditor.h" compile="0" resource="0"

@ -133,7 +133,7 @@ void AlgoDisplay::drawOp(Graphics &g, int x, int y, int num) {
EnvDisplay::EnvDisplay() { EnvDisplay::EnvDisplay() {
pvalues = (char *) &TMP_LEVEL_PTR; pvalues = (char *) &TMP_LEVEL_PTR;
} }
/*
void EnvDisplay::paint(Graphics &g) { void EnvDisplay::paint(Graphics &g) {
g.setColour(Colours::black.withAlpha(0.5f)); g.setColour(Colours::black.withAlpha(0.5f));
g.fillRoundedRectangle (0.0f, 0.0f, (float) getWidth(), (float) getHeight(), 1.0f); g.fillRoundedRectangle (0.0f, 0.0f, (float) getWidth(), (float) getHeight(), 1.0f);
@ -198,6 +198,227 @@ void EnvDisplay::paint(Graphics &g) {
len << ((int) vPos); len << ((int) vPos);
g.drawText(len, 5, 1, 72, 14, Justification::left, true); g.drawText(len, 5, 1, 72, 14, Justification::left, true);
} }
*/
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
};
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;
}
void EnvDisplay::paint(Graphics &g) {
g.setColour(Colours::black.withAlpha(0.5f));
g.fillRoundedRectangle (0.0f, 0.0f, (float) getWidth(), (float) getHeight(), 1.0f);
int h = getHeight();
char *rates = pvalues;
char *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(Colour(0xFF0FC00F).withAlpha(0.3f));
g.fillPath(p);
g.setColour(Colour(0xFFFFFFFF));
String len;
len << ((int) vPos);
g.drawText(len, 5, 1, 72, 14, Justification::left, true);
}
PitchEnvDisplay::PitchEnvDisplay() { PitchEnvDisplay::PitchEnvDisplay() {

@ -20,7 +20,7 @@
#include "DXLookNFeel.h" #include "DXLookNFeel.h"
Colour DXLookNFeel::dxDarkBrown = Colour(0xFF0FC00F); Colour DXLookNFeel::dxDarkBrown = Colour(0xFF47260D);
Colour DXLookNFeel::dxLightBrown = Colour(0xFFA87B67); Colour DXLookNFeel::dxLightBrown = Colour(0xFFA87B67);
DXLookNFeel::DXLookNFeel() { DXLookNFeel::DXLookNFeel() {

@ -0,0 +1,172 @@
/*
==============================================================================
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.1.0
------------------------------------------------------------------------------
The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-13 by Raw Material Software Ltd.
==============================================================================
*/
//[Headers] You can add your own extra header files here...
//[/Headers]
#include "ParamDialog.h"
//[MiscUserDefs] You can add your own user definitions and misc code here...
//[/MiscUserDefs]
//==============================================================================
ParamDialog::ParamDialog ()
{
addAndMakeVisible (pitchRange = new Slider ("pitchRange"));
pitchRange->setRange (0, 12, 1);
pitchRange->setSliderStyle (Slider::Rotary);
pitchRange->setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20);
pitchRange->addListener (this);
addAndMakeVisible (pitchStep = new Slider ("pitchStep"));
pitchStep->setRange (0, 12, 1);
pitchStep->setSliderStyle (Slider::Rotary);
pitchStep->setTextBoxStyle (Slider::TextBoxLeft, false, 80, 20);
pitchStep->addListener (this);
//[UserPreSize]
//[/UserPreSize]
setSize (280, 200);
//[Constructor] You can add your own custom stuff here..
//[/Constructor]
}
ParamDialog::~ParamDialog()
{
//[Destructor_pre]. You can add your own custom destruction code here..
//[/Destructor_pre]
pitchRange = nullptr;
pitchStep = 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 (0xff4e270d));
g.setColour (Colours::white);
g.setFont (Font (15.00f, Font::plain));
g.drawText (TRANS("Pitch Bend Range"),
28, 20, 131, 23,
Justification::centredLeft, true);
g.setColour (Colours::white);
g.setFont (Font (15.00f, Font::plain));
g.drawText (TRANS("Pitch Bend Step"),
28, 52, 128, 23,
Justification::centredLeft, true);
//[UserPaint] Add your own custom painting code here..
//[/UserPaint]
}
void ParamDialog::resized()
{
pitchRange->setBounds (184, 16, 72, 24);
pitchStep->setBounds (184, 56, 72, 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..
//[/UserSliderCode_pitchStep]
}
//[UsersliderValueChanged_Post]
//[/UsersliderValueChanged_Post]
}
//[MiscUserCode] You can add your own definitions of your custom methods or any other code here...
void ParamDialog::setDialogValues(Controllers &c) {
pitchRange->setValue(c.values_[kControllerPitchRange]);
pitchStep->setValue(c.values_[kControllerPitchStep]);
}
void ParamDialog::getDialogValues(Controllers &c) {
c.values_[kControllerPitchRange] = pitchRange->getValue();
c.values_[kControllerPitchStep] = pitchStep->getValue();
}
//[/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="280" initialHeight="200">
<BACKGROUND backgroundColour="ff4e270d">
<TEXT pos="28 20 131 23" fill="solid: ffffffff" hasStroke="0" text="Pitch Bend Range"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
<TEXT pos="28 52 128 23" fill="solid: ffffffff" hasStroke="0" text="Pitch Bend Step"
fontname="Default font" fontsize="15" bold="0" italic="0" justification="33"/>
</BACKGROUND>
<SLIDER name="pitchRange" id="7409be5a8dfaa91" memberName="pitchRange"
virtualName="" explicitFocusOrder="0" pos="184 16 72 24" min="0"
max="12" int="1" style="Rotary" textBoxPos="TextBoxLeft" textBoxEditable="1"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
<SLIDER name="pitchStep" id="b86af4b792e768ca" memberName="pitchStep"
virtualName="" explicitFocusOrder="0" pos="184 56 72 24" min="0"
max="12" int="1" style="Rotary" textBoxPos="TextBoxLeft" textBoxEditable="1"
textBoxWidth="80" textBoxHeight="20" skewFactor="1"/>
</JUCER_COMPONENT>
END_JUCER_METADATA
*/
#endif
//[EndFile] You can add extra defines here...
//[/EndFile]

@ -0,0 +1,75 @@
/*
==============================================================================
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.1.0
------------------------------------------------------------------------------
The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-13 by Raw Material Software 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"
//[/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:
//==============================================================================
ParamDialog ();
~ParamDialog();
//==============================================================================
//[UserMethods] -- You can add your own custom methods in this section.
void setDialogValues(Controllers &c);
void getDialogValues(Controllers &c);
//[/UserMethods]
void paint (Graphics& g);
void resized();
void sliderValueChanged (Slider* sliderThatWasMoved);
private:
//[UserVariables] -- You can add your own custom variables in this section.
//[/UserVariables]
//==============================================================================
ScopedPointer<Slider> pitchRange;
ScopedPointer<Slider> pitchStep;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ParamDialog)
};
//[EndFile] You can add extra defines here...
//[/EndFile]
#endif // __JUCE_HEADER_D00F97AD887A66__

@ -21,6 +21,7 @@
#include "PluginProcessor.h" #include "PluginProcessor.h"
#include "PluginEditor.h" #include "PluginEditor.h"
#include "GlobalEditor.h" #include "GlobalEditor.h"
#include "ParamDialog.h"
#include "math.h" #include "math.h"
#include <fstream> #include <fstream>
@ -202,6 +203,25 @@ void DexedAudioProcessorEditor::buttonClicked(Button *buttonThatWasClicked) {
return; return;
} }
if (buttonThatWasClicked == settingsButton) {
AlertWindow window("","", AlertWindow::NoIcon, this);
ParamDialog param;
param.setColour(AlertWindow::backgroundColourId, Colour(0x32FFFFFF));
param.setDialogValues(processor->controllers);
window.addCustomComponent(&param);
window.addButton("OK", 0);
window.addButton("Cancel" ,1);
if ( window.runModalLoop() != 0 )
return;
param.getDialogValues(processor->controllers);
processor->savePreference();
return;
}
if (buttonThatWasClicked == aboutButton) { if (buttonThatWasClicked == aboutButton) {
AlertWindow::showMessageBoxAsync(AlertWindow::NoIcon, "DEXED - DX Emulator 0.4", "https://github.com/asb2m10/dexed\n" AlertWindow::showMessageBoxAsync(AlertWindow::NoIcon, "DEXED - DX Emulator 0.4", "https://github.com/asb2m10/dexed\n"
"(c) 2013-2014 Pascal Gauthier\nUnder the GPL v2\n\n" "(c) 2013-2014 Pascal Gauthier\nUnder the GPL v2\n\n"

@ -444,12 +444,24 @@ void DexedAudioProcessor::loadPreference() {
if ( prop.containsKey( String("normalizeDxVelocity") ) ) { if ( prop.containsKey( String("normalizeDxVelocity") ) ) {
normalizeDxVelocity = prop.getIntValue( 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") );
}
} }
void DexedAudioProcessor::savePreference() { void DexedAudioProcessor::savePreference() {
PropertiesFile prop(prefOptions); PropertiesFile prop(prefOptions);
prop.setValue(String("normalizeDxVelocity"), normalizeDxVelocity); prop.setValue(String("normalizeDxVelocity"), normalizeDxVelocity);
prop.setValue(String("pitchRange"), controllers.values_[kControllerPitchRange]);
prop.setValue(String("pitchStep"), controllers.values_[kControllerPitchStep]);
prop.save(); prop.save();
} }

@ -58,6 +58,11 @@ DexedAudioProcessor::DexedAudioProcessor() {
prefOptions.filenameSuffix = String("xml"); prefOptions.filenameSuffix = String("xml");
prefOptions.folderName = String("DigitalSuburban"); prefOptions.folderName = String("DigitalSuburban");
prefOptions.osxLibrarySubFolder = String("Application Support"); prefOptions.osxLibrarySubFolder = String("Application Support");
controllers.values_[kControllerPitchRange] = 3;
controllers.values_[kControllerPitchStep] = 0;
loadPreference();
} }
DexedAudioProcessor::~DexedAudioProcessor() { DexedAudioProcessor::~DexedAudioProcessor() {
@ -80,7 +85,9 @@ void DexedAudioProcessor::prepareToPlay(double sampleRate, int samplesPerBlock)
currentNote = 0; currentNote = 0;
controllers.values_[kControllerPitch] = 0x2000; controllers.values_[kControllerPitch] = 0x2000;
controllers.values_[KcontrollerModWheel] = 0; controllers.values_[kControllerModWheel] = 0;
sustain = false; sustain = false;
extra_buf_size = 0; extra_buf_size = 0;
@ -270,7 +277,7 @@ void DexedAudioProcessor::processMidiMessage(MidiMessage *msg) {
// mod wheel // mod wheel
if ( controller == 1 ) { if ( controller == 1 ) {
controllers.values_[KcontrollerModWheel] = value; controllers.values_[kControllerModWheel] = value;
return; return;
} }
@ -297,7 +304,7 @@ void DexedAudioProcessor::processMidiMessage(MidiMessage *msg) {
switch (cmd) { switch (cmd) {
case 0xe0 : case 0xe0 :
controllers.values_[kControllerPitch] = (char) buf[1] | (buf[2] << 7); controllers.values_[kControllerPitch] = buf[1] | (buf[2] << 7);
break; break;
} }

@ -51,8 +51,6 @@ class DexedAudioProcessor : public AudioProcessor, public AsyncUpdater
// The original DX7 had one single LFO. Later units had an LFO per note. // The original DX7 had one single LFO. Later units had an LFO per note.
Lfo lfo; Lfo lfo;
// in MIDI units (0x4000 is neutral)
Controllers controllers;
bool sustain; bool sustain;
// Extra buffering for when GetSamples wants a buffer not a multiple of N // Extra buffering for when GetSamples wants a buffer not a multiple of N
@ -105,6 +103,8 @@ class DexedAudioProcessor : public AudioProcessor, public AsyncUpdater
public : public :
// in MIDI units (0x4000 is neutral)
Controllers controllers;
StringArray programNames; StringArray programNames;
char sysex[4096]; char sysex[4096];
char data[161]; char data[161];

@ -18,12 +18,14 @@
#define __CONTROLLERS_H #define __CONTROLLERS_H
// State of MIDI controllers // State of MIDI controllers
const int KcontrollerModWheel = 1; const int kControllerModWheel = 1;
const int kControllerPitch = 128; const int kControllerPitch = 128;
const int kControllerPitchRange = 129;
const int kControllerPitchStep = 130;
class Controllers { class Controllers {
public: public:
int values_[129]; int values_[131];
}; };
#endif // __CONTROLLERS_H #endif // __CONTROLLERS_H

@ -184,15 +184,23 @@ void Dx7Note::compute(int32_t *buf, int32_t lfo_val, int32_t lfo_delay,
int32_t pitchmod = pitchenv_.getsample(); int32_t pitchmod = pitchenv_.getsample();
uint32_t pmd = pitchmoddepth_ * lfo_delay; // Q32 uint32_t pmd = pitchmoddepth_ * lfo_delay; // Q32
// TODO: add modulation sources (mod wheel, etc) // TODO: add modulation sources (mod wheel, etc)
uint32_t pwmd = (ctrls->values_[KcontrollerModWheel] * 0.7874) * (1 << 24); uint32_t pwmd = (ctrls->values_[kControllerModWheel] * 0.7874) * (1 << 24);
int32_t senslfo = pitchmodsens_ * (lfo_val - (1 << 23)); int32_t senslfo = pitchmodsens_ * (lfo_val - (1 << 23));
pitchmod += (((int64_t)pwmd) * (int64_t)senslfo) >> 39; pitchmod += (((int64_t)pwmd) * (int64_t)senslfo) >> 39;
pitchmod += (((int64_t)pmd) * (int64_t)senslfo) >> 39; pitchmod += (((int64_t)pmd) * (int64_t)senslfo) >> 39;
// hardcodes a pitchbend range of 3 semitones, TODO make configurable
int pitchbend = ctrls->values_[kControllerPitch]; int pitchbend = ctrls->values_[kControllerPitch];
int32_t pb = (pitchbend - 0x2000) << 9; int32_t pb;
if ( ctrls->values_[kControllerPitchStep] == 0 ) {
pb = ((float)((pitchbend - 0x2000) << 11)) * ((float)ctrls->values_[kControllerPitchRange]) / 12.0;
} else {
int stp = 12 / ctrls->values_[kControllerPitchStep];
pb = (pitchbend - 0x2000) / stp;
pb = (pb * stp) << 11;
}
pitchmod += pb; pitchmod += pb;
for (int op = 0; op < 6; op++) { for (int op = 0; op < 6; op++) {
params_[op].gain[0] = params_[op].gain[1]; params_[op].gain[0] = params_[op].gain[1];

Loading…
Cancel
Save