diff --git a/Builds/MacOSX/Dexed.xcodeproj/project.pbxproj b/Builds/MacOSX/Dexed.xcodeproj/project.pbxproj index b800a6f..d6d8d51 100644 --- a/Builds/MacOSX/Dexed.xcodeproj/project.pbxproj +++ b/Builds/MacOSX/Dexed.xcodeproj/project.pbxproj @@ -17,8 +17,9 @@ A7D45B047CA84D7EF7018CDC = { isa = PBXBuildFile; fileRef = 2F55D83145737DE69999DB92; }; 7E444608AFB10ED54DB5C9AB = { isa = PBXBuildFile; fileRef = 5E966C95FACF7B8D5A907FE3; }; 813B2285513D65DDA30AA6E3 = { isa = PBXBuildFile; fileRef = 6F9852573AA442CFBAD9695F; }; - C510246D7D5E162C9DE63DDE = { isa = PBXBuildFile; fileRef = 19CEF599CB23958AC63D427E; }; - 082D6FF34EFF195C3A3B0CFB = { isa = PBXBuildFile; fileRef = 838E63F5800CA577B92EF6AE; }; + 1CBFE444B43C89E749602B7F = { isa = PBXBuildFile; fileRef = 45ADFD8885BE76C7F7D999AC; }; + 623AFA9E78826CA0136251DF = { isa = PBXBuildFile; fileRef = 59D15F780D468B587F9C7E78; }; + 8BE2A084394DA3E45DDB5646 = { isa = PBXBuildFile; fileRef = 7936BBAA586387B2FAFB958B; }; 3AB728E101D7B85DD39C5CC8 = { isa = PBXBuildFile; fileRef = 3715DFDD7A1B12083F051F5A; }; FAC9C3E771D11FDA4DFAF17E = { isa = PBXBuildFile; fileRef = 2D26E2304C0F6FC633936014; }; 47C317B0F77A29ECA0400B2B = { isa = PBXBuildFile; fileRef = AE09B4C2A4BDE8FDA01A8A13; }; @@ -28,10 +29,11 @@ 434647C21C803FA8A4D44A70 = { isa = PBXBuildFile; fileRef = 78CA76788217B98287D9E007; }; 95105DC8536836A06FD5C7BB = { isa = PBXBuildFile; fileRef = 51E5757E2D48E638F9A4CB61; }; 0D3132A8B412AE9E63024927 = { isa = PBXBuildFile; fileRef = B0230FCCA099E6430411DFC9; }; - D5A4D43A16EA4C71D53E96CD = { isa = PBXBuildFile; fileRef = A02775EA788AD4BF7DD1B1A1; }; - 1CBFE444B43C89E749602B7F = { isa = PBXBuildFile; fileRef = 45ADFD8885BE76C7F7D999AC; }; 478699B4EF80A1A1C0D34C10 = { isa = PBXBuildFile; fileRef = 018D0FB9E97B68D2EB3E3F72; }; - 623AFA9E78826CA0136251DF = { isa = PBXBuildFile; fileRef = 59D15F780D468B587F9C7E78; }; + C510246D7D5E162C9DE63DDE = { isa = PBXBuildFile; fileRef = 19CEF599CB23958AC63D427E; }; + 082D6FF34EFF195C3A3B0CFB = { isa = PBXBuildFile; fileRef = 838E63F5800CA577B92EF6AE; }; + D5A4D43A16EA4C71D53E96CD = { isa = PBXBuildFile; fileRef = A02775EA788AD4BF7DD1B1A1; }; + 8121E10419E2D99645EA254E = { isa = PBXBuildFile; fileRef = D984CE634945077E682B48F3; }; B18C192606DF6079E7B9AEB9 = { isa = PBXBuildFile; fileRef = 8BADEB7BF1A65E83A7A1736D; }; 1C87DA0B69D67481FC6CF4FD = { isa = PBXBuildFile; fileRef = 54363D0B39B88D43447C0123; }; E3FA856CA4DB2009BB0F13E7 = { isa = PBXBuildFile; fileRef = 505852570B48EB3F18076B03; }; @@ -284,6 +286,7 @@ 448630170E2B48A00FBBA757 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_linux_Threads.cpp"; path = "../../JuceLibraryCode/modules/juce_core/native/juce_linux_Threads.cpp"; sourceTree = "SOURCE_ROOT"; }; 4497D4F58A495EF3F3DB7DD2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_ReadWriteLock.h"; path = "../../JuceLibraryCode/modules/juce_core/threads/juce_ReadWriteLock.h"; sourceTree = "SOURCE_ROOT"; }; 452C1184BD776249B33151E5 = { isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DiscRecording.framework; path = System/Library/Frameworks/DiscRecording.framework; sourceTree = SDKROOT; }; + 4567FB06348FF519FDC6D698 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = DXComponents.h; path = ../../Source/DXComponents.h; sourceTree = "SOURCE_ROOT"; }; 4574217C2F5219DEDDDC9656 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_RTAS_DigiCode3.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_plugin_client/RTAS/juce_RTAS_DigiCode3.cpp"; sourceTree = "SOURCE_ROOT"; }; 45ADFD8885BE76C7F7D999AC = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = PluginProcessor.cpp; path = ../../Source/PluginProcessor.cpp; sourceTree = "SOURCE_ROOT"; }; 45CC11D2029BA2CEAE1B0F76 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_CharPointer_UTF16.h"; path = "../../JuceLibraryCode/modules/juce_core/text/juce_CharPointer_UTF16.h"; sourceTree = "SOURCE_ROOT"; }; @@ -436,6 +439,7 @@ 78934C6C88D2B35DEF15BAB8 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = "juce_AudioUnitPluginFormat.mm"; path = "../../JuceLibraryCode/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm"; sourceTree = "SOURCE_ROOT"; }; 78A82E89AC0283CC1329E84E = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Timer.h"; path = "../../JuceLibraryCode/modules/juce_events/timers/juce_Timer.h"; sourceTree = "SOURCE_ROOT"; }; 78CA76788217B98287D9E007 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "fm_op_kernel.cc"; path = "../../Source/msfa/fm_op_kernel.cc"; sourceTree = "SOURCE_ROOT"; }; + 7936BBAA586387B2FAFB958B = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = PluginData.cpp; path = ../../Source/PluginData.cpp; sourceTree = "SOURCE_ROOT"; }; 7A0FB6545BA2E344A1F45EA5 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Decibels.h"; path = "../../JuceLibraryCode/modules/juce_audio_basics/effects/juce_Decibels.h"; sourceTree = "SOURCE_ROOT"; }; 7A26D67672786E0663369D49 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_IIRFilterAudioSource.cpp"; path = "../../JuceLibraryCode/modules/juce_audio_basics/sources/juce_IIRFilterAudioSource.cpp"; sourceTree = "SOURCE_ROOT"; }; 7A38190CB0652B0EBA02100C = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_FileFilter.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/filebrowser/juce_FileFilter.cpp"; sourceTree = "SOURCE_ROOT"; }; @@ -677,6 +681,7 @@ C48DAE373124C258F3414CDB = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_GIFLoader.cpp"; path = "../../JuceLibraryCode/modules/juce_graphics/image_formats/juce_GIFLoader.cpp"; sourceTree = "SOURCE_ROOT"; }; C49F636E4677A7C8C62A9859 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_Synthesiser.h"; path = "../../JuceLibraryCode/modules/juce_audio_basics/synthesisers/juce_Synthesiser.h"; sourceTree = "SOURCE_ROOT"; }; C4A2C1FDE57CCF33BE778B39 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_AppleRemote.h"; path = "../../JuceLibraryCode/modules/juce_gui_extra/misc/juce_AppleRemote.h"; sourceTree = "SOURCE_ROOT"; }; + C56E401381FF968837F82364 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PluginData.h; path = ../../Source/PluginData.h; sourceTree = "SOURCE_ROOT"; }; C5E92613992AB74C2E715271 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ApplicationCommandManager.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/commands/juce_ApplicationCommandManager.cpp"; sourceTree = "SOURCE_ROOT"; }; C6559A509BD759234BFFCA5D = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_TooltipWindow.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/windows/juce_TooltipWindow.cpp"; sourceTree = "SOURCE_ROOT"; }; C6928FE8579AE1980061CA43 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = dx7note.h; path = ../../Source/msfa/dx7note.h; sourceTree = "SOURCE_ROOT"; }; @@ -729,6 +734,7 @@ D8498304CBB374B2800442D4 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_LassoComponent.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/mouse/juce_LassoComponent.h"; sourceTree = "SOURCE_ROOT"; }; D90A42D47F3DD9C505D8A925 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_SystemStats.h"; path = "../../JuceLibraryCode/modules/juce_core/system/juce_SystemStats.h"; sourceTree = "SOURCE_ROOT"; }; D921C8001631F2FC4D7EFF9D = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_KeyboardFocusTraverser.h"; path = "../../JuceLibraryCode/modules/juce_gui_basics/keyboard/juce_KeyboardFocusTraverser.h"; sourceTree = "SOURCE_ROOT"; }; + D984CE634945077E682B48F3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = DXComponents.cpp; path = ../../Source/DXComponents.cpp; sourceTree = "SOURCE_ROOT"; }; DA27D90A90F1795DCD9DA064 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_Value.cpp"; path = "../../JuceLibraryCode/modules/juce_data_structures/values/juce_Value.cpp"; sourceTree = "SOURCE_ROOT"; }; DA4359972E065615EEF392EB = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = "juce_ProgressBar.cpp"; path = "../../JuceLibraryCode/modules/juce_gui_basics/widgets/juce_ProgressBar.cpp"; sourceTree = "SOURCE_ROOT"; }; DAEFEE4711393EBF6BC1EB3A = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "juce_DropShadowEffect.h"; path = "../../JuceLibraryCode/modules/juce_graphics/effects/juce_DropShadowEffect.h"; sourceTree = "SOURCE_ROOT"; }; @@ -878,19 +884,23 @@ 3BE8F91A99E8F48CB9F10C1F, 68D35AFE11BAA35EAE497D47 ); name = msfa; sourceTree = ""; }; 29B923E6EB12F97B68585AFC = { isa = PBXGroup; children = ( + 45ADFD8885BE76C7F7D999AC, + 5C0A1B7E2BF8FCAF5A1E8616, + 59D15F780D468B587F9C7E78, + EA6FC4F1F0D6EAE661569905, + 7936BBAA586387B2FAFB958B, + C56E401381FF968837F82364, + BDC5059F1563FD8DD69AD324, + 018D0FB9E97B68D2EB3E3F72, + BD25F7AC4728A7875B6AE9D5, 19CEF599CB23958AC63D427E, 4B70CBF4DB4E571EDF5D3114, 838E63F5800CA577B92EF6AE, C2AA393651CBC37DCD7718BD, - BDC5059F1563FD8DD69AD324, A02775EA788AD4BF7DD1B1A1, 29D6A187B80D22EB609C256D, - 45ADFD8885BE76C7F7D999AC, - 5C0A1B7E2BF8FCAF5A1E8616, - 018D0FB9E97B68D2EB3E3F72, - BD25F7AC4728A7875B6AE9D5, - 59D15F780D468B587F9C7E78, - EA6FC4F1F0D6EAE661569905, + D984CE634945077E682B48F3, + 4567FB06348FF519FDC6D698, 8BADEB7BF1A65E83A7A1736D, DC75DFCDFCDB425927B11EC0 ); name = Source; sourceTree = ""; }; C21CEF3B473FDC99270B7623 = { isa = PBXGroup; children = ( @@ -1930,8 +1940,9 @@ 9D042F9D005532F763A72C26, E293B9570C97E4BAD129D4A2 ); runOnlyForDeploymentPostprocessing = 0; }; 9DB7317ADCFFCEAB747A09AF = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - C510246D7D5E162C9DE63DDE, - 082D6FF34EFF195C3A3B0CFB, + 1CBFE444B43C89E749602B7F, + 623AFA9E78826CA0136251DF, + 8BE2A084394DA3E45DDB5646, 3AB728E101D7B85DD39C5CC8, FAC9C3E771D11FDA4DFAF17E, 47C317B0F77A29ECA0400B2B, @@ -1941,10 +1952,11 @@ 434647C21C803FA8A4D44A70, 95105DC8536836A06FD5C7BB, 0D3132A8B412AE9E63024927, - D5A4D43A16EA4C71D53E96CD, - 1CBFE444B43C89E749602B7F, 478699B4EF80A1A1C0D34C10, - 623AFA9E78826CA0136251DF, + C510246D7D5E162C9DE63DDE, + 082D6FF34EFF195C3A3B0CFB, + D5A4D43A16EA4C71D53E96CD, + 8121E10419E2D99645EA254E, B18C192606DF6079E7B9AEB9, 1C87DA0B69D67481FC6CF4FD, E3FA856CA4DB2009BB0F13E7, diff --git a/Builds/MacOSX/Dexed.xcodeproj/project.xcworkspace/xcuserdata/asb2m10.xcuserdatad/UserInterfaceState.xcuserstate b/Builds/MacOSX/Dexed.xcodeproj/project.xcworkspace/xcuserdata/asb2m10.xcuserdatad/UserInterfaceState.xcuserstate index 6ef498b..4952004 100644 Binary files a/Builds/MacOSX/Dexed.xcodeproj/project.xcworkspace/xcuserdata/asb2m10.xcuserdatad/UserInterfaceState.xcuserstate and b/Builds/MacOSX/Dexed.xcodeproj/project.xcworkspace/xcuserdata/asb2m10.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Builds/VisualStudio2012/Dexed.vcxproj b/Builds/VisualStudio2012/Dexed.vcxproj index 744d5bf..9ccec7a 100644 --- a/Builds/VisualStudio2012/Dexed.vcxproj +++ b/Builds/VisualStudio2012/Dexed.vcxproj @@ -133,8 +133,9 @@ - - + + + @@ -144,10 +145,11 @@ - - - + + + + true @@ -1111,8 +1113,9 @@ - - + + + @@ -1126,10 +1129,11 @@ - - - + + + + diff --git a/Builds/VisualStudio2012/Dexed.vcxproj.filters b/Builds/VisualStudio2012/Dexed.vcxproj.filters index 93a09a1..3569e1b 100644 --- a/Builds/VisualStudio2012/Dexed.vcxproj.filters +++ b/Builds/VisualStudio2012/Dexed.vcxproj.filters @@ -268,10 +268,13 @@ - + Dexed\Source - + + Dexed\Source + + Dexed\Source @@ -301,16 +304,19 @@ Dexed\Source\msfa - + Dexed\Source - + Dexed\Source - + Dexed\Source - + + Dexed\Source + + Dexed\Source @@ -1383,10 +1389,13 @@ - + Dexed\Source - + + Dexed\Source + + Dexed\Source @@ -1428,16 +1437,19 @@ Dexed\Source\msfa - + Dexed\Source - + Dexed\Source - + Dexed\Source - + + Dexed\Source + + Dexed\Source diff --git a/Dexed.jucer b/Dexed.jucer index c91259f..9921676 100644 --- a/Dexed.jucer +++ b/Dexed.jucer @@ -14,13 +14,14 @@ - - - - + + + + + + @@ -45,17 +46,21 @@ - - - - - - + + + + + + + + diff --git a/Source/DXComponents.cpp b/Source/DXComponents.cpp new file mode 100644 index 0000000..74d2824 --- /dev/null +++ b/Source/DXComponents.cpp @@ -0,0 +1,246 @@ +/** + * + * 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 2 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 "DXComponents.h" +#include "PluginProcessor.h" +#include "msfa/pitchenv.h" + +/** + * Algorithm arrangements, based on the DX1 display. + */ +static const char algoArr[][13] = { + // 1 2 3 4 5 6 7 8 9 A B C D + { 0, 0, 1, 3, 0, 0, 0, 2, 4, 0, 0, 5, -6 }, // 1 + { 0, 0, 1, 3, 0, 0, 0, -2, 4, 0, 0, 5, 6 }, // 2 + { 0, 0, 1, 4, 0, 0, 0, 2, 5, 0, 3, -6, 0 }, // 3 + { 0, 0, 1, -4, 0, 0, 0, 2, -5, 0, 3, -6, 0 }, // 4 + { 0, 1, 3, 5, 0, 0, 2, 4, -6, 0, 0, 0, 0 }, // 5 + { 0, 1, 3, -5, 0, 0, 2, 4, -6, 0, 0, 0, 0 }, // 6 + { 0, 1, 3, 0, 0, 0, -2, 4, 5, 0, 0, 6, 0 }, // 7 + { 0, 1, 3, 0, 0, 0, 2, -4, 5, 0, 0, 6, 0 }, // 8 + { 0, 1, 3, 0, 0, 0, -2, 4, 5, 0, 0, 6, 0 }, // 9 + { 0, 0, 4, 1, 0, 0, 5, 6, 2, 0, 0, -3, 0 }, // 10 + { 0, 0, 4, 1, 0, 0, 5, -6, 2, 0, 0, 3, 0 }, // 11 + { 0, 0, 3, 0, 1, 0, 4, 5, 6, -2, 0, 0, 0 }, // 12 + { 0, 0, 3, 0, 1, 0, 4, 5, -6, 2, 0, 0, 0 }, // 13 + // 1 2 3 4 5 6 7 8 9 A B C D + { 0, 0, 1, 3, 0, 0, 0, 2, 4, 0, 5, -6, 0 }, // 14 + { 0, 0, 1, 3, 0, 0, 0, -2, 4, 0, 5, 6, 0 }, // 15 + { 0, 0, 1, 0, 0, 0, 2, 3, 5, 0, 4, -6, 0 }, // 16 + { 0, 0, 1, 0, 0, 0, -2, 3, 5, 0, 4, 6, 0 }, // 17 + { 0, 0, 1, 0, 0, 0, 2, -3, 4, 0, 0, 5, 6 }, // 18 + { 0, 0, 1, 4, 5, 0, 0, 2, -6, 0, 3, 0, 0 }, // 19 + { 0, 1, 2, 0, 4, 0, -3, 0, 5, 6, 0, 0, 0 }, // 20 + { 0, 1, 2, 4, 5, 0, -3, 0, 6, 0, 0, 0, 0 }, // 21 + { 0, 1, 3, 4, 5, 0, 2, 0, -6, 0, 0, 0, 0 }, // 22 + { 0, 1, 2, 4, 5, 0, 0, 3, -6, 0, 0, 0, 0 }, // 23 + { 1, 2, 3, 4, 5, 0, 0, 0, -6, 0, 0, 0, 0 }, // 24 + { 1, 2, 3, 4, 5, 0, 0, 0, -6, 0, 0, 0, 0 }, // 25 + { 0, 1, 2, 0, 4, 0, 0, 3, 5, -6, 0, 0, 0 }, // 26 + // 1 2 3 4 5 6 7 8 9 A B C D + { 0, 1, 2, 0, 4, 0, 0, -3, 5, 6, 0, 0, 0 }, // 27 + { 0, 1, 3, 6, 0, 0, 2, 4, 0, 0, -5, 0, 0 }, // 28 + { 0, 1, 2, 3, 5, 0, 0, 0, 4, -6, 0, 0, 0 }, // 29 + { 0, 1, 2, 3, 6, 0, 0, 0, 4, 0, 0, -5, 0 }, // 30 + { 1, 2, 3, 4, 5, 0, 0, 0, 0, -6, 0, 0, 0 }, // 31 + { 1, 2, 3, 4, 5, -6, 0, 0, 0, 0, 0, 0, 0 } // 32 +}; + +static char TMP_LEVEL_PTR[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + +AlgoDisplay::AlgoDisplay() { + static char tmpAlgo = 0; + algo = &tmpAlgo; +} + +void AlgoDisplay::paint(Graphics &g) { + int alg; + + if ( *algo <= 31 ) { + alg = *algo; + } else { + alg = 31; + } + const char *arr = algoArr[alg]; + + g.setColour (Colours::black.withAlpha(0.1f)); + g.fillRoundedRectangle (0.0f, 0.0f, (float) getWidth(), (float) getHeight(), 1.0f); + + for(int i=0;i<13;i++) { + int target = arr[i]; + if ( target == 0 ) + continue; + + if ( i < 6 ) { + drawOp(g, i, 3, target); + continue; + } + + if ( i < 10 ){ + drawOp(g, (i-6)+1, 2, target); + continue; + } + + if ( i < 12 ) { + drawOp(g, (i-10)+2, 1, target); + continue; + } + + // last one + drawOp(g, (i-12)+3, 0, target); + } + + String algoTxt; + algoTxt << (alg+1); + g.drawText(algoTxt, 5, 1, 21, 14, Justification::left, true); +} + +void AlgoDisplay::drawOp(Graphics &g, int x, int y, int num) { + String txt; + txt << abs(num); + + int offx = 24; + int offy = 17; + + g.setColour(Colour(0xFF0FC00F)); + g.fillRect(x*offx+4, y*offy+3, offx-2, offy-1); + g.setColour(Colour(0xFFFFFFFF)); + g.drawText(txt, x*offx+3, y*offy+2, offx+2, offy+2, Justification::centred, true); + if ( num < 0 ) { + g.setColour(Colour(0xFFFFFFFF)); + int x1 = (x*offx) + 24; + g.drawLine(x1+1, y*offy+3, x1+1, y*offy+offy+2, 3); + } +} + +EnvDisplay::EnvDisplay() { + pvalues = (char *) &TMP_LEVEL_PTR; +} + +void EnvDisplay::paint(Graphics &g) { + int rate[4]; + int level[4]; + + g.setColour(Colours::black.withAlpha(0.1f)); + g.fillRoundedRectangle (0.0f, 0.0f, (float) getWidth(), (float) getHeight(), 1.0f); + g.setColour(Colours::white); + + for (int i = 0; i < 4; i++) { + rate[i] = pvalues[i]; + level[i] = pvalues[i+4]; + } + + env.init(rate, level, 99 << 5, 0); + env.keydown(true); + for (int i = 0; i < 72; i++) { + int32_t pos = env.getsample(); + for (int j = 0; j < 16; j++) { + env.getsample(); + } + g.setPixel(i, 32 - (sqrt(pos) / 512)); + } + env.keydown(false); + for (int i = 0; i < 24; i++) { + int32_t pos = env.getsample(); + for (int j = 0; j < 16; j++) { + env.getsample(); + } + g.setPixel(i + 72, 32 - (sqrt(pos) / 512)); + } +} + +PitchEnvDisplay::PitchEnvDisplay() { + pvalues = (char *) &TMP_LEVEL_PTR; +} + +void PitchEnvDisplay::paint(Graphics &g) { + g.setColour(Colours::black.withAlpha(0.1f)); + g.fillRoundedRectangle (0.0f, 0.0f, (float) getWidth(), (float) getHeight(), 1.0f); + g.setColour(Colours::white); + + char *levels = pvalues + 4; + char *rates = pvalues; + + float dist[4]; + float total; + + 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; + } + + TRACE("total %f", total); + TRACE("level %d %d %d %d", levels[0], levels[1], levels[2], levels[3]); + TRACE("dist %f %f %f %f", dist[0], dist[1], dist[2], dist[3]); + + // TODO : this is WIP + float ratio = 96 / total; + + int oldx = 0; + int oldy = (pitchenv_tab[levels[3]] + 128) / 10; + + for(int i=0;i<4;i++) { + int newx = dist[i] * ratio + oldx; + int newy = (pitchenv_tab[levels[i]] + 128) / 10; + + g.drawLine(oldx, oldy, newx, newy, 2); + + oldx = newx; + oldy = newy; + } +} + + +void VuMeter::paint(Graphics &g) { + + // taken from the drawLevelMeter ; + float width = getWidth(); + float height = getHeight(); + + g.setColour (Colours::black); + g.fillRoundedRectangle (0.0f, 0.0f, (float) width, (float) height, 0); + /*g.setColour (Colours::black.withAlpha (0.2f)); + g.drawRoundedRectangle (1.0f, 1.0f, width - 2.0f, height - 2.0f, 3.0f, 1.0f);*/ + + const int totalBlocks = 16; + const int numBlocks = roundToInt (totalBlocks * v); + const float h = (height - 6.0f) / (float) totalBlocks; + + for (int i = 0; i < totalBlocks; ++i) { + g.setColour (Colours::red); + if (i >= numBlocks) + g.setColour (Colours::red.withAlpha (0.2f)); + else + g.setColour (Colours::red); + //g.fillRoundedRectangle (3.0f + i * w + w * 0.1f, 3.0f, w * 0.8f, height - 6.0f, w * 0.4f); + + g.fillRoundedRectangle (3.0f, (height-3.0f) - (3.0f + i * h + h * 0.1f) , width - 6.0f, h * 0.8f, 0); + } +} \ No newline at end of file diff --git a/Source/DXComponents.h b/Source/DXComponents.h new file mode 100644 index 0000000..4da3d46 --- /dev/null +++ b/Source/DXComponents.h @@ -0,0 +1,58 @@ +/** + * + * 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 2 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 "msfa/env.h" + +class EnvDisplay : public Component { + Env env; +public: + EnvDisplay(); + char *pvalues; + void paint(Graphics &g); +}; + +class PitchEnvDisplay : public Component { + char rvalues[8]; +public: + PitchEnvDisplay(); + char *pvalues; + void paint(Graphics &g); +}; + +class AlgoDisplay : public Component { + void drawOp(Graphics &g, int x, int y, int num); +public: + AlgoDisplay(); + char *algo; + void paint(Graphics &g); +}; + +class VuMeter: public Component { + void paint(Graphics &g); + public : + float v; +}; + +#endif // DXCOMPONENTS_H_INCLUDED diff --git a/Source/DXLookNFeel.cpp b/Source/DXLookNFeel.cpp index 2bd95c7..272f249 100644 --- a/Source/DXLookNFeel.cpp +++ b/Source/DXLookNFeel.cpp @@ -19,226 +19,6 @@ */ #include "DXLookNFeel.h" -#include "PluginProcessor.h" - -/** - * Algorithm arrangements, based on the DX1 display. - */ -static const char algoArr[][13] = { - // 1 2 3 4 5 6 7 8 9 A B C D - { 0, 0, 1, 3, 0, 0, 0, 2, 4, 0, 0, 5, -6 }, // 1 - { 0, 0, 1, 3, 0, 0, 0, -2, 4, 0, 0, 5, 6 }, // 2 - { 0, 0, 1, 4, 0, 0, 0, 2, 5, 0, 3, -6, 0 }, // 3 - { 0, 0, 1, -4, 0, 0, 0, 2, -5, 0, 3, -6, 0 }, // 4 - { 0, 1, 3, 5, 0, 0, 2, 4, -6, 0, 0, 0, 0 }, // 5 - { 0, 1, 3, -5, 0, 0, 2, 4, -6, 0, 0, 0, 0 }, // 6 - { 0, 1, 3, 0, 0, 0, -2, 4, 5, 0, 0, 6, 0 }, // 7 - { 0, 1, 3, 0, 0, 0, 2, -4, 5, 0, 0, 6, 0 }, // 8 - { 0, 1, 3, 0, 0, 0, -2, 4, 5, 0, 0, 6, 0 }, // 9 - { 0, 0, 4, 1, 0, 0, 5, 6, 2, 0, 0, -3, 0 }, // 10 - { 0, 0, 4, 1, 0, 0, 5, -6, 2, 0, 0, 3, 0 }, // 11 - { 0, 0, 3, 0, 1, 0, 4, 5, 6, -2, 0, 0, 0 }, // 12 - { 0, 0, 3, 0, 1, 0, 4, 5, -6, 2, 0, 0, 0 }, // 13 - // 1 2 3 4 5 6 7 8 9 A B C D - { 0, 0, 1, 3, 0, 0, 0, 2, 4, 0, 5, -6, 0 }, // 14 - { 0, 0, 1, 3, 0, 0, 0, -2, 4, 0, 5, 6, 0 }, // 15 - { 0, 0, 1, 0, 0, 0, 2, 3, 5, 0, 4, -6, 0 }, // 16 - { 0, 0, 1, 0, 0, 0, -2, 3, 5, 0, 4, 6, 0 }, // 17 - { 0, 0, 1, 0, 0, 0, 2, -3, 4, 0, 0, 5, 6 }, // 18 - { 0, 0, 1, 4, 5, 0, 0, 2, -6, 0, 3, 0, 0 }, // 19 - { 0, 1, 2, 0, 4, 0, -3, 0, 5, 6, 0, 0, 0 }, // 20 - { 0, 1, 2, 4, 5, 0, -3, 0, 6, 0, 0, 0, 0 }, // 21 - { 0, 1, 3, 4, 5, 0, 2, 0, -6, 0, 0, 0, 0 }, // 22 - { 0, 1, 2, 4, 5, 0, 0, 3, -6, 0, 0, 0, 0 }, // 23 - { 1, 2, 3, 4, 5, 0, 0, 0, -6, 0, 0, 0, 0 }, // 24 - { 1, 2, 3, 4, 5, 0, 0, 0, -6, 0, 0, 0, 0 }, // 25 - { 0, 1, 2, 0, 4, 0, 0, 3, 5, -6, 0, 0, 0 }, // 26 - // 1 2 3 4 5 6 7 8 9 A B C D - { 0, 1, 2, 0, 4, 0, 0, -3, 5, 6, 0, 0, 0 }, // 27 - { 0, 1, 3, 6, 0, 0, 2, 4, 0, 0, -5, 0, 0 }, // 28 - { 0, 1, 2, 3, 5, 0, 0, 0, 4, -6, 0, 0, 0 }, // 29 - { 0, 1, 2, 3, 6, 0, 0, 0, 4, 0, 0, -5, 0 }, // 30 - { 1, 2, 3, 4, 5, 0, 0, 0, 0, -6, 0, 0, 0 }, // 31 - { 1, 2, 3, 4, 5, -6, 0, 0, 0, 0, 0, 0, 0 } // 32 -}; - -AlgoDisplay::AlgoDisplay() { - static char tmpAlgo = 0; - algo = &tmpAlgo; -} - -/** - * For now, this is hardcoded 126x56 (21x14 each) - */ -void AlgoDisplay::paint(Graphics &g) { - int alg; - - if ( *algo <= 31 ) { - alg = *algo; - } else { - alg = 31; - } - const char *arr = algoArr[alg]; - - g.setColour (Colours::black.withAlpha(0.1f)); - g.fillRoundedRectangle (0.0f, 0.0f, (float) getWidth(), (float) getHeight(), 1.0f); - - for(int i=0;i<13;i++) { - int target = arr[i]; - if ( target == 0 ) - continue; - - if ( i < 6 ) { - drawOp(g, i, 3, target); - continue; - } - - if ( i < 10 ){ - drawOp(g, (i-6)+1, 2, target); - continue; - } - - if ( i < 12 ) { - drawOp(g, (i-10)+2, 1, target); - continue; - } - - // last one - drawOp(g, (i-12)+3, 0, target); - } - - String algoTxt; - algoTxt << (alg+1); - g.drawText(algoTxt, 5, 1, 21, 14, Justification::left, true); -} - -void AlgoDisplay::drawOp(Graphics &g, int x, int y, int num) { - String txt; - txt << abs(num); - - int offx = 24; - int offy = 17; - - g.setColour(Colour(0xFF0FC00F)); - g.fillRect(x*offx+4, y*offy+3, offx-2, offy-1); - g.setColour(Colour(0xFFFFFFFF)); - g.drawText(txt, x*offx+3, y*offy+2, offx+2, offy+2, Justification::centred, true); - if ( num < 0 ) { - g.setColour(Colour(0xFFFFFFFF)); - int x1 = (x*offx) + 24; - g.drawLine(x1+1, y*offy+3, x1+1, y*offy+offy+2, 3); - } -} - -void EnvDisplay::paint(Graphics &g) { - int rate[4]; - int level[4]; - - g.setColour(Colours::black.withAlpha(0.1f)); - g.fillRoundedRectangle (0.0f, 0.0f, (float) getWidth(), (float) getHeight(), 1.0f); - g.setColour(Colours::white); - - for (int i = 0; i < 4; i++) { - rate[i] = s_rate[i]->getValue(); - level[i] = s_level[i]->getValue(); - } - - env.init(rate, level, 99 << 5, 0); - env.keydown(true); - for (int i = 0; i < 72; i++) { - int32_t pos = env.getsample(); - for (int j = 0; j < 16; j++) { - env.getsample(); - } - g.setPixel(i, 32 - (sqrt(pos) / 512)); - } - env.keydown(false); - for (int i = 0; i < 24; i++) { - int32_t pos = env.getsample(); - for (int j = 0; j < 16; j++) { - env.getsample(); - } - g.setPixel(i + 72, 32 - (sqrt(pos) / 512)); - } -} - -PitchEnvDisplay::PitchEnvDisplay() { - static char tmpDisplay[8]; - memset(&tmpDisplay, 0x00, 8); - pvalues = (char *) &tmpDisplay; -} - -void PitchEnvDisplay::paint(Graphics &g) { - g.setColour(Colours::black.withAlpha(0.1f)); - g.fillRoundedRectangle (0.0f, 0.0f, (float) getWidth(), (float) getHeight(), 1.0f); - g.setColour(Colours::white); - - char *levels = pvalues; - char *rates = pvalues + 4; - - float dist[4]; - float total; - - 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 ) { - dist[0] = 1; - total = 1; - } - //TRACE("DISPLAY %f %f %f %f", dist[0], dist[1], dist[2], dist[3]); - - // TODO : this is WIP - float ratio = 96 / total; - - int oldx = 0; - int oldy = (pitchenv_tab[levels[3]] + 128) / 10; - - for(int i=0;i<4;i++) { - int newx = dist[i] * ratio + oldx; - int newy = (pitchenv_tab[levels[i]] + 128) / 10; - - g.drawLine(oldx, oldy, newx, newy, 2); - - oldx = newx; - oldy = newy; - } -} - - -void VuMeter::paint(Graphics &g) { - - // taken from the drawLevelMeter ; - float width = getWidth(); - float height = getHeight(); - - g.setColour (Colours::black); - g.fillRoundedRectangle (0.0f, 0.0f, (float) width, (float) height, 0); - /*g.setColour (Colours::black.withAlpha (0.2f)); - g.drawRoundedRectangle (1.0f, 1.0f, width - 2.0f, height - 2.0f, 3.0f, 1.0f);*/ - - const int totalBlocks = 16; - const int numBlocks = roundToInt (totalBlocks * v); - const float h = (height - 6.0f) / (float) totalBlocks; - - for (int i = 0; i < totalBlocks; ++i) { - g.setColour (Colours::red); - if (i >= numBlocks) - g.setColour (Colours::red.withAlpha (0.2f)); - else - g.setColour (Colours::red); - //g.fillRoundedRectangle (3.0f + i * w + w * 0.1f, 3.0f, w * 0.8f, height - 6.0f, w * 0.4f); - - g.fillRoundedRectangle (3.0f, (height-3.0f) - (3.0f + i * h + h * 0.1f) , width - 6.0f, h * 0.8f, 0); - } -} DXLookNFeel::DXLookNFeel() { setColour(TextButton::buttonColourId,Colour(0xFF0FC00F)); diff --git a/Source/DXLookNFeel.h b/Source/DXLookNFeel.h index 2312014..fe295fc 100644 --- a/Source/DXLookNFeel.h +++ b/Source/DXLookNFeel.h @@ -22,49 +22,10 @@ #define DXLOOKNFEEL_H_INCLUDED #include "../JuceLibraryCode/JuceHeader.h" -#include "msfa/env.h" -#include "msfa/pitchenv.h" - -class EnvDisplay : public Component { - Env env; -public: - Slider *s_rate[4]; - Slider *s_level[4]; - - void paint(Graphics &g); -}; - -class PitchEnvDisplay : public Component { - char rvalues[8]; - char render[96]; - - void renderDisplay(); -public: - PitchEnvDisplay(); - - char *pvalues; - - void paint(Graphics &g); -}; - -class AlgoDisplay : public Component { - void drawOp(Graphics &g, int x, int y, int num); - -public: - AlgoDisplay(); - char *algo; - - void paint(Graphics &g); -}; class DXLookNFeel : public LookAndFeel_V3 { public: DXLookNFeel(); }; -class VuMeter: public Component { - void paint(Graphics &g); -public : - float v; -}; #endif // DXLOOKNFEEL_H_INCLUDED diff --git a/Source/GlobalEditor.h b/Source/GlobalEditor.h index 5b42147..9689fc5 100644 --- a/Source/GlobalEditor.h +++ b/Source/GlobalEditor.h @@ -23,7 +23,7 @@ //[Headers] -- You can add your own extra header files here -- #include "JuceHeader.h" #include "PluginProcessor.h" -#include "DXLookNFeel.h" +#include "DXComponents.h" //[/Headers] diff --git a/Source/OperatorEditor.cpp b/Source/OperatorEditor.cpp index 7996748..caee165 100644 --- a/Source/OperatorEditor.cpp +++ b/Source/OperatorEditor.cpp @@ -196,14 +196,6 @@ OperatorEditor::OperatorEditor () //[Constructor] You can add your own custom stuff here.. - envDisplay->s_rate[0] = s_egv1; - envDisplay->s_rate[1] = s_egv2; - envDisplay->s_rate[2] = s_egv3; - envDisplay->s_rate[3] = s_egv4; - envDisplay->s_level[0] = s_egl1; - envDisplay->s_level[1] = s_egl2; - envDisplay->s_level[2] = s_egl3; - envDisplay->s_level[3] = s_egl4; //[/Constructor] } @@ -447,15 +439,16 @@ void OperatorEditor::bind(DexedAudioProcessor *parent, int op) { parent->opCtrl[op].sclRate->bind(sclRateScaling); parent->opCtrl[op].ampModSens->bind(ampModSens); parent->opCtrl[op].velModSens->bind(keyVelSens); + + int offset = parent->opCtrl[op].egRate[0]->getOffset(); + envDisplay->pvalues = &(parent->data[offset]); } - void OperatorEditor::updateGain(float v) { vu->v = v; vu->repaint(); } - void OperatorEditor::updateDisplay() { float freq = opCoarse->getValue(); float fine = opFine->getValue(); diff --git a/Source/OperatorEditor.h b/Source/OperatorEditor.h index d5f0171..bd92829 100644 --- a/Source/OperatorEditor.h +++ b/Source/OperatorEditor.h @@ -23,6 +23,7 @@ //[Headers] -- You can add your own extra header files here -- #include "JuceHeader.h" #include "PluginProcessor.h" +#include "DXComponents.h" #include "DXLookNFeel.h" //[/Headers] diff --git a/Source/PluginData.cpp b/Source/PluginData.cpp new file mode 100644 index 0000000..4df1558 --- /dev/null +++ b/Source/PluginData.cpp @@ -0,0 +1,293 @@ +/** + * + * 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 2 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 + +#include "PluginParam.h" +#include "PluginProcessor.h" +#include "PluginData.h" + + +uint8_t sysexChecksum(const char *sysex) { + uint8_t sum = 0; + for (int i=0; i<4096; i++) + sum = (sum + sysex[i]) % (1 << 8); + return ((1 << 8) - sum); +} + + +void extractProgramNames(const char *block, StringArray &dest) { + char programName[11]; + + dest.clear(); + + for (int i = 0; i < 32; i++) { + memcpy(programName, block + ((i * 128) + 118), 11); + + for (int j = 0; j < 10; j++) { + char c = (unsigned char) programName[j]; + switch (c) { + case 92: + c = 'Y'; + break; /* yen */ + case 126: + c = '>'; + break; /* >> */ + case 127: + c = '<'; + break; /* << */ + default: + if (c < 32 || c > 127) + c = 32; + break; + } + programName[j] = c; + } + programName[10] = 0; + + dest.add(String(programName)); + } +} + +int DexedAudioProcessor::importSysex(const char *imported) { + memcpy(sysex, imported + 6, 4096); + + uint8_t checksum = sysexChecksum(sysex); + extractProgramNames(sysex, programNames); + + if ( checksum != imported[4102] ) { + TRACE("sysex import checksum doesnt match"); + return 1; + } + + return 0; +} + +void DexedAudioProcessor::exportSysex(char *dest) { + uint8_t header[] = { 0xF0, 0x43, 0x00, 0x09, 0x20, 0x00 }; + memcpy(dest, header, 6); + + // copy 32 voices + memcpy(dest+6, sysex, 4096); + + // make checksum for dump + uint8_t footer[] = { sysexChecksum(sysex), 0xF7 }; + + memcpy(dest+4102, footer, 2); +} + +/** + * This function normalize data that comes from corrupted sysex data. + * It used to avoid engine crashing upon extrem values + */ +char normparm(char value, char max) { + if ( value <= max ) + 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. + + return ((float)value)/255 * max; +} + +void DexedAudioProcessor::unpackProgram(int idx) { + char *bulk = sysex + (idx * 128); + + for (int op = 0; op < 6; op++) { + // eg rate and level, brk pt, depth, scaling + memcpy(data + op * 21, bulk + op * 17, 11); + char leftrightcurves = bulk[op * 17 + 11]; + data[op * 21 + 11] = leftrightcurves & 3; + data[op * 21 + 12] = (leftrightcurves >> 2) & 3; + char detune_rs = bulk[op * 17 + 12]; + data[op * 21 + 13] = detune_rs & 7; + char kvs_ams = bulk[op * 17 + 13]; + data[op * 21 + 14] = kvs_ams & 3; + data[op * 21 + 15] = kvs_ams >> 2; + data[op * 21 + 16] = bulk[op * 17 + 14]; // output level + char fcoarse_mode = bulk[op * 17 + 15]; + data[op * 21 + 17] = fcoarse_mode & 1; + data[op * 21 + 18] = fcoarse_mode >> 1; + data[op * 21 + 19] = bulk[op * 17 + 16]; // fine freq + data[op * 21 + 20] = detune_rs >> 3; + } + memcpy(data + 126, bulk + 102, 9); // pitch env, algo + char oks_fb = bulk[111]; + data[135] = oks_fb & 7; + data[136] = oks_fb >> 3; + memcpy(data + 137, bulk + 112, 4); // lfo + char lpms_lfw_lks = bulk[116]; + data[141] = lpms_lfw_lks & 1; + data[142] = (lpms_lfw_lks >> 1) & 7; + data[143] = lpms_lfw_lks >> 4; + memcpy(data + 144, bulk + 117, 11); // transpose, name + data[155] = 1; // operator on/off + data[156] = 1; + data[157] = 1; + data[158] = 1; + data[159] = 1; + data[160] = 1; +} + +void DexedAudioProcessor::packProgram(int idx, const char *name) { + char *bulk = sysex + (idx * 128); + + for(int op = 0; op < 6; op++) { + // eg rate and level, brk pt, depth, scaling + memcpy(bulk + op * 17, data + op * 21, 11); + int pp = op*17; + int up = op*21; + + // left curves + bulk[pp+11] = (data[up+11]&0x03) | ((data[up+12]&0x03) << 2); + bulk[pp+12] = (data[up+13]&0x07) | ((data[up+20]&0x0f) << 3); + // kvs_ams + bulk[pp+13] = (data[up+14]&0x03) | ((data[up+15]&0x07) << 2); + // output lvl + bulk[pp+14] = data[up+16]; + // fcoarse_mode + bulk[pp+15] = (data[up+17]&0x01) | ((data[up+18]&0x1f) << 1); + // fine freq + bulk[pp+16] = data[up+19]; + } + memcpy(bulk + 102, data + 126, 9); // pitch env, algo + bulk[111] = (data[135]&0x07) | ((data[136]&0x01) << 3); + memcpy(bulk + 112, data + 137, 4); // lfo + bulk[116] = (data[141]&0x01) | (((data[142]&0x07) << 1) | ((data[143]&0x07) << 4)); + bulk[117] = data[144]; + int eos = 0; + for(int i=0; i < 10; i++) { + char c = name[i]; + if ( c == 0 ) + eos = 1; + if ( eos ) { + bulk[117+i] = ' '; + continue; + } + c = c < 32 ? ' ' : c; + c = c > 127 ? ' ' : c; + bulk[117+i] = c; + } + + char programName[11]; + memcpy(programName, bulk+117, 10); + programName[10] = 0; + programNames.set(idx, String(programName)); +} + +void DexedAudioProcessor::updateProgramFromSysex(const uint8 *rawdata) { + memcpy(data, rawdata, 160); + refreshUI = true; +} + +void DexedAudioProcessor::loadBuiltin(int idx) { + InputStream *is = builtin_pgm->createStreamForEntry(idx); + + if ( is == NULL ) { + TRACE("ENTRY IN ZIP NOT FOUND"); + return; + } + + uint8_t syx_data[4104]; + is->read(&syx_data, 4104); + delete is; + + importSysex((char *) &syx_data); +} + +#define CURRENT_PLUGINSTATE_VERSION 2 +struct PluginState { + int version; + uint8_t sysex[4104]; + uint8_t program[161]; + float cutoff; + float reso; + int programNum; +}; + +//============================================================================== +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 + + PluginState state; + + state.version = CURRENT_PLUGINSTATE_VERSION; + + exportSysex((char *)(&state.sysex)); + memcpy(state.program, data, 161); + state.cutoff = fx.uiCutoff; + state.reso = fx.uiReso; + state.programNum = currentProgram; + + destData.insert(&state, sizeof(PluginState), 0); +} + +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 + + PluginState state; + + if ( sizeInBytes < sizeof(PluginState) ) { + TRACE("too small plugin state size %d", sizeInBytes); + return; + } + + if ( sizeInBytes > sizeof(PluginState) ) { + TRACE("too big plugin state size %d", sizeInBytes); + sizeInBytes = sizeof(PluginState); + } + + memcpy((void *) &state, source, sizeInBytes); + + if ( state.version != CURRENT_PLUGINSTATE_VERSION ) { + TRACE("version of VST chunk is not compatible, bailing out"); + return; + } + + importSysex((char *) state.sysex); + memcpy(data, state.program, 161); + + fx.uiCutoff = state.cutoff; + fx.uiReso = state.reso; + currentProgram = state.programNum; + + lastStateSave = (long) time(NULL); + TRACE("setting VST STATE"); + updateUI(); +} + +//============================================================================== +/*void DexedAudioProcessor::getCurrentProgramStateInformation( + MemoryBlock& destData) { + destData.insert(data, 161, 0); + } + + void DexedAudioProcessor::setCurrentProgramStateInformation(const void* source, + int sizeInBytes) { + memcpy((void *) data, source, sizeInBytes); + updateUI(); + }*/ diff --git a/Source/PluginData.h b/Source/PluginData.h new file mode 100644 index 0000000..cdda13e --- /dev/null +++ b/Source/PluginData.h @@ -0,0 +1,27 @@ +/** + * + * 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 2 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" + + +#endif // PLUGINDATA_H_INCLUDED diff --git a/Source/PluginEditor.cpp b/Source/PluginEditor.cpp index 323c4bf..1486954 100755 --- a/Source/PluginEditor.cpp +++ b/Source/PluginEditor.cpp @@ -212,10 +212,9 @@ void DexedAudioProcessorEditor::buttonClicked(Button *buttonThatWasClicked) { for(int i=0;ibuiltin_pgm->getNumEntries();i++) { const ZipFile::ZipEntry *e = processor->builtin_pgm->getEntry(i); - cart.add(e->filename.dropLastCharacters(4)); - } + AlertWindow dialog(String("Builtin cartridges"), "", AlertWindow::NoIcon, this); dialog.addComboBox(String("cart"), cart); dialog.addButton("OK", 0, KeyPress(KeyPress::returnKey)); @@ -234,7 +233,7 @@ void DexedAudioProcessorEditor::buttonClicked(Button *buttonThatWasClicked) { if (buttonThatWasClicked == aboutButton) { AlertWindow::showMessageBoxAsync(AlertWindow::NoIcon, "DEXED - DX Emulator 0.3", "https://github.com/asb2m10/dexed\n" - "(c) 2013 Pascal Gauthier\nUnder the GPL v2\n\n" + "(c) 2013-2014 Pascal Gauthier\nUnder the GPL v2\n\n" "Based on Music Synthesizer for Android\nhttps://code.google.com/p/music-synthesizer-for-android"); return; } diff --git a/Source/PluginEditor.h b/Source/PluginEditor.h index 90483eb..ff0d774 100755 --- a/Source/PluginEditor.h +++ b/Source/PluginEditor.h @@ -25,7 +25,7 @@ #include "PluginProcessor.h" #include "OperatorEditor.h" #include "GlobalEditor.h" -#include "DXLookNFeel.h" +#include "DXComponents.h" //============================================================================== /** diff --git a/Source/PluginParam.cpp b/Source/PluginParam.cpp index 2d2a190..01fe8af 100755 --- a/Source/PluginParam.cpp +++ b/Source/PluginParam.cpp @@ -18,8 +18,6 @@ * Boston, MA 02110-1301 USA. */ -#include - #include "PluginParam.h" #include "PluginProcessor.h" #include "PluginEditor.h" @@ -362,155 +360,6 @@ void DexedAudioProcessor::initCtrl() { } } -int DexedAudioProcessor::importSysex(const char *imported) { - memcpy(sysex, imported + 6, 4096); - for (int i = 0; i < 32; i++) { - memcpy(patchNames[i], sysex + ((i * 128) + 118), 11); - - for (int j = 0; j < 10; j++) { - char c = (unsigned char) patchNames[i][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; - } - patchNames[i][j] = c; - } - patchNames[i][10] = 0; - } - return 0; -} - -void DexedAudioProcessor::exportSysex(char *dest) { - uint8_t header[] = { 0xF0, 0x43, 0x00, 0x09, 0x20, 0x00 }; - memcpy(dest, header, 6); - - // copy 32 voices - memcpy(dest+6, sysex, 4096); - - // make checksum for dump - uint8_t footer[] = { 0x00, 0xF7 }; - uint8_t sum = 0; - for (int i=0; i<4096; i++) - sum = (sum + sysex[i]) % (1 << 8); - footer[0] = ((1 << 8) - sum); - - memcpy(dest+4102, footer, 2); -} - -/** - * This function normalize data that comes from corrupted sysex data. - * It used to avoid engine crashing upon extrem values - */ -char normparm(char value, char max) { - if ( value <= max ) - 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. - - return ((float)value)/255 * max; -} - - -void DexedAudioProcessor::unpackProgram(int idx) { - char *bulk = sysex + (idx * 128); - - for (int op = 0; op < 6; op++) { - // eg rate and level, brk pt, depth, scaling - memcpy(data + op * 21, bulk + op * 17, 11); - char leftrightcurves = bulk[op * 17 + 11]; - data[op * 21 + 11] = leftrightcurves & 3; - data[op * 21 + 12] = (leftrightcurves >> 2) & 3; - char detune_rs = bulk[op * 17 + 12]; - data[op * 21 + 13] = detune_rs & 7; - char kvs_ams = bulk[op * 17 + 13]; - data[op * 21 + 14] = kvs_ams & 3; - data[op * 21 + 15] = kvs_ams >> 2; - data[op * 21 + 16] = bulk[op * 17 + 14]; // output level - char fcoarse_mode = bulk[op * 17 + 15]; - data[op * 21 + 17] = fcoarse_mode & 1; - data[op * 21 + 18] = fcoarse_mode >> 1; - data[op * 21 + 19] = bulk[op * 17 + 16]; // fine freq - data[op * 21 + 20] = detune_rs >> 3; - } - memcpy(data + 126, bulk + 102, 9); // pitch env, algo - char oks_fb = bulk[111]; - data[135] = oks_fb & 7; - data[136] = oks_fb >> 3; - memcpy(data + 137, bulk + 112, 4); // lfo - char lpms_lfw_lks = bulk[116]; - data[141] = lpms_lfw_lks & 1; - data[142] = (lpms_lfw_lks >> 1) & 7; - data[143] = lpms_lfw_lks >> 4; - memcpy(data + 144, bulk + 117, 11); // transpose, name - data[155] = 1; // operator on/off - data[156] = 1; - data[157] = 1; - data[158] = 1; - data[159] = 1; - data[160] = 1; -} - -void DexedAudioProcessor::packProgram(int idx, const char *name) { - char *bulk = sysex + (idx * 128); - - for(int op = 0; op < 6; op++) { - // eg rate and level, brk pt, depth, scaling - memcpy(bulk + op * 17, data + op * 21, 11); - int pp = op*17; - int up = op*21; - - // left curves - bulk[pp+11] = (data[up+11]&0x03) | ((data[up+12]&0x03) << 2); - bulk[pp+12] = (data[up+13]&0x07) | ((data[up+20]&0x0f) << 3); - // kvs_ams - bulk[pp+13] = (data[up+14]&0x03) | ((data[up+15]&0x07) << 2); - // output lvl - bulk[pp+14] = data[up+16]; - // fcoarse_mode - bulk[pp+15] = (data[up+17]&0x01) | ((data[up+18]&0x1f) << 1); - // fine freq - bulk[pp+16] = data[up+19]; - } - memcpy(bulk + 102, data + 126, 9); // pitch env, algo - bulk[111] = (data[135]&0x07) | ((data[136]&0x01) << 3); - memcpy(bulk + 112, data + 137, 4); // lfo - bulk[116] = (data[141]&0x01) | (((data[142]&0x07) << 1) | ((data[143]&0x07) << 4)); - bulk[117] = data[144]; - int eos = 0; - for(int i=0; i < 10; i++) { - char c = name[i]; - if ( c == 0 ) - eos = 1; - if ( eos ) { - bulk[117+i] = ' '; - continue; - } - c = c < 32 ? ' ' : c; - c = c > 127 ? ' ' : c; - bulk[117+i] = c; - } - - memcpy(patchNames[idx], bulk+117, 10); - patchNames[idx][10] = 0; -} - -void DexedAudioProcessor::updateProgramFromSysex(const uint8 *rawdata) { - memcpy(data, rawdata, 160); - refreshUI = true; -} - void DexedAudioProcessor::setDxValue(int offset, int v) { TRACE("setting dx %d %d", offset, v); refreshVoice = true; @@ -524,21 +373,6 @@ void DexedAudioProcessor::setDxValue(int offset, int v) { midiOut.addEvent(msg, 7, 0); } -void DexedAudioProcessor::loadBuiltin(int idx) { - InputStream *is = builtin_pgm->createStreamForEntry(idx); - - if ( is == NULL ) { - TRACE("ENTRY IN ZIP NOT FOUND"); - return; - } - - uint8_t syx_data[4104]; - is->read(&syx_data, 4104); - delete is; - - importSysex((char *) &syx_data); -} - void DexedAudioProcessor::unbindUI() { for (int i = 0; i < ctrl.size(); i++) { ctrl[i]->unbind(); @@ -589,7 +423,7 @@ void DexedAudioProcessor::setCurrentProgram(int index) { const String DexedAudioProcessor::getProgramName(int index) { if (index >= 32) index = 31; - return String(patchNames[index]); + return programNames[index]; } void DexedAudioProcessor::changeProgramName(int index, const String& newName) { @@ -603,82 +437,5 @@ const String DexedAudioProcessor::getParameterText(int index) { return ctrl[index]->getValueDisplay(); } -#define CURRENT_PLUGINSTATE_VERSION 2 -struct PluginState { - int version; - uint8_t sysex[4104]; - uint8_t program[161]; - float cutoff; - float reso; - int programNum; -}; -//============================================================================== -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 - - PluginState state; - - state.version = CURRENT_PLUGINSTATE_VERSION; - - exportSysex((char *)(&state.sysex)); - memcpy(state.program, data, 161); - state.cutoff = fx.uiCutoff; - state.reso = fx.uiReso; - state.programNum = currentProgram; - - destData.insert(&state, sizeof(PluginState), 0); -} - -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 - - PluginState state; - - if ( sizeInBytes < sizeof(PluginState) ) { - TRACE("too small plugin state size %d", sizeInBytes); - return; - } - - if ( sizeInBytes > sizeof(PluginState) ) { - TRACE("too big plugin state size %d", sizeInBytes); - sizeInBytes = sizeof(PluginState); - } - - memcpy((void *) &state, source, sizeInBytes); - - if ( state.version != CURRENT_PLUGINSTATE_VERSION ) { - TRACE("version of VST chunk is not compatible, bailing out"); - return; - } - importSysex((char *) state.sysex); - memcpy(data, state.program, 161); - - fx.uiCutoff = state.cutoff; - fx.uiReso = state.reso; - currentProgram = state.programNum; - - lastStateSave = (long) time(NULL); - TRACE("setting VST STATE"); - updateUI(); -} - -//============================================================================== -/*void DexedAudioProcessor::getCurrentProgramStateInformation( - MemoryBlock& destData) { - destData.insert(data, 161, 0); -} - -void DexedAudioProcessor::setCurrentProgramStateInformation(const void* source, - int sizeInBytes) { - memcpy((void *) data, source, sizeInBytes); - updateUI(); -}*/ diff --git a/Source/PluginProcessor.h b/Source/PluginProcessor.h index 679f310..38fbd68 100755 --- a/Source/PluginProcessor.h +++ b/Source/PluginProcessor.h @@ -62,8 +62,8 @@ class DexedAudioProcessor : public AudioProcessor int workBlockSize; int currentProgram; char sysex[4096]; - char patchNames[32][13]; - + StringArray programNames; + /** * The last time the state was save, to be able to bypass a VST host bug. */