First commit
This commit is contained in:
commit
56df0ac2d5
38 changed files with 14245 additions and 0 deletions
179
OB-Xd.jucer
Normal file
179
OB-Xd.jucer
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<JUCERPROJECT id="mxW328" name="Obxd" projectType="audioplug" version="1.4.1"
|
||||||
|
bundleIdentifier="com.Datsounds.Obxd" includeBinaryInAppConfig="1"
|
||||||
|
buildVST="1" buildVST3="0" buildAU="1" buildRTAS="0" buildAAX="0"
|
||||||
|
pluginName="OB-Xd" pluginDesc="Emulation of famous OB-X, OB-Xa and OB-8 synths"
|
||||||
|
pluginManufacturer="Datsounds" pluginManufacturerCode="Dats"
|
||||||
|
pluginCode="Obxd" pluginChannelConfigs="{0, 2}" pluginIsSynth="1"
|
||||||
|
pluginWantsMidiIn="1" pluginProducesMidiOut="0" pluginSilenceInIsSilenceOut="0"
|
||||||
|
pluginEditorRequiresKeys="0" pluginAUExportPrefix="" pluginRTASCategory="ePlugInCategory_SWGenerators"
|
||||||
|
aaxIdentifier="" pluginAAXCategory="" jucerVersion="4.3.0" companyName="2Dat"
|
||||||
|
companyWebsite="http://obxd.wordpress.com" companyEmail="" buildAUv3="0"
|
||||||
|
pluginIsMidiEffectPlugin="0" pluginAUMainType="">
|
||||||
|
<MAINGROUP id="NZ3n4V" name="Obxd">
|
||||||
|
<GROUP id="{90740217-84AB-FD0D-FBC4-CA9EA2C68D5E}" name="Source">
|
||||||
|
<GROUP id="{5F0B15D1-4D92-B2FF-5904-9CF4C3CE645F}" name="Images">
|
||||||
|
<FILE id="IV8Ubu" name="button.png" compile="0" resource="1" file="Source/Images/button.png"/>
|
||||||
|
<FILE id="gUrdhJ" name="knoblsd.png" compile="0" resource="1" file="Source/Images/knoblsd.png"/>
|
||||||
|
<FILE id="FzhdQQ" name="knobssd.png" compile="0" resource="1" file="Source/Images/knobssd.png"/>
|
||||||
|
<FILE id="syMyon" name="legato.png" compile="0" resource="1" file="Source/Images/legato.png"/>
|
||||||
|
<FILE id="kwaOoZ" name="main.png" compile="0" resource="1" file="Source/Images/main.png"/>
|
||||||
|
<FILE id="UHyt7V" name="voices.png" compile="0" resource="1" file="Source/Images/voices.png"/>
|
||||||
|
</GROUP>
|
||||||
|
<GROUP id="{6995BDF2-263F-3CA7-8CA4-4E21F325477A}" name="Gui">
|
||||||
|
<FILE id="zJoidp" name="ButtonList.h" compile="0" resource="0" file="Source/Gui/ButtonList.h"/>
|
||||||
|
<FILE id="lB2ss0" name="Knob.h" compile="0" resource="0" file="Source/Gui/Knob.h"/>
|
||||||
|
<FILE id="YKpBza" name="TooglableButton.h" compile="0" resource="0"
|
||||||
|
file="Source/Gui/TooglableButton.h"/>
|
||||||
|
</GROUP>
|
||||||
|
<GROUP id="{1A73CFC2-DCEB-F0B6-8B56-21F49DA2C76A}" name="Engine">
|
||||||
|
<FILE id="puIwTg" name="AdsrEnvelope.h" compile="0" resource="0" file="Source/Engine/AdsrEnvelope.h"/>
|
||||||
|
<FILE id="gX1oGg" name="APInterpolator.h" compile="0" resource="0"
|
||||||
|
file="Source/Engine/APInterpolator.h"/>
|
||||||
|
<FILE id="QrrECt" name="AudioUtils.h" compile="0" resource="0" file="Source/Engine/AudioUtils.h"/>
|
||||||
|
<FILE id="oR4aDr" name="BlepData.h" compile="0" resource="0" file="Source/Engine/BlepData.h"/>
|
||||||
|
<FILE id="Kfut62" name="Decimator.h" compile="0" resource="0" file="Source/Engine/Decimator.h"/>
|
||||||
|
<FILE id="OGpoX0" name="DelayLine.h" compile="0" resource="0" file="Source/Engine/DelayLine.h"/>
|
||||||
|
<FILE id="MD0CpM" name="Filter.h" compile="0" resource="0" file="Source/Engine/Filter.h"/>
|
||||||
|
<FILE id="uAQRsN" name="Lfo.h" compile="0" resource="0" file="Source/Engine/Lfo.h"/>
|
||||||
|
<FILE id="hisHmA" name="midiMap.h" compile="0" resource="0" file="Source/Engine/midiMap.h"/>
|
||||||
|
<FILE id="PCXDan" name="Motherboard.h" compile="0" resource="0" file="Source/Engine/Motherboard.h"/>
|
||||||
|
<FILE id="VMrHE6" name="ObxdBank.h" compile="0" resource="0" file="Source/Engine/ObxdBank.h"/>
|
||||||
|
<FILE id="kuzEP4" name="ObxdOscillatorB.h" compile="0" resource="0"
|
||||||
|
file="Source/Engine/ObxdOscillatorB.h"/>
|
||||||
|
<FILE id="WpXJsN" name="ObxdVoice.h" compile="0" resource="0" file="Source/Engine/ObxdVoice.h"/>
|
||||||
|
<FILE id="mATgXj" name="Params.h" compile="0" resource="0" file="Source/Engine/Params.h"/>
|
||||||
|
<FILE id="gcujnI" name="ParamsEnum.h" compile="0" resource="0" file="Source/Engine/ParamsEnum.h"/>
|
||||||
|
<FILE id="rkbmLG" name="ParamSmoother.h" compile="0" resource="0" file="Source/Engine/ParamSmoother.h"/>
|
||||||
|
<FILE id="upfVOc" name="PulseOsc.h" compile="0" resource="0" file="Source/Engine/PulseOsc.h"/>
|
||||||
|
<FILE id="cJCh5P" name="SawOsc.h" compile="0" resource="0" file="Source/Engine/SawOsc.h"/>
|
||||||
|
<FILE id="gXSGsx" name="SynthEngine.h" compile="0" resource="0" file="Source/Engine/SynthEngine.h"/>
|
||||||
|
<FILE id="dJvsex" name="TriangleOsc.h" compile="0" resource="0" file="Source/Engine/TriangleOsc.h"/>
|
||||||
|
<FILE id="eM2bUm" name="VoiceQueue.h" compile="0" resource="0" file="Source/Engine/VoiceQueue.h"/>
|
||||||
|
</GROUP>
|
||||||
|
<FILE id="QQwhFQ" name="PluginProcessor.cpp" compile="1" resource="0"
|
||||||
|
file="Source/PluginProcessor.cpp"/>
|
||||||
|
<FILE id="LYHxdB" name="PluginProcessor.h" compile="0" resource="0"
|
||||||
|
file="Source/PluginProcessor.h"/>
|
||||||
|
<FILE id="VISBqh" name="PluginEditor.cpp" compile="1" resource="0"
|
||||||
|
file="Source/PluginEditor.cpp"/>
|
||||||
|
<FILE id="LkXqq2" name="PluginEditor.h" compile="0" resource="0" file="Source/PluginEditor.h"/>
|
||||||
|
</GROUP>
|
||||||
|
</MAINGROUP>
|
||||||
|
<EXPORTFORMATS>
|
||||||
|
<XCODE_MAC targetFolder="Builds/MacOSX" vstFolder="modules/vstsdk3" extraCompilerFlags="-I../../modules/vstsdk3"
|
||||||
|
vst3Folder="modules/vstsdk3">
|
||||||
|
<CONFIGURATIONS>
|
||||||
|
<CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="Obxd" osxArchitecture="64BitUniversal"
|
||||||
|
stripLocalSymbols="0" osxCompatibility="10.6 SDK" osxSDK="default"
|
||||||
|
linkTimeOptimisation="0"/>
|
||||||
|
<CONFIGURATION name="Release" isDebug="0" optimisation="3" targetName="Obxd"
|
||||||
|
osxArchitecture="64BitUniversal" stripLocalSymbols="1" osxCompatibility="10.6 SDK"
|
||||||
|
osxSDK="default" linkTimeOptimisation="0"/>
|
||||||
|
</CONFIGURATIONS>
|
||||||
|
<MODULEPATHS>
|
||||||
|
<MODULEPATH id="juce_opengl" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_gui_extra" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_gui_basics" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_graphics" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_events" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_data_structures" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_core" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_audio_processors" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_audio_plugin_client" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_audio_formats" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_audio_devices" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_audio_basics" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_audio_utils" path="modules"/>
|
||||||
|
</MODULEPATHS>
|
||||||
|
</XCODE_MAC>
|
||||||
|
<VS2010 targetFolder="Builds/VisualStudio2010" vstFolder="modules/vstsdk3">
|
||||||
|
<CONFIGURATIONS>
|
||||||
|
<CONFIGURATION name="Release32" winWarningLevel="2" generateManifest="1" winArchitecture="32-bit"
|
||||||
|
isDebug="0" optimisation="3" targetName="Obxd" useRuntimeLibDLL="0"/>
|
||||||
|
<CONFIGURATION name="Release64" winWarningLevel="2" generateManifest="1" winArchitecture="x64"
|
||||||
|
optimisation="3" targetName="Obxd64" useRuntimeLibDLL="0"/>
|
||||||
|
</CONFIGURATIONS>
|
||||||
|
<MODULEPATHS>
|
||||||
|
<MODULEPATH id="juce_opengl" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_gui_extra" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_gui_basics" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_graphics" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_events" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_data_structures" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_core" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_audio_utils" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_audio_processors" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_audio_plugin_client" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_audio_formats" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_audio_devices" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_audio_basics" path="modules"/>
|
||||||
|
</MODULEPATHS>
|
||||||
|
</VS2010>
|
||||||
|
<LINUX_MAKE targetFolder="Builds/LinuxMakefile" vstFolder="modules/vstsdk2.4">
|
||||||
|
<CONFIGURATIONS>
|
||||||
|
<CONFIGURATION name="Release64" libraryPath="/usr/X11R6/lib/" isDebug="0" optimisation="3"
|
||||||
|
targetName="Obxd64"/>
|
||||||
|
<CONFIGURATION name="Release32" libraryPath="/usr/X11R6/lib/" linuxArchitecture="-m32"
|
||||||
|
optimisation="3" targetName="Obxd"/>
|
||||||
|
</CONFIGURATIONS>
|
||||||
|
<MODULEPATHS>
|
||||||
|
<MODULEPATH id="juce_opengl" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_gui_extra" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_gui_basics" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_graphics" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_events" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_data_structures" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_core" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_audio_utils" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_audio_processors" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_audio_plugin_client" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_audio_formats" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_audio_devices" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_audio_basics" path="modules"/>
|
||||||
|
</MODULEPATHS>
|
||||||
|
</LINUX_MAKE>
|
||||||
|
<VS2013 targetFolder="Builds/VisualStudio2013">
|
||||||
|
<CONFIGURATIONS>
|
||||||
|
<CONFIGURATION name="Debug" winWarningLevel="4" generateManifest="1" winArchitecture="x64"
|
||||||
|
isDebug="1" optimisation="3" targetName="Obxd"/>
|
||||||
|
<CONFIGURATION name="Release64" winWarningLevel="4" generateManifest="1" winArchitecture="x64"
|
||||||
|
isDebug="0" optimisation="3" targetName="Obxd64" useRuntimeLibDLL="0"/>
|
||||||
|
<CONFIGURATION name="Release32" winWarningLevel="4" generateManifest="1" winArchitecture="32-bit"
|
||||||
|
isDebug="0" optimisation="3" targetName="Obxd" useRuntimeLibDLL="0"/>
|
||||||
|
</CONFIGURATIONS>
|
||||||
|
<MODULEPATHS>
|
||||||
|
<MODULEPATH id="juce_opengl" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_gui_extra" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_gui_basics" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_graphics" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_events" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_data_structures" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_core" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_audio_utils" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_audio_processors" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_audio_plugin_client" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_audio_formats" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_audio_devices" path="modules"/>
|
||||||
|
<MODULEPATH id="juce_audio_basics" path="modules"/>
|
||||||
|
</MODULEPATHS>
|
||||||
|
</VS2013>
|
||||||
|
</EXPORTFORMATS>
|
||||||
|
<MODULES>
|
||||||
|
<MODULES id="juce_audio_basics" showAllCode="1" useLocalCopy="1"/>
|
||||||
|
<MODULES id="juce_audio_devices" showAllCode="1" useLocalCopy="1"/>
|
||||||
|
<MODULES id="juce_audio_formats" showAllCode="1" useLocalCopy="1"/>
|
||||||
|
<MODULES id="juce_audio_plugin_client" showAllCode="1" useLocalCopy="1"/>
|
||||||
|
<MODULES id="juce_audio_processors" showAllCode="1" useLocalCopy="1"/>
|
||||||
|
<MODULE id="juce_audio_utils" showAllCode="1" useLocalCopy="1"/>
|
||||||
|
<MODULES id="juce_core" showAllCode="1" useLocalCopy="1"/>
|
||||||
|
<MODULES id="juce_data_structures" showAllCode="1" useLocalCopy="1"/>
|
||||||
|
<MODULES id="juce_events" showAllCode="1" useLocalCopy="1"/>
|
||||||
|
<MODULES id="juce_graphics" showAllCode="1" useLocalCopy="1"/>
|
||||||
|
<MODULES id="juce_gui_basics" showAllCode="1" useLocalCopy="1"/>
|
||||||
|
<MODULES id="juce_gui_extra" showAllCode="1" useLocalCopy="1"/>
|
||||||
|
<MODULES id="juce_opengl" showAllCode="1" useLocalCopy="1"/>
|
||||||
|
</MODULES>
|
||||||
|
<JUCEOPTIONS JUCE_QUICKTIME="disabled"/>
|
||||||
|
</JUCERPROJECT>
|
45
Source/Engine/APInterpolator.h
Executable file
45
Source/Engine/APInterpolator.h
Executable file
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
This file is part of Obxd synthesizer.
|
||||||
|
|
||||||
|
Copyright © 2013-2014 Filatov Vadim
|
||||||
|
|
||||||
|
Contact author via email :
|
||||||
|
justdat_@_e1.ru
|
||||||
|
|
||||||
|
This file may be licensed under the terms of of the
|
||||||
|
GNU General Public License Version 2 (the ``GPL'').
|
||||||
|
|
||||||
|
Software distributed under the License is distributed
|
||||||
|
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
|
||||||
|
express or implied. See the GPL for the specific language
|
||||||
|
governing rights and limitations.
|
||||||
|
|
||||||
|
You should have received a copy of the GPL along with this
|
||||||
|
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||||
|
or write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include "SynthEngine.h"
|
||||||
|
class ApInterpolator
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
const float Nu;
|
||||||
|
float zd;
|
||||||
|
float li;
|
||||||
|
public :
|
||||||
|
ApInterpolator() : Nu(( 1 - 0.5) /(1 + 0.5))
|
||||||
|
{
|
||||||
|
zd = 0;
|
||||||
|
li=0;
|
||||||
|
};
|
||||||
|
inline float getInterp(float in)
|
||||||
|
{
|
||||||
|
float out = Nu * ( in - zd) + li;
|
||||||
|
zd = out;
|
||||||
|
li = in;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
};
|
150
Source/Engine/AdsrEnvelope.h
Executable file
150
Source/Engine/AdsrEnvelope.h
Executable file
|
@ -0,0 +1,150 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
This file is part of Obxd synthesizer.
|
||||||
|
|
||||||
|
Copyright © 2013-2014 Filatov Vadim
|
||||||
|
|
||||||
|
Contact author via email :
|
||||||
|
justdat_@_e1.ru
|
||||||
|
|
||||||
|
This file may be licensed under the terms of of the
|
||||||
|
GNU General Public License Version 2 (the ``GPL'').
|
||||||
|
|
||||||
|
Software distributed under the License is distributed
|
||||||
|
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
|
||||||
|
express or implied. See the GPL for the specific language
|
||||||
|
governing rights and limitations.
|
||||||
|
|
||||||
|
You should have received a copy of the GPL along with this
|
||||||
|
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||||
|
or write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include "ObxdVoice.h"
|
||||||
|
class AdsrEnvelope
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
float Value;
|
||||||
|
float attack, decay, sustain, release;
|
||||||
|
float ua,ud,us,ur;
|
||||||
|
float coef;
|
||||||
|
int state;//1 - attack 2- decay 3 - sustain 4 - release 5-silence
|
||||||
|
float SampleRate;
|
||||||
|
float uf;
|
||||||
|
public:
|
||||||
|
AdsrEnvelope()
|
||||||
|
{
|
||||||
|
uf = 1;
|
||||||
|
Value = 0.0;
|
||||||
|
attack=decay=sustain=release=0.0001;
|
||||||
|
ua=ud=us=ur=0.0001;
|
||||||
|
coef = 0;
|
||||||
|
state = 5;
|
||||||
|
SampleRate = 44000;
|
||||||
|
}
|
||||||
|
void ResetEnvelopeState()
|
||||||
|
{
|
||||||
|
Value = 0.0;
|
||||||
|
state = 5;
|
||||||
|
}
|
||||||
|
void setSampleRate(float sr)
|
||||||
|
{
|
||||||
|
SampleRate = sr;
|
||||||
|
}
|
||||||
|
void setUniqueDeriviance(float der)
|
||||||
|
{
|
||||||
|
uf = der;
|
||||||
|
setAttack(ua);
|
||||||
|
setDecay(ud);
|
||||||
|
setSustain(us);
|
||||||
|
setRelease(ur);
|
||||||
|
}
|
||||||
|
void setAttack(float atk)
|
||||||
|
{
|
||||||
|
ua = atk;
|
||||||
|
attack = atk*uf;
|
||||||
|
if(state == 1)
|
||||||
|
coef = (float)((log(0.001) - log(1.3)) / (SampleRate * (atk) / 1000));
|
||||||
|
}
|
||||||
|
void setDecay(float dec)
|
||||||
|
{
|
||||||
|
ud = dec;
|
||||||
|
decay = dec*uf;
|
||||||
|
if(state == 2)
|
||||||
|
coef = (float)((log(jmin(sustain + 0.0001,0.99)) - log(1.0)) / (SampleRate * (dec) / 1000));
|
||||||
|
}
|
||||||
|
void setSustain(float sust)
|
||||||
|
{
|
||||||
|
us = sust;
|
||||||
|
sustain = sust;
|
||||||
|
if(state == 2)
|
||||||
|
coef = (float)((log(jmin(sustain + 0.0001,0.99)) - log(1.0)) / (SampleRate * (decay) / 1000));
|
||||||
|
}
|
||||||
|
void setRelease(float rel)
|
||||||
|
{
|
||||||
|
ur = rel;
|
||||||
|
release = rel*uf;
|
||||||
|
if(state == 4)
|
||||||
|
coef = (float)((log(0.00001) - log(Value + 0.0001)) / (SampleRate * (rel) / 1000));
|
||||||
|
}
|
||||||
|
void triggerAttack()
|
||||||
|
{
|
||||||
|
state = 1;
|
||||||
|
//Value = Value +0.00001f;
|
||||||
|
coef = (float)((log(0.001) - log(1.3)) / (SampleRate * (attack)/1000 ));
|
||||||
|
}
|
||||||
|
void triggerRelease()
|
||||||
|
{
|
||||||
|
if(state!=4)
|
||||||
|
coef = (float)((log(0.00001) - log(Value+0.0001)) / (SampleRate * (release) / 1000));
|
||||||
|
state = 4;
|
||||||
|
}
|
||||||
|
inline bool isActive()
|
||||||
|
{
|
||||||
|
return state!=5;
|
||||||
|
}
|
||||||
|
inline float processSample()
|
||||||
|
{
|
||||||
|
switch (state)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
if (Value - 1 > -0.1)
|
||||||
|
{
|
||||||
|
Value = jmin(Value, 0.99f);
|
||||||
|
state = 2;
|
||||||
|
coef = (float)((log(jmin(sustain + 0.0001, 0.99)) - log(1.0)) / (SampleRate * (decay) / 1000));
|
||||||
|
goto dec;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Value = Value - (1-Value)*(coef);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
dec:
|
||||||
|
if (Value - sustain < 10e-6)
|
||||||
|
{
|
||||||
|
state = 3;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Value =Value + Value * coef;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3: Value = jmin(sustain, 0.9f);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
if (Value > 20e-6)
|
||||||
|
Value = Value + Value * coef + dc;
|
||||||
|
else state = 5;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
Value = 0.0f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
90
Source/Engine/AudioUtils.h
Executable file
90
Source/Engine/AudioUtils.h
Executable file
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
This file is part of Obxd synthesizer.
|
||||||
|
|
||||||
|
Copyright © 2013-2014 Filatov Vadim
|
||||||
|
|
||||||
|
Contact author via email :
|
||||||
|
justdat_@_e1.ru
|
||||||
|
|
||||||
|
This file may be licensed under the terms of of the
|
||||||
|
GNU General Public License Version 2 (the ``GPL'').
|
||||||
|
|
||||||
|
Software distributed under the License is distributed
|
||||||
|
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
|
||||||
|
express or implied. See the GPL for the specific language
|
||||||
|
governing rights and limitations.
|
||||||
|
|
||||||
|
You should have received a copy of the GPL along with this
|
||||||
|
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||||
|
or write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SynthEngine.h"
|
||||||
|
|
||||||
|
const float sq2_12 = 1.0594630943592953f;
|
||||||
|
|
||||||
|
const float dc = 1e-18;
|
||||||
|
const float ln2 = 0.69314718056f;
|
||||||
|
const float mult = ln2 / 12.0;
|
||||||
|
inline static float getPitch(float index)
|
||||||
|
{
|
||||||
|
//Lookup table is not that effective compared to SSE exp
|
||||||
|
//SSE should be on
|
||||||
|
|
||||||
|
//const int mulres = 2;
|
||||||
|
//const int lowerBound = -94;
|
||||||
|
//const int upperBound = 94;
|
||||||
|
//const int lutlen = (upperBound-lowerBound)*2;
|
||||||
|
return 440 * expf(mult * index);
|
||||||
|
//static const float lut [lutlen]={1.929,1.986,2.044,2.104,2.165,2.229,2.294,2.361,2.431,2.502,2.575,2.651,2.728,2.808,2.891,2.975,3.062,3.152,3.245,3.340,3.437,3.538,3.642,3.749,3.858,3.972,4.088,4.208,4.331,4.458,4.589,4.723,4.861,5.004,5.150,5.301,5.457,5.617,5.781,5.951,6.125,6.304,6.489,6.679,6.875,7.076,7.284,7.497,7.717,7.943,8.176,8.415,8.662,8.916,9.177,9.446,9.723,10.008,10.301,10.603,10.913,11.233,11.562,11.901,12.250,12.609,12.978,13.359,13.750,14.153,14.568,14.994,15.434,15.886,16.352,16.831,17.324,17.832,18.354,18.892,19.445,20.015,20.602,21.205,21.827,22.466,23.125,23.802,24.500,25.218,25.957,26.717,27.500,28.306,29.135,29.989,30.868,31.772,32.703,33.661,34.648,35.663,36.708,37.784,38.891,40.030,41.203,42.411,43.654,44.933,46.249,47.605,48.999,50.435,51.913,53.434,55.000,56.612,58.270,59.978,61.735,63.544,65.406,67.323,69.296,71.326,73.416,75.567,77.782,80.061,82.407,84.822,87.307,89.865,92.499,95.209,97.999,100.870,103.826,106.869,110.000,113.223,116.541,119.956,123.471,127.089,130.813,134.646,138.591,142.652,146.832,151.135,155.563,160.122,164.814,169.643,174.614,179.731,184.997,190.418,195.998,201.741,207.652,213.737,220.000,226.446,233.082,239.912,246.942,254.178,261.626,269.292,277.183,285.305,293.665,302.270,311.127,320.244,329.628,339.286,349.228,359.461,369.994,380.836,391.995,403.482,415.305,427.474,440.000,452.893,466.164,479.823,493.883,508.355,523.251,538.584,554.365,570.609,587.330,604.540,622.254,640.487,659.255,678.573,698.456,718.923,739.989,761.672,783.991,806.964,830.609,854.948,880.000,905.786,932.328,959.647,987.767,1016.710,1046.502,1077.167,1108.731,1141.219,1174.659,1209.079,1244.508,1280.975,1318.510,1357.146,1396.913,1437.846,1479.978,1523.344,1567.982,1613.927,1661.219,1709.896,1760.000,1811.572,1864.655,1919.294,1975.533,2033.421,2093.005,2154.334,2217.461,2282.438,2349.318,2418.158,2489.016,2561.950,2637.020,2714.291,2793.826,2875.691,2959.955,3046.689,3135.964,3227.854,3322.438,3419.792,3520.000,3623.144,3729.310,3838.587,3951.066,4066.842,4186.009,4308.668,4434.922,4564.875,4698.636,4836.317,4978.032,5123.899,5274.041,5428.582,5587.652,5751.382,5919.911,6093.377,6271.927,6455.709,6644.875,6839.585,7040.000,7246.288,7458.620,7677.174,7902.133,8133.683,8372.018,8617.337,8869.844,9129.751,9397.273,9672.634,9956.064,10247.798,10548.082,10857.164,11175.304,11502.765,11839.822,12186.755,12543.854,12911.417,13289.750,13679.170,14080.000,14492.576,14917.241,15354.349,15804.266,16267.366,16744.036,17234.674,17739.689,18259.501,18794.545,19345.268,19912.127,20495.597,21096.164,21714.329,22350.607,23005.530,23679.643,24373.510,25087.708,25822.834,26579.501,27358.340,28160.000,28985.151,29834.481,30708.698,31608.532,32534.732,33488.073,34469.348,35479.377,36519.002,37589.091,38690.535,39824.254,40991.194,42192.328,43428.657,44701.214,46011.060,47359.287,48747.020,50175.416,51645.668,53159.002,54716.680,56320.001,57970.303,59668.962,61417.396,63217.063,65069.465,66976.146,68938.697,70958.755,73038.005,75178.182,77381.071,79648.509,81982.388,84384.656,86857.315,89402.429,92022.120,94718.574,97494.040};
|
||||||
|
//if(index > 92.0)
|
||||||
|
// return lut[lutlen-1];
|
||||||
|
//if(index < -94.0)
|
||||||
|
// return lut[0];
|
||||||
|
//index = (index - lowerBound)*mulres;
|
||||||
|
//int mi = floor(index);
|
||||||
|
//float ofs = index-mi;
|
||||||
|
//
|
||||||
|
// return lut[mi] + (lut[mi+1] - lut[mi]) * ofs;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline static float tptlpupw(float & state , float inp , float cutoff , float srInv)
|
||||||
|
{
|
||||||
|
cutoff = (cutoff * srInv)*juce::float_Pi;
|
||||||
|
double v = (inp - state) * cutoff / (1 + cutoff);
|
||||||
|
double res = v + state;
|
||||||
|
state = res + v;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static float tptlp(float& state,float inp,float cutoff,float srInv)
|
||||||
|
{
|
||||||
|
cutoff = tan(cutoff * (srInv)* (juce::float_Pi)) ;
|
||||||
|
double v = (inp - state) * cutoff / (1 + cutoff);
|
||||||
|
double res = v + state;
|
||||||
|
state = res + v;
|
||||||
|
return res;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline static float tptpc(float& state,float inp,float cutoff)
|
||||||
|
{
|
||||||
|
double v = (inp - state) * cutoff / (1 + cutoff);
|
||||||
|
double res = v + state;
|
||||||
|
state = res + v;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static float linsc(float param,const float min,const float max)
|
||||||
|
{
|
||||||
|
return (param) * (max - min) + min;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static float logsc(float param, const float min,const float max,const float rolloff = 19.0f)
|
||||||
|
{
|
||||||
|
return ((expf(param * logf(rolloff+1)) - 1.0f) / (rolloff)) * (max-min) + min;
|
||||||
|
}
|
||||||
|
|
35
Source/Engine/BlepData.h
Executable file
35
Source/Engine/BlepData.h
Executable file
File diff suppressed because one or more lines are too long
86
Source/Engine/Decimator.h
Executable file
86
Source/Engine/Decimator.h
Executable file
|
@ -0,0 +1,86 @@
|
||||||
|
#pragma once
|
||||||
|
//MusicDsp
|
||||||
|
// T.Rochebois
|
||||||
|
//still indev
|
||||||
|
class Decimator17
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
const float h0,h1,h3,h5,h7,h9,h11,h13,h15,h17;
|
||||||
|
float R1,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,R12,R13,R14,R15,R16,R17;
|
||||||
|
public:
|
||||||
|
Decimator17()
|
||||||
|
: h0(0.5)
|
||||||
|
, h1(0.314356238)
|
||||||
|
, h3(-0.0947515890)
|
||||||
|
, h5(0.0463142134)
|
||||||
|
, h7(-0.0240881704)
|
||||||
|
, h9(0.0120250406)
|
||||||
|
, h11(-0.00543170841)
|
||||||
|
, h13(0.00207426259)
|
||||||
|
, h15(-0.000572688237)
|
||||||
|
, h17(5.18944944e-005)
|
||||||
|
{
|
||||||
|
R1=R2=R3=R4=R5=R6=R7=R8=R9=R10=R11=R12=R13=R14=R15=R16=R17=0;
|
||||||
|
}
|
||||||
|
float Calc(const float x0,const float x1)
|
||||||
|
{
|
||||||
|
float h17x0 = h17 *x0;
|
||||||
|
float h15x0 = h15 *x0;
|
||||||
|
float h13x0 = h13 *x0;
|
||||||
|
float h11x0= h11 *x0;
|
||||||
|
float h9x0=h9*x0;
|
||||||
|
float h7x0=h7*x0;
|
||||||
|
float h5x0=h5*x0;
|
||||||
|
float h3x0=h3*x0;
|
||||||
|
float h1x0=h1*x0;
|
||||||
|
float R18=R17+h17x0;
|
||||||
|
R17 = R16 + h15x0;
|
||||||
|
R16 = R15 + h13x0;
|
||||||
|
R15 = R14 + h11x0;
|
||||||
|
R14 = R13 + h9x0;
|
||||||
|
R13 = R12 + h7x0;
|
||||||
|
R12 = R11 + h5x0;
|
||||||
|
R11 = R10 + h3x0;
|
||||||
|
R10 = R9 + h1x0;
|
||||||
|
R9 = R8 + h1x0 + h0*x1;
|
||||||
|
R8 = R7 + h3x0;
|
||||||
|
R7 = R6 + h5x0;
|
||||||
|
R6 = R5 + h7x0;
|
||||||
|
R5 = R4 + h9x0;
|
||||||
|
R4 = R3 + h11x0;
|
||||||
|
R3 = R2 + h13x0;
|
||||||
|
R2 = R1 + h15x0;
|
||||||
|
R1 = h17x0;
|
||||||
|
return R18;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
class Decimator9
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
const float h0,h1,h3,h5,h7,h9;
|
||||||
|
float R1,R2,R3,R4,R5,R6,R7,R8,R9;
|
||||||
|
public:
|
||||||
|
Decimator9() : h0(8192/16384.0f),h1(5042/16384.0f),h3(-1277/16384.0f),h5(429/16384.0f),h7(-116/16384.0f),h9(18/16384.0f)
|
||||||
|
{
|
||||||
|
R1=R2=R3=R4=R5=R6=R7=R8=R9=0.0f;
|
||||||
|
}
|
||||||
|
inline float Calc(const float x0,const float x1)
|
||||||
|
{
|
||||||
|
float h9x0=h9*x0;
|
||||||
|
float h7x0=h7*x0;
|
||||||
|
float h5x0=h5*x0;
|
||||||
|
float h3x0=h3*x0;
|
||||||
|
float h1x0=h1*x0;
|
||||||
|
float R10=R9+h9x0;
|
||||||
|
R9=R8+h7x0;
|
||||||
|
R8=R7+h5x0;
|
||||||
|
R7=R6+h3x0;
|
||||||
|
R6=R5+h1x0;
|
||||||
|
R5=R4+h1x0+h0*x1;
|
||||||
|
R4=R3+h3x0;
|
||||||
|
R3=R2+h5x0;
|
||||||
|
R2=R1+h7x0;
|
||||||
|
R1=h9x0;
|
||||||
|
return R10;
|
||||||
|
}
|
||||||
|
};
|
71
Source/Engine/DelayLine.h
Executable file
71
Source/Engine/DelayLine.h
Executable file
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
This file is part of Obxd synthesizer.
|
||||||
|
|
||||||
|
Copyright © 2013-2014 Filatov Vadim
|
||||||
|
|
||||||
|
Contact author via email :
|
||||||
|
justdat_@_e1.ru
|
||||||
|
|
||||||
|
This file may be licensed under the terms of of the
|
||||||
|
GNU General Public License Version 2 (the ``GPL'').
|
||||||
|
|
||||||
|
Software distributed under the License is distributed
|
||||||
|
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
|
||||||
|
express or implied. See the GPL for the specific language
|
||||||
|
governing rights and limitations.
|
||||||
|
|
||||||
|
You should have received a copy of the GPL along with this
|
||||||
|
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||||
|
or write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include "SynthEngine.h"
|
||||||
|
//Always feed first then get delayed sample!
|
||||||
|
#define DEMAX 64
|
||||||
|
template<unsigned int DM> class DelayLine
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
float dl[DEMAX];
|
||||||
|
int iidx;
|
||||||
|
public:
|
||||||
|
DelayLine()
|
||||||
|
{
|
||||||
|
iidx = 0;
|
||||||
|
zeromem(dl,sizeof(float)*DEMAX);
|
||||||
|
//jassert(DM > DMAX);
|
||||||
|
}
|
||||||
|
inline float feedReturn(float sm)
|
||||||
|
{
|
||||||
|
dl[iidx] = sm;
|
||||||
|
iidx--;
|
||||||
|
iidx=(iidx&(DEMAX-1));
|
||||||
|
return dl[(iidx + DM)&(DEMAX-1)];
|
||||||
|
}
|
||||||
|
inline void fillZeroes()
|
||||||
|
{
|
||||||
|
zeromem(dl,DEMAX*sizeof(float));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template<unsigned int DM> class DelayLineBoolean
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
bool dl[DEMAX];
|
||||||
|
int iidx;
|
||||||
|
public:
|
||||||
|
DelayLineBoolean()
|
||||||
|
{
|
||||||
|
iidx = 0;
|
||||||
|
zeromem(dl,sizeof(bool)*DEMAX);
|
||||||
|
}
|
||||||
|
inline float feedReturn(bool sm)
|
||||||
|
{
|
||||||
|
dl[iidx] = sm;
|
||||||
|
iidx--;
|
||||||
|
iidx=(iidx&(DEMAX-1));
|
||||||
|
return dl[(iidx + DM)&(DEMAX-1)];
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
185
Source/Engine/Filter.h
Executable file
185
Source/Engine/Filter.h
Executable file
|
@ -0,0 +1,185 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
This file is part of Obxd synthesizer.
|
||||||
|
|
||||||
|
Copyright © 2013-2014 Filatov Vadim
|
||||||
|
|
||||||
|
Contact author via email :
|
||||||
|
justdat_@_e1.ru
|
||||||
|
|
||||||
|
This file may be licensed under the terms of of the
|
||||||
|
GNU General Public License Version 2 (the ``GPL'').
|
||||||
|
|
||||||
|
Software distributed under the License is distributed
|
||||||
|
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
|
||||||
|
express or implied. See the GPL for the specific language
|
||||||
|
governing rights and limitations.
|
||||||
|
|
||||||
|
You should have received a copy of the GPL along with this
|
||||||
|
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||||
|
or write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include "ObxdVoice.h"
|
||||||
|
#include <math.h>
|
||||||
|
class Filter
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
float s1,s2,s3,s4;
|
||||||
|
float R;
|
||||||
|
float R24;
|
||||||
|
float rcor,rcorInv;
|
||||||
|
float rcor24,rcor24Inv;
|
||||||
|
|
||||||
|
//24 db multimode
|
||||||
|
float mmt;
|
||||||
|
int mmch;
|
||||||
|
public:
|
||||||
|
float SampleRate;
|
||||||
|
float sampleRateInv;
|
||||||
|
bool bandPassSw;
|
||||||
|
float mm;
|
||||||
|
bool selfOscPush;
|
||||||
|
Filter()
|
||||||
|
{
|
||||||
|
selfOscPush = false;
|
||||||
|
bandPassSw = false;
|
||||||
|
mm=0;
|
||||||
|
s1=s2=s3=s4=0;
|
||||||
|
SampleRate = 44000;
|
||||||
|
sampleRateInv = 1 / SampleRate;
|
||||||
|
rcor =500.0 / 44000;
|
||||||
|
rcorInv = 1 / rcor;
|
||||||
|
rcor24 = 970.0 / 44000;
|
||||||
|
rcor24Inv = 1 / rcor24;
|
||||||
|
R=1;
|
||||||
|
R24=0;
|
||||||
|
}
|
||||||
|
void setMultimode(float m)
|
||||||
|
{
|
||||||
|
mm = m;
|
||||||
|
mmch = (int)(mm * 3);
|
||||||
|
mmt = mm*3-mmch;
|
||||||
|
}
|
||||||
|
inline void setSampleRate(float sr)
|
||||||
|
{
|
||||||
|
SampleRate = sr;
|
||||||
|
sampleRateInv = 1/SampleRate;
|
||||||
|
float rcrate =sqrt((44000/SampleRate));
|
||||||
|
rcor = (500.0 / 44000)*rcrate;
|
||||||
|
rcor24 = (970.0 / 44000)*rcrate;
|
||||||
|
rcorInv = 1 / rcor;
|
||||||
|
rcor24Inv = 1 / rcor24;
|
||||||
|
}
|
||||||
|
inline void setResonance(float res)
|
||||||
|
{
|
||||||
|
R = 1-res;
|
||||||
|
R24 =( 3.5 * res);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float diodePairResistanceApprox(float x)
|
||||||
|
{
|
||||||
|
return (((((0.0103592f)*x + 0.00920833f)*x + 0.185f)*x + 0.05f )*x + 1.0f);
|
||||||
|
//Taylor approx of slightly mismatched diode pair
|
||||||
|
}
|
||||||
|
//resolve 0-delay feedback
|
||||||
|
inline float NR(float sample, float g)
|
||||||
|
{
|
||||||
|
//calculating feedback non-linear transconducance and compensated for R (-1)
|
||||||
|
//Boosting non-linearity
|
||||||
|
float tCfb;
|
||||||
|
if(!selfOscPush)
|
||||||
|
tCfb = diodePairResistanceApprox(s1*0.0876f) - 1.0f;
|
||||||
|
else
|
||||||
|
tCfb = diodePairResistanceApprox(s1*0.0876f) - 1.035f;
|
||||||
|
//float tCfb = 0;
|
||||||
|
//disable non-linearity == digital filter
|
||||||
|
|
||||||
|
//resolve linear feedback
|
||||||
|
float y = ((sample - 2*(s1*(R+tCfb)) - g*s1 - s2)/(1+ g*(2*(R+tCfb)+ g)));
|
||||||
|
|
||||||
|
//float y = ((sample - 2*(s1*(R+tCfb)) - g2*s1 - s2)/(1+ g1*(2*(R+tCfb)+ g2)));
|
||||||
|
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
inline float Apply(float sample,float g)
|
||||||
|
{
|
||||||
|
|
||||||
|
float gpw = tanf(g *sampleRateInv * juce::float_Pi);
|
||||||
|
g = gpw;
|
||||||
|
//float v = ((sample- R * s1*2 - g2*s1 - s2)/(1+ R*g1*2 + g1*g2));
|
||||||
|
float v = NR(sample,g);
|
||||||
|
|
||||||
|
float y1 = v*g + s1;
|
||||||
|
s1 = v*g + y1;
|
||||||
|
|
||||||
|
float y2 = y1*g + s2;
|
||||||
|
s2 = y1*g + y2;
|
||||||
|
|
||||||
|
float mc;
|
||||||
|
if(!bandPassSw)
|
||||||
|
mc = (1-mm)*y2 + (mm)*v;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
mc =2 * ( mm < 0.5 ?
|
||||||
|
((0.5 - mm) * y2 + (mm) * y1):
|
||||||
|
((1-mm) * y1 + (mm-0.5) * v)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mc;
|
||||||
|
}
|
||||||
|
inline float NR24(float sample,float g,float lpc)
|
||||||
|
{
|
||||||
|
float ml = 1 / (1+g);
|
||||||
|
float S = (lpc*(lpc*(lpc*s1 + s2) + s3) +s4)*ml;
|
||||||
|
float G = lpc*lpc*lpc*lpc;
|
||||||
|
float y = (sample - R24 * S) / (1 + R24*G);
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
inline float Apply4Pole(float sample,float g)
|
||||||
|
{
|
||||||
|
float g1 = (float)tan(g *sampleRateInv * juce::float_Pi);
|
||||||
|
g = g1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
float lpc = g / (1 + g);
|
||||||
|
float y0 = NR24(sample,g,lpc);
|
||||||
|
//first low pass in cascade
|
||||||
|
double v = (y0 - s1) * lpc;
|
||||||
|
double res = v + s1;
|
||||||
|
s1 = res + v;
|
||||||
|
//damping
|
||||||
|
s1 =atan(s1*rcor24)*rcor24Inv;
|
||||||
|
|
||||||
|
float y1= res;
|
||||||
|
float y2 = tptpc(s2,y1,g);
|
||||||
|
float y3 = tptpc(s3,y2,g);
|
||||||
|
float y4 = tptpc(s4,y3,g);
|
||||||
|
float mc;
|
||||||
|
switch(mmch)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
mc = ((1 - mmt) * y4 + (mmt) * y3);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
mc = ((1 - mmt) * y3 + (mmt) * y2);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
mc = ((1 - mmt) * y2 + (mmt) * y1);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
mc = y1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mc=0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//half volume comp
|
||||||
|
return mc * (1 + R24 * 0.45);
|
||||||
|
}
|
||||||
|
};
|
159
Source/Engine/Lfo.h
Executable file
159
Source/Engine/Lfo.h
Executable file
|
@ -0,0 +1,159 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
This file is part of Obxd synthesizer.
|
||||||
|
|
||||||
|
Copyright © 2013-2014 Filatov Vadim
|
||||||
|
|
||||||
|
Contact author via email :
|
||||||
|
justdat_@_e1.ru
|
||||||
|
|
||||||
|
This file may be licensed under the terms of of the
|
||||||
|
GNU General Public License Version 2 (the ``GPL'').
|
||||||
|
|
||||||
|
Software distributed under the License is distributed
|
||||||
|
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
|
||||||
|
express or implied. See the GPL for the specific language
|
||||||
|
governing rights and limitations.
|
||||||
|
|
||||||
|
You should have received a copy of the GPL along with this
|
||||||
|
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||||
|
or write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include "SynthEngine.h"
|
||||||
|
class Lfo
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
float phase;
|
||||||
|
float s, sq, sh;
|
||||||
|
float s1;
|
||||||
|
Random rg;
|
||||||
|
float SampleRate;
|
||||||
|
float SampleRateInv;
|
||||||
|
|
||||||
|
float syncRate;
|
||||||
|
bool synced;
|
||||||
|
|
||||||
|
public:
|
||||||
|
float Frequency;
|
||||||
|
float phaseInc;
|
||||||
|
float frUnsc;//frequency value without sync
|
||||||
|
float rawParam;
|
||||||
|
int waveForm;
|
||||||
|
Lfo()
|
||||||
|
{
|
||||||
|
phaseInc = 0;
|
||||||
|
frUnsc=0;
|
||||||
|
syncRate = 1;
|
||||||
|
rawParam=0;
|
||||||
|
synced = false;
|
||||||
|
s1=0;
|
||||||
|
Frequency=1;
|
||||||
|
phase=0;
|
||||||
|
s=sq=sh=0;
|
||||||
|
rg=Random();
|
||||||
|
}
|
||||||
|
void setSynced()
|
||||||
|
{
|
||||||
|
synced = true;
|
||||||
|
recalcRate(rawParam);
|
||||||
|
}
|
||||||
|
void setUnsynced()
|
||||||
|
{
|
||||||
|
synced = false;
|
||||||
|
phaseInc = frUnsc;
|
||||||
|
}
|
||||||
|
void hostSyncRetrigger(float bpm,float quaters)
|
||||||
|
{
|
||||||
|
if(synced)
|
||||||
|
{
|
||||||
|
phaseInc = (bpm/60.0)*syncRate;
|
||||||
|
phase = phaseInc*quaters;
|
||||||
|
phase = (fmod(phase,1)*float_Pi*2-float_Pi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline float getVal()
|
||||||
|
{
|
||||||
|
float Res = 0;
|
||||||
|
if((waveForm &1) !=0 )
|
||||||
|
Res+=s;
|
||||||
|
if((waveForm&2)!=0)
|
||||||
|
Res+=sq;
|
||||||
|
if((waveForm&4)!=0)
|
||||||
|
Res+=sh;
|
||||||
|
return tptlpupw(s1, Res,3000,SampleRateInv);
|
||||||
|
}
|
||||||
|
void setSamlpeRate(float sr)
|
||||||
|
{
|
||||||
|
SampleRate=sr;
|
||||||
|
SampleRateInv = 1 / SampleRate;
|
||||||
|
}
|
||||||
|
inline void update()
|
||||||
|
{
|
||||||
|
phase+=((phaseInc * float_Pi*2 * SampleRateInv));
|
||||||
|
sq = (phase>0?1:-1);
|
||||||
|
s = sin(phase);
|
||||||
|
if(phase > float_Pi)
|
||||||
|
{
|
||||||
|
phase-=2*float_Pi;
|
||||||
|
sh = rg.nextFloat()*2-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
void setFrequency(float val)
|
||||||
|
{
|
||||||
|
frUnsc = val;
|
||||||
|
if(!synced)
|
||||||
|
phaseInc = val;
|
||||||
|
}
|
||||||
|
void setRawParam(float param)//used for synced rate changes
|
||||||
|
{
|
||||||
|
rawParam = param;
|
||||||
|
if(synced)
|
||||||
|
{
|
||||||
|
recalcRate(param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void recalcRate(float param)
|
||||||
|
{
|
||||||
|
const int ratesCount = 9;
|
||||||
|
int parval = (int)(param*(ratesCount-1));
|
||||||
|
float rt = 1;
|
||||||
|
switch(parval)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
rt = 1.0 / 8;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
rt = 1.0 / 4;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
rt = 1.0 / 3;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
rt = 1.0 / 2;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
rt = 1.0;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
rt = 3.0 / 2;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
rt = 2;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
rt = 3;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
rt = 4;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rt = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
syncRate = rt;
|
||||||
|
}
|
||||||
|
};
|
380
Source/Engine/Motherboard.h
Executable file
380
Source/Engine/Motherboard.h
Executable file
|
@ -0,0 +1,380 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
This file is part of Obxd synthesizer.
|
||||||
|
|
||||||
|
Copyright <EFBFBD> 2013-2014 Filatov Vadim
|
||||||
|
|
||||||
|
Contact author via email :
|
||||||
|
justdat_@_e1.ru
|
||||||
|
|
||||||
|
This file may be licensed under the terms of of the
|
||||||
|
GNU General Public License Version 2 (the ``GPL'').
|
||||||
|
|
||||||
|
Software distributed under the License is distributed
|
||||||
|
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
|
||||||
|
express or implied. See the GPL for the specific language
|
||||||
|
governing rights and limitations.
|
||||||
|
|
||||||
|
You should have received a copy of the GPL along with this
|
||||||
|
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||||
|
or write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <climits>
|
||||||
|
#include "VoiceQueue.h"
|
||||||
|
#include "SynthEngine.h"
|
||||||
|
#include "Lfo.h"
|
||||||
|
|
||||||
|
class Motherboard
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
VoiceQueue vq;
|
||||||
|
int totalvc;
|
||||||
|
bool wasUni;
|
||||||
|
bool awaitingkeys[129];
|
||||||
|
int priorities[129];
|
||||||
|
|
||||||
|
Decimator17 left,right;
|
||||||
|
int asPlayedCounter;
|
||||||
|
float lkl,lkr;
|
||||||
|
float sampleRate,sampleRateInv;
|
||||||
|
//JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Motherboard)
|
||||||
|
public:
|
||||||
|
bool asPlayedMode;
|
||||||
|
Lfo mlfo,vibratoLfo;
|
||||||
|
float vibratoAmount;
|
||||||
|
bool vibratoEnabled;
|
||||||
|
|
||||||
|
float Volume;
|
||||||
|
const static int MAX_VOICES=8;
|
||||||
|
float pannings[MAX_VOICES];
|
||||||
|
ObxdVoice voices[MAX_VOICES];
|
||||||
|
bool uni;
|
||||||
|
bool Oversample;
|
||||||
|
|
||||||
|
bool economyMode;
|
||||||
|
Motherboard(): left(),right()
|
||||||
|
{
|
||||||
|
economyMode = true;
|
||||||
|
lkl=lkr=0;
|
||||||
|
vibratoEnabled = true;
|
||||||
|
asPlayedMode = false;
|
||||||
|
asPlayedCounter = 0;
|
||||||
|
for(int i = 0 ; i < 129 ; i++)
|
||||||
|
{
|
||||||
|
awaitingkeys[i] = false;
|
||||||
|
priorities[i] = 0;
|
||||||
|
}
|
||||||
|
vibratoAmount = 0;
|
||||||
|
Oversample=false;
|
||||||
|
mlfo= Lfo();
|
||||||
|
vibratoLfo=Lfo();
|
||||||
|
vibratoLfo.waveForm = 1;
|
||||||
|
uni = false;
|
||||||
|
wasUni = false;
|
||||||
|
Volume=0;
|
||||||
|
// voices = new ObxdVoice* [MAX_VOICES];
|
||||||
|
// pannings = new float[MAX_VOICES];
|
||||||
|
totalvc = MAX_VOICES;
|
||||||
|
vq = VoiceQueue(MAX_VOICES,voices);
|
||||||
|
for(int i = 0 ; i < MAX_VOICES;++i)
|
||||||
|
{
|
||||||
|
pannings[i]= 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
~Motherboard()
|
||||||
|
{
|
||||||
|
//delete pannings;
|
||||||
|
//for(int i = 0 ; i < MAX_VOICES;++i)
|
||||||
|
//{
|
||||||
|
// delete voices[i];
|
||||||
|
//}
|
||||||
|
//delete voices;
|
||||||
|
}
|
||||||
|
void setVoiceCount(int count)
|
||||||
|
{
|
||||||
|
for(int i = count ; i < MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
voices[i].NoteOff();
|
||||||
|
voices[i].ResetEnvelope();
|
||||||
|
}
|
||||||
|
vq.reInit(count);
|
||||||
|
totalvc = count;
|
||||||
|
}
|
||||||
|
void unisonOn()
|
||||||
|
{
|
||||||
|
//for(int i = 0 ; i < 110;i++)
|
||||||
|
// awaitingkeys[i] = false;
|
||||||
|
}
|
||||||
|
void setSampleRate(float sr)
|
||||||
|
{
|
||||||
|
sampleRate = sr;
|
||||||
|
sampleRateInv = 1 / sampleRate;
|
||||||
|
mlfo.setSamlpeRate(sr);
|
||||||
|
vibratoLfo.setSamlpeRate(sr);
|
||||||
|
for(int i = 0 ; i < MAX_VOICES;++i)
|
||||||
|
{
|
||||||
|
voices[i].setSampleRate(sr);
|
||||||
|
}
|
||||||
|
SetOversample(Oversample);
|
||||||
|
}
|
||||||
|
void sustainOn()
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
ObxdVoice* p = vq.getNext();
|
||||||
|
p->sustOn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void sustainOff()
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
ObxdVoice* p = vq.getNext();
|
||||||
|
p->sustOff();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void setNoteOn(int noteNo,float velocity)
|
||||||
|
{
|
||||||
|
asPlayedCounter++;
|
||||||
|
priorities[noteNo] = asPlayedCounter;
|
||||||
|
bool processed=false;
|
||||||
|
if (wasUni != uni)
|
||||||
|
unisonOn();
|
||||||
|
if (uni)
|
||||||
|
{
|
||||||
|
if(!asPlayedMode)
|
||||||
|
{
|
||||||
|
int minmidi = 129;
|
||||||
|
for(int i = 0 ; i < totalvc; i++)
|
||||||
|
{
|
||||||
|
ObxdVoice* p = vq.getNext();
|
||||||
|
if(p->midiIndx < minmidi && p->Active)
|
||||||
|
{
|
||||||
|
minmidi = p->midiIndx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(minmidi < noteNo)
|
||||||
|
{
|
||||||
|
awaitingkeys[noteNo] = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < totalvc;i++)
|
||||||
|
{
|
||||||
|
ObxdVoice* p = vq.getNext();
|
||||||
|
if(p->midiIndx > noteNo && p->Active)
|
||||||
|
{
|
||||||
|
awaitingkeys[p->midiIndx] = true;
|
||||||
|
p->NoteOn(noteNo,-0.5);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p->NoteOn(noteNo,velocity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
processed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < totalvc; i++)
|
||||||
|
{
|
||||||
|
ObxdVoice* p = vq.getNext();
|
||||||
|
if(p->Active)
|
||||||
|
{
|
||||||
|
awaitingkeys[p->midiIndx] = true;
|
||||||
|
p->NoteOn(noteNo,-0.5);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p->NoteOn(noteNo,velocity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
processed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 0; i < totalvc && !processed; i++)
|
||||||
|
{
|
||||||
|
ObxdVoice* p = vq.getNext();
|
||||||
|
if (!p->Active)
|
||||||
|
{
|
||||||
|
p->NoteOn(noteNo,velocity);
|
||||||
|
processed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if voice steal occured
|
||||||
|
if(!processed)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
if(!asPlayedMode)
|
||||||
|
{
|
||||||
|
int maxmidi = 0;
|
||||||
|
ObxdVoice* highestVoiceAvalible = NULL;
|
||||||
|
for(int i = 0 ; i < totalvc; i++)
|
||||||
|
{
|
||||||
|
ObxdVoice* p = vq.getNext();
|
||||||
|
if(p->midiIndx > maxmidi)
|
||||||
|
{
|
||||||
|
maxmidi = p->midiIndx;
|
||||||
|
highestVoiceAvalible = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(maxmidi < noteNo)
|
||||||
|
{
|
||||||
|
awaitingkeys[noteNo] = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
highestVoiceAvalible->NoteOn(noteNo,-0.5);
|
||||||
|
awaitingkeys[maxmidi] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int minPriority = INT_MAX;
|
||||||
|
ObxdVoice* minPriorityVoice = NULL;
|
||||||
|
for(int i = 0 ; i < totalvc; i++)
|
||||||
|
{
|
||||||
|
ObxdVoice* p = vq.getNext();
|
||||||
|
if(priorities[p->midiIndx] <minPriority)
|
||||||
|
{
|
||||||
|
minPriority = priorities[p->midiIndx];
|
||||||
|
minPriorityVoice = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
awaitingkeys[minPriorityVoice->midiIndx] = true;
|
||||||
|
minPriorityVoice->NoteOn(noteNo,-0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wasUni = uni;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setNoteOff(int noteNo)
|
||||||
|
{
|
||||||
|
awaitingkeys[noteNo] = false;
|
||||||
|
int reallocKey = 0;
|
||||||
|
//Voice release case
|
||||||
|
if(!asPlayedMode)
|
||||||
|
{
|
||||||
|
while(reallocKey < 129 &&(!awaitingkeys[reallocKey]))
|
||||||
|
{
|
||||||
|
reallocKey++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reallocKey = 129;
|
||||||
|
int maxPriority = INT_MIN;
|
||||||
|
for(int i = 0 ; i < 129;i++)
|
||||||
|
{
|
||||||
|
if(awaitingkeys[i] && (maxPriority < priorities[i]))
|
||||||
|
{
|
||||||
|
reallocKey = i;
|
||||||
|
maxPriority = priorities[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(reallocKey !=129)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < totalvc; i++)
|
||||||
|
{
|
||||||
|
ObxdVoice* p = vq.getNext();
|
||||||
|
if((p->midiIndx == noteNo) && (p->Active))
|
||||||
|
{
|
||||||
|
p->NoteOn(reallocKey,-0.5);
|
||||||
|
awaitingkeys[reallocKey] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
//No realloc
|
||||||
|
{
|
||||||
|
for (int i = 0; i < totalvc; i++)
|
||||||
|
{
|
||||||
|
ObxdVoice* n = vq.getNext();
|
||||||
|
if (n->midiIndx==noteNo && n->Active)
|
||||||
|
{
|
||||||
|
n->NoteOff();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void SetOversample(bool over)
|
||||||
|
{
|
||||||
|
if(over==true)
|
||||||
|
{
|
||||||
|
mlfo.setSamlpeRate(sampleRate*2);
|
||||||
|
vibratoLfo.setSamlpeRate(sampleRate*2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mlfo.setSamlpeRate(sampleRate);
|
||||||
|
vibratoLfo.setSamlpeRate(sampleRate);
|
||||||
|
}
|
||||||
|
for(int i = 0 ; i < MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
voices[i].setHQ(over);
|
||||||
|
if(over)
|
||||||
|
voices[i].setSampleRate(sampleRate*2);
|
||||||
|
else
|
||||||
|
voices[i].setSampleRate(sampleRate);
|
||||||
|
}
|
||||||
|
Oversample = over;
|
||||||
|
}
|
||||||
|
inline float processSynthVoice(ObxdVoice& b,float lfoIn,float vibIn )
|
||||||
|
{
|
||||||
|
if(economyMode)
|
||||||
|
b.checkAdsrState();
|
||||||
|
if(b.shouldProcessed||(!economyMode))
|
||||||
|
{
|
||||||
|
b.lfoIn=lfoIn;
|
||||||
|
b.lfoVibratoIn=vibIn;
|
||||||
|
return b.ProcessSample();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
void processSample(float* sm1,float* sm2)
|
||||||
|
{
|
||||||
|
mlfo.update();
|
||||||
|
vibratoLfo.update();
|
||||||
|
float vl=0,vr=0;
|
||||||
|
float vlo = 0 , vro = 0 ;
|
||||||
|
float lfovalue = mlfo.getVal();
|
||||||
|
float viblfo = vibratoEnabled?(vibratoLfo.getVal() * vibratoAmount):0;
|
||||||
|
float lfovalue2=0,viblfo2;
|
||||||
|
if(Oversample)
|
||||||
|
{
|
||||||
|
mlfo.update();
|
||||||
|
vibratoLfo.update();
|
||||||
|
lfovalue2 = mlfo.getVal();
|
||||||
|
viblfo2 = vibratoEnabled?(vibratoLfo.getVal() * vibratoAmount):0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0 ; i < totalvc;i++)
|
||||||
|
{
|
||||||
|
float x1 = processSynthVoice(voices[i],lfovalue,viblfo);
|
||||||
|
if(Oversample)
|
||||||
|
{
|
||||||
|
float x2 = processSynthVoice(voices[i],lfovalue2,viblfo2);
|
||||||
|
vlo+=x2*(1-pannings[i]);
|
||||||
|
vro+=x2*(pannings[i]);
|
||||||
|
}
|
||||||
|
vl+=x1*(1-pannings[i]);
|
||||||
|
vr+=x1*(pannings[i]);
|
||||||
|
}
|
||||||
|
if(Oversample)
|
||||||
|
{
|
||||||
|
vl = left.Calc(vl,vlo);
|
||||||
|
vr = right.Calc(vr,vro);
|
||||||
|
}
|
||||||
|
*sm1 = vl*Volume;
|
||||||
|
*sm2 = vr*Volume;
|
||||||
|
}
|
||||||
|
};
|
39
Source/Engine/ObxdBank.h
Executable file
39
Source/Engine/ObxdBank.h
Executable file
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
This file is part of Obxd synthesizer.
|
||||||
|
|
||||||
|
Copyright © 2013-2014 Filatov Vadim
|
||||||
|
|
||||||
|
Contact author via email :
|
||||||
|
justdat_@_e1.ru
|
||||||
|
|
||||||
|
This file may be licensed under the terms of of the
|
||||||
|
GNU General Public License Version 2 (the ``GPL'').
|
||||||
|
|
||||||
|
Software distributed under the License is distributed
|
||||||
|
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
|
||||||
|
express or implied. See the GPL for the specific language
|
||||||
|
governing rights and limitations.
|
||||||
|
|
||||||
|
You should have received a copy of the GPL along with this
|
||||||
|
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||||
|
or write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include "ObxdVoice.h"
|
||||||
|
#include "ParamsEnum.h"
|
||||||
|
const int PROGRAMCOUNT = 128;
|
||||||
|
class ObxdBank
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ObxdParams programs[PROGRAMCOUNT];
|
||||||
|
ObxdParams* currentProgramPtr;
|
||||||
|
int currentProgram;
|
||||||
|
ObxdBank()
|
||||||
|
{
|
||||||
|
currentProgram=0;
|
||||||
|
currentProgramPtr = programs+currentProgram;
|
||||||
|
}
|
||||||
|
};
|
253
Source/Engine/ObxdOscillatorB.h
Executable file
253
Source/Engine/ObxdOscillatorB.h
Executable file
|
@ -0,0 +1,253 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
This file is part of Obxd synthesizer.
|
||||||
|
|
||||||
|
Copyright <EFBFBD> 2013-2014 Filatov Vadim
|
||||||
|
|
||||||
|
Contact author via email :
|
||||||
|
justdat_@_e1.ru
|
||||||
|
|
||||||
|
This file may be licensed under the terms of of the
|
||||||
|
GNU General Public License Version 2 (the ``GPL'').
|
||||||
|
|
||||||
|
Software distributed under the License is distributed
|
||||||
|
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
|
||||||
|
express or implied. See the GPL for the specific language
|
||||||
|
governing rights and limitations.
|
||||||
|
|
||||||
|
You should have received a copy of the GPL along with this
|
||||||
|
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||||
|
or write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ObxdVoice.h"
|
||||||
|
#include "SynthEngine.h"
|
||||||
|
#include "AudioUtils.h"
|
||||||
|
#include "BlepData.h"
|
||||||
|
#include "DelayLine.h"
|
||||||
|
#include "SawOsc.h"
|
||||||
|
#include "PulseOsc.h"
|
||||||
|
#include "TriangleOsc.h"
|
||||||
|
|
||||||
|
class ObxdOscillatorB
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
float SampleRate;
|
||||||
|
float pitch1;
|
||||||
|
float pitch2;
|
||||||
|
float sampleRateInv;
|
||||||
|
|
||||||
|
|
||||||
|
float x1,x2;
|
||||||
|
|
||||||
|
float osc1Factor;
|
||||||
|
float osc2Factor;
|
||||||
|
|
||||||
|
float pw1w,pw2w;
|
||||||
|
//blep const
|
||||||
|
const int n;
|
||||||
|
const int hsam;
|
||||||
|
//delay line implements fixed sample delay
|
||||||
|
DelayLine<Samples> del1,del2;
|
||||||
|
DelayLine<Samples> xmodd;
|
||||||
|
DelayLineBoolean<Samples> syncd;
|
||||||
|
DelayLine<Samples> syncFracd;
|
||||||
|
DelayLine<Samples> cvd;
|
||||||
|
Random wn;
|
||||||
|
SawOsc o1s,o2s;
|
||||||
|
PulseOsc o1p,o2p;
|
||||||
|
TriangleOsc o1t,o2t;
|
||||||
|
public:
|
||||||
|
|
||||||
|
float tune;//+-1
|
||||||
|
int oct;
|
||||||
|
|
||||||
|
float dirt;
|
||||||
|
|
||||||
|
float notePlaying;
|
||||||
|
|
||||||
|
|
||||||
|
float totalDetune;
|
||||||
|
|
||||||
|
float osc2Det;
|
||||||
|
float pulseWidth;
|
||||||
|
float pw1,pw2;
|
||||||
|
|
||||||
|
|
||||||
|
bool quantizeCw;
|
||||||
|
|
||||||
|
float o1mx,o2mx;
|
||||||
|
float nmx;
|
||||||
|
float pto1,pto2;
|
||||||
|
|
||||||
|
|
||||||
|
//osc pitches
|
||||||
|
float osc1Saw,osc2Saw,
|
||||||
|
osc1Pul,osc2Pul;
|
||||||
|
|
||||||
|
float osc1p,osc2p;
|
||||||
|
bool hardSync;
|
||||||
|
float xmod;
|
||||||
|
|
||||||
|
|
||||||
|
ObxdOscillatorB() :
|
||||||
|
n(Samples*2),
|
||||||
|
hsam(Samples),
|
||||||
|
o1s(),o2s(),
|
||||||
|
o1p(),o2p(),
|
||||||
|
o1t(),o2t()
|
||||||
|
{
|
||||||
|
dirt = 0.1;
|
||||||
|
totalDetune = 0;
|
||||||
|
wn = Random(Random::getSystemRandom().nextInt64());
|
||||||
|
osc1Factor = wn.nextFloat()-0.5;
|
||||||
|
osc2Factor = wn.nextFloat()-0.5;
|
||||||
|
nmx=0;
|
||||||
|
oct=0;
|
||||||
|
tune=0;
|
||||||
|
pw1w=pw2w=0;
|
||||||
|
pto1=pto2=0;
|
||||||
|
pw1=pw2=0;
|
||||||
|
xmod = 0;
|
||||||
|
hardSync = false;
|
||||||
|
osc1p=osc2p=10;
|
||||||
|
osc1Saw=osc2Saw=osc1Pul=osc2Pul=false;
|
||||||
|
osc2Det = 0;
|
||||||
|
notePlaying = 30;
|
||||||
|
pulseWidth = 0;
|
||||||
|
o1mx=o2mx=0;
|
||||||
|
x1=wn.nextFloat();
|
||||||
|
x2=wn.nextFloat();
|
||||||
|
|
||||||
|
//del1 = new DelayLine(hsam);
|
||||||
|
//del2 = new DelayLine(hsam);
|
||||||
|
//xmodd = new DelayLine(hsam);
|
||||||
|
//syncd = new DelayLineBoolean(hsam);
|
||||||
|
//syncFracd = new DelayLine(hsam);
|
||||||
|
//cvd = new DelayLine(hsam);
|
||||||
|
}
|
||||||
|
~ObxdOscillatorB()
|
||||||
|
{
|
||||||
|
//delete del1;
|
||||||
|
//delete del2;
|
||||||
|
//delete xmodd;
|
||||||
|
//delete cvd;
|
||||||
|
//delete syncd;
|
||||||
|
//delete syncFracd;
|
||||||
|
}
|
||||||
|
void setDecimation()
|
||||||
|
{
|
||||||
|
o1p.setDecimation();
|
||||||
|
o1t.setDecimation();
|
||||||
|
o1s.setDecimation();
|
||||||
|
o2p.setDecimation();
|
||||||
|
o2t.setDecimation();
|
||||||
|
o2s.setDecimation();
|
||||||
|
}
|
||||||
|
void removeDecimation()
|
||||||
|
{
|
||||||
|
o1p.removeDecimation();
|
||||||
|
o1t.removeDecimation();
|
||||||
|
o1s.removeDecimation();
|
||||||
|
o2p.removeDecimation();
|
||||||
|
o2t.removeDecimation();
|
||||||
|
o2s.removeDecimation();
|
||||||
|
}
|
||||||
|
void setSampleRate(float sr)
|
||||||
|
{
|
||||||
|
SampleRate = sr;
|
||||||
|
sampleRateInv = 1.0f / SampleRate;
|
||||||
|
}
|
||||||
|
inline float ProcessSample()
|
||||||
|
{
|
||||||
|
float noiseGen = wn.nextFloat()-0.5;
|
||||||
|
pitch1 = getPitch(dirt * noiseGen + notePlaying + (quantizeCw?((int)(osc1p)):osc1p)+ pto1 + tune + oct+totalDetune*osc1Factor);
|
||||||
|
bool hsr = false;
|
||||||
|
float hsfrac=0;
|
||||||
|
float fs = jmin(pitch1*(sampleRateInv),0.45f);
|
||||||
|
x1+=fs;
|
||||||
|
hsfrac = 0;
|
||||||
|
float osc1mix=0.0f;
|
||||||
|
float pwcalc =jlimit<float>(0.1f,1.0f,(pulseWidth + pw1)*0.5f + 0.5f);
|
||||||
|
|
||||||
|
if(osc1Pul)
|
||||||
|
o1p.processMaster(x1,fs,pwcalc,pw1w);
|
||||||
|
if(osc1Saw)
|
||||||
|
o1s.processMaster(x1,fs);
|
||||||
|
else if(!osc1Pul)
|
||||||
|
o1t.processMaster(x1,fs);
|
||||||
|
|
||||||
|
if(x1 >= 1.0f)
|
||||||
|
{
|
||||||
|
x1-=1.0f;
|
||||||
|
hsfrac = x1/fs;
|
||||||
|
hsr = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pw1w = pwcalc;
|
||||||
|
|
||||||
|
hsr &= hardSync;
|
||||||
|
//Delaying our hard sync gate signal and frac
|
||||||
|
hsr = syncd.feedReturn(hsr) != 0.0f;
|
||||||
|
hsfrac = syncFracd.feedReturn(hsfrac);
|
||||||
|
|
||||||
|
if(osc1Pul)
|
||||||
|
osc1mix += o1p.getValue(x1,pwcalc) + o1p.aliasReduction();
|
||||||
|
if(osc1Saw)
|
||||||
|
osc1mix += o1s.getValue(x1) + o1s.aliasReduction();
|
||||||
|
else if(!osc1Pul)
|
||||||
|
osc1mix = o1t.getValue(x1) + o1t.aliasReduction();
|
||||||
|
//Pitch control needs additional delay buffer to compensate
|
||||||
|
//This will give us less aliasing on xmod
|
||||||
|
//Hard sync gate signal delayed too
|
||||||
|
noiseGen = wn.nextFloat()-0.5;
|
||||||
|
pitch2 = getPitch(cvd.feedReturn(dirt *noiseGen + notePlaying + osc2Det + (quantizeCw?((int)(osc2p)):osc2p) + pto2+ osc1mix *xmod + tune + oct +totalDetune*osc2Factor));
|
||||||
|
|
||||||
|
fs = jmin(pitch2 * (sampleRateInv),0.45f);
|
||||||
|
|
||||||
|
pwcalc = jlimit<float>(0.1f,1.0f,(pulseWidth + pw2)*0.5f + 0.5f);
|
||||||
|
|
||||||
|
float osc2mix=0.0f;
|
||||||
|
|
||||||
|
x2 +=fs;
|
||||||
|
|
||||||
|
if(osc2Pul)
|
||||||
|
o2p.processSlave(x2,fs,hsr,hsfrac,pwcalc,pw2w);
|
||||||
|
if(osc2Saw)
|
||||||
|
o2s.processSlave(x2,fs,hsr,hsfrac);
|
||||||
|
else if(!osc2Pul)
|
||||||
|
o2t.processSlave(x2,fs,hsr,hsfrac);
|
||||||
|
|
||||||
|
|
||||||
|
if(x2 >= 1.0f)
|
||||||
|
x2-=1.0;
|
||||||
|
|
||||||
|
|
||||||
|
pw2w=pwcalc;
|
||||||
|
//On hard sync reset slave phase is affected that way
|
||||||
|
if(hsr)
|
||||||
|
{
|
||||||
|
float fracMaster = (fs * hsfrac);
|
||||||
|
x2 =fracMaster;
|
||||||
|
}
|
||||||
|
//Delaying osc1 signal
|
||||||
|
//And getting delayed back
|
||||||
|
osc1mix = xmodd.feedReturn(osc1mix);
|
||||||
|
|
||||||
|
if(osc2Pul)
|
||||||
|
osc2mix += o2p.getValue(x2,pwcalc) + o2p.aliasReduction();
|
||||||
|
if(osc2Saw)
|
||||||
|
osc2mix += o2s.getValue(x2) + o2s.aliasReduction();
|
||||||
|
else if(!osc2Pul)
|
||||||
|
osc2mix = o2t.getValue(x2) + o2t.aliasReduction();
|
||||||
|
|
||||||
|
//mixing
|
||||||
|
float res =o1mx*osc1mix + o2mx *osc2mix + (noiseGen)*(nmx*1.3 + 0.0006);
|
||||||
|
return res*3;
|
||||||
|
}
|
||||||
|
};
|
312
Source/Engine/ObxdVoice.h
Executable file
312
Source/Engine/ObxdVoice.h
Executable file
|
@ -0,0 +1,312 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
This file is part of Obxd synthesizer.
|
||||||
|
|
||||||
|
Copyright <EFBFBD> 2013-2014 Filatov Vadim
|
||||||
|
|
||||||
|
Contact author via email :
|
||||||
|
justdat_@_e1.ru
|
||||||
|
|
||||||
|
This file may be licensed under the terms of of the
|
||||||
|
GNU General Public License Version 2 (the ``GPL'').
|
||||||
|
|
||||||
|
Software distributed under the License is distributed
|
||||||
|
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
|
||||||
|
express or implied. See the GPL for the specific language
|
||||||
|
governing rights and limitations.
|
||||||
|
|
||||||
|
You should have received a copy of the GPL along with this
|
||||||
|
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||||
|
or write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include "ObxdOscillatorB.h"
|
||||||
|
#include "AdsrEnvelope.h"
|
||||||
|
#include "Filter.h"
|
||||||
|
#include "Decimator.h"
|
||||||
|
#include "APInterpolator.h"
|
||||||
|
|
||||||
|
class ObxdVoice
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
float SampleRate;
|
||||||
|
float sampleRateInv;
|
||||||
|
float Volume;
|
||||||
|
float port;
|
||||||
|
float velocityValue;
|
||||||
|
|
||||||
|
float d1,d2;
|
||||||
|
float c1,c2;
|
||||||
|
|
||||||
|
bool hq;
|
||||||
|
|
||||||
|
//JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ObxdVoice)
|
||||||
|
public:
|
||||||
|
bool sustainHold;
|
||||||
|
//bool resetAdsrsOnAttack;
|
||||||
|
|
||||||
|
AdsrEnvelope env;
|
||||||
|
AdsrEnvelope fenv;
|
||||||
|
ObxdOscillatorB osc;
|
||||||
|
Filter flt;
|
||||||
|
|
||||||
|
Random ng;
|
||||||
|
|
||||||
|
float vamp,vflt;
|
||||||
|
|
||||||
|
float cutoff;
|
||||||
|
float fenvamt;
|
||||||
|
|
||||||
|
float EnvDetune;
|
||||||
|
float FenvDetune;
|
||||||
|
|
||||||
|
float FltDetune;
|
||||||
|
float FltDetAmt;
|
||||||
|
|
||||||
|
float PortaDetune;
|
||||||
|
float PortaDetuneAmt;
|
||||||
|
|
||||||
|
float levelDetune;
|
||||||
|
float levelDetuneAmt;
|
||||||
|
|
||||||
|
float brightCoef;
|
||||||
|
|
||||||
|
int midiIndx;
|
||||||
|
|
||||||
|
bool Active;
|
||||||
|
bool shouldProcessed;
|
||||||
|
|
||||||
|
float fltKF;
|
||||||
|
|
||||||
|
float porta;
|
||||||
|
float prtst;
|
||||||
|
|
||||||
|
float cutoffwas,envelopewas;
|
||||||
|
|
||||||
|
float lfoIn;
|
||||||
|
float lfoVibratoIn;
|
||||||
|
|
||||||
|
float pitchWheel;
|
||||||
|
float pitchWheelAmt;
|
||||||
|
bool pitchWheelOsc2Only;
|
||||||
|
|
||||||
|
float lfoa1,lfoa2;
|
||||||
|
bool lfoo1,lfoo2,lfof;
|
||||||
|
bool lfopw1,lfopw2;
|
||||||
|
|
||||||
|
bool Oversample;
|
||||||
|
bool selfOscPush;
|
||||||
|
|
||||||
|
float envpitchmod;
|
||||||
|
float pwenvmod;
|
||||||
|
|
||||||
|
float pwOfs;
|
||||||
|
bool pwEnvBoth;
|
||||||
|
bool pitchModBoth;
|
||||||
|
|
||||||
|
bool invertFenv;
|
||||||
|
|
||||||
|
|
||||||
|
bool fourpole;
|
||||||
|
|
||||||
|
|
||||||
|
DelayLine<Samples*2> lenvd,fenvd,lfod;
|
||||||
|
|
||||||
|
ApInterpolator ap;
|
||||||
|
float oscpsw;
|
||||||
|
int legatoMode;
|
||||||
|
float briHold;
|
||||||
|
|
||||||
|
ObxdVoice()
|
||||||
|
: ap()
|
||||||
|
{
|
||||||
|
hq = false;
|
||||||
|
selfOscPush = false;
|
||||||
|
pitchModBoth = false;
|
||||||
|
pwOfs = 0 ;
|
||||||
|
invertFenv = false;
|
||||||
|
pwEnvBoth = false;
|
||||||
|
ng = Random(Random::getSystemRandom().nextInt64());
|
||||||
|
sustainHold = false;
|
||||||
|
shouldProcessed = false;
|
||||||
|
vamp=vflt=0;
|
||||||
|
velocityValue=0;
|
||||||
|
lfoVibratoIn=0;
|
||||||
|
fourpole = false;
|
||||||
|
legatoMode = 0;
|
||||||
|
brightCoef =briHold= 1;
|
||||||
|
envpitchmod = 0;
|
||||||
|
pwenvmod = 0;
|
||||||
|
oscpsw = 0;
|
||||||
|
cutoffwas = envelopewas=0;
|
||||||
|
Oversample= false;
|
||||||
|
c1=c2=d1=d2=0;
|
||||||
|
pitchWheel=pitchWheelAmt=0;
|
||||||
|
lfoIn=0;
|
||||||
|
PortaDetuneAmt=0;
|
||||||
|
FltDetAmt=0;
|
||||||
|
levelDetuneAmt=0;
|
||||||
|
porta =0;
|
||||||
|
prtst=0;
|
||||||
|
fltKF= false;
|
||||||
|
cutoff=0;
|
||||||
|
fenvamt = 0;
|
||||||
|
Active = false;
|
||||||
|
midiIndx = 30;
|
||||||
|
levelDetune = Random::getSystemRandom().nextFloat()-0.5;
|
||||||
|
EnvDetune = Random::getSystemRandom().nextFloat()-0.5;
|
||||||
|
FenvDetune = Random::getSystemRandom().nextFloat()-0.5;
|
||||||
|
FltDetune = Random::getSystemRandom().nextFloat()-0.5;
|
||||||
|
PortaDetune =Random::getSystemRandom().nextFloat()-0.5;
|
||||||
|
// lenvd=new DelayLine(Samples*2);
|
||||||
|
// fenvd=new DelayLine(Samples*2);
|
||||||
|
}
|
||||||
|
~ObxdVoice()
|
||||||
|
{
|
||||||
|
// delete lenvd;
|
||||||
|
// delete fenvd;
|
||||||
|
}
|
||||||
|
inline float ProcessSample()
|
||||||
|
{
|
||||||
|
//portamento on osc input voltage
|
||||||
|
//implements rc circuit
|
||||||
|
float ptNote =tptlpupw(prtst, midiIndx-81, porta * (1+PortaDetune*PortaDetuneAmt),sampleRateInv);
|
||||||
|
osc.notePlaying = ptNote;
|
||||||
|
//both envelopes and filter cv need a delay equal to osc internal delay
|
||||||
|
float lfoDelayed = lfod.feedReturn(lfoIn);
|
||||||
|
//filter envelope undelayed
|
||||||
|
float envm = fenv.processSample() * (1 - (1-velocityValue)*vflt);
|
||||||
|
if(invertFenv)
|
||||||
|
envm = -envm;
|
||||||
|
//filter exp cutoff calculation
|
||||||
|
float cutoffcalc = jmin(
|
||||||
|
getPitch(
|
||||||
|
(lfof?lfoDelayed*lfoa1:0)+
|
||||||
|
cutoff+
|
||||||
|
FltDetune*FltDetAmt+
|
||||||
|
fenvamt*fenvd.feedReturn(envm)+
|
||||||
|
-45 + (fltKF*(ptNote+40))
|
||||||
|
)
|
||||||
|
//noisy filter cutoff
|
||||||
|
+(ng.nextFloat()-0.5f)*3.5f
|
||||||
|
, (flt.SampleRate*0.5f-120.0f));//for numerical stability purposes
|
||||||
|
|
||||||
|
//limit our max cutoff on self osc to prevent alising
|
||||||
|
if(selfOscPush)
|
||||||
|
cutoffcalc = jmin(cutoffcalc,19000.0f);
|
||||||
|
|
||||||
|
|
||||||
|
//PW modulation
|
||||||
|
osc.pw1 = (lfopw1?(lfoIn * lfoa2):0) + (pwEnvBoth?(pwenvmod * envm) : 0);
|
||||||
|
osc.pw2 = (lfopw2?(lfoIn * lfoa2):0) + pwenvmod * envm + pwOfs;
|
||||||
|
|
||||||
|
//Pitch modulation
|
||||||
|
osc.pto1 = (!pitchWheelOsc2Only? (pitchWheel*pitchWheelAmt):0 ) + ( lfoo1?(lfoIn * lfoa1):0) + (pitchModBoth?(envpitchmod * envm):0) + lfoVibratoIn;
|
||||||
|
osc.pto2 = (pitchWheel *pitchWheelAmt) + (lfoo2?lfoIn*lfoa1:0) + (envpitchmod * envm) + lfoVibratoIn;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//variable sort magic - upsample trick
|
||||||
|
float envVal = lenvd.feedReturn(env.processSample() * (1 - (1-velocityValue)*vamp));
|
||||||
|
|
||||||
|
float oscps = osc.ProcessSample() * (1 - levelDetuneAmt*levelDetune);
|
||||||
|
|
||||||
|
|
||||||
|
oscps = oscps - tptlpupw(c1,oscps,12,sampleRateInv);
|
||||||
|
|
||||||
|
float x1 = oscps;
|
||||||
|
x1 = tptpc(d2,x1,brightCoef);
|
||||||
|
if(fourpole)
|
||||||
|
x1 = flt.Apply4Pole(x1,(cutoffcalc));
|
||||||
|
else
|
||||||
|
x1 = flt.Apply(x1,(cutoffcalc));
|
||||||
|
x1 *= (envVal);
|
||||||
|
return x1;
|
||||||
|
}
|
||||||
|
void setBrightness(float val)
|
||||||
|
{
|
||||||
|
briHold = val;
|
||||||
|
brightCoef = tan(jmin(val,flt.SampleRate*0.5f-10)* (juce::float_Pi)*flt.sampleRateInv);
|
||||||
|
|
||||||
|
}
|
||||||
|
void setEnvDer(float d)
|
||||||
|
{
|
||||||
|
env.setUniqueDeriviance(1 + EnvDetune*d);
|
||||||
|
fenv.setUniqueDeriviance(1 + FenvDetune*d);
|
||||||
|
}
|
||||||
|
void setHQ(bool hq)
|
||||||
|
{
|
||||||
|
if(hq)
|
||||||
|
{
|
||||||
|
osc.setDecimation();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
osc.removeDecimation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void setSampleRate(float sr)
|
||||||
|
{
|
||||||
|
flt.setSampleRate(sr);
|
||||||
|
osc.setSampleRate(sr);
|
||||||
|
env.setSampleRate(sr);
|
||||||
|
fenv.setSampleRate(sr);
|
||||||
|
SampleRate = sr;
|
||||||
|
sampleRateInv = 1 / sr;
|
||||||
|
brightCoef = tan(jmin(briHold,flt.SampleRate*0.5f-10)* (juce::float_Pi) * flt.sampleRateInv);
|
||||||
|
}
|
||||||
|
void checkAdsrState()
|
||||||
|
{
|
||||||
|
shouldProcessed = env.isActive();
|
||||||
|
}
|
||||||
|
void ResetEnvelope()
|
||||||
|
{
|
||||||
|
env.ResetEnvelopeState();
|
||||||
|
fenv.ResetEnvelopeState();
|
||||||
|
}
|
||||||
|
void NoteOn(int mididx,float velocity)
|
||||||
|
{
|
||||||
|
if(!shouldProcessed)
|
||||||
|
{
|
||||||
|
//When your processing is paused we need to clear delay lines and envelopes
|
||||||
|
//Not doing this will cause clicks or glitches
|
||||||
|
lenvd.fillZeroes();
|
||||||
|
fenvd.fillZeroes();
|
||||||
|
ResetEnvelope();
|
||||||
|
}
|
||||||
|
shouldProcessed = true;
|
||||||
|
if(velocity!=-0.5)
|
||||||
|
velocityValue = velocity;
|
||||||
|
midiIndx = mididx;
|
||||||
|
if((!Active)||(legatoMode&1))
|
||||||
|
env.triggerAttack();
|
||||||
|
if((!Active)||(legatoMode&2))
|
||||||
|
fenv.triggerAttack();
|
||||||
|
Active = true;
|
||||||
|
}
|
||||||
|
void NoteOff()
|
||||||
|
{
|
||||||
|
if(!sustainHold)
|
||||||
|
{
|
||||||
|
env.triggerRelease();
|
||||||
|
fenv.triggerRelease();
|
||||||
|
}
|
||||||
|
Active = false;
|
||||||
|
}
|
||||||
|
void sustOn()
|
||||||
|
{
|
||||||
|
sustainHold = true;
|
||||||
|
}
|
||||||
|
void sustOff()
|
||||||
|
{
|
||||||
|
sustainHold = false;
|
||||||
|
if(!Active)
|
||||||
|
{
|
||||||
|
env.triggerRelease();
|
||||||
|
fenv.triggerRelease();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
54
Source/Engine/ParamSmoother.h
Executable file
54
Source/Engine/ParamSmoother.h
Executable file
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
This file is part of Obxd synthesizer.
|
||||||
|
|
||||||
|
Copyright © 2013-2014 Filatov Vadim
|
||||||
|
|
||||||
|
Contact author via email :
|
||||||
|
justdat_@_e1.ru
|
||||||
|
|
||||||
|
This file may be licensed under the terms of of the
|
||||||
|
GNU General Public License Version 2 (the ``GPL'').
|
||||||
|
|
||||||
|
Software distributed under the License is distributed
|
||||||
|
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
|
||||||
|
express or implied. See the GPL for the specific language
|
||||||
|
governing rights and limitations.
|
||||||
|
|
||||||
|
You should have received a copy of the GPL along with this
|
||||||
|
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||||
|
or write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include "SynthEngine.h"
|
||||||
|
|
||||||
|
const float PSSC = 0.0030;
|
||||||
|
class ParamSmoother
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
float steepValue;
|
||||||
|
float integralValue;
|
||||||
|
float srCor;
|
||||||
|
public :
|
||||||
|
ParamSmoother()
|
||||||
|
{
|
||||||
|
steepValue=integralValue=0;
|
||||||
|
srCor=1;
|
||||||
|
};
|
||||||
|
float smoothStep()
|
||||||
|
{
|
||||||
|
integralValue = integralValue + ( steepValue - integralValue)*PSSC*srCor + dc;
|
||||||
|
return integralValue;
|
||||||
|
}
|
||||||
|
void setSteep(float value)
|
||||||
|
{
|
||||||
|
steepValue = value;
|
||||||
|
}
|
||||||
|
void setSampleRate(float sr)
|
||||||
|
{
|
||||||
|
srCor = sr / 44000;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
79
Source/Engine/Params.h
Executable file
79
Source/Engine/Params.h
Executable file
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
This file is part of Obxd synthesizer.
|
||||||
|
|
||||||
|
Copyright <EFBFBD> 2013-2014 Filatov Vadim
|
||||||
|
|
||||||
|
Contact author via email :
|
||||||
|
justdat_@_e1.ru
|
||||||
|
|
||||||
|
This file may be licensed under the terms of of the
|
||||||
|
GNU General Public License Version 2 (the ``GPL'').
|
||||||
|
|
||||||
|
Software distributed under the License is distributed
|
||||||
|
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
|
||||||
|
express or implied. See the GPL for the specific language
|
||||||
|
governing rights and limitations.
|
||||||
|
|
||||||
|
You should have received a copy of the GPL along with this
|
||||||
|
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||||
|
or write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include "ObxdVoice.h"
|
||||||
|
#include "ParamsEnum.h"
|
||||||
|
class ObxdParams
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
float values[PARAM_COUNT];
|
||||||
|
String name;
|
||||||
|
ObxdParams()
|
||||||
|
{
|
||||||
|
name = "Default";
|
||||||
|
//values = new float[PARAM_COUNT];
|
||||||
|
setDefaultValues();
|
||||||
|
}
|
||||||
|
void setDefaultValues()
|
||||||
|
{
|
||||||
|
for(int k = 0 ; k < PARAM_COUNT;++k)
|
||||||
|
{
|
||||||
|
values[k] = 0.0f;
|
||||||
|
}
|
||||||
|
values[VOICE_COUNT] = 1.0f;
|
||||||
|
values[BRIGHTNESS]=1.0f;
|
||||||
|
values[OCTAVE]=0.5;
|
||||||
|
values[TUNE] = 0.5f;
|
||||||
|
values[OSC2_DET]=0.4;
|
||||||
|
values[LSUS]=1.0f;
|
||||||
|
values[CUTOFF]=1.0f;
|
||||||
|
values[VOLUME]=0.5f;
|
||||||
|
values[OSC1MIX]=1;
|
||||||
|
values[OSC2MIX]=1;
|
||||||
|
values[OSC1Saw]=1;
|
||||||
|
values[OSC2Saw]=1;
|
||||||
|
values[BENDLFORATE]=0.6;
|
||||||
|
|
||||||
|
// values[FILTER_DRIVE]= 0.01;
|
||||||
|
values[PAN1]=0.5;
|
||||||
|
values[PAN2]=0.5;
|
||||||
|
values[PAN3]=0.5;
|
||||||
|
values[PAN4]=0.5;
|
||||||
|
values[PAN5]=0.5;
|
||||||
|
values[PAN6]=0.5;
|
||||||
|
values[PAN7]=0.5;
|
||||||
|
values[PAN8]=0.5;
|
||||||
|
values[ECONOMY_MODE] = 1;
|
||||||
|
values[ENVDER] = 0.3;
|
||||||
|
values[FILTERDER]=0.3;
|
||||||
|
values[LEVEL_DIF]=0.3;
|
||||||
|
values[PORTADER]=0.3;
|
||||||
|
values[UDET]=0.2;
|
||||||
|
}
|
||||||
|
~ObxdParams()
|
||||||
|
{
|
||||||
|
//delete values;
|
||||||
|
}
|
||||||
|
//JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ObxdParams)
|
||||||
|
};
|
94
Source/Engine/ParamsEnum.h
Executable file
94
Source/Engine/ParamsEnum.h
Executable file
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
This file is part of Obxd synthesizer.
|
||||||
|
|
||||||
|
Copyright © 2013-2014 Filatov Vadim
|
||||||
|
|
||||||
|
Contact author via email :
|
||||||
|
justdat_@_e1.ru
|
||||||
|
|
||||||
|
This file may be licensed under the terms of of the
|
||||||
|
GNU General Public License Version 2 (the ``GPL'').
|
||||||
|
|
||||||
|
Software distributed under the License is distributed
|
||||||
|
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
|
||||||
|
express or implied. See the GPL for the specific language
|
||||||
|
governing rights and limitations.
|
||||||
|
|
||||||
|
You should have received a copy of the GPL along with this
|
||||||
|
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||||
|
or write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include "ObxdVoice.h"
|
||||||
|
enum ObxdParameters
|
||||||
|
{
|
||||||
|
UNDEFINED,
|
||||||
|
MIDILEARN,
|
||||||
|
VOLUME,
|
||||||
|
VOICE_COUNT,
|
||||||
|
TUNE,
|
||||||
|
OCTAVE,
|
||||||
|
BENDRANGE,
|
||||||
|
BENDOSC2,
|
||||||
|
LEGATOMODE,
|
||||||
|
BENDLFORATE,
|
||||||
|
VFLTENV,
|
||||||
|
VAMPENV,
|
||||||
|
|
||||||
|
ASPLAYEDALLOCATION,
|
||||||
|
PORTAMENTO,
|
||||||
|
UNISON,
|
||||||
|
UDET,
|
||||||
|
OSC2_DET,
|
||||||
|
LFOFREQ,
|
||||||
|
LFOSINWAVE,LFOSQUAREWAVE,LFOSHWAVE,
|
||||||
|
LFO1AMT,LFO2AMT,
|
||||||
|
LFOOSC1,LFOOSC2,LFOFILTER,LFOPW1,LFOPW2,
|
||||||
|
OSC2HS,
|
||||||
|
XMOD,
|
||||||
|
OSC1P,
|
||||||
|
OSC2P,
|
||||||
|
OSCQuantize,
|
||||||
|
OSC1Saw,
|
||||||
|
OSC1Pul,
|
||||||
|
OSC2Saw,
|
||||||
|
OSC2Pul,
|
||||||
|
PW,
|
||||||
|
BRIGHTNESS,
|
||||||
|
ENVPITCH,
|
||||||
|
OSC1MIX,
|
||||||
|
OSC2MIX,
|
||||||
|
NOISEMIX,
|
||||||
|
FLT_KF,
|
||||||
|
CUTOFF,
|
||||||
|
RESONANCE,
|
||||||
|
MULTIMODE,
|
||||||
|
FILTER_WARM,
|
||||||
|
BANDPASS,
|
||||||
|
FOURPOLE,
|
||||||
|
ENVELOPE_AMT,
|
||||||
|
LATK,
|
||||||
|
LDEC,
|
||||||
|
LSUS,
|
||||||
|
LREL,
|
||||||
|
FATK,
|
||||||
|
FDEC,
|
||||||
|
FSUS,
|
||||||
|
FREL,
|
||||||
|
ENVDER,FILTERDER,PORTADER,
|
||||||
|
PAN1,PAN2,PAN3,PAN4,PAN5,PAN6,PAN7,PAN8,
|
||||||
|
UNLEARN,
|
||||||
|
ECONOMY_MODE,
|
||||||
|
LFO_SYNC,
|
||||||
|
PW_ENV,
|
||||||
|
PW_ENV_BOTH,
|
||||||
|
ENV_PITCH_BOTH,
|
||||||
|
FENV_INVERT,
|
||||||
|
PW_OSC2_OFS,
|
||||||
|
LEVEL_DIF,
|
||||||
|
SELF_OSC_PUSH,
|
||||||
|
PARAM_COUNT,
|
||||||
|
};
|
194
Source/Engine/PulseOsc.h
Executable file
194
Source/Engine/PulseOsc.h
Executable file
|
@ -0,0 +1,194 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
This file is part of Obxd synthesizer.
|
||||||
|
|
||||||
|
Copyright <EFBFBD> 2013-2014 Filatov Vadim
|
||||||
|
|
||||||
|
Contact author via email :
|
||||||
|
justdat_@_e1.ru
|
||||||
|
|
||||||
|
This file may be licensed under the terms of of the
|
||||||
|
GNU General Public License Version 2 (the ``GPL'').
|
||||||
|
|
||||||
|
Software distributed under the License is distributed
|
||||||
|
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
|
||||||
|
express or implied. See the GPL for the specific language
|
||||||
|
governing rights and limitations.
|
||||||
|
|
||||||
|
You should have received a copy of the GPL along with this
|
||||||
|
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||||
|
or write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include "SynthEngine.h"
|
||||||
|
#include "BlepData.h"
|
||||||
|
class PulseOsc
|
||||||
|
{
|
||||||
|
DelayLine<Samples> del1;
|
||||||
|
bool pw1t;
|
||||||
|
float buffer1[Samples*2];
|
||||||
|
const int hsam;
|
||||||
|
const int n;
|
||||||
|
float const * blepPTR;
|
||||||
|
int bP1;
|
||||||
|
public:
|
||||||
|
PulseOsc() : hsam(Samples)
|
||||||
|
, n(Samples*2)
|
||||||
|
{
|
||||||
|
// del1 = new DelayLine(hsam);
|
||||||
|
pw1t = false;
|
||||||
|
bP1=0;
|
||||||
|
//buffer1= new float[n];
|
||||||
|
for(int i = 0 ; i < n ; i++)
|
||||||
|
buffer1[i]=0;
|
||||||
|
blepPTR = blep;
|
||||||
|
}
|
||||||
|
~PulseOsc()
|
||||||
|
{
|
||||||
|
// delete buffer1;
|
||||||
|
// delete del1;
|
||||||
|
}
|
||||||
|
inline void setDecimation()
|
||||||
|
{
|
||||||
|
blepPTR = blepd2;
|
||||||
|
}
|
||||||
|
inline void removeDecimation()
|
||||||
|
{
|
||||||
|
blepPTR = blep;
|
||||||
|
}
|
||||||
|
inline float aliasReduction()
|
||||||
|
{
|
||||||
|
return -getNextBlep(buffer1,bP1);
|
||||||
|
}
|
||||||
|
inline void processMaster(float x,float delta,float pulseWidth,float pulseWidthWas)
|
||||||
|
{
|
||||||
|
float summated = delta- (pulseWidth - pulseWidthWas);
|
||||||
|
if((pw1t) && x >= 1.0f)
|
||||||
|
{
|
||||||
|
x -= 1.0f;
|
||||||
|
if(pw1t)
|
||||||
|
mixInImpulseCenter(buffer1,bP1,x/delta, 1);
|
||||||
|
pw1t=false;
|
||||||
|
}
|
||||||
|
if((!pw1t)&& (x >= pulseWidth)&&(x - summated <=pulseWidth))
|
||||||
|
{
|
||||||
|
pw1t=true;
|
||||||
|
float frac =(x-pulseWidth) / summated;
|
||||||
|
mixInImpulseCenter(buffer1,bP1,frac,-1);
|
||||||
|
}
|
||||||
|
if((pw1t) && x >= 1.0f)
|
||||||
|
{
|
||||||
|
x-=1.0f;
|
||||||
|
if(pw1t)
|
||||||
|
mixInImpulseCenter(buffer1,bP1,x/delta, 1);
|
||||||
|
pw1t=false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
inline float getValue(float x,float pulseWidth)
|
||||||
|
{
|
||||||
|
float oscmix;
|
||||||
|
if(x >= pulseWidth)
|
||||||
|
oscmix = 1 - (0.5-pulseWidth) - 0.5;
|
||||||
|
else
|
||||||
|
oscmix = -(0.5-pulseWidth) - 0.5;
|
||||||
|
return del1.feedReturn(oscmix);
|
||||||
|
}
|
||||||
|
inline float getValueFast(float x,float pulseWidth)
|
||||||
|
{
|
||||||
|
float oscmix;
|
||||||
|
if(x >= pulseWidth)
|
||||||
|
oscmix = 1 - (0.5-pulseWidth) - 0.5;
|
||||||
|
else
|
||||||
|
oscmix = -(0.5-pulseWidth) - 0.5;
|
||||||
|
return oscmix;
|
||||||
|
}
|
||||||
|
inline void processSlave(float x , float delta,bool hardSyncReset,float hardSyncFrac,float pulseWidth,float pulseWidthWas)
|
||||||
|
{
|
||||||
|
float summated = delta- (pulseWidth - pulseWidthWas);
|
||||||
|
|
||||||
|
if((pw1t) && x >= 1.0f)
|
||||||
|
{
|
||||||
|
x -= 1.0f;
|
||||||
|
if(((!hardSyncReset)||(x/delta > hardSyncFrac)))//de morgan processed equation
|
||||||
|
{
|
||||||
|
if(pw1t)
|
||||||
|
mixInImpulseCenter(buffer1,bP1,x/delta, 1);
|
||||||
|
pw1t=false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x+=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if((!pw1t)&& (x >= pulseWidth) && (x - summated <=pulseWidth))
|
||||||
|
{
|
||||||
|
pw1t=true;
|
||||||
|
float frac =(x-pulseWidth) / summated;
|
||||||
|
if(((!hardSyncReset)||(frac > hardSyncFrac)))//de morgan processed equation
|
||||||
|
{
|
||||||
|
//transition to 1
|
||||||
|
mixInImpulseCenter(buffer1,bP1,frac,-1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//if transition do not ocurred
|
||||||
|
pw1t=false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if((pw1t) && x >= 1.0f)
|
||||||
|
{
|
||||||
|
x -= 1.0f;
|
||||||
|
if(((!hardSyncReset)||(x/delta > hardSyncFrac)))//de morgan processed equation
|
||||||
|
{
|
||||||
|
if(pw1t)
|
||||||
|
mixInImpulseCenter(buffer1,bP1,x/delta, 1);
|
||||||
|
pw1t=false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x+=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(hardSyncReset)
|
||||||
|
{
|
||||||
|
//float fracMaster = (delta * hardSyncFrac);
|
||||||
|
float trans =(pw1t?1:0);
|
||||||
|
mixInImpulseCenter(buffer1,bP1,hardSyncFrac,trans);
|
||||||
|
pw1t = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
inline void mixInImpulseCenter(float * buf,int& bpos,float offset, float scale)
|
||||||
|
{
|
||||||
|
int lpIn =(int)(B_OVERSAMPLING*(offset));
|
||||||
|
float frac = offset * B_OVERSAMPLING - lpIn;
|
||||||
|
float f1 = 1.0f-frac;
|
||||||
|
for(int i = 0 ; i < Samples;i++)
|
||||||
|
{
|
||||||
|
float mixvalue = (blepPTR[lpIn]*f1+blepPTR[lpIn+1]*(frac));
|
||||||
|
buf[(bpos+i)&(n-1)] += mixvalue*scale;
|
||||||
|
lpIn += B_OVERSAMPLING;
|
||||||
|
}
|
||||||
|
for(int i = Samples ; i <n;i++)
|
||||||
|
{
|
||||||
|
float mixvalue = (blepPTR[lpIn]*f1+blepPTR[lpIn+1]*(frac));
|
||||||
|
buf[(bpos+i)&(n-1)] -= mixvalue*scale;
|
||||||
|
lpIn += B_OVERSAMPLING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline float getNextBlep(float* buf,int& bpos)
|
||||||
|
{
|
||||||
|
buf[bpos]= 0.0f;
|
||||||
|
bpos++;
|
||||||
|
|
||||||
|
// Wrap pos
|
||||||
|
bpos&=(n-1);
|
||||||
|
return buf[bpos];
|
||||||
|
}
|
||||||
|
};
|
128
Source/Engine/SawOsc.h
Executable file
128
Source/Engine/SawOsc.h
Executable file
|
@ -0,0 +1,128 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
This file is part of Obxd synthesizer.
|
||||||
|
|
||||||
|
Copyright © 2013-2014 Filatov Vadim
|
||||||
|
|
||||||
|
Contact author via email :
|
||||||
|
justdat_@_e1.ru
|
||||||
|
|
||||||
|
This file may be licensed under the terms of of the
|
||||||
|
GNU General Public License Version 2 (the ``GPL'').
|
||||||
|
|
||||||
|
Software distributed under the License is distributed
|
||||||
|
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
|
||||||
|
express or implied. See the GPL for the specific language
|
||||||
|
governing rights and limitations.
|
||||||
|
|
||||||
|
You should have received a copy of the GPL along with this
|
||||||
|
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||||
|
or write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include "SynthEngine.h"
|
||||||
|
#include "BlepData.h"
|
||||||
|
class SawOsc
|
||||||
|
{
|
||||||
|
DelayLine<Samples> del1;
|
||||||
|
float buffer1[Samples*2];
|
||||||
|
const int hsam;
|
||||||
|
const int n;
|
||||||
|
float const * blepPTR;
|
||||||
|
int bP1;
|
||||||
|
public:
|
||||||
|
SawOsc() : hsam(Samples)
|
||||||
|
, n(Samples*2)
|
||||||
|
{
|
||||||
|
bP1=0;
|
||||||
|
//del1 = new DelayLine(hsam);
|
||||||
|
//buffer1= new float[n];
|
||||||
|
for(int i = 0 ; i < n ; i++)
|
||||||
|
buffer1[i]=0;
|
||||||
|
blepPTR = blep;
|
||||||
|
}
|
||||||
|
~SawOsc()
|
||||||
|
{
|
||||||
|
//delete del1;
|
||||||
|
//delete buffer1;
|
||||||
|
}
|
||||||
|
inline void setDecimation()
|
||||||
|
{
|
||||||
|
blepPTR = blepd2;
|
||||||
|
}
|
||||||
|
inline void removeDecimation()
|
||||||
|
{
|
||||||
|
blepPTR = blep;
|
||||||
|
}
|
||||||
|
inline float aliasReduction()
|
||||||
|
{
|
||||||
|
return -getNextBlep(buffer1,bP1);
|
||||||
|
}
|
||||||
|
inline void processMaster(float x,float delta)
|
||||||
|
{
|
||||||
|
if(x >= 1.0f)
|
||||||
|
{
|
||||||
|
x-=1.0f;
|
||||||
|
mixInImpulseCenter(buffer1,bP1,x/delta, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline float getValue(float x)
|
||||||
|
{
|
||||||
|
return del1.feedReturn(x-0.5);
|
||||||
|
}
|
||||||
|
inline float getValueFast(float x)
|
||||||
|
{
|
||||||
|
return x - 0.5;
|
||||||
|
}
|
||||||
|
inline void processSlave(float x , float delta,bool hardSyncReset,float hardSyncFrac)
|
||||||
|
{
|
||||||
|
if(x >= 1.0f)
|
||||||
|
{
|
||||||
|
x -= 1.0f;
|
||||||
|
if(((!hardSyncReset)||(x/delta > hardSyncFrac)))//de morgan processed equation
|
||||||
|
{
|
||||||
|
mixInImpulseCenter(buffer1,bP1,x/delta, 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//if transition do not ocurred
|
||||||
|
x+=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(hardSyncReset)
|
||||||
|
{
|
||||||
|
float fracMaster = (delta * hardSyncFrac);
|
||||||
|
float trans = (x-fracMaster);
|
||||||
|
mixInImpulseCenter(buffer1,bP1,hardSyncFrac,trans);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void mixInImpulseCenter(float * buf,int& bpos,float offset, float scale)
|
||||||
|
{
|
||||||
|
int lpIn =(int)(B_OVERSAMPLING*(offset));
|
||||||
|
float frac = offset * B_OVERSAMPLING - lpIn;
|
||||||
|
float f1 = 1.0f-frac;
|
||||||
|
for(int i = 0 ; i < Samples;i++)
|
||||||
|
{
|
||||||
|
float mixvalue = (blepPTR[lpIn]*f1+blepPTR[lpIn+1]*frac);
|
||||||
|
buf[(bpos+i)&(n-1)] += mixvalue*scale;
|
||||||
|
lpIn += B_OVERSAMPLING;
|
||||||
|
}
|
||||||
|
for(int i = Samples ; i <n;i++)
|
||||||
|
{
|
||||||
|
float mixvalue = (blepPTR[lpIn]*f1+blepPTR[lpIn+1]*frac);
|
||||||
|
buf[(bpos+i)&(n-1)] -= mixvalue*scale;
|
||||||
|
lpIn += B_OVERSAMPLING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline float getNextBlep(float* buf,int& bpos)
|
||||||
|
{
|
||||||
|
buf[bpos]= 0.0f;
|
||||||
|
bpos++;
|
||||||
|
|
||||||
|
// Wrap pos
|
||||||
|
bpos&=(n-1);
|
||||||
|
return buf[bpos];
|
||||||
|
}
|
||||||
|
};
|
603
Source/Engine/SynthEngine.h
Executable file
603
Source/Engine/SynthEngine.h
Executable file
|
@ -0,0 +1,603 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
This file is part of Obxd synthesizer.
|
||||||
|
|
||||||
|
Copyright ) 2013-2014 Filatov Vadim
|
||||||
|
|
||||||
|
Contact author via email :
|
||||||
|
justdat_@_e1.ru
|
||||||
|
|
||||||
|
This file may be licensed under the terms of of the
|
||||||
|
GNU General Public License Version 2 (the ``GPL'').
|
||||||
|
|
||||||
|
Software distributed under the License is distributed
|
||||||
|
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
|
||||||
|
express or implied. See the GPL for the specific language
|
||||||
|
governing rights and limitations.
|
||||||
|
|
||||||
|
You should have received a copy of the GPL along with this
|
||||||
|
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||||
|
or write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../PluginProcessor.h"
|
||||||
|
#include "ObxdVoice.h"
|
||||||
|
#include "Motherboard.h"
|
||||||
|
#include "Params.h"
|
||||||
|
#include "ParamSmoother.h"
|
||||||
|
|
||||||
|
class SynthEngine
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Motherboard synth;
|
||||||
|
ParamSmoother cutoffSmoother;
|
||||||
|
ParamSmoother pitchWheelSmoother;
|
||||||
|
ParamSmoother modWheelSmoother;
|
||||||
|
float sampleRate;
|
||||||
|
//JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SynthEngine)
|
||||||
|
public:
|
||||||
|
SynthEngine():
|
||||||
|
cutoffSmoother(),
|
||||||
|
//synth = new Motherboard();
|
||||||
|
pitchWheelSmoother(),
|
||||||
|
modWheelSmoother()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
~SynthEngine()
|
||||||
|
{
|
||||||
|
//delete synth;
|
||||||
|
}
|
||||||
|
void setPlayHead(float bpm,float retrPos)
|
||||||
|
{
|
||||||
|
synth.mlfo.hostSyncRetrigger(bpm,retrPos);
|
||||||
|
}
|
||||||
|
void setSampleRate(float sr)
|
||||||
|
{
|
||||||
|
sampleRate = sr;
|
||||||
|
cutoffSmoother.setSampleRate(sr);
|
||||||
|
pitchWheelSmoother.setSampleRate(sr);
|
||||||
|
modWheelSmoother.setSampleRate(sr);
|
||||||
|
synth.setSampleRate(sr);
|
||||||
|
}
|
||||||
|
void processSample(float *left,float *right)
|
||||||
|
{
|
||||||
|
processCutoffSmoothed(cutoffSmoother.smoothStep());
|
||||||
|
procPitchWheelSmoothed(pitchWheelSmoother.smoothStep());
|
||||||
|
procModWheelSmoothed(modWheelSmoother.smoothStep());
|
||||||
|
|
||||||
|
synth.processSample(left,right);
|
||||||
|
}
|
||||||
|
void allNotesOff()
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < 128;i++)
|
||||||
|
{
|
||||||
|
procNoteOff(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void allSoundOff()
|
||||||
|
{
|
||||||
|
allNotesOff();
|
||||||
|
for(int i = 0 ; i < Motherboard::MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].ResetEnvelope();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void sustainOn()
|
||||||
|
{
|
||||||
|
synth.sustainOn();
|
||||||
|
}
|
||||||
|
void sustainOff()
|
||||||
|
{
|
||||||
|
synth.sustainOff();
|
||||||
|
}
|
||||||
|
void procLfoSync(float val)
|
||||||
|
{
|
||||||
|
if(val > 0.5)
|
||||||
|
synth.mlfo.setSynced();
|
||||||
|
else
|
||||||
|
synth.mlfo.setUnsynced();
|
||||||
|
}
|
||||||
|
void procAsPlayedAlloc(float val)
|
||||||
|
{
|
||||||
|
synth.asPlayedMode = val > 0.5;
|
||||||
|
}
|
||||||
|
void procNoteOn(int noteNo,float velocity)
|
||||||
|
{
|
||||||
|
synth.setNoteOn(noteNo,velocity);
|
||||||
|
}
|
||||||
|
void procNoteOff(int noteNo)
|
||||||
|
{
|
||||||
|
synth.setNoteOff(noteNo);
|
||||||
|
}
|
||||||
|
void procEconomyMode(float val)
|
||||||
|
{
|
||||||
|
synth.economyMode = val>0.5;
|
||||||
|
}
|
||||||
|
#define ForEachVoice(expr) \
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++) \
|
||||||
|
{\
|
||||||
|
synth.voices[i].expr;\
|
||||||
|
}\
|
||||||
|
|
||||||
|
void procAmpVelocityAmount(float val)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].vamp= val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void procFltVelocityAmount(float val)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].vflt= val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void procModWheel(float val)
|
||||||
|
{
|
||||||
|
modWheelSmoother.setSteep(val);
|
||||||
|
}
|
||||||
|
void procModWheelSmoothed(float val)
|
||||||
|
{
|
||||||
|
synth.vibratoAmount = val;
|
||||||
|
}
|
||||||
|
void procModWheelFrequency(float val)
|
||||||
|
{
|
||||||
|
synth.vibratoLfo.setFrequency (logsc(val,3,10));
|
||||||
|
synth.vibratoEnabled = val>0.05;
|
||||||
|
}
|
||||||
|
void procPitchWheel(float val)
|
||||||
|
{
|
||||||
|
pitchWheelSmoother.setSteep(val);
|
||||||
|
//for(int i = 0 ; i < synth->MAX_VOICES;i++)
|
||||||
|
//{
|
||||||
|
// synth->voices[i]->pitchWheel = val;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
inline void procPitchWheelSmoothed(float val)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].pitchWheel = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void setVoiceCount(float param)
|
||||||
|
{
|
||||||
|
synth.setVoiceCount(roundToInt((param*7) +1));
|
||||||
|
}
|
||||||
|
void procPitchWheelAmount(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].pitchWheelAmt = param>0.5?12:2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void procPitchWheelOsc2Only(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].pitchWheelOsc2Only = param>0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processPan(float param,int idx)
|
||||||
|
{
|
||||||
|
synth.pannings[idx-1] = param;
|
||||||
|
}
|
||||||
|
void processTune(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].osc.tune = param*2-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processLegatoMode(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].legatoMode = roundToInt(param*3 + 1) -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processOctave(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].osc.oct = (roundToInt(param*4) -2)*12;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processFilterKeyFollow(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].fltKF = param;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processSelfOscPush(float param)
|
||||||
|
{
|
||||||
|
ForEachVoice(selfOscPush = param>0.5);
|
||||||
|
ForEachVoice(flt.selfOscPush = param>0.5);
|
||||||
|
}
|
||||||
|
void processUnison(float param)
|
||||||
|
{
|
||||||
|
synth.uni = param>0.5f;
|
||||||
|
}
|
||||||
|
void processPortamento(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].porta =logsc(1-param,0.14,250,150);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processVolume(float param)
|
||||||
|
{
|
||||||
|
synth.Volume = linsc(param,0,0.30);
|
||||||
|
}
|
||||||
|
void processLfoFrequency(float param)
|
||||||
|
{
|
||||||
|
synth.mlfo.setRawParam(param);
|
||||||
|
synth.mlfo.setFrequency(logsc(param,0,50,120));
|
||||||
|
}
|
||||||
|
void processLfoSine(float param)
|
||||||
|
{
|
||||||
|
if(param>0.5)
|
||||||
|
{
|
||||||
|
synth.mlfo.waveForm |=1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
synth.mlfo.waveForm&=~1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processLfoSquare(float param)
|
||||||
|
{
|
||||||
|
if(param>0.5)
|
||||||
|
{
|
||||||
|
synth.mlfo.waveForm |=2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
synth.mlfo.waveForm&=~2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processLfoSH(float param)
|
||||||
|
{
|
||||||
|
if(param>0.5)
|
||||||
|
{
|
||||||
|
synth.mlfo.waveForm |=4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
synth.mlfo.waveForm&=~4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processLfoAmt1(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].lfoa1 = logsc(logsc(param,0,1,60),0,60,10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processLfoOsc1(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].lfoo1 = param>0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processLfoOsc2(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].lfoo2 = param>0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processLfoFilter(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].lfof = param>0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processLfoPw1(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].lfopw1 = param>0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processLfoPw2(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].lfopw2 = param>0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processLfoAmt2(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].lfoa2 = linsc(param,0,0.7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processDetune(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].osc.totalDetune = logsc(param,0.001,0.90);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processPulseWidth(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].osc.pulseWidth = linsc(param,0.0,0.95);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processPwEnv(float param)
|
||||||
|
{
|
||||||
|
ForEachVoice (pwenvmod=linsc(param,0,0.85));
|
||||||
|
}
|
||||||
|
void processPwOfs(float param)
|
||||||
|
{
|
||||||
|
ForEachVoice(pwOfs = linsc(param,0,0.75));
|
||||||
|
}
|
||||||
|
void processPwEnvBoth(float param)
|
||||||
|
{
|
||||||
|
ForEachVoice(pwEnvBoth = param>0.5);
|
||||||
|
}
|
||||||
|
void processInvertFenv(float param)
|
||||||
|
{
|
||||||
|
ForEachVoice(invertFenv = param>0.5);
|
||||||
|
}
|
||||||
|
void processPitchModBoth(float param)
|
||||||
|
{
|
||||||
|
ForEachVoice(pitchModBoth = param>0.5);
|
||||||
|
}
|
||||||
|
void processOsc2Xmod(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].osc.xmod= param*24;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processEnvelopeToPitch(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].envpitchmod= param*36;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processOsc2HardSync(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].osc.hardSync = param>0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processOsc1Pitch(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].osc.osc1p = (param * 48);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processOsc2Pitch(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].osc.osc2p = (param * 48);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processPitchQuantization(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].osc.quantizeCw = param>0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processOsc1Mix(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].osc.o1mx = param;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processOsc2Mix(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].osc.o2mx = param;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processNoiseMix(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].osc.nmx = logsc(param,0,1,35);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processBrightness(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].setBrightness( linsc(param,7000,26000));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processOsc2Det(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].osc.osc2Det = logsc(param,0.001,0.6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void processOsc1Saw(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].osc.osc1Saw = param>0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processOsc1Pulse(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].osc.osc1Pul = param>0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processOsc2Saw(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].osc.osc2Saw= param>0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processOsc2Pulse(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].osc.osc2Pul= param>0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void processCutoff(float param)
|
||||||
|
{
|
||||||
|
cutoffSmoother.setSteep( linsc(param,0,120));
|
||||||
|
// for(int i = 0 ; i < synth->MAX_VOICES;i++)
|
||||||
|
// {
|
||||||
|
//synth->voices[i]->cutoff = logsc(param,60,19000,30);
|
||||||
|
// synth->voices[i]->cutoff = linsc(param,0,120);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
inline void processCutoffSmoothed(float param)
|
||||||
|
{
|
||||||
|
ForEachVoice(cutoff=param);
|
||||||
|
}
|
||||||
|
void processBandpassSw(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
//synth.voices[i].cutoff = logsc(param,60,19000,30);
|
||||||
|
synth.voices[i].flt.bandPassSw = param>0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processResonance(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].flt.setResonance(0.991-logsc(1-param,0,0.991,40));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processFourPole(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
//synth.voices[i].flt ;
|
||||||
|
synth.voices[i].fourpole = param>0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processMultimode(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
//synth.voices[i].flt ;
|
||||||
|
synth.voices[i].flt.setMultimode(linsc(param,0,1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processOversampling(float param)
|
||||||
|
{
|
||||||
|
synth.SetOversample(param>0.5);
|
||||||
|
}
|
||||||
|
void processFilterEnvelopeAmt(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].fenvamt = linsc(param,0,140);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processLoudnessEnvelopeAttack(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].env.setAttack(logsc(param,4,60000,900));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processLoudnessEnvelopeDecay(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].env.setDecay(logsc(param,4,60000,900));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processLoudnessEnvelopeRelease(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].env.setRelease(logsc(param,8,60000,900));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processLoudnessEnvelopeSustain(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].env.setSustain(param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processFilterEnvelopeAttack(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].fenv.setAttack(logsc(param,1,60000,900));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processFilterEnvelopeDecay(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].fenv.setDecay(logsc(param,1,60000,900));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processFilterEnvelopeRelease(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].fenv.setRelease(logsc(param,1,60000,900));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processFilterEnvelopeSustain(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].fenv.setSustain(param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processEnvelopeDetune(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].setEnvDer(linsc(param,0.0,1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processFilterDetune(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].FltDetAmt = linsc(param,0.0,18);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processPortamentoDetune(float param)
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < synth.MAX_VOICES;i++)
|
||||||
|
{
|
||||||
|
synth.voices[i].PortaDetuneAmt = linsc(param,0.0,0.75);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void processLoudnessDetune(float param)
|
||||||
|
{
|
||||||
|
ForEachVoice(levelDetuneAmt = linsc(param,0.0,0.67));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
183
Source/Engine/TriangleOsc.h
Executable file
183
Source/Engine/TriangleOsc.h
Executable file
|
@ -0,0 +1,183 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
This file is part of Obxd synthesizer.
|
||||||
|
|
||||||
|
Copyright © 2013-2014 Filatov Vadim
|
||||||
|
|
||||||
|
Contact author via email :
|
||||||
|
justdat_@_e1.ru
|
||||||
|
|
||||||
|
This file may be licensed under the terms of of the
|
||||||
|
GNU General Public License Version 2 (the ``GPL'').
|
||||||
|
|
||||||
|
Software distributed under the License is distributed
|
||||||
|
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
|
||||||
|
express or implied. See the GPL for the specific language
|
||||||
|
governing rights and limitations.
|
||||||
|
|
||||||
|
You should have received a copy of the GPL along with this
|
||||||
|
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||||
|
or write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include "SynthEngine.h"
|
||||||
|
#include "BlepData.h"
|
||||||
|
class TriangleOsc
|
||||||
|
{
|
||||||
|
DelayLine<Samples> del1;
|
||||||
|
bool fall;
|
||||||
|
float buffer1[Samples*2];
|
||||||
|
const int hsam;
|
||||||
|
const int n;
|
||||||
|
float const * blepPTR;
|
||||||
|
float const * blampPTR;
|
||||||
|
|
||||||
|
int bP1,bP2;
|
||||||
|
public:
|
||||||
|
TriangleOsc() : hsam(Samples)
|
||||||
|
, n(Samples*2)
|
||||||
|
{
|
||||||
|
//del1 =new DelayLine(hsam);
|
||||||
|
fall = false;
|
||||||
|
bP1=bP2=0;
|
||||||
|
// buffer1= new float[n];
|
||||||
|
for(int i = 0 ; i < n ; i++)
|
||||||
|
buffer1[i]=0;
|
||||||
|
blepPTR = blep;
|
||||||
|
blampPTR = blamp;
|
||||||
|
}
|
||||||
|
~TriangleOsc()
|
||||||
|
{
|
||||||
|
//delete buffer1;
|
||||||
|
//delete del1;
|
||||||
|
}
|
||||||
|
inline void setDecimation()
|
||||||
|
{
|
||||||
|
blepPTR = blepd2;
|
||||||
|
blampPTR = blampd2;
|
||||||
|
}
|
||||||
|
inline void removeDecimation()
|
||||||
|
{
|
||||||
|
blepPTR = blep;
|
||||||
|
blampPTR = blamp;
|
||||||
|
}
|
||||||
|
inline float aliasReduction()
|
||||||
|
{
|
||||||
|
return -getNextBlep(buffer1,bP1);
|
||||||
|
}
|
||||||
|
inline void processMaster(float x,float delta)
|
||||||
|
{
|
||||||
|
if(x >= 1.0)
|
||||||
|
{
|
||||||
|
x-=1.0;
|
||||||
|
mixInBlampCenter(buffer1,bP1,x/delta,-4*Samples*delta);
|
||||||
|
}
|
||||||
|
if(x >= 0.5 && x - delta < 0.5)
|
||||||
|
{
|
||||||
|
mixInBlampCenter(buffer1,bP1,(x-0.5)/delta,4*Samples*delta);
|
||||||
|
}
|
||||||
|
if(x >= 1.0)
|
||||||
|
{
|
||||||
|
x-=1.0;
|
||||||
|
mixInBlampCenter(buffer1,bP1,x/delta,-4*Samples*delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline float getValue(float x)
|
||||||
|
{
|
||||||
|
float mix = x < 0.5 ? 2*x-0.5 : 1.5-2*x;
|
||||||
|
return del1.feedReturn(mix);
|
||||||
|
}
|
||||||
|
inline float getValueFast(float x)
|
||||||
|
{
|
||||||
|
float mix = x < 0.5 ? 2*x-0.5 : 1.5-2*x;
|
||||||
|
return mix;
|
||||||
|
}
|
||||||
|
inline void processSlave(float x , float delta,bool hardSyncReset,float hardSyncFrac)
|
||||||
|
{
|
||||||
|
bool hspass = true;
|
||||||
|
if(x >= 1.0)
|
||||||
|
{
|
||||||
|
x-=1.0;
|
||||||
|
if(((!hardSyncReset)||(x/delta > hardSyncFrac)))//de morgan processed equation
|
||||||
|
{
|
||||||
|
mixInBlampCenter(buffer1,bP1,x/delta,-4*Samples*delta);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x+=1;
|
||||||
|
hspass = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(x >= 0.5 && x - delta < 0.5 &&hspass)
|
||||||
|
{
|
||||||
|
float frac = (x - 0.5) / delta;
|
||||||
|
if(((!hardSyncReset)||(frac > hardSyncFrac)))//de morgan processed equation
|
||||||
|
{
|
||||||
|
mixInBlampCenter(buffer1,bP1,frac,4*Samples*delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(x >= 1.0 && hspass)
|
||||||
|
{
|
||||||
|
x-=1.0;
|
||||||
|
if(((!hardSyncReset)||(x/delta > hardSyncFrac)))//de morgan processed equation
|
||||||
|
{
|
||||||
|
mixInBlampCenter(buffer1,bP1,x/delta,-4*Samples*delta);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//if transition do not ocurred
|
||||||
|
x+=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(hardSyncReset)
|
||||||
|
{
|
||||||
|
float fracMaster = (delta * hardSyncFrac);
|
||||||
|
float trans = (x-fracMaster);
|
||||||
|
float mix = trans < 0.5 ? 2*trans-0.5 : 1.5-2*trans;
|
||||||
|
if(trans >0.5)
|
||||||
|
mixInBlampCenter(buffer1,bP1,hardSyncFrac,-4*Samples*delta);
|
||||||
|
mixInImpulseCenter(buffer1,bP1,hardSyncFrac,mix+0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void mixInBlampCenter(float * buf,int& bpos,float offset, float scale)
|
||||||
|
{
|
||||||
|
int lpIn =(int)(B_OVERSAMPLING*(offset));
|
||||||
|
float frac = offset * B_OVERSAMPLING - lpIn;
|
||||||
|
float f1 = 1.0f-frac;
|
||||||
|
for(int i = 0 ; i < n;i++)
|
||||||
|
{
|
||||||
|
float mixvalue = (blampPTR[lpIn]*f1+blampPTR[lpIn+1]*(frac));
|
||||||
|
buf[(bpos+i)&(n-1)] += mixvalue*scale;
|
||||||
|
lpIn += B_OVERSAMPLING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline void mixInImpulseCenter(float * buf,int& bpos,float offset, float scale)
|
||||||
|
{
|
||||||
|
int lpIn =(int)(B_OVERSAMPLING*(offset));
|
||||||
|
float frac = offset * B_OVERSAMPLING - lpIn;
|
||||||
|
float f1 = 1.0f-frac;
|
||||||
|
for(int i = 0 ; i < Samples;i++)
|
||||||
|
{
|
||||||
|
float mixvalue = (blepPTR[lpIn]*f1+blepPTR[lpIn+1]*(frac));
|
||||||
|
buf[(bpos+i)&(n-1)] += mixvalue*scale;
|
||||||
|
lpIn += B_OVERSAMPLING;
|
||||||
|
}
|
||||||
|
for(int i = Samples ; i <n;i++)
|
||||||
|
{
|
||||||
|
float mixvalue = (blepPTR[lpIn]*f1+blepPTR[lpIn+1]*(frac));
|
||||||
|
buf[(bpos+i)&(n-1)] -= mixvalue*scale;
|
||||||
|
lpIn += B_OVERSAMPLING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline float getNextBlep(float* buf,int& bpos)
|
||||||
|
{
|
||||||
|
buf[bpos]= 0.0f;
|
||||||
|
bpos++;
|
||||||
|
|
||||||
|
// Wrap pos
|
||||||
|
bpos&=(n-1);
|
||||||
|
return buf[bpos];
|
||||||
|
}
|
||||||
|
};
|
54
Source/Engine/VoiceQueue.h
Executable file
54
Source/Engine/VoiceQueue.h
Executable file
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
This file is part of Obxd synthesizer.
|
||||||
|
|
||||||
|
Copyright ) 2013-2014 Filatov Vadim
|
||||||
|
|
||||||
|
Contact author via email :
|
||||||
|
justdat_@_e1.ru
|
||||||
|
|
||||||
|
This file may be licensed under the terms of of the
|
||||||
|
GNU General Public License Version 2 (the ``GPL'').
|
||||||
|
|
||||||
|
Software distributed under the License is distributed
|
||||||
|
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
|
||||||
|
express or implied. See the GPL for the specific language
|
||||||
|
governing rights and limitations.
|
||||||
|
|
||||||
|
You should have received a copy of the GPL along with this
|
||||||
|
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||||
|
or write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include "ObxdVoice.h"
|
||||||
|
class VoiceQueue
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
ObxdVoice* voices;
|
||||||
|
int idx,total;
|
||||||
|
public:
|
||||||
|
VoiceQueue()
|
||||||
|
{
|
||||||
|
voices = NULL;
|
||||||
|
idx = 0;
|
||||||
|
total = 0;
|
||||||
|
}
|
||||||
|
VoiceQueue(int voiceCount,ObxdVoice* voicesReference)
|
||||||
|
{
|
||||||
|
voices = voicesReference;
|
||||||
|
idx = 0;total = voiceCount;
|
||||||
|
}
|
||||||
|
inline ObxdVoice* getNext()
|
||||||
|
{
|
||||||
|
idx = idx + 1;
|
||||||
|
idx %=total;
|
||||||
|
return &voices[idx];
|
||||||
|
}
|
||||||
|
inline void reInit(int voiceCount)
|
||||||
|
{
|
||||||
|
total = voiceCount;
|
||||||
|
idx = idx%total;
|
||||||
|
}
|
||||||
|
};
|
35
Source/Engine/midiMap.h
Executable file
35
Source/Engine/midiMap.h
Executable file
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
This file is part of Obxd synthesizer.
|
||||||
|
|
||||||
|
Copyright © 2013-2014 Filatov Vadim
|
||||||
|
|
||||||
|
Contact author via email :
|
||||||
|
justdat_@_e1.ru
|
||||||
|
|
||||||
|
This file may be licensed under the terms of of the
|
||||||
|
GNU General Public License Version 2 (the ``GPL'').
|
||||||
|
|
||||||
|
Software distributed under the License is distributed
|
||||||
|
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
|
||||||
|
express or implied. See the GPL for the specific language
|
||||||
|
governing rights and limitations.
|
||||||
|
|
||||||
|
You should have received a copy of the GPL along with this
|
||||||
|
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||||
|
or write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include "SynthEngine.h"
|
||||||
|
class MidiMap
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int controllers[255];
|
||||||
|
MidiMap()
|
||||||
|
{
|
||||||
|
for(int i = 0 ; i < 255;i++)
|
||||||
|
controllers[i] = 0;
|
||||||
|
}
|
||||||
|
};
|
7884
Source/Gui/BinaryData.cpp
Normal file
7884
Source/Gui/BinaryData.cpp
Normal file
File diff suppressed because it is too large
Load diff
41
Source/Gui/BinaryData.h
Normal file
41
Source/Gui/BinaryData.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/* =========================================================================================
|
||||||
|
|
||||||
|
This is an auto-generated file: Any edits you make may be overwritten!
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BINARYDATA_H_12816941_INCLUDED
|
||||||
|
#define BINARYDATA_H_12816941_INCLUDED
|
||||||
|
|
||||||
|
namespace BinaryData
|
||||||
|
{
|
||||||
|
extern const char* knoblsd_png;
|
||||||
|
const int knoblsd_pngSize = 214673;
|
||||||
|
|
||||||
|
extern const char* knobssd_png;
|
||||||
|
const int knobssd_pngSize = 174727;
|
||||||
|
|
||||||
|
extern const char* legato_png;
|
||||||
|
const int legato_pngSize = 7913;
|
||||||
|
|
||||||
|
extern const char* voices_png;
|
||||||
|
const int voices_pngSize = 3496;
|
||||||
|
|
||||||
|
extern const char* button_png;
|
||||||
|
const int button_pngSize = 1794;
|
||||||
|
|
||||||
|
extern const char* main_png;
|
||||||
|
const int main_pngSize = 147135;
|
||||||
|
|
||||||
|
// Points to the start of a list of resource names.
|
||||||
|
extern const char* namedResourceList[];
|
||||||
|
|
||||||
|
// Number of elements in the namedResourceList array.
|
||||||
|
const int namedResourceListSize = 6;
|
||||||
|
|
||||||
|
// If you provide the name of one of the binary resource variables above, this function will
|
||||||
|
// return the corresponding data and its size (or a null pointer if the name isn't found).
|
||||||
|
const char* getNamedResource (const char* resourceNameUTF8, int& dataSizeInBytes) throw();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
60
Source/Gui/ButtonList.h
Executable file
60
Source/Gui/ButtonList.h
Executable file
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
This file is part of Obxd synthesizer.
|
||||||
|
|
||||||
|
Copyright <EFBFBD> 2013-2014 Filatov Vadim
|
||||||
|
|
||||||
|
Contact author via email :
|
||||||
|
justdat_@_e1.ru
|
||||||
|
|
||||||
|
This file may be licensed under the terms of of the
|
||||||
|
GNU General Public License Version 2 (the ``GPL'').
|
||||||
|
|
||||||
|
Software distributed under the License is distributed
|
||||||
|
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
|
||||||
|
express or implied. See the GPL for the specific language
|
||||||
|
governing rights and limitations.
|
||||||
|
|
||||||
|
You should have received a copy of the GPL along with this
|
||||||
|
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||||
|
or write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include "../Source/Engine/SynthEngine.h"
|
||||||
|
class ButtonList : public ComboBox{
|
||||||
|
private :
|
||||||
|
int count;
|
||||||
|
Image kni;
|
||||||
|
int w2,h2;
|
||||||
|
public:
|
||||||
|
ButtonList(Image k,int fh) :ComboBox("cb")
|
||||||
|
{
|
||||||
|
kni = k;
|
||||||
|
count = 0;
|
||||||
|
h2 =fh;
|
||||||
|
w2 = k.getWidth();
|
||||||
|
}
|
||||||
|
//int addItem
|
||||||
|
void addChoise(String name)
|
||||||
|
{
|
||||||
|
addItem(name,++count);
|
||||||
|
}
|
||||||
|
float getValue()
|
||||||
|
{
|
||||||
|
return ((getSelectedId()-1)/ (float)(count-1));
|
||||||
|
}
|
||||||
|
void setValue(float val,NotificationType notify)
|
||||||
|
{
|
||||||
|
setSelectedId((int)(val*(count -1) + 1),notify);
|
||||||
|
}
|
||||||
|
void paintOverChildren(Graphics& g)
|
||||||
|
{
|
||||||
|
int ofs = getSelectedId()-1;
|
||||||
|
g.drawImage(kni, 0, 0, getWidth(), getHeight(),
|
||||||
|
0, h2*ofs, w2, h2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
55
Source/Gui/Knob.h
Executable file
55
Source/Gui/Knob.h
Executable file
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
This file is part of Obxd synthesizer.
|
||||||
|
|
||||||
|
Copyright © 2013-2014 Filatov Vadim
|
||||||
|
|
||||||
|
Contact author via email :
|
||||||
|
justdat_@_e1.ru
|
||||||
|
|
||||||
|
This file may be licensed under the terms of of the
|
||||||
|
GNU General Public License Version 2 (the ``GPL'').
|
||||||
|
|
||||||
|
Software distributed under the License is distributed
|
||||||
|
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
|
||||||
|
express or implied. See the GPL for the specific language
|
||||||
|
governing rights and limitations.
|
||||||
|
|
||||||
|
You should have received a copy of the GPL along with this
|
||||||
|
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||||
|
or write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include "../Source/Engine/SynthEngine.h"
|
||||||
|
class Knob : public Slider
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//Knob(Image image, const int numFrames, const bool stripIsHorizontal) : Slider("Knob")
|
||||||
|
//{
|
||||||
|
|
||||||
|
// setTextBoxStyle(NoTextBox, 0, 0, 0);
|
||||||
|
// setSliderStyle(RotaryVerticalDrag);
|
||||||
|
// setRange(0.0f, 1.0f, 0.001f);
|
||||||
|
//}
|
||||||
|
Knob(Image k,int fh) : Slider("Knob")
|
||||||
|
{
|
||||||
|
h2 =fh;
|
||||||
|
w2 = k.getWidth();
|
||||||
|
numFr = k.getHeight() / h2;
|
||||||
|
kni = k;
|
||||||
|
};
|
||||||
|
|
||||||
|
void paint(Graphics& g)
|
||||||
|
{
|
||||||
|
int ofs = (int)((getValue() - getMinimum()) / (getMaximum() - getMinimum()) * (numFr - 1));
|
||||||
|
g.drawImage(kni, 0, 0, getWidth(), getHeight(),
|
||||||
|
0, h2*ofs, w2, h2);
|
||||||
|
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
Image kni;
|
||||||
|
int fh,numFr;
|
||||||
|
int w2,h2;
|
||||||
|
};
|
83
Source/Gui/TooglableButton.h
Executable file
83
Source/Gui/TooglableButton.h
Executable file
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
This file is part of Obxd synthesizer.
|
||||||
|
|
||||||
|
Copyright © 2013-2014 Filatov Vadim
|
||||||
|
|
||||||
|
Contact author via email :
|
||||||
|
justdat_@_e1.ru
|
||||||
|
|
||||||
|
This file may be licensed under the terms of of the
|
||||||
|
GNU General Public License Version 2 (the ``GPL'').
|
||||||
|
|
||||||
|
Software distributed under the License is distributed
|
||||||
|
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
|
||||||
|
express or implied. See the GPL for the specific language
|
||||||
|
governing rights and limitations.
|
||||||
|
|
||||||
|
You should have received a copy of the GPL along with this
|
||||||
|
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||||
|
or write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include "../Source/Engine/SynthEngine.h"
|
||||||
|
class TooglableButton : public ImageButton
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool toogled;
|
||||||
|
TooglableButton(Image k) :ImageButton()
|
||||||
|
{
|
||||||
|
//this->setImages
|
||||||
|
kni = k;
|
||||||
|
toogled = false;
|
||||||
|
width = kni.getWidth();
|
||||||
|
height = kni.getHeight();
|
||||||
|
w2=width;
|
||||||
|
h2 = height / 2;
|
||||||
|
this->setClickingTogglesState(true);
|
||||||
|
}
|
||||||
|
void clicked()
|
||||||
|
{
|
||||||
|
toogled = !toogled;
|
||||||
|
//this->setColour(1,Colours::blue);
|
||||||
|
//if(toogled)
|
||||||
|
// this->setColour(TextButton::ColourIds::buttonColourId,Colours::lightgreen);
|
||||||
|
//else
|
||||||
|
// this->removeColour(TextButton::ColourIds::buttonColourId);
|
||||||
|
//this->setColour(DrawableButton::ColourIds::backgroundColourId,Colours::lightpink);
|
||||||
|
Button::clicked();
|
||||||
|
|
||||||
|
};
|
||||||
|
void paintButton(Graphics& g, bool isMouseOverButton, bool isButtonDown)
|
||||||
|
{
|
||||||
|
int offset = 0;
|
||||||
|
if (toogled)
|
||||||
|
{
|
||||||
|
offset = 1;
|
||||||
|
}
|
||||||
|
g.drawImage(kni, 0, 0, getWidth(), getHeight(),
|
||||||
|
0, offset *h2, w2,h2);
|
||||||
|
}
|
||||||
|
void setValue(float state,int notify)
|
||||||
|
{
|
||||||
|
if(state > 0.5)
|
||||||
|
toogled = true;
|
||||||
|
else toogled = false;
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
float getValue()
|
||||||
|
{
|
||||||
|
if(toogled)
|
||||||
|
return 1;
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
//void paint(Graphics& g)
|
||||||
|
//{
|
||||||
|
// g.drawImageTransformed(kni,AffineTransform::rotation(((getValue() - getMinimum())/(getMaximum() - getMinimum()))*float_Pi - float_Pi*2));
|
||||||
|
//}
|
||||||
|
private:
|
||||||
|
Image kni;
|
||||||
|
int width,height,w2,h2;
|
||||||
|
};
|
BIN
Source/Images/button.png
Normal file
BIN
Source/Images/button.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
BIN
Source/Images/knoblsd.png
Normal file
BIN
Source/Images/knoblsd.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 210 KiB |
BIN
Source/Images/knobssd.png
Normal file
BIN
Source/Images/knobssd.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 171 KiB |
BIN
Source/Images/legato.png
Normal file
BIN
Source/Images/legato.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.7 KiB |
BIN
Source/Images/main.png
Normal file
BIN
Source/Images/main.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 146 KiB |
BIN
Source/Images/voices.png
Normal file
BIN
Source/Images/voices.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.4 KiB |
731
Source/PluginEditor.cpp
Executable file
731
Source/PluginEditor.cpp
Executable file
|
@ -0,0 +1,731 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
|
||||||
|
This file was auto-generated by the Introjucer!
|
||||||
|
|
||||||
|
It contains the basic startup code for a Juce application.
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
#include "PluginProcessor.h"
|
||||||
|
#include "PluginEditor.h"
|
||||||
|
#include <utility>
|
||||||
|
// #include "GUI/BinaryData.h"
|
||||||
|
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
ObxdAudioProcessorEditor::ObxdAudioProcessorEditor (ObxdAudioProcessor* ownerFilter)
|
||||||
|
: AudioProcessorEditor (ownerFilter)
|
||||||
|
{
|
||||||
|
rebuildComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
ObxdAudioProcessorEditor::~ObxdAudioProcessorEditor()
|
||||||
|
{
|
||||||
|
getFilter()->removeChangeListener(this);
|
||||||
|
|
||||||
|
deleteAllChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObxdAudioProcessorEditor::placeLabel(int x , int y , String text)
|
||||||
|
{
|
||||||
|
Label* lab = new Label();
|
||||||
|
lab->setBounds(x,y,110,20);
|
||||||
|
lab->setJustificationType(Justification::centred);
|
||||||
|
lab->setText(text,dontSendNotification);lab->setInterceptsMouseClicks(false,true);
|
||||||
|
addAndMakeVisible(lab);
|
||||||
|
}
|
||||||
|
|
||||||
|
ButtonList* ObxdAudioProcessorEditor::addNormalButtonList(int x, int y,int width, ObxdAudioProcessor* filter, int parameter,String name,Image img)
|
||||||
|
{
|
||||||
|
ButtonList *bl = new ButtonList(img,24);
|
||||||
|
bl->setBounds(x, y, width, 24);
|
||||||
|
//bl->setValue(filter->getParameter(parameter),dontSendNotification);
|
||||||
|
addAndMakeVisible(bl);
|
||||||
|
bl->addListener (this);
|
||||||
|
return bl;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Knob* ObxdAudioProcessorEditor::addNormalKnob(int x , int y ,ObxdAudioProcessor* filter, int parameter,String name,float defval)
|
||||||
|
{
|
||||||
|
Knob* knob = new Knob(ImageCache::getFromMemory(BinaryData::knoblsd_png,BinaryData::knoblsd_pngSize),48);
|
||||||
|
//Label* knobl = new Label();
|
||||||
|
knob->setSliderStyle(Slider::RotaryVerticalDrag);
|
||||||
|
knob->setTextBoxStyle(knob->NoTextBox,true,0,0);
|
||||||
|
knob->setRange(0,1);
|
||||||
|
addAndMakeVisible(knob);
|
||||||
|
//addAndMakeVisible(knobl);
|
||||||
|
knob->setBounds(x, y, 48,48);
|
||||||
|
knob->setValue(filter->getParameter(parameter),dontSendNotification);
|
||||||
|
//knobl->setJustificationType(Justification::centred);
|
||||||
|
//knobl->setInterceptsMouseClicks(false,true);
|
||||||
|
//knobl->setBounds(x-10,y+40,60,10);
|
||||||
|
//knobl->setText(name,dontSendNotification);
|
||||||
|
knob->setTextBoxIsEditable(false);
|
||||||
|
knob->setDoubleClickReturnValue(true,defval);
|
||||||
|
knob->addListener (this);
|
||||||
|
return knob;
|
||||||
|
}
|
||||||
|
|
||||||
|
Knob* ObxdAudioProcessorEditor::addNormalKnobClassic(int x , int y ,ObxdAudioProcessor* filter, int parameter,String name,float defval)
|
||||||
|
{
|
||||||
|
Knob* knob = new Knob(ImageCache::getFromMemory(BinaryData::knoblsd_png,BinaryData::knoblsd_pngSize),48);
|
||||||
|
//Label* knobl = new Label();
|
||||||
|
knob->setSliderStyle(Slider::RotaryVerticalDrag);
|
||||||
|
knob->setTextBoxStyle(knob->NoTextBox,true,0,0);
|
||||||
|
knob->setRange(0,1);
|
||||||
|
addAndMakeVisible(knob);
|
||||||
|
//addAndMakeVisible(knobl);
|
||||||
|
knob->setBounds(x+2, y, 42,42);
|
||||||
|
knob->setValue(filter->getParameter(parameter),dontSendNotification);
|
||||||
|
//knobl->setJustificationType(Justification::centred);
|
||||||
|
//knobl->setInterceptsMouseClicks(false,true);
|
||||||
|
//knobl->setBounds(x-10,y+40,60,10);
|
||||||
|
//knobl->setText(name,dontSendNotification);
|
||||||
|
knob->setTextBoxIsEditable(false);
|
||||||
|
knob->setDoubleClickReturnValue(true,defval);
|
||||||
|
knob->addListener (this);
|
||||||
|
return knob;
|
||||||
|
}
|
||||||
|
|
||||||
|
Knob* ObxdAudioProcessorEditor::addTinyKnob(int x , int y ,ObxdAudioProcessor* filter, int parameter,String name,float defval)
|
||||||
|
{
|
||||||
|
//Knob* knob = new Knob(ImageCache::getFromMemory(BinaryData::knobssd_png,BinaryData::knobssd_pngSize),42);
|
||||||
|
Knob* knob = new Knob(ImageCache::getFromMemory(BinaryData::knoblsd_png,BinaryData::knoblsd_pngSize),48);
|
||||||
|
//Label* knobl = new Label();
|
||||||
|
knob->setSliderStyle(Slider::RotaryVerticalDrag);
|
||||||
|
knob->setTextBoxStyle(knob->NoTextBox,true,0,0);
|
||||||
|
knob->setRange(0,1);
|
||||||
|
addAndMakeVisible(knob);
|
||||||
|
//addAndMakeVisible(knobl);
|
||||||
|
knob->setBounds(x, y, 36,36);
|
||||||
|
knob->setValue(filter->getParameter(parameter),dontSendNotification);
|
||||||
|
//knobl->setJustificationType(Justification::centred);
|
||||||
|
//knobl->setInterceptsMouseClicks(false,true);
|
||||||
|
//knobl->setBounds(x-10,y+25,50,10);
|
||||||
|
//knobl->setText(name,dontSendNotification);
|
||||||
|
knob->setTextBoxIsEditable(false);
|
||||||
|
knob->setDoubleClickReturnValue(true,defval);
|
||||||
|
knob->addListener (this);
|
||||||
|
return knob;
|
||||||
|
}
|
||||||
|
|
||||||
|
TooglableButton* ObxdAudioProcessorEditor::addNormalTooglableButton(int x , int y , ObxdAudioProcessor* filter,int parameter,String name)
|
||||||
|
{
|
||||||
|
TooglableButton* button = new TooglableButton(ImageCache::getFromMemory(BinaryData::button_png,BinaryData::button_pngSize));
|
||||||
|
// button->setButtonStyle(DrawableButton::ButtonStyle::ImageAboveTextLabel);
|
||||||
|
addAndMakeVisible(button);
|
||||||
|
button->setBounds(x,y,19,35);
|
||||||
|
button->setButtonText(name);
|
||||||
|
button->setValue(filter->getParameter(parameter),0);
|
||||||
|
button->addListener(this);
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
TooglableButton* ObxdAudioProcessorEditor::addTinyTooglableButton(int x , int y , ObxdAudioProcessor* filter,int parameter,String name)
|
||||||
|
{
|
||||||
|
TooglableButton* button = new TooglableButton(ImageCache::getFromMemory(BinaryData::button_png,BinaryData::button_pngSize));
|
||||||
|
// button->setButtonStyle(DrawableButton::ButtonStyle::ImageAboveTextLabel);
|
||||||
|
addAndMakeVisible(button);
|
||||||
|
button->setBounds(x,y,20,20);
|
||||||
|
button->setButtonText(name);
|
||||||
|
button->setValue(filter->getParameter(parameter),0);
|
||||||
|
button->addListener(this);
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
ButtonList* ObxdAudioProcessorEditor::addNormalButtonListClassic(int x, int y,int width, ObxdAudioProcessor* filter, int parameter,String name,Image img)
|
||||||
|
{
|
||||||
|
ButtonList *bl = new ButtonList(img,32);
|
||||||
|
bl->setBounds(x, y, width, 32);
|
||||||
|
//bl->setValue(filter->getParameter(parameter),dontSendNotification);
|
||||||
|
addAndMakeVisible(bl);
|
||||||
|
bl->addListener (this);
|
||||||
|
return bl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Knob* ObxdAudioProcessorEditor::addTinyKnobClassic(int x , int y ,ObxdAudioProcessor* filter, int parameter,String name,float defval)
|
||||||
|
{
|
||||||
|
Knob* knob = new Knob(ImageCache::getFromMemory(BinaryData::knoblsd_png,BinaryData::knoblsd_pngSize),48);
|
||||||
|
//Label* knobl = new Label();
|
||||||
|
knob->setSliderStyle(Slider::RotaryVerticalDrag);
|
||||||
|
knob->setTextBoxStyle(knob->NoTextBox,true,0,0);
|
||||||
|
knob->setRange(0,1);
|
||||||
|
addAndMakeVisible(knob);
|
||||||
|
//addAndMakeVisible(knobl);
|
||||||
|
knob->setBounds(x+3, y+3, 36,36);
|
||||||
|
knob->setValue(filter->getParameter(parameter),dontSendNotification);
|
||||||
|
//knobl->setJustificationType(Justification::centred);
|
||||||
|
//knobl->setInterceptsMouseClicks(false,true);
|
||||||
|
//knobl->setBounds(x-10,y+25,50,10);
|
||||||
|
//knobl->setText(name,dontSendNotification);
|
||||||
|
knob->setTextBoxIsEditable(false);
|
||||||
|
knob->setDoubleClickReturnValue(true,defval);
|
||||||
|
knob->addListener (this);
|
||||||
|
return knob;
|
||||||
|
}
|
||||||
|
|
||||||
|
TooglableButton* ObxdAudioProcessorEditor::addNormalTooglableButtonClassic(int x , int y , ObxdAudioProcessor* filter,int parameter,String name)
|
||||||
|
{
|
||||||
|
TooglableButton* button = new TooglableButton(ImageCache::getFromFile(skinFolder.getChildFile("button.png")));
|
||||||
|
// button->setButtonStyle(DrawableButton::ButtonStyle::ImageAboveTextLabel);
|
||||||
|
addAndMakeVisible(button);
|
||||||
|
button->setBounds(x,y,28,35);
|
||||||
|
button->setButtonText(name);
|
||||||
|
button->setValue(filter->getParameter(parameter),0);
|
||||||
|
button->addListener(this);
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObxdAudioProcessorEditor::rebuildComponents()
|
||||||
|
{
|
||||||
|
ObxdAudioProcessor* ownerFilter = getFilter();
|
||||||
|
|
||||||
|
skinFolder = ownerFilter->getCurrentSkinFolder();
|
||||||
|
bool useClassicSkin = skinFolder.getChildFile("legato.png").existsAsFile();
|
||||||
|
|
||||||
|
ownerFilter->removeChangeListener(this);
|
||||||
|
|
||||||
|
deleteAllChildren();
|
||||||
|
|
||||||
|
if (! useClassicSkin)
|
||||||
|
{
|
||||||
|
// This is where our plugin's editor size is set.
|
||||||
|
|
||||||
|
setSize (1440, 450);
|
||||||
|
cutoffKnob = addNormalKnob(893,77,ownerFilter,CUTOFF,"Cutoff",0.4);
|
||||||
|
resonanceKnob = addNormalKnob(990,77,ownerFilter,RESONANCE,"Resonance",0);
|
||||||
|
filterEnvelopeAmtKnob = addNormalKnob(1088,77,ownerFilter,ENVELOPE_AMT,"Envelope",0);
|
||||||
|
multimodeKnob = addNormalKnob(990,167,ownerFilter,MULTIMODE,"Multimode",0.5);
|
||||||
|
|
||||||
|
volumeKnob = addNormalKnob(56,77,ownerFilter,VOLUME,"Volume",0.4);
|
||||||
|
portamentoKnob = addNormalKnob(188,77,ownerFilter,PORTAMENTO,"Portamento",0);
|
||||||
|
osc1PitchKnob = addNormalKnob(593,77,ownerFilter,OSC1P,"Osc1Pitch",0);
|
||||||
|
pulseWidthKnob = addNormalKnob(691,77,ownerFilter,PW,"PW",0);
|
||||||
|
osc2PitchKnob = addNormalKnob(788,77,ownerFilter,OSC2P,"Osc2Pitch",0);
|
||||||
|
|
||||||
|
osc1MixKnob = addNormalKnob(597,237,ownerFilter,OSC1MIX,"Osc1",1);
|
||||||
|
osc2MixKnob = addNormalKnob(788,237,ownerFilter,OSC2MIX,"Osc2",1);
|
||||||
|
noiseMixKnob = addNormalKnob(691,237,ownerFilter,NOISEMIX,"Noise",0);
|
||||||
|
|
||||||
|
xmodKnob = addNormalKnob(656,324,ownerFilter,XMOD,"Xmod",0);
|
||||||
|
osc2DetuneKnob = addNormalKnob(800,324,ownerFilter,OSC2_DET,"Detune",0);
|
||||||
|
|
||||||
|
envPitchModKnob = addNormalKnob(728,324,ownerFilter,ENVPITCH,"PEnv",0);
|
||||||
|
brightnessKnob = addNormalKnob(586,324,ownerFilter,BRIGHTNESS,"Bri",1);
|
||||||
|
|
||||||
|
attackKnob = addNormalKnob(1182,165,ownerFilter,LATK,"Atk",0);
|
||||||
|
decayKnob = addNormalKnob(1246,165,ownerFilter,LDEC,"Dec",0);
|
||||||
|
sustainKnob = addNormalKnob(1309,165,ownerFilter,LSUS,"Sus",1);
|
||||||
|
releaseKnob = addNormalKnob(1373,165,ownerFilter,LREL,"Rel",0);
|
||||||
|
|
||||||
|
fattackKnob = addNormalKnob(1182,75,ownerFilter,FATK,"Atk",0);
|
||||||
|
fdecayKnob = addNormalKnob(1246,75,ownerFilter,FDEC,"Dec",0);
|
||||||
|
fsustainKnob = addNormalKnob(1309,75,ownerFilter,FSUS,"Sus",1);
|
||||||
|
freleaseKnob = addNormalKnob(1373,75,ownerFilter,FREL,"Rel",0);
|
||||||
|
|
||||||
|
lfoFrequencyKnob = addNormalKnob(293,77,ownerFilter,LFOFREQ,"Freq",0);
|
||||||
|
lfoAmt1Knob = addNormalKnob(390,77,ownerFilter,LFO1AMT,"Pitch",0);
|
||||||
|
lfoAmt2Knob = addNormalKnob(488,77,ownerFilter,LFO2AMT,"PWM",0);
|
||||||
|
|
||||||
|
lfoSinButton = addNormalTooglableButton(309,162,ownerFilter,LFOSINWAVE,"Sin");
|
||||||
|
lfoSquareButton = addNormalTooglableButton(309,252,ownerFilter,LFOSQUAREWAVE,"SQ");
|
||||||
|
lfoSHButton = addNormalTooglableButton(309,335,ownerFilter,LFOSHWAVE,"S&H");
|
||||||
|
|
||||||
|
lfoOsc1Button = addNormalTooglableButton(406,162,ownerFilter,LFOOSC1,"Osc1");
|
||||||
|
lfoOsc2Button = addNormalTooglableButton(406,252,ownerFilter,LFOOSC2,"Osc2");
|
||||||
|
lfoFilterButton = addNormalTooglableButton(406,335,ownerFilter,LFOFILTER,"Filt");
|
||||||
|
|
||||||
|
lfoPwm1Button = addNormalTooglableButton(504,162,ownerFilter,LFOPW1,"Osc1");
|
||||||
|
lfoPwm2Button = addNormalTooglableButton(504,252,ownerFilter,LFOPW2,"Osc2");
|
||||||
|
|
||||||
|
hardSyncButton = addNormalTooglableButton(730,162,ownerFilter,OSC2HS,"Sync");
|
||||||
|
osc1SawButton = addNormalTooglableButton(587,162,ownerFilter,OSC1Saw,"S");
|
||||||
|
osc2SawButton = addNormalTooglableButton(782,162,ownerFilter,OSC2Saw,"S");
|
||||||
|
|
||||||
|
osc1PulButton = addNormalTooglableButton(632,162,ownerFilter,OSC1Pul,"P");
|
||||||
|
osc2PulButton = addNormalTooglableButton(827,162,ownerFilter,OSC2Pul,"P");
|
||||||
|
|
||||||
|
pitchQuantButton = addNormalTooglableButton(684,162,ownerFilter,OSCQuantize,"Step");
|
||||||
|
|
||||||
|
filterBPBlendButton = addNormalTooglableButton(1082,162,ownerFilter,BANDPASS,"Bp");
|
||||||
|
fourPoleButton = addNormalTooglableButton(1127,162,ownerFilter,FOURPOLE,"24");
|
||||||
|
filterHQButton = addNormalTooglableButton(932,162,ownerFilter,FILTER_WARM,"HQ");
|
||||||
|
|
||||||
|
filterKeyFollowButton = addNormalTooglableButton(887,162,ownerFilter,FLT_KF,"Key");
|
||||||
|
unisonButton = addNormalTooglableButton(205,162,ownerFilter,UNISON,"Uni");
|
||||||
|
|
||||||
|
tuneKnob = addNormalKnob(30,252,ownerFilter,TUNE,"Tune",0.5);
|
||||||
|
transposeKnob = addNormalKnob(90,252,ownerFilter,OCTAVE,"Transpose",0.5);
|
||||||
|
|
||||||
|
voiceDetuneKnob =addNormalKnob(188,252,ownerFilter,UDET,"VoiceDet",0);
|
||||||
|
|
||||||
|
bendLfoRateKnob = addTinyKnob(928,300,ownerFilter,BENDLFORATE,"ModRate",0.4);
|
||||||
|
veloFltEnvKnob = addTinyKnob(1013,300,ownerFilter,VFLTENV,"VFE",0);
|
||||||
|
veloAmpEnvKnob = addTinyKnob(1111,300,ownerFilter,VAMPENV,"VAE",0);
|
||||||
|
|
||||||
|
midiLearnButton = addNormalTooglableButton(74,162,ownerFilter,MIDILEARN,"LEA");
|
||||||
|
midiUnlearnButton = addNormalTooglableButton(122,162,ownerFilter,UNLEARN,"UNL");
|
||||||
|
|
||||||
|
pan1Knob = addTinyKnob(914,368,ownerFilter,PAN1,"1",0.5);
|
||||||
|
pan2Knob = addTinyKnob(977,368,ownerFilter,PAN2,"2",0.5);
|
||||||
|
pan3Knob = addTinyKnob(1040,368,ownerFilter,PAN3,"3",0.5);
|
||||||
|
pan4Knob = addTinyKnob(1103,368,ownerFilter,PAN4,"4",0.5);
|
||||||
|
|
||||||
|
pan5Knob = addTinyKnob(1165,368,ownerFilter,PAN5,"5",0.5);
|
||||||
|
pan6Knob = addTinyKnob(1228,368,ownerFilter,PAN6,"6",0.5);
|
||||||
|
pan7Knob = addTinyKnob(1290,368,ownerFilter,PAN7,"7",0.5);
|
||||||
|
pan8Knob = addTinyKnob(1353,368,ownerFilter,PAN8,"8",0.5);
|
||||||
|
|
||||||
|
bendOsc2OnlyButton = addNormalTooglableButton(228,335,ownerFilter,BENDOSC2,"Osc2");
|
||||||
|
bendRangeButton = addNormalTooglableButton(183,335,ownerFilter,BENDRANGE,"12");
|
||||||
|
asPlayedAllocButton = addNormalTooglableButton(25,162,ownerFilter,ASPLAYEDALLOCATION,"APA");
|
||||||
|
|
||||||
|
filterDetuneKnob = addTinyKnob(1228,300,ownerFilter,FILTERDER,"Flt",0.2);
|
||||||
|
portamentoDetuneKnob = addTinyKnob(1291,300,ownerFilter,PORTADER,"Port",0.2);
|
||||||
|
envelopeDetuneKnob = addTinyKnob(1353,300,ownerFilter,ENVDER,"Env",0.2);
|
||||||
|
|
||||||
|
voiceSwitch = addNormalButtonList(124,338,17,ownerFilter,VOICE_COUNT,"VoiceCount",ImageCache::getFromMemory(BinaryData::voices_png,BinaryData::voices_pngSize));
|
||||||
|
voiceSwitch ->addChoise("1");
|
||||||
|
voiceSwitch ->addChoise("2");
|
||||||
|
voiceSwitch ->addChoise("3");
|
||||||
|
voiceSwitch ->addChoise("4");
|
||||||
|
voiceSwitch ->addChoise("5");
|
||||||
|
voiceSwitch ->addChoise("6");
|
||||||
|
voiceSwitch ->addChoise("7");
|
||||||
|
voiceSwitch ->addChoise("8");
|
||||||
|
voiceSwitch ->setValue(ownerFilter->getParameter(VOICE_COUNT),dontSendNotification);
|
||||||
|
|
||||||
|
legatoSwitch = addNormalButtonList(25,338,65,ownerFilter,LEGATOMODE,"Legato",ImageCache::getFromMemory(BinaryData::legato_png,BinaryData::legato_pngSize));
|
||||||
|
legatoSwitch ->addChoise("Keep All");
|
||||||
|
legatoSwitch ->addChoise("Keep Filter Envelope");
|
||||||
|
legatoSwitch ->addChoise("Keep Amplitude Envelope");
|
||||||
|
legatoSwitch ->addChoise("Retrig");
|
||||||
|
legatoSwitch ->setValue(ownerFilter->getParameter(LEGATOMODE),dontSendNotification);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// This is where our plugin's editor size is set.
|
||||||
|
|
||||||
|
setSize (1087, 442);
|
||||||
|
cutoffKnob = addNormalKnobClassic(577,40,ownerFilter,CUTOFF,"Cutoff",0.4);
|
||||||
|
resonanceKnob = addNormalKnobClassic(638,40,ownerFilter,RESONANCE,"Resonance",0);
|
||||||
|
filterEnvelopeAmtKnob = addNormalKnobClassic(699,40,ownerFilter,ENVELOPE_AMT,"Envelope",0);
|
||||||
|
multimodeKnob = addTinyKnobClassic(643,106,ownerFilter,MULTIMODE,"Multimode",0.5);
|
||||||
|
|
||||||
|
volumeKnob = addNormalKnobClassic(53,120,ownerFilter,VOLUME,"Volume",0.4);
|
||||||
|
portamentoKnob = addNormalKnobClassic(175,241,ownerFilter,PORTAMENTO,"Portamento",0);
|
||||||
|
osc1PitchKnob = addNormalKnobClassic(271,40,ownerFilter,OSC1P,"Osc1Pitch",0);
|
||||||
|
pulseWidthKnob = addNormalKnobClassic(334,40,ownerFilter,PW,"PW",0);
|
||||||
|
osc2PitchKnob = addNormalKnobClassic(397,40,ownerFilter,OSC2P,"Osc2Pitch",0);
|
||||||
|
|
||||||
|
osc1MixKnob = addNormalKnobClassic(490,40,ownerFilter,OSC1MIX,"Osc1",1);
|
||||||
|
osc2MixKnob = addNormalKnobClassic(490,132,ownerFilter,OSC2MIX,"Osc2",1);
|
||||||
|
noiseMixKnob = addNormalKnobClassic(490,224,ownerFilter,NOISEMIX,"Noise",0);
|
||||||
|
|
||||||
|
xmodKnob = addNormalKnobClassic(334,168,ownerFilter,XMOD,"Xmod",0);
|
||||||
|
osc2DetuneKnob = addNormalKnobClassic(334,104,ownerFilter,OSC2_DET,"Detune",0);
|
||||||
|
|
||||||
|
envPitchModKnob = addNormalKnobClassic(376,232,ownerFilter,ENVPITCH,"PEnv",0);
|
||||||
|
brightnessKnob = addNormalKnobClassic(291,232,ownerFilter,BRIGHTNESS,"Bri",1);
|
||||||
|
|
||||||
|
attackKnob = addNormalKnobClassic(791,132,ownerFilter,LATK,"Atk",0);
|
||||||
|
decayKnob = addNormalKnobClassic(853,132,ownerFilter,LDEC,"Dec",0);
|
||||||
|
sustainKnob = addNormalKnobClassic(916,132,ownerFilter,LSUS,"Sus",1);
|
||||||
|
releaseKnob = addNormalKnobClassic(980,132,ownerFilter,LREL,"Rel",0);
|
||||||
|
|
||||||
|
fattackKnob = addNormalKnobClassic(791,40,ownerFilter,FATK,"Atk",0);
|
||||||
|
fdecayKnob = addNormalKnobClassic(853,40,ownerFilter,FDEC,"Dec",0);
|
||||||
|
fsustainKnob = addNormalKnobClassic(916,40,ownerFilter,FSUS,"Sus",1);
|
||||||
|
freleaseKnob = addNormalKnobClassic(980,40,ownerFilter,FREL,"Rel",0);
|
||||||
|
|
||||||
|
lfoFrequencyKnob = addNormalKnobClassic(576,207,ownerFilter,LFOFREQ,"Freq",0);
|
||||||
|
lfoAmt1Knob = addNormalKnobClassic(640,207,ownerFilter,LFO1AMT,"Pitch",0);
|
||||||
|
lfoAmt2Knob = addNormalKnobClassic(704,207,ownerFilter,LFO2AMT,"PWM",0);
|
||||||
|
|
||||||
|
lfoSinButton = addNormalTooglableButtonClassic(587,269,ownerFilter,LFOSINWAVE,"Sin");
|
||||||
|
lfoSquareButton = addNormalTooglableButtonClassic(587,323,ownerFilter,LFOSQUAREWAVE,"SQ");
|
||||||
|
lfoSHButton = addNormalTooglableButtonClassic(587,378,ownerFilter,LFOSHWAVE,"S&H");
|
||||||
|
|
||||||
|
lfoOsc1Button = addNormalTooglableButtonClassic(651,269,ownerFilter,LFOOSC1,"Osc1");
|
||||||
|
lfoOsc2Button = addNormalTooglableButtonClassic(651,323,ownerFilter,LFOOSC2,"Osc2");
|
||||||
|
lfoFilterButton = addNormalTooglableButtonClassic(651,378,ownerFilter,LFOFILTER,"Filt");
|
||||||
|
|
||||||
|
lfoPwm1Button = addNormalTooglableButtonClassic(714,269,ownerFilter,LFOPW1,"Osc1");
|
||||||
|
lfoPwm2Button = addNormalTooglableButtonClassic(714,323,ownerFilter,LFOPW2,"Osc2");
|
||||||
|
|
||||||
|
hardSyncButton = addNormalTooglableButtonClassic(282,178,ownerFilter,OSC2HS,"Sync");
|
||||||
|
osc1SawButton = addNormalTooglableButtonClassic(265,114,ownerFilter,OSC1Saw,"S");
|
||||||
|
osc2SawButton = addNormalTooglableButtonClassic(394,114,ownerFilter,OSC2Saw,"S");
|
||||||
|
|
||||||
|
osc1PulButton = addNormalTooglableButtonClassic(296,114,ownerFilter,OSC1Pul,"P");
|
||||||
|
osc2PulButton = addNormalTooglableButtonClassic(425,114,ownerFilter,OSC2Pul,"P");
|
||||||
|
|
||||||
|
pitchQuantButton = addNormalTooglableButtonClassic(407,178,ownerFilter,OSCQuantize,"Step");
|
||||||
|
|
||||||
|
filterBPBlendButton = addNormalTooglableButtonClassic(697,110,ownerFilter,BANDPASS,"Bp");
|
||||||
|
fourPoleButton = addNormalTooglableButtonClassic(728,110,ownerFilter,FOURPOLE,"24");
|
||||||
|
filterHQButton = addNormalTooglableButtonClassic(604,110,ownerFilter,FILTER_WARM,"HQ");
|
||||||
|
|
||||||
|
filterKeyFollowButton = addNormalTooglableButtonClassic(573,110,ownerFilter,FLT_KF,"Key");
|
||||||
|
unisonButton = addNormalTooglableButtonClassic(125,251,ownerFilter,UNISON,"Uni");
|
||||||
|
tuneKnob = addNormalKnobClassic(114,120,ownerFilter,TUNE,"Tune",0.5);
|
||||||
|
voiceDetuneKnob =addNormalKnobClassic(53,241,ownerFilter,UDET,"VoiceDet",0);
|
||||||
|
|
||||||
|
veloAmpEnvKnob = addNormalKnobClassic(486,345,ownerFilter,VAMPENV,"VAE",0);
|
||||||
|
veloFltEnvKnob = addNormalKnobClassic(428,345,ownerFilter,VFLTENV,"VFE",0);
|
||||||
|
midiLearnButton = addNormalTooglableButtonClassic(126,372,ownerFilter,MIDILEARN,"LEA");
|
||||||
|
midiUnlearnButton = addNormalTooglableButtonClassic(185,372,ownerFilter,UNLEARN,"UNL");
|
||||||
|
transposeKnob = addNormalKnobClassic(176,120,ownerFilter,OCTAVE,"Transpose",0.5);
|
||||||
|
|
||||||
|
pan1Knob = addTinyKnobClassic(796,318,ownerFilter,PAN1,"1",0.5);
|
||||||
|
pan2Knob = addTinyKnobClassic(858,318,ownerFilter,PAN2,"2",0.5);
|
||||||
|
pan3Knob = addTinyKnobClassic(921,318,ownerFilter,PAN3,"3",0.5);
|
||||||
|
pan4Knob = addTinyKnobClassic(984,318,ownerFilter,PAN4,"4",0.5);
|
||||||
|
|
||||||
|
pan5Knob = addTinyKnobClassic(796,371,ownerFilter,PAN5,"5",0.5);
|
||||||
|
pan6Knob = addTinyKnobClassic(858,371,ownerFilter,PAN6,"6",0.5);
|
||||||
|
pan7Knob = addTinyKnobClassic(921,371,ownerFilter,PAN7,"7",0.5);
|
||||||
|
pan8Knob = addTinyKnobClassic(984,371,ownerFilter,PAN8,"8",0.5);
|
||||||
|
|
||||||
|
bendOsc2OnlyButton = addNormalTooglableButtonClassic(321,354,ownerFilter,BENDOSC2,"Osc2");
|
||||||
|
bendRangeButton = addNormalTooglableButtonClassic(267,354,ownerFilter,BENDRANGE,"12");
|
||||||
|
asPlayedAllocButton = addNormalTooglableButtonClassic(65,372,ownerFilter,ASPLAYEDALLOCATION,"APA");
|
||||||
|
|
||||||
|
filterDetuneKnob = addTinyKnobClassic(817,240,ownerFilter,FILTERDER,"Flt",0.2);
|
||||||
|
envelopeDetuneKnob = addTinyKnobClassic(963,240,ownerFilter,ENVDER,"Env",0.2);
|
||||||
|
portamentoDetuneKnob = addTinyKnobClassic(890,240,ownerFilter,PORTADER,"Port",0.2);
|
||||||
|
|
||||||
|
bendLfoRateKnob = addNormalKnobClassic(364,345,ownerFilter,BENDLFORATE,"ModRate",0.4);
|
||||||
|
|
||||||
|
voiceSwitch = addNormalButtonListClassic(172,321,38,ownerFilter,VOICE_COUNT,"VoiceCount",ImageCache::getFromFile(skinFolder.getChildFile("voices.png")));
|
||||||
|
voiceSwitch ->addChoise("1");
|
||||||
|
voiceSwitch ->addChoise("2");
|
||||||
|
voiceSwitch ->addChoise("3");
|
||||||
|
voiceSwitch ->addChoise("4");
|
||||||
|
voiceSwitch ->addChoise("5");
|
||||||
|
voiceSwitch ->addChoise("6");
|
||||||
|
voiceSwitch ->addChoise("7");
|
||||||
|
voiceSwitch ->addChoise("8");
|
||||||
|
voiceSwitch ->setValue(ownerFilter->getParameter(VOICE_COUNT),dontSendNotification);
|
||||||
|
|
||||||
|
legatoSwitch = addNormalButtonListClassic(65,321,95,ownerFilter,LEGATOMODE,"Legato",ImageCache::getFromFile(skinFolder.getChildFile("legato.png")));
|
||||||
|
legatoSwitch ->addChoise("Keep all");
|
||||||
|
legatoSwitch ->addChoise("Keep fenv");
|
||||||
|
legatoSwitch ->addChoise("Keep aenv");
|
||||||
|
legatoSwitch ->addChoise("Retrig");
|
||||||
|
legatoSwitch ->setValue(ownerFilter->getParameter(LEGATOMODE),dontSendNotification);
|
||||||
|
}
|
||||||
|
|
||||||
|
ownerFilter->addChangeListener(this);
|
||||||
|
|
||||||
|
repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObxdAudioProcessorEditor::buttonClicked(Button * b)
|
||||||
|
{
|
||||||
|
TooglableButton* tb = (TooglableButton*)(b);
|
||||||
|
ObxdAudioProcessor* flt = getFilter();
|
||||||
|
#define bp(T) {flt->setParameterNotifyingHost(T,tb->getValue());}
|
||||||
|
#define handleBParam(K,T) if (tb == K) {bp(T)} else
|
||||||
|
handleBParam(hardSyncButton,OSC2HS)
|
||||||
|
handleBParam(osc1SawButton,OSC1Saw)
|
||||||
|
handleBParam(osc2SawButton,OSC2Saw)
|
||||||
|
handleBParam(osc1PulButton,OSC1Pul)
|
||||||
|
handleBParam(osc2PulButton,OSC2Pul)
|
||||||
|
handleBParam(filterKeyFollowButton,FLT_KF)
|
||||||
|
handleBParam(pitchQuantButton,OSCQuantize)
|
||||||
|
handleBParam(unisonButton,UNISON)
|
||||||
|
handleBParam(filterHQButton,FILTER_WARM)
|
||||||
|
handleBParam(filterBPBlendButton,BANDPASS)
|
||||||
|
|
||||||
|
handleBParam(lfoSinButton,LFOSINWAVE)
|
||||||
|
handleBParam(lfoSquareButton,LFOSQUAREWAVE)
|
||||||
|
handleBParam(lfoSHButton,LFOSHWAVE)
|
||||||
|
|
||||||
|
handleBParam(lfoOsc1Button,LFOOSC1)
|
||||||
|
handleBParam(lfoOsc2Button,LFOOSC2)
|
||||||
|
handleBParam(lfoFilterButton,LFOFILTER)
|
||||||
|
handleBParam(lfoPwm1Button,LFOPW1)
|
||||||
|
handleBParam(lfoPwm2Button,LFOPW2)
|
||||||
|
handleBParam(bendOsc2OnlyButton,BENDOSC2)
|
||||||
|
handleBParam(bendRangeButton,BENDRANGE)
|
||||||
|
handleBParam(fourPoleButton,FOURPOLE)
|
||||||
|
handleBParam(asPlayedAllocButton,ASPLAYEDALLOCATION)
|
||||||
|
handleBParam(midiLearnButton,MIDILEARN)
|
||||||
|
handleBParam(midiUnlearnButton,UNLEARN)
|
||||||
|
{};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObxdAudioProcessorEditor::comboBoxChanged (ComboBox* cb)
|
||||||
|
{
|
||||||
|
ButtonList* bl = (ButtonList*)(cb);
|
||||||
|
ObxdAudioProcessor* flt = getFilter();
|
||||||
|
#define cp(T) {flt->setParameterNotifyingHost(T,bl->getValue());}
|
||||||
|
#define handleCParam(K,T) if (bl == K) {cp(T)} else
|
||||||
|
handleCParam(voiceSwitch,VOICE_COUNT)
|
||||||
|
handleCParam(legatoSwitch,LEGATOMODE)
|
||||||
|
{};
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObxdAudioProcessorEditor::sliderValueChanged (Slider* c)
|
||||||
|
{
|
||||||
|
ObxdAudioProcessor* flt = getFilter();
|
||||||
|
// flt->beginParameterChangeGesture();
|
||||||
|
#define sp(T) {flt->setParameterNotifyingHost(T,c->getValue());}
|
||||||
|
#define handleSParam(K,T) if (c == K) {sp(T)} else
|
||||||
|
handleSParam(cutoffKnob,CUTOFF)
|
||||||
|
handleSParam(resonanceKnob,RESONANCE)
|
||||||
|
handleSParam(volumeKnob,VOLUME)
|
||||||
|
handleSParam(osc1PitchKnob,OSC1P)
|
||||||
|
handleSParam(osc2PitchKnob,OSC2P)
|
||||||
|
handleSParam(osc2DetuneKnob,OSC2_DET)
|
||||||
|
handleSParam(portamentoKnob,PORTAMENTO)
|
||||||
|
handleSParam(filterEnvelopeAmtKnob,ENVELOPE_AMT)
|
||||||
|
handleSParam(pulseWidthKnob,PW)
|
||||||
|
handleSParam(xmodKnob,XMOD)
|
||||||
|
handleSParam(multimodeKnob,MULTIMODE)
|
||||||
|
|
||||||
|
handleSParam(attackKnob,LATK)
|
||||||
|
handleSParam(decayKnob,LDEC)
|
||||||
|
handleSParam(sustainKnob,LSUS)
|
||||||
|
handleSParam(releaseKnob,LREL)
|
||||||
|
|
||||||
|
handleSParam(fattackKnob,FATK)
|
||||||
|
handleSParam(fdecayKnob,FDEC)
|
||||||
|
handleSParam(fsustainKnob,FSUS)
|
||||||
|
handleSParam(freleaseKnob,FREL)
|
||||||
|
|
||||||
|
handleSParam(osc1MixKnob,OSC1MIX)
|
||||||
|
handleSParam(osc2MixKnob,OSC2MIX)
|
||||||
|
handleSParam(noiseMixKnob,NOISEMIX)
|
||||||
|
handleSParam(voiceDetuneKnob,UDET)
|
||||||
|
|
||||||
|
handleSParam(filterDetuneKnob,FILTERDER)
|
||||||
|
handleSParam(envelopeDetuneKnob,ENVDER)
|
||||||
|
handleSParam(portamentoDetuneKnob,PORTADER)
|
||||||
|
|
||||||
|
handleSParam(lfoFrequencyKnob,LFOFREQ)
|
||||||
|
handleSParam(lfoAmt1Knob,LFO1AMT)
|
||||||
|
handleSParam(lfoAmt2Knob,LFO2AMT)
|
||||||
|
|
||||||
|
handleSParam(pan1Knob,PAN1)
|
||||||
|
handleSParam(pan2Knob,PAN2)
|
||||||
|
handleSParam(pan3Knob,PAN3)
|
||||||
|
handleSParam(pan4Knob,PAN4)
|
||||||
|
handleSParam(pan5Knob,PAN5)
|
||||||
|
handleSParam(pan6Knob,PAN6)
|
||||||
|
handleSParam(pan7Knob,PAN7)
|
||||||
|
handleSParam(pan8Knob,PAN8)
|
||||||
|
|
||||||
|
handleSParam(tuneKnob,TUNE)
|
||||||
|
handleSParam(brightnessKnob,BRIGHTNESS)
|
||||||
|
handleSParam(envPitchModKnob,ENVPITCH)
|
||||||
|
|
||||||
|
handleSParam(bendLfoRateKnob,BENDLFORATE)
|
||||||
|
handleSParam(veloAmpEnvKnob,VAMPENV)
|
||||||
|
handleSParam(veloFltEnvKnob,VFLTENV)
|
||||||
|
handleSParam(transposeKnob,OCTAVE)
|
||||||
|
//magic crystal
|
||||||
|
{};
|
||||||
|
|
||||||
|
//else if(c == cutoffKnob)
|
||||||
|
//{sp(CUTOFF);}
|
||||||
|
//else if(c == resonanceKnob)
|
||||||
|
//{sp(RESONANCE);}
|
||||||
|
//else if(c == portamentoKnob)
|
||||||
|
//{sp(PORTAMENTO);}
|
||||||
|
//else if(c == volumeKnob)
|
||||||
|
//{sp(VOLUME);}
|
||||||
|
//else if(c == osc1PitchKnob)
|
||||||
|
//{sp(OSC1P);}
|
||||||
|
//else if (c == osc2PitchKnob)
|
||||||
|
//{sp(OSC2P);}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
void ObxdAudioProcessorEditor::changeListenerCallback (ChangeBroadcaster* source)
|
||||||
|
{
|
||||||
|
ObxdAudioProcessor* filter = getFilter();
|
||||||
|
|
||||||
|
float pr[PARAM_COUNT];
|
||||||
|
filter->getCallbackLock().enter();
|
||||||
|
for(int i = 0 ; i < PARAM_COUNT;++i)
|
||||||
|
pr[i] = filter->getPrograms().currentProgramPtr->values[i];
|
||||||
|
filter->getCallbackLock().exit();
|
||||||
|
#define rn(T,P) (T->setValue(pr[P],dontSendNotification));
|
||||||
|
rn(cutoffKnob,CUTOFF)
|
||||||
|
rn(resonanceKnob,RESONANCE)
|
||||||
|
rn(volumeKnob,VOLUME)
|
||||||
|
rn(osc1PitchKnob,OSC1P)
|
||||||
|
rn(osc2PitchKnob,OSC2P)
|
||||||
|
rn(osc2DetuneKnob,OSC2_DET)
|
||||||
|
rn(portamentoKnob,PORTAMENTO)
|
||||||
|
rn(filterEnvelopeAmtKnob,ENVELOPE_AMT)
|
||||||
|
rn(pulseWidthKnob,PW)
|
||||||
|
rn(xmodKnob,XMOD)
|
||||||
|
rn(multimodeKnob,MULTIMODE)
|
||||||
|
rn(brightnessKnob,BRIGHTNESS)
|
||||||
|
rn(envPitchModKnob,ENVPITCH)
|
||||||
|
|
||||||
|
rn(attackKnob,LATK)
|
||||||
|
rn(decayKnob,LDEC)
|
||||||
|
rn(sustainKnob,LSUS)
|
||||||
|
rn(releaseKnob,LREL)
|
||||||
|
|
||||||
|
rn(fattackKnob,FATK)
|
||||||
|
rn(fdecayKnob,FDEC)
|
||||||
|
rn(fsustainKnob,FSUS)
|
||||||
|
rn(freleaseKnob,FREL)
|
||||||
|
|
||||||
|
rn(osc1MixKnob,OSC1MIX)
|
||||||
|
rn(osc2MixKnob,OSC2MIX)
|
||||||
|
rn(noiseMixKnob,NOISEMIX)
|
||||||
|
rn(voiceDetuneKnob,UDET)
|
||||||
|
|
||||||
|
rn(lfoFrequencyKnob,LFOFREQ)
|
||||||
|
rn(lfoAmt1Knob,LFO1AMT)
|
||||||
|
rn(lfoAmt2Knob,LFO2AMT)
|
||||||
|
rn(tuneKnob,TUNE)
|
||||||
|
rn(bendLfoRateKnob,BENDLFORATE)
|
||||||
|
rn(veloAmpEnvKnob,VAMPENV)
|
||||||
|
rn(veloFltEnvKnob,VFLTENV)
|
||||||
|
//buttons
|
||||||
|
rn(hardSyncButton,OSC2HS)
|
||||||
|
rn(osc1SawButton,OSC1Saw)
|
||||||
|
rn(osc2SawButton,OSC2Saw)
|
||||||
|
rn(osc1PulButton,OSC1Pul)
|
||||||
|
rn(osc2PulButton,OSC2Pul)
|
||||||
|
|
||||||
|
rn(filterKeyFollowButton,FLT_KF)
|
||||||
|
rn(pitchQuantButton,OSCQuantize)
|
||||||
|
rn(unisonButton,UNISON)
|
||||||
|
|
||||||
|
rn(filterDetuneKnob,FILTERDER)
|
||||||
|
rn(envelopeDetuneKnob,ENVDER)
|
||||||
|
rn(portamentoDetuneKnob,PORTADER)
|
||||||
|
|
||||||
|
rn(filterHQButton,FILTER_WARM)
|
||||||
|
rn(filterBPBlendButton,BANDPASS)
|
||||||
|
rn(lfoSinButton,LFOSINWAVE)
|
||||||
|
rn(lfoSquareButton,LFOSQUAREWAVE)
|
||||||
|
rn(lfoSHButton,LFOSHWAVE)
|
||||||
|
|
||||||
|
rn(bendOsc2OnlyButton,BENDOSC2)
|
||||||
|
rn(bendRangeButton,BENDRANGE)
|
||||||
|
|
||||||
|
rn(lfoOsc1Button,LFOOSC1)
|
||||||
|
rn(lfoOsc2Button,LFOOSC2)
|
||||||
|
rn(lfoFilterButton,LFOFILTER)
|
||||||
|
rn(lfoPwm1Button,LFOPW1)
|
||||||
|
rn(lfoPwm2Button,LFOPW2)
|
||||||
|
rn(fourPoleButton,FOURPOLE)
|
||||||
|
|
||||||
|
rn(transposeKnob,OCTAVE)
|
||||||
|
|
||||||
|
rn(pan1Knob,PAN1)
|
||||||
|
rn(pan2Knob,PAN2)
|
||||||
|
rn(pan3Knob,PAN3)
|
||||||
|
rn(pan4Knob,PAN4)
|
||||||
|
rn(pan5Knob,PAN5)
|
||||||
|
rn(pan6Knob,PAN6)
|
||||||
|
rn(pan7Knob,PAN7)
|
||||||
|
rn(pan8Knob,PAN8)
|
||||||
|
|
||||||
|
rn(voiceSwitch,VOICE_COUNT)
|
||||||
|
rn(legatoSwitch,LEGATOMODE)
|
||||||
|
rn(asPlayedAllocButton,ASPLAYEDALLOCATION)
|
||||||
|
rn(midiLearnButton,MIDILEARN)
|
||||||
|
rn(midiUnlearnButton,UNLEARN)
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObxdAudioProcessorEditor::mouseUp(const MouseEvent& e)
|
||||||
|
{
|
||||||
|
if (e.mods.isRightButtonDown() || e.mods.isCommandDown())
|
||||||
|
{
|
||||||
|
PopupMenu menu;
|
||||||
|
PopupMenu skinMenu;
|
||||||
|
PopupMenu bankMenu;
|
||||||
|
|
||||||
|
Array<File> skins;
|
||||||
|
const Array<File>& banks = getFilter()->getBankFiles();
|
||||||
|
|
||||||
|
int skinStart = 0;
|
||||||
|
{
|
||||||
|
DirectoryIterator it(getFilter()->getSkinFolder(), false, "*", File::findDirectories);
|
||||||
|
while (it.next())
|
||||||
|
{
|
||||||
|
skins.add(it.getFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < skins.size(); ++i)
|
||||||
|
{
|
||||||
|
const File skin = skins.getUnchecked(i);
|
||||||
|
skinMenu.addItem(i + skinStart + 1, skin.getFileName(), true, skin.getFileName() == skinFolder.getFileName());
|
||||||
|
}
|
||||||
|
|
||||||
|
menu.addSubMenu("Skins", skinMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
int bankStart = 1000;
|
||||||
|
{
|
||||||
|
const String currentBank = getFilter()->getCurrentBankFile().getFileName();
|
||||||
|
|
||||||
|
for (int i = 0; i < banks.size(); ++i)
|
||||||
|
{
|
||||||
|
const File bank = banks.getUnchecked(i);
|
||||||
|
bankMenu.addItem(i + bankStart + 1, bank.getFileName(), true, bank.getFileName() == currentBank);
|
||||||
|
}
|
||||||
|
|
||||||
|
menu.addSubMenu("Banks", bankMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Point<int> pos = e.getMouseDownScreenPosition();
|
||||||
|
|
||||||
|
int result = menu.showAt(Rectangle<int>(pos.getX(), pos.getY(), 1, 1));
|
||||||
|
if (result >= (skinStart + 1) && result <= (skinStart + skins.size()))
|
||||||
|
{
|
||||||
|
result -= 1;
|
||||||
|
result -= skinStart;
|
||||||
|
|
||||||
|
const File newSkinFolder = skins.getUnchecked(result);
|
||||||
|
getFilter()->setCurrentSkinFolder(newSkinFolder.getFileName());
|
||||||
|
|
||||||
|
rebuildComponents();
|
||||||
|
}
|
||||||
|
else if (result >= (bankStart + 1) && result <= (bankStart + banks.size()))
|
||||||
|
{
|
||||||
|
result -= 1;
|
||||||
|
result -= bankStart;
|
||||||
|
|
||||||
|
const File bankFile = banks.getUnchecked(result);
|
||||||
|
getFilter()->loadFromFXBFile(bankFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObxdAudioProcessorEditor::paint(Graphics& g)
|
||||||
|
{
|
||||||
|
g.fillAll (Colours::white);
|
||||||
|
|
||||||
|
const File mainFile(skinFolder.getChildFile("main.png"));
|
||||||
|
|
||||||
|
if (skinFolder.exists() && mainFile.exists())
|
||||||
|
{
|
||||||
|
const Image image = ImageCache::getFromFile(mainFile);
|
||||||
|
|
||||||
|
g.drawImage (image,
|
||||||
|
0, 0, image.getWidth(), image.getHeight(),
|
||||||
|
0, 0, image.getWidth(), image.getHeight());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const Image image = ImageCache::getFromMemory(BinaryData::main_png, BinaryData::main_pngSize);
|
||||||
|
|
||||||
|
g.drawImage (image,
|
||||||
|
0, 0, image.getWidth(), image.getHeight(),
|
||||||
|
0, 0, image.getWidth(), image.getHeight());
|
||||||
|
}
|
||||||
|
}
|
88
Source/PluginEditor.h
Executable file
88
Source/PluginEditor.h
Executable file
|
@ -0,0 +1,88 @@
|
||||||
|
#pragma once
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
|
||||||
|
This file was auto-generated by the Introjucer!
|
||||||
|
|
||||||
|
It contains the basic startup code for a Juce application.
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PLUGINEDITOR_H_INCLUDED
|
||||||
|
#define PLUGINEDITOR_H_INCLUDED
|
||||||
|
|
||||||
|
#include "../JuceLibraryCode/JuceHeader.h"
|
||||||
|
#include "PluginProcessor.h"
|
||||||
|
#include "Gui/Knob.h"
|
||||||
|
#include "Gui/TooglableButton.h"
|
||||||
|
#include "Gui/ButtonList.h"
|
||||||
|
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
class ObxdAudioProcessorEditor :
|
||||||
|
public AudioProcessorEditor,
|
||||||
|
// public AudioProcessorListener,
|
||||||
|
public ChangeListener,
|
||||||
|
public Slider::Listener,
|
||||||
|
public Button::Listener,
|
||||||
|
public ComboBox::Listener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ObxdAudioProcessorEditor(ObxdAudioProcessor* ownerFilter);
|
||||||
|
~ObxdAudioProcessorEditor();
|
||||||
|
|
||||||
|
void mouseUp(const MouseEvent& e);
|
||||||
|
void paint(Graphics& g);
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
void changeListenerCallback (ChangeBroadcaster* source);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Knob* addNormalKnob(int x , int y ,ObxdAudioProcessor* filter, int parameter,String name,float defval);
|
||||||
|
Knob* addTinyKnob(int x , int y ,ObxdAudioProcessor* filter, int parameter,String name,float defval);
|
||||||
|
void placeLabel(int x , int y,String text);
|
||||||
|
TooglableButton* addNormalTooglableButton(int x , int y , ObxdAudioProcessor* filter,int parameter,String name);
|
||||||
|
TooglableButton* addTinyTooglableButton(int x , int y , ObxdAudioProcessor* filter,int parameter,String name);
|
||||||
|
|
||||||
|
ButtonList* addNormalButtonList(int x , int y ,int width, ObxdAudioProcessor* filter,int parameter,String name,Image img);
|
||||||
|
void sliderValueChanged (Slider*);
|
||||||
|
void buttonClicked (Button *);
|
||||||
|
void comboBoxChanged(ComboBox*);
|
||||||
|
|
||||||
|
Knob* addNormalKnobClassic(int x , int y ,ObxdAudioProcessor* filter, int parameter,String name,float defval);
|
||||||
|
Knob* addTinyKnobClassic(int x , int y ,ObxdAudioProcessor* filter, int parameter,String name,float defval);
|
||||||
|
TooglableButton* addNormalTooglableButtonClassic(int x , int y , ObxdAudioProcessor* filter,int parameter,String name);
|
||||||
|
ButtonList* addNormalButtonListClassic(int x , int y ,int width, ObxdAudioProcessor* filter,int parameter,String name,Image img);
|
||||||
|
|
||||||
|
void rebuildComponents();
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
ObxdAudioProcessor* getFilter() noexcept { return (ObxdAudioProcessor*)getAudioProcessor();}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
Knob* cutoffKnob,*resonanceKnob,*osc1PitchKnob,*osc2PitchKnob,*osc2DetuneKnob,*volumeKnob,
|
||||||
|
*portamentoKnob,*voiceDetuneKnob,*filterEnvelopeAmtKnob,*pulseWidthKnob,*xmodKnob,*multimodeKnob,*attackKnob,*decayKnob,*sustainKnob,*releaseKnob,
|
||||||
|
*fattackKnob,*fdecayKnob,*fsustainKnob,*freleaseKnob,*osc1MixKnob,*osc2MixKnob,*noiseMixKnob,
|
||||||
|
*filterDetuneKnob,*envelopeDetuneKnob,*portamentoDetuneKnob,
|
||||||
|
*tuneKnob,
|
||||||
|
*lfoFrequencyKnob,*lfoAmt1Knob,*lfoAmt2Knob,
|
||||||
|
*pan1Knob,*pan2Knob,*pan3Knob,*pan4Knob,*pan5Knob,*pan6Knob,*pan7Knob,*pan8Knob,
|
||||||
|
*brightnessKnob,*envPitchModKnob,
|
||||||
|
*bendLfoRateKnob,*veloAmpEnvKnob,*veloFltEnvKnob,*transposeKnob;
|
||||||
|
|
||||||
|
TooglableButton* hardSyncButton,*osc1SawButton,*osc2SawButton,*osc1PulButton,*osc2PulButton,*filterKeyFollowButton,*unisonButton,*pitchQuantButton,
|
||||||
|
*filterHQButton,*filterBPBlendButton,
|
||||||
|
*lfoSinButton,*lfoSquareButton,*lfoSHButton,*lfoOsc1Button,*lfoOsc2Button,*lfoFilterButton,
|
||||||
|
*lfoPwm1Button,*lfoPwm2Button,
|
||||||
|
*bendRangeButton,*bendOsc2OnlyButton,
|
||||||
|
*fourPoleButton,*asPlayedAllocButton,*midiLearnButton,*midiUnlearnButton;
|
||||||
|
|
||||||
|
ButtonList *voiceSwitch,*legatoSwitch;
|
||||||
|
|
||||||
|
File skinFolder;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PLUGINEDITOR_H_INCLUDED
|
999
Source/PluginProcessor.cpp
Executable file
999
Source/PluginProcessor.cpp
Executable file
|
@ -0,0 +1,999 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
|
||||||
|
This file was auto-generated!
|
||||||
|
|
||||||
|
It contains the basic startup code for a Juce application.
|
||||||
|
|
||||||
|
==============================================================================
|
||||||
|
*/
|
||||||
|
#include "PluginProcessor.h"
|
||||||
|
#include "PluginEditor.h"
|
||||||
|
#include "Engine/Params.h"
|
||||||
|
|
||||||
|
//only sse2 version on windows
|
||||||
|
#ifdef _WINDOWS
|
||||||
|
#define __SSE2__
|
||||||
|
#define __SSE__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __SSE2__
|
||||||
|
#include <xmmintrin.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
#define S(T) (juce::String(T))
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
ObxdAudioProcessor::ObxdAudioProcessor()
|
||||||
|
: bindings()
|
||||||
|
, programs()
|
||||||
|
, configLock("__" JucePlugin_Name "ConfigLock__")
|
||||||
|
{
|
||||||
|
isHostAutomatedChange = true;
|
||||||
|
midiControlledParamSet = false;
|
||||||
|
lastMovedController = 0;
|
||||||
|
lastUsedParameter = 0;
|
||||||
|
|
||||||
|
synth.setSampleRate(44100);
|
||||||
|
|
||||||
|
PropertiesFile::Options options;
|
||||||
|
options.applicationName = JucePlugin_Name;
|
||||||
|
options.storageFormat = PropertiesFile::storeAsXML;
|
||||||
|
options.millisecondsBeforeSaving = 2500;
|
||||||
|
options.processLock = &configLock;
|
||||||
|
config = new PropertiesFile(getDocumentFolder().getChildFile("Settings.xml"), options);
|
||||||
|
|
||||||
|
currentSkin = config->containsKey("skin") ? config->getValue("skin") : "discoDSP Grey";
|
||||||
|
currentBank = "Init";
|
||||||
|
|
||||||
|
scanAndUpdateBanks();
|
||||||
|
initAllParams();
|
||||||
|
|
||||||
|
if (bankFiles.size() > 0)
|
||||||
|
{
|
||||||
|
loadFromFXBFile(bankFiles[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ObxdAudioProcessor::~ObxdAudioProcessor()
|
||||||
|
{
|
||||||
|
config->saveIfNeeded();
|
||||||
|
config = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
void ObxdAudioProcessor::initAllParams()
|
||||||
|
{
|
||||||
|
for (int i = 0 ; i < PARAM_COUNT; i++)
|
||||||
|
{
|
||||||
|
setParameter(i, programs.currentProgramPtr->values[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
int ObxdAudioProcessor::getNumParameters()
|
||||||
|
{
|
||||||
|
return PARAM_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
float ObxdAudioProcessor::getParameter (int index)
|
||||||
|
{
|
||||||
|
return programs.currentProgramPtr->values[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObxdAudioProcessor::setParameter (int index, float newValue)
|
||||||
|
{
|
||||||
|
if(!midiControlledParamSet || index==MIDILEARN || index==UNLEARN)
|
||||||
|
lastUsedParameter = index;
|
||||||
|
programs.currentProgramPtr->values[index] = newValue;
|
||||||
|
switch(index)
|
||||||
|
{
|
||||||
|
case SELF_OSC_PUSH:
|
||||||
|
synth.processSelfOscPush(newValue);
|
||||||
|
break;
|
||||||
|
case PW_ENV_BOTH:
|
||||||
|
synth.processPwEnvBoth(newValue);
|
||||||
|
break;
|
||||||
|
case PW_OSC2_OFS:
|
||||||
|
synth.processPwOfs(newValue);
|
||||||
|
break;
|
||||||
|
case ENV_PITCH_BOTH:
|
||||||
|
synth.processPitchModBoth(newValue);
|
||||||
|
break;
|
||||||
|
case FENV_INVERT:
|
||||||
|
synth.processInvertFenv(newValue);
|
||||||
|
break;
|
||||||
|
case LEVEL_DIF:
|
||||||
|
synth.processLoudnessDetune(newValue);
|
||||||
|
break;
|
||||||
|
case PW_ENV:
|
||||||
|
synth.processPwEnv(newValue);
|
||||||
|
break;
|
||||||
|
case LFO_SYNC:
|
||||||
|
synth.procLfoSync(newValue);
|
||||||
|
break;
|
||||||
|
case ECONOMY_MODE:
|
||||||
|
synth.procEconomyMode(newValue);
|
||||||
|
break;
|
||||||
|
case VAMPENV:
|
||||||
|
synth.procAmpVelocityAmount(newValue);
|
||||||
|
break;
|
||||||
|
case VFLTENV:
|
||||||
|
synth.procFltVelocityAmount(newValue);
|
||||||
|
break;
|
||||||
|
case ASPLAYEDALLOCATION:
|
||||||
|
synth.procAsPlayedAlloc(newValue);
|
||||||
|
break;
|
||||||
|
case BENDLFORATE:
|
||||||
|
synth.procModWheelFrequency(newValue);
|
||||||
|
break;
|
||||||
|
case FOURPOLE:
|
||||||
|
synth.processFourPole(newValue);
|
||||||
|
break;
|
||||||
|
case LEGATOMODE:
|
||||||
|
synth.processLegatoMode(newValue);
|
||||||
|
break;
|
||||||
|
case ENVPITCH:
|
||||||
|
synth.processEnvelopeToPitch(newValue);
|
||||||
|
break;
|
||||||
|
case OSCQuantize:
|
||||||
|
synth.processPitchQuantization(newValue);
|
||||||
|
break;
|
||||||
|
case VOICE_COUNT:
|
||||||
|
synth.setVoiceCount(newValue);
|
||||||
|
break;
|
||||||
|
case BANDPASS:
|
||||||
|
synth.processBandpassSw(newValue);
|
||||||
|
break;
|
||||||
|
case FILTER_WARM:
|
||||||
|
synth.processOversampling(newValue);
|
||||||
|
break;
|
||||||
|
case BENDOSC2:
|
||||||
|
synth.procPitchWheelOsc2Only(newValue);
|
||||||
|
break;
|
||||||
|
case BENDRANGE:
|
||||||
|
synth.procPitchWheelAmount(newValue);
|
||||||
|
break;
|
||||||
|
case NOISEMIX:
|
||||||
|
synth.processNoiseMix(newValue);
|
||||||
|
break;
|
||||||
|
case OCTAVE:
|
||||||
|
synth.processOctave(newValue);
|
||||||
|
break;
|
||||||
|
case TUNE:
|
||||||
|
synth.processTune(newValue);
|
||||||
|
break;
|
||||||
|
case BRIGHTNESS:
|
||||||
|
synth.processBrightness(newValue);
|
||||||
|
break;
|
||||||
|
case MULTIMODE:
|
||||||
|
synth.processMultimode(newValue);
|
||||||
|
break;
|
||||||
|
case LFOFREQ:
|
||||||
|
synth.processLfoFrequency(newValue);
|
||||||
|
break;
|
||||||
|
case LFO1AMT:
|
||||||
|
synth.processLfoAmt1(newValue);
|
||||||
|
break;
|
||||||
|
case LFO2AMT:
|
||||||
|
synth.processLfoAmt2(newValue);
|
||||||
|
break;
|
||||||
|
case LFOSINWAVE:
|
||||||
|
synth.processLfoSine(newValue);
|
||||||
|
break;
|
||||||
|
case LFOSQUAREWAVE:
|
||||||
|
synth.processLfoSquare(newValue);
|
||||||
|
break;
|
||||||
|
case LFOSHWAVE:
|
||||||
|
synth.processLfoSH(newValue);
|
||||||
|
break;
|
||||||
|
case LFOFILTER:
|
||||||
|
synth.processLfoFilter(newValue);
|
||||||
|
break;
|
||||||
|
case LFOOSC1:
|
||||||
|
synth.processLfoOsc1(newValue);
|
||||||
|
break;
|
||||||
|
case LFOOSC2:
|
||||||
|
synth.processLfoOsc2(newValue);
|
||||||
|
break;
|
||||||
|
case LFOPW1:
|
||||||
|
synth.processLfoPw1(newValue);
|
||||||
|
break;
|
||||||
|
case LFOPW2:
|
||||||
|
synth.processLfoPw2(newValue);
|
||||||
|
break;
|
||||||
|
case PORTADER:
|
||||||
|
synth.processPortamentoDetune(newValue);
|
||||||
|
break;
|
||||||
|
case FILTERDER:
|
||||||
|
synth.processFilterDetune(newValue);
|
||||||
|
break;
|
||||||
|
case ENVDER:
|
||||||
|
synth.processEnvelopeDetune(newValue);
|
||||||
|
break;
|
||||||
|
case XMOD:
|
||||||
|
synth.processOsc2Xmod(newValue);
|
||||||
|
break;
|
||||||
|
case OSC2HS:
|
||||||
|
synth.processOsc2HardSync(newValue);
|
||||||
|
break;
|
||||||
|
case OSC2P:
|
||||||
|
synth.processOsc2Pitch(newValue);
|
||||||
|
break;
|
||||||
|
case OSC1P:
|
||||||
|
synth.processOsc1Pitch(newValue);
|
||||||
|
break;
|
||||||
|
case PORTAMENTO:
|
||||||
|
synth.processPortamento(newValue);
|
||||||
|
break;
|
||||||
|
case UNISON:
|
||||||
|
synth.processUnison(newValue);
|
||||||
|
break;
|
||||||
|
case FLT_KF:
|
||||||
|
synth.processFilterKeyFollow(newValue);
|
||||||
|
break;
|
||||||
|
case OSC1MIX:
|
||||||
|
synth.processOsc1Mix(newValue);
|
||||||
|
break;
|
||||||
|
case OSC2MIX:
|
||||||
|
synth.processOsc2Mix(newValue);
|
||||||
|
break;
|
||||||
|
case PW:
|
||||||
|
synth.processPulseWidth(newValue);
|
||||||
|
break;
|
||||||
|
case OSC1Saw:
|
||||||
|
synth.processOsc1Saw(newValue);
|
||||||
|
break;
|
||||||
|
case OSC2Saw:
|
||||||
|
synth.processOsc2Saw(newValue);
|
||||||
|
break;
|
||||||
|
case OSC1Pul:
|
||||||
|
synth.processOsc1Pulse(newValue);
|
||||||
|
break;
|
||||||
|
case OSC2Pul:
|
||||||
|
synth.processOsc2Pulse(newValue);
|
||||||
|
break;
|
||||||
|
case VOLUME:
|
||||||
|
synth.processVolume(newValue);
|
||||||
|
break;
|
||||||
|
case UDET:
|
||||||
|
synth.processDetune(newValue);
|
||||||
|
break;
|
||||||
|
case OSC2_DET:
|
||||||
|
synth.processOsc2Det(newValue);
|
||||||
|
break;
|
||||||
|
case CUTOFF:
|
||||||
|
synth.processCutoff(newValue);
|
||||||
|
break;
|
||||||
|
case RESONANCE:
|
||||||
|
synth.processResonance(newValue);
|
||||||
|
break;
|
||||||
|
case ENVELOPE_AMT:
|
||||||
|
synth.processFilterEnvelopeAmt(newValue);
|
||||||
|
break;
|
||||||
|
case LATK:
|
||||||
|
synth.processLoudnessEnvelopeAttack(newValue);
|
||||||
|
break;
|
||||||
|
case LDEC:
|
||||||
|
synth.processLoudnessEnvelopeDecay(newValue);
|
||||||
|
break;
|
||||||
|
case LSUS:
|
||||||
|
synth.processLoudnessEnvelopeSustain(newValue);
|
||||||
|
break;
|
||||||
|
case LREL:
|
||||||
|
synth.processLoudnessEnvelopeRelease(newValue);
|
||||||
|
break;
|
||||||
|
case FATK:
|
||||||
|
synth.processFilterEnvelopeAttack(newValue);
|
||||||
|
break;
|
||||||
|
case FDEC:
|
||||||
|
synth.processFilterEnvelopeDecay(newValue);
|
||||||
|
break;
|
||||||
|
case FSUS:
|
||||||
|
synth.processFilterEnvelopeSustain(newValue);
|
||||||
|
break;
|
||||||
|
case FREL:
|
||||||
|
synth.processFilterEnvelopeRelease(newValue);
|
||||||
|
break;
|
||||||
|
case PAN1:
|
||||||
|
synth.processPan(newValue,1);
|
||||||
|
break;
|
||||||
|
case PAN2:
|
||||||
|
synth.processPan(newValue,2);
|
||||||
|
break;
|
||||||
|
case PAN3:
|
||||||
|
synth.processPan(newValue,3);
|
||||||
|
break;
|
||||||
|
case PAN4:
|
||||||
|
synth.processPan(newValue,4);
|
||||||
|
break;
|
||||||
|
case PAN5:
|
||||||
|
synth.processPan(newValue,5);
|
||||||
|
break;
|
||||||
|
case PAN6:
|
||||||
|
synth.processPan(newValue,6);
|
||||||
|
break;
|
||||||
|
case PAN7:
|
||||||
|
synth.processPan(newValue,7);
|
||||||
|
break;
|
||||||
|
case PAN8:
|
||||||
|
synth.processPan(newValue,8);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//DIRTY HACK
|
||||||
|
//This should be checked to avoid stalling on gui update
|
||||||
|
//It is needed because some hosts do wierd stuff
|
||||||
|
if(isHostAutomatedChange)
|
||||||
|
sendChangeMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
const String ObxdAudioProcessor::getParameterName (int index)
|
||||||
|
{
|
||||||
|
switch(index)
|
||||||
|
{
|
||||||
|
case SELF_OSC_PUSH:
|
||||||
|
return S("SelfOscPush");
|
||||||
|
case ENV_PITCH_BOTH:
|
||||||
|
return S("EnvPitchBoth");
|
||||||
|
case FENV_INVERT:
|
||||||
|
return S("FenvInvert");
|
||||||
|
case PW_OSC2_OFS:
|
||||||
|
return S("PwOfs");
|
||||||
|
case LEVEL_DIF:
|
||||||
|
return S("LevelDif");
|
||||||
|
case PW_ENV_BOTH:
|
||||||
|
return S("PwEnvBoth");
|
||||||
|
case PW_ENV:
|
||||||
|
return S("PwEnv");
|
||||||
|
case LFO_SYNC:
|
||||||
|
return S("LfoSync");
|
||||||
|
case ECONOMY_MODE:
|
||||||
|
return S("EconomyMode");
|
||||||
|
case UNLEARN:
|
||||||
|
return S("MidiUnlearn");
|
||||||
|
case MIDILEARN:
|
||||||
|
return S("MidiLearn");
|
||||||
|
case VAMPENV:
|
||||||
|
return S("VAmpFactor");
|
||||||
|
case VFLTENV:
|
||||||
|
return S("VFltFactor");
|
||||||
|
case ASPLAYEDALLOCATION:
|
||||||
|
return S("AsPlayedAllocation");
|
||||||
|
case BENDLFORATE:
|
||||||
|
return S("VibratoRate");
|
||||||
|
case FOURPOLE:
|
||||||
|
return S("FourPole");
|
||||||
|
case LEGATOMODE:
|
||||||
|
return S("LegatoMode");
|
||||||
|
case ENVPITCH:
|
||||||
|
return S("EnvelopeToPitch");
|
||||||
|
case OSCQuantize:
|
||||||
|
return S("PitchQuant");
|
||||||
|
case VOICE_COUNT:
|
||||||
|
return S("VoiceCount");
|
||||||
|
case BANDPASS:
|
||||||
|
return S("BandpassBlend");
|
||||||
|
case FILTER_WARM:
|
||||||
|
return S("Filter_Warm");
|
||||||
|
case BENDRANGE:
|
||||||
|
return S("BendRange");
|
||||||
|
case BENDOSC2:
|
||||||
|
return S("BendOsc2Only");
|
||||||
|
case OCTAVE:
|
||||||
|
return S("Octave");
|
||||||
|
case TUNE:
|
||||||
|
return S("Tune");
|
||||||
|
case BRIGHTNESS:
|
||||||
|
return S("Brightness");
|
||||||
|
case NOISEMIX:
|
||||||
|
return S("NoiseMix");
|
||||||
|
case OSC1MIX:
|
||||||
|
return S("Osc1Mix");
|
||||||
|
case OSC2MIX:
|
||||||
|
return S("Osc2Mix");
|
||||||
|
case MULTIMODE:
|
||||||
|
return S("Multimode");
|
||||||
|
case LFOSHWAVE:
|
||||||
|
return S("LfoSampleHoldWave");
|
||||||
|
case LFOSINWAVE:
|
||||||
|
return S("LfoSineWave");
|
||||||
|
case LFOSQUAREWAVE:
|
||||||
|
return S("LfoSquareWave");
|
||||||
|
case LFO1AMT:
|
||||||
|
return S("LfoAmount1");
|
||||||
|
case LFO2AMT:
|
||||||
|
return S("LfoAmount2");
|
||||||
|
case LFOFILTER:
|
||||||
|
return S("LfoFilter");
|
||||||
|
case LFOOSC1:
|
||||||
|
return S("LfoOsc1");
|
||||||
|
case LFOOSC2:
|
||||||
|
return S("LfoOsc2");
|
||||||
|
case LFOFREQ:
|
||||||
|
return S("LfoFrequency");
|
||||||
|
case LFOPW1:
|
||||||
|
return S("LfoPw1");
|
||||||
|
case LFOPW2:
|
||||||
|
return S("LfoPw2");
|
||||||
|
case PORTADER:
|
||||||
|
return S("PortamentoDetune");
|
||||||
|
case FILTERDER:
|
||||||
|
return S("FilterDetune");
|
||||||
|
case ENVDER:
|
||||||
|
return S("EnvelopeDetune");
|
||||||
|
case PAN1:
|
||||||
|
return S("Pan1");
|
||||||
|
case PAN2:
|
||||||
|
return S("Pan2");
|
||||||
|
case PAN3:
|
||||||
|
return S("Pan3");
|
||||||
|
case PAN4:
|
||||||
|
return S("Pan4");
|
||||||
|
case PAN5:
|
||||||
|
return S("Pan5");
|
||||||
|
case PAN6:
|
||||||
|
return S("Pan6");
|
||||||
|
case PAN7:
|
||||||
|
return S("Pan7");
|
||||||
|
case PAN8:
|
||||||
|
return S("Pan8");
|
||||||
|
case XMOD:
|
||||||
|
return S("Xmod");
|
||||||
|
case OSC2HS:
|
||||||
|
return S("Osc2HardSync");
|
||||||
|
case OSC1P:
|
||||||
|
return S("Osc1Pitch");
|
||||||
|
case OSC2P:
|
||||||
|
return S("Osc2Pitch");
|
||||||
|
case PORTAMENTO:
|
||||||
|
return S("Portamento");
|
||||||
|
case UNISON:
|
||||||
|
return S("Unison");
|
||||||
|
case FLT_KF:
|
||||||
|
return S("FilterKeyFollow");
|
||||||
|
case PW:
|
||||||
|
return S("PulseWidth");
|
||||||
|
case OSC2Saw:
|
||||||
|
return S("Osc2Saw");
|
||||||
|
case OSC1Saw:
|
||||||
|
return S("Osc1Saw");
|
||||||
|
case OSC1Pul:
|
||||||
|
return S("Osc1Pulse");
|
||||||
|
case OSC2Pul:
|
||||||
|
return S("Osc2Pulse");
|
||||||
|
case VOLUME:
|
||||||
|
return S("Volume");
|
||||||
|
case UDET:
|
||||||
|
return S("VoiceDetune");
|
||||||
|
case OSC2_DET:
|
||||||
|
return S("Oscillator2detune");
|
||||||
|
case CUTOFF:
|
||||||
|
return S("Cutoff");
|
||||||
|
case RESONANCE:
|
||||||
|
return S("Resonance");
|
||||||
|
case ENVELOPE_AMT:
|
||||||
|
return S("FilterEnvAmount");
|
||||||
|
case LATK:
|
||||||
|
return S("Attack");
|
||||||
|
case LDEC:
|
||||||
|
return S("Decay");
|
||||||
|
case LSUS:
|
||||||
|
return S("Sustain");
|
||||||
|
case LREL:
|
||||||
|
return S("Release");
|
||||||
|
case FATK:
|
||||||
|
return S("FilterAttack");
|
||||||
|
case FDEC:
|
||||||
|
return S("FilterDecay");
|
||||||
|
case FSUS:
|
||||||
|
return S("FilterSustain");
|
||||||
|
case FREL:
|
||||||
|
return S("FilterRelease");
|
||||||
|
}
|
||||||
|
return String::empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
const String ObxdAudioProcessor::getParameterText (int index)
|
||||||
|
{
|
||||||
|
return String(programs.currentProgramPtr->values[index],2);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
const String ObxdAudioProcessor::getName() const
|
||||||
|
{
|
||||||
|
return JucePlugin_Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
const String ObxdAudioProcessor::getInputChannelName (int channelIndex) const
|
||||||
|
{
|
||||||
|
return String (channelIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const String ObxdAudioProcessor::getOutputChannelName (int channelIndex) const
|
||||||
|
{
|
||||||
|
return String (channelIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObxdAudioProcessor::isInputChannelStereoPair (int index) const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObxdAudioProcessor::isOutputChannelStereoPair (int index) const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObxdAudioProcessor::acceptsMidi() const
|
||||||
|
{
|
||||||
|
#if JucePlugin_WantsMidiInput
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObxdAudioProcessor::producesMidi() const
|
||||||
|
{
|
||||||
|
#if JucePlugin_ProducesMidiOutput
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObxdAudioProcessor::silenceInProducesSilenceOut() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
double ObxdAudioProcessor::getTailLengthSeconds() const
|
||||||
|
{
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
int ObxdAudioProcessor::getNumPrograms()
|
||||||
|
{
|
||||||
|
return PROGRAMCOUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ObxdAudioProcessor::getCurrentProgram()
|
||||||
|
{
|
||||||
|
return programs.currentProgram;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObxdAudioProcessor::setCurrentProgram (int index)
|
||||||
|
{
|
||||||
|
programs.currentProgram = index;
|
||||||
|
programs.currentProgramPtr = programs.programs + programs.currentProgram;
|
||||||
|
isHostAutomatedChange = false;
|
||||||
|
for(int i = 0 ; i < PARAM_COUNT;i++)
|
||||||
|
setParameter(i,programs.currentProgramPtr->values[i]);
|
||||||
|
isHostAutomatedChange = true;
|
||||||
|
sendChangeMessage();
|
||||||
|
updateHostDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
const String ObxdAudioProcessor::getProgramName (int index)
|
||||||
|
{
|
||||||
|
return programs.programs[index].name;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObxdAudioProcessor::changeProgramName (int index, const String& newName)
|
||||||
|
{
|
||||||
|
programs.programs[index].name = newName;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
void ObxdAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock)
|
||||||
|
{
|
||||||
|
// Use this method as the place to do any pre-playback
|
||||||
|
// initialisation that you need..
|
||||||
|
nextMidi= new MidiMessage(0xF0);
|
||||||
|
midiMsg = new MidiMessage(0xF0);
|
||||||
|
synth.setSampleRate(sampleRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObxdAudioProcessor::releaseResources()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ObxdAudioProcessor::processMidiPerSample(MidiBuffer::Iterator* iter,const int samplePos)
|
||||||
|
{
|
||||||
|
while (getNextEvent(iter, samplePos))
|
||||||
|
{
|
||||||
|
if(midiMsg->isNoteOn())
|
||||||
|
{
|
||||||
|
synth.procNoteOn(midiMsg->getNoteNumber(),midiMsg->getFloatVelocity());
|
||||||
|
}
|
||||||
|
if (midiMsg->isNoteOff())
|
||||||
|
{
|
||||||
|
synth.procNoteOff(midiMsg->getNoteNumber());
|
||||||
|
}
|
||||||
|
if(midiMsg->isPitchWheel())
|
||||||
|
{
|
||||||
|
// [0..16383] center = 8192;
|
||||||
|
synth.procPitchWheel((midiMsg->getPitchWheelValue()-8192) / 8192.0);
|
||||||
|
}
|
||||||
|
if(midiMsg->isController() && midiMsg->getControllerNumber()==1)
|
||||||
|
synth.procModWheel(midiMsg->getControllerValue() / 127.0);
|
||||||
|
if(midiMsg->isController())
|
||||||
|
{
|
||||||
|
lastMovedController = midiMsg->getControllerNumber();
|
||||||
|
if(programs.currentProgramPtr->values[MIDILEARN] > 0.5)
|
||||||
|
bindings.controllers[lastMovedController] = lastUsedParameter;
|
||||||
|
if(programs.currentProgramPtr->values[UNLEARN] >0.5)
|
||||||
|
{
|
||||||
|
midiControlledParamSet = true;
|
||||||
|
bindings.controllers[lastMovedController] = 0;
|
||||||
|
setParameter(UNLEARN,0);
|
||||||
|
lastMovedController = 0;
|
||||||
|
lastUsedParameter = 0;
|
||||||
|
midiControlledParamSet = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bindings.controllers[lastMovedController] > 0)
|
||||||
|
{
|
||||||
|
midiControlledParamSet = true;
|
||||||
|
setParameter(bindings.controllers[lastMovedController],midiMsg->getControllerValue() / 127.0);
|
||||||
|
setParameter(MIDILEARN,0);
|
||||||
|
lastMovedController = 0;
|
||||||
|
lastUsedParameter = 0;
|
||||||
|
|
||||||
|
midiControlledParamSet = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if(midiMsg->isSustainPedalOn())
|
||||||
|
{
|
||||||
|
synth.sustainOn();
|
||||||
|
}
|
||||||
|
if(midiMsg->isSustainPedalOff() || midiMsg->isAllNotesOff()||midiMsg->isAllSoundOff())
|
||||||
|
{
|
||||||
|
synth.sustainOff();
|
||||||
|
}
|
||||||
|
if(midiMsg->isAllNotesOff())
|
||||||
|
{
|
||||||
|
synth.allNotesOff();
|
||||||
|
}
|
||||||
|
if(midiMsg->isAllSoundOff())
|
||||||
|
{
|
||||||
|
synth.allSoundOff();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObxdAudioProcessor::getNextEvent(MidiBuffer::Iterator* iter,const int samplePos)
|
||||||
|
{
|
||||||
|
if (hasMidiMessage && midiEventPos <= samplePos)
|
||||||
|
{
|
||||||
|
*midiMsg = *nextMidi;
|
||||||
|
hasMidiMessage = iter->getNextEvent(*nextMidi, midiEventPos);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObxdAudioProcessor::processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages)
|
||||||
|
{
|
||||||
|
//SSE flags set
|
||||||
|
#ifdef __SSE__
|
||||||
|
_MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON);
|
||||||
|
#endif
|
||||||
|
#ifdef __SSE2__
|
||||||
|
// _MM_SET_DENORMALS_ZERO_MODE(_MM_DENORMALS_ZERO_ON);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
MidiBuffer::Iterator ppp(midiMessages);
|
||||||
|
hasMidiMessage = ppp.getNextEvent(*nextMidi,midiEventPos);
|
||||||
|
|
||||||
|
int samplePos = 0;
|
||||||
|
int numSamples = buffer.getNumSamples();
|
||||||
|
float* channelData1 = buffer.getWritePointer(0);
|
||||||
|
float* channelData2 = buffer.getWritePointer(1);
|
||||||
|
|
||||||
|
AudioPlayHead::CurrentPositionInfo pos;
|
||||||
|
if (getPlayHead() != 0 && getPlayHead()->getCurrentPosition (pos))
|
||||||
|
{
|
||||||
|
synth.setPlayHead(pos.bpm,pos.ppqPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (samplePos < numSamples)
|
||||||
|
{
|
||||||
|
processMidiPerSample(&ppp,samplePos);
|
||||||
|
|
||||||
|
synth.processSample(channelData1+samplePos,channelData2+samplePos);
|
||||||
|
|
||||||
|
samplePos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
bool ObxdAudioProcessor::hasEditor() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
AudioProcessorEditor* ObxdAudioProcessor::createEditor()
|
||||||
|
{
|
||||||
|
return new ObxdAudioProcessorEditor (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
void ObxdAudioProcessor::getStateInformation (MemoryBlock& destData)
|
||||||
|
{
|
||||||
|
XmlElement xmlState = XmlElement("Datsounds");
|
||||||
|
xmlState.setAttribute(S("currentProgram"), programs.currentProgram);
|
||||||
|
|
||||||
|
XmlElement* xprogs = new XmlElement("programs");
|
||||||
|
for (int i = 0; i < PROGRAMCOUNT; ++i)
|
||||||
|
{
|
||||||
|
XmlElement* xpr = new XmlElement("program");
|
||||||
|
xpr->setAttribute(S("programName"), programs.programs[i].name);
|
||||||
|
|
||||||
|
for (int k = 0; k < PARAM_COUNT; ++k)
|
||||||
|
{
|
||||||
|
xpr->setAttribute(String(k), programs.programs[i].values[k]);
|
||||||
|
}
|
||||||
|
|
||||||
|
xprogs->addChildElement(xpr);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlState.addChildElement(xprogs);
|
||||||
|
|
||||||
|
for (int i = 0; i < 255; ++i)
|
||||||
|
{
|
||||||
|
xmlState.setAttribute(String(i), bindings.controllers[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
copyXmlToBinary(xmlState,destData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObxdAudioProcessor::setStateInformation (const void* data, int sizeInBytes)
|
||||||
|
{
|
||||||
|
if (XmlElement* const xmlState = getXmlFromBinary(data,sizeInBytes))
|
||||||
|
{
|
||||||
|
XmlElement* xprogs = xmlState->getFirstChildElement();
|
||||||
|
if (xprogs->hasTagName(S("programs")))
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
forEachXmlChildElement(*xprogs, e)
|
||||||
|
{
|
||||||
|
programs.programs[i].setDefaultValues();
|
||||||
|
|
||||||
|
for (int k = 0; k < PARAM_COUNT; ++k)
|
||||||
|
{
|
||||||
|
programs.programs[i].values[k] = e->getDoubleAttribute(String(k), programs.programs[i].values[k]);
|
||||||
|
}
|
||||||
|
|
||||||
|
programs.programs[i].name = e->getStringAttribute(S("programName"), S("Default"));
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 255; ++i)
|
||||||
|
{
|
||||||
|
bindings.controllers[i] = xmlState->getIntAttribute(String(i), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
setCurrentProgram(xmlState->getIntAttribute(S("currentProgram"), 0));
|
||||||
|
|
||||||
|
delete xmlState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObxdAudioProcessor::setCurrentProgramStateInformation(const void* data,int sizeInBytes)
|
||||||
|
{
|
||||||
|
if (XmlElement* const e = getXmlFromBinary(data, sizeInBytes))
|
||||||
|
{
|
||||||
|
programs.currentProgramPtr->setDefaultValues();
|
||||||
|
|
||||||
|
for (int k = 0; k < PARAM_COUNT; ++k)
|
||||||
|
{
|
||||||
|
programs.currentProgramPtr->values[k] = e->getDoubleAttribute(String(k), programs.currentProgramPtr->values[k]);
|
||||||
|
}
|
||||||
|
|
||||||
|
programs.currentProgramPtr->name = e->getStringAttribute(S("programName"), S("Default"));
|
||||||
|
|
||||||
|
setCurrentProgram(programs.currentProgram);
|
||||||
|
|
||||||
|
delete e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObxdAudioProcessor::getCurrentProgramStateInformation(MemoryBlock& destData)
|
||||||
|
{
|
||||||
|
XmlElement xmlState = XmlElement("Datsounds");
|
||||||
|
|
||||||
|
for (int k = 0; k < PARAM_COUNT; ++k)
|
||||||
|
{
|
||||||
|
xmlState.setAttribute(String(k), programs.currentProgramPtr->values[k]);
|
||||||
|
}
|
||||||
|
|
||||||
|
xmlState.setAttribute(S("programName"), programs.currentProgramPtr->name);
|
||||||
|
|
||||||
|
copyXmlToBinary(xmlState, destData);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
bool ObxdAudioProcessor::loadFromFXBFile(const File& fxbFile)
|
||||||
|
{
|
||||||
|
MemoryBlock mb;
|
||||||
|
if (! fxbFile.loadFileAsData(mb))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const void* const data = mb.getData();
|
||||||
|
const size_t dataSize = mb.getSize();
|
||||||
|
|
||||||
|
if (dataSize < 28)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const fxSet* const set = (const fxSet*) data;
|
||||||
|
|
||||||
|
if ((! compareMagic (set->chunkMagic, "CcnK")) || fxbSwap (set->version) > fxbVersionNum)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (compareMagic (set->fxMagic, "FxBk"))
|
||||||
|
{
|
||||||
|
// bank of programs
|
||||||
|
if (fxbSwap (set->numPrograms) >= 0)
|
||||||
|
{
|
||||||
|
const int oldProg = getCurrentProgram();
|
||||||
|
const int numParams = fxbSwap (((const fxProgram*) (set->programs))->numParams);
|
||||||
|
const int progLen = (int) sizeof (fxProgram) + (numParams - 1) * (int) sizeof (float);
|
||||||
|
|
||||||
|
for (int i = 0; i < fxbSwap (set->numPrograms); ++i)
|
||||||
|
{
|
||||||
|
if (i != oldProg)
|
||||||
|
{
|
||||||
|
const fxProgram* const prog = (const fxProgram*) (((const char*) (set->programs)) + i * progLen);
|
||||||
|
if (((const char*) prog) - ((const char*) set) >= (ssize_t) dataSize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (fxbSwap (set->numPrograms) > 0)
|
||||||
|
setCurrentProgram (i);
|
||||||
|
|
||||||
|
if (! restoreProgramSettings (prog))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fxbSwap (set->numPrograms) > 0)
|
||||||
|
setCurrentProgram (oldProg);
|
||||||
|
|
||||||
|
const fxProgram* const prog = (const fxProgram*) (((const char*) (set->programs)) + oldProg * progLen);
|
||||||
|
if (((const char*) prog) - ((const char*) set) >= (ssize_t) dataSize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (! restoreProgramSettings (prog))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (compareMagic (set->fxMagic, "FxCk"))
|
||||||
|
{
|
||||||
|
// single program
|
||||||
|
const fxProgram* const prog = (const fxProgram*) data;
|
||||||
|
|
||||||
|
if (! compareMagic (prog->chunkMagic, "CcnK"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
changeProgramName (getCurrentProgram(), prog->prgName);
|
||||||
|
|
||||||
|
for (int i = 0; i < fxbSwap (prog->numParams); ++i)
|
||||||
|
setParameter (i, fxbSwapFloat (prog->params[i]));
|
||||||
|
}
|
||||||
|
else if (compareMagic (set->fxMagic, "FBCh"))
|
||||||
|
{
|
||||||
|
// non-preset chunk
|
||||||
|
const fxChunkSet* const cset = (const fxChunkSet*) data;
|
||||||
|
|
||||||
|
if ((size_t) fxbSwap (cset->chunkSize) + sizeof (fxChunkSet) - 8 > (size_t) dataSize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
setStateInformation(cset->chunk, fxbSwap (cset->chunkSize));
|
||||||
|
}
|
||||||
|
else if (compareMagic (set->fxMagic, "FPCh"))
|
||||||
|
{
|
||||||
|
// preset chunk
|
||||||
|
const fxProgramSet* const cset = (const fxProgramSet*) data;
|
||||||
|
|
||||||
|
if ((size_t) fxbSwap (cset->chunkSize) + sizeof (fxProgramSet) - 8 > (size_t) dataSize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
setCurrentProgramStateInformation(cset->chunk, fxbSwap (cset->chunkSize));
|
||||||
|
|
||||||
|
changeProgramName (getCurrentProgram(), cset->name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentBank = fxbFile.getFileName();
|
||||||
|
|
||||||
|
updateHostDisplay();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObxdAudioProcessor::restoreProgramSettings(const fxProgram* const prog)
|
||||||
|
{
|
||||||
|
if (compareMagic (prog->chunkMagic, "CcnK")
|
||||||
|
&& compareMagic (prog->fxMagic, "FxCk"))
|
||||||
|
{
|
||||||
|
changeProgramName (getCurrentProgram(), prog->prgName);
|
||||||
|
|
||||||
|
for (int i = 0; i < fxbSwap (prog->numParams); ++i)
|
||||||
|
setParameter (i, fxbSwapFloat (prog->params[i]));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
void ObxdAudioProcessor::scanAndUpdateBanks()
|
||||||
|
{
|
||||||
|
bankFiles.clearQuick();
|
||||||
|
|
||||||
|
DirectoryIterator it(getBanksFolder(), false, "*.fxb", File::findFiles);
|
||||||
|
while (it.next())
|
||||||
|
{
|
||||||
|
bankFiles.add(it.getFile());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Array<File>& ObxdAudioProcessor::getBankFiles() const
|
||||||
|
{
|
||||||
|
return bankFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
File ObxdAudioProcessor::getCurrentBankFile() const
|
||||||
|
{
|
||||||
|
return getBanksFolder().getChildFile(currentBank);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
File ObxdAudioProcessor::getDocumentFolder() const
|
||||||
|
{
|
||||||
|
File folder = File::getSpecialLocation(File::userDocumentsDirectory).getChildFile("discoDSP").getChildFile("OB-Xd");
|
||||||
|
if (folder.isSymbolicLink())
|
||||||
|
folder = folder.getLinkedTarget();
|
||||||
|
return folder;
|
||||||
|
}
|
||||||
|
|
||||||
|
File ObxdAudioProcessor::getSkinFolder() const
|
||||||
|
{
|
||||||
|
return getDocumentFolder().getChildFile("Skins");
|
||||||
|
}
|
||||||
|
|
||||||
|
File ObxdAudioProcessor::getBanksFolder() const
|
||||||
|
{
|
||||||
|
return getDocumentFolder().getChildFile("Banks");
|
||||||
|
}
|
||||||
|
|
||||||
|
File ObxdAudioProcessor::getCurrentSkinFolder() const
|
||||||
|
{
|
||||||
|
return getSkinFolder().getChildFile(currentSkin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ObxdAudioProcessor::setCurrentSkinFolder(const String& folderName)
|
||||||
|
{
|
||||||
|
currentSkin = folderName;
|
||||||
|
|
||||||
|
config->setValue("skin", folderName);
|
||||||
|
config->setNeedsToBeSaved(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// This creates new instances of the plugin..
|
||||||
|
AudioProcessor* JUCE_CALLTYPE createPluginFilter()
|
||||||
|
{
|
||||||
|
return new ObxdAudioProcessor();
|
||||||
|
}
|
222
Source/PluginProcessor.h
Executable file
222
Source/PluginProcessor.h
Executable file
|
@ -0,0 +1,222 @@
|
||||||
|
/*
|
||||||
|
==============================================================================
|
||||||
|
This file is part of Obxd synthesizer.
|
||||||
|
|
||||||
|
Copyright © 2013-2014 Filatov Vadim
|
||||||
|
|
||||||
|
Contact author via email :
|
||||||
|
justdat_@_e1.ru
|
||||||
|
|
||||||
|
This file may be licensed under the terms of of the
|
||||||
|
GNU General Public License Version 2 (the ``GPL'').
|
||||||
|
|
||||||
|
Software distributed under the License is distributed
|
||||||
|
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
|
||||||
|
express or implied. See the GPL for the specific language
|
||||||
|
governing rights and limitations.
|
||||||
|
|
||||||
|
You should have received a copy of the GPL along with this
|
||||||
|
program. If not, go to http://www.gnu.org/licenses/gpl.html
|
||||||
|
or 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 "../JuceLibraryCode/JuceHeader.h"
|
||||||
|
#include "Engine/SynthEngine.h"
|
||||||
|
//#include <stack>
|
||||||
|
#include "Engine/midiMap.h"
|
||||||
|
#include "Engine/ObxdBank.h"
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
const int fxbVersionNum = 1;
|
||||||
|
|
||||||
|
struct fxProgram
|
||||||
|
{
|
||||||
|
int32 chunkMagic; // 'CcnK'
|
||||||
|
int32 byteSize; // of this chunk, excl. magic + byteSize
|
||||||
|
int32 fxMagic; // 'FxCk'
|
||||||
|
int32 version;
|
||||||
|
int32 fxID; // fx unique id
|
||||||
|
int32 fxVersion;
|
||||||
|
int32 numParams;
|
||||||
|
char prgName[28];
|
||||||
|
float params[1]; // variable no. of parameters
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fxSet
|
||||||
|
{
|
||||||
|
int32 chunkMagic; // 'CcnK'
|
||||||
|
int32 byteSize; // of this chunk, excl. magic + byteSize
|
||||||
|
int32 fxMagic; // 'FxBk'
|
||||||
|
int32 version;
|
||||||
|
int32 fxID; // fx unique id
|
||||||
|
int32 fxVersion;
|
||||||
|
int32 numPrograms;
|
||||||
|
char future[128];
|
||||||
|
fxProgram programs[1]; // variable no. of programs
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fxChunkSet
|
||||||
|
{
|
||||||
|
int32 chunkMagic; // 'CcnK'
|
||||||
|
int32 byteSize; // of this chunk, excl. magic + byteSize
|
||||||
|
int32 fxMagic; // 'FxCh', 'FPCh', or 'FBCh'
|
||||||
|
int32 version;
|
||||||
|
int32 fxID; // fx unique id
|
||||||
|
int32 fxVersion;
|
||||||
|
int32 numPrograms;
|
||||||
|
char future[128];
|
||||||
|
int32 chunkSize;
|
||||||
|
char chunk[8]; // variable
|
||||||
|
};
|
||||||
|
|
||||||
|
struct fxProgramSet
|
||||||
|
{
|
||||||
|
int32 chunkMagic; // 'CcnK'
|
||||||
|
int32 byteSize; // of this chunk, excl. magic + byteSize
|
||||||
|
int32 fxMagic; // 'FxCh', 'FPCh', or 'FBCh'
|
||||||
|
int32 version;
|
||||||
|
int32 fxID; // fx unique id
|
||||||
|
int32 fxVersion;
|
||||||
|
int32 numPrograms;
|
||||||
|
char name[28];
|
||||||
|
int32 chunkSize;
|
||||||
|
char chunk[8]; // variable
|
||||||
|
};
|
||||||
|
|
||||||
|
// Compares a magic value in either endianness.
|
||||||
|
static inline bool compareMagic (int32 magic, const char* name) noexcept
|
||||||
|
{
|
||||||
|
return magic == (int32) ByteOrder::littleEndianInt (name)
|
||||||
|
|| magic == (int32) ByteOrder::bigEndianInt (name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int32 fxbName (const char* name) noexcept { return (int32) ByteOrder::littleEndianInt (name); }
|
||||||
|
static inline int32 fxbSwap (const int32 x) noexcept { return (int32) ByteOrder::swapIfLittleEndian ((uint32) x); }
|
||||||
|
|
||||||
|
static inline float fxbSwapFloat (const float x) noexcept
|
||||||
|
{
|
||||||
|
#ifdef JUCE_LITTLE_ENDIAN
|
||||||
|
union { uint32 asInt; float asFloat; } n;
|
||||||
|
n.asFloat = x;
|
||||||
|
n.asInt = ByteOrder::swap (n.asInt);
|
||||||
|
return n.asFloat;
|
||||||
|
#else
|
||||||
|
return x;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
class ObxdAudioProcessor :
|
||||||
|
public AudioProcessor,
|
||||||
|
// public AudioProcessorListener,
|
||||||
|
public ChangeBroadcaster
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//==============================================================================
|
||||||
|
ObxdAudioProcessor();
|
||||||
|
~ObxdAudioProcessor();
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
void prepareToPlay (double sampleRate, int samplesPerBlock);
|
||||||
|
void releaseResources();
|
||||||
|
|
||||||
|
void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiMessages);
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
AudioProcessorEditor* createEditor();
|
||||||
|
bool hasEditor() const;
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
void processMidiPerSample(MidiBuffer::Iterator* iter,const int samplePos);
|
||||||
|
bool getNextEvent(MidiBuffer::Iterator* iter,const int samplePos);
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
void initAllParams();
|
||||||
|
|
||||||
|
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;
|
||||||
|
const String getName() const;
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
int getNumPrograms();
|
||||||
|
int getCurrentProgram();
|
||||||
|
void setCurrentProgram (int index);
|
||||||
|
const String getProgramName (int index);
|
||||||
|
void changeProgramName (int index, const String& newName);
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
void getStateInformation (MemoryBlock& destData);
|
||||||
|
void setStateInformation (const void* data, int sizeInBytes);
|
||||||
|
void setCurrentProgramStateInformation(const void* data,int sizeInBytes);
|
||||||
|
void getCurrentProgramStateInformation(MemoryBlock& destData);
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
void scanAndUpdateBanks();
|
||||||
|
const Array<File>& getBankFiles() const;
|
||||||
|
bool loadFromFXBFile(const File& fxbFile);
|
||||||
|
bool restoreProgramSettings(const fxProgram* const prog);
|
||||||
|
File getCurrentBankFile() const;
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
const ObxdBank& getPrograms() const { return programs; }
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
File getDocumentFolder() const;
|
||||||
|
File getSkinFolder() const;
|
||||||
|
File getBanksFolder() const;
|
||||||
|
|
||||||
|
File getCurrentSkinFolder() const;
|
||||||
|
void setCurrentSkinFolder(const String& folderName);
|
||||||
|
|
||||||
|
private:
|
||||||
|
//==============================================================================
|
||||||
|
bool isHostAutomatedChange;
|
||||||
|
|
||||||
|
int lastMovedController;
|
||||||
|
int lastUsedParameter;
|
||||||
|
|
||||||
|
MidiMessage* nextMidi;
|
||||||
|
MidiMessage* midiMsg;
|
||||||
|
MidiMap bindings;
|
||||||
|
bool midiControlledParamSet;
|
||||||
|
|
||||||
|
bool hasMidiMessage;
|
||||||
|
int midiEventPos;
|
||||||
|
|
||||||
|
SynthEngine synth;
|
||||||
|
ObxdBank programs;
|
||||||
|
|
||||||
|
String currentSkin;
|
||||||
|
String currentBank;
|
||||||
|
Array<File> bankFiles;
|
||||||
|
|
||||||
|
ScopedPointer<PropertiesFile> config;
|
||||||
|
InterProcessLock configLock;
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ObxdAudioProcessor)
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // PLUGINPROCESSOR_H_INCLUDED
|
674
license.txt
Executable file
674
license.txt
Executable file
|
@ -0,0 +1,674 @@
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
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, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
Loading…
Reference in a new issue