Output Gain

pull/1/head
asb2m10 11 years ago
parent bff764d5d4
commit 3104d39f9f
  1. BIN
      Builds/MacOSX/Dexed.xcodeproj/project.xcworkspace/xcuserdata/asb2m10.xcuserdatad/UserInterfaceState.xcuserstate
  2. 1
      README.md
  3. 12
      Source/DXComponents.cpp
  4. 4
      Source/DXComponents.h
  5. 70
      Source/GlobalEditor.cpp
  6. 3
      Source/GlobalEditor.h
  7. 2
      Source/PluginData.cpp
  8. 1
      Source/PluginEditor.cpp
  9. 115
      Source/PluginFx.cpp
  10. 3
      Source/PluginFx.h
  11. 3
      Source/PluginParam.cpp
  12. 15
      Source/PluginProcessor.cpp
  13. 3
      Source/PluginProcessor.h

@ -28,6 +28,7 @@ Changelog
* Modulation wheel support
* Now using the [Obxd](https://obxd.wordpress.com) 4-pole lowpass filter implementation
* Pitchbend range / step
* Output VU status
Binary downloads
----------------

@ -413,6 +413,10 @@ void PitchEnvDisplay::paint(Graphics &g) {
}
}
VuMeter::VuMeter() {
totalBlocks = 16;
}
void VuMeter::paint(Graphics &g) {
// taken from the drawLevelMeter ;
float width = getWidth();
@ -420,22 +424,16 @@ void VuMeter::paint(Graphics &g) {
g.setColour (Colours::black);
g.fillRoundedRectangle (0.0f, 0.0f, (float) width, (float) height, 0);
/*g.setColour (Colours::black.withAlpha (0.2f));
g.drawRoundedRectangle (1.0f, 1.0f, width - 2.0f, height - 2.0f, 3.0f, 1.0f);*/
const int totalBlocks = 16;
const int numBlocks = roundToInt (totalBlocks * v);
const float h = (height - 6.0f) / (float) totalBlocks;
for (int i = 0; i < totalBlocks; ++i) {
g.setColour (Colours::red);
if (i >= numBlocks)
g.setColour (Colours::red.withAlpha (0.2f));
else
g.setColour (Colours::red);
//g.fillRoundedRectangle (3.0f + i * w + w * 0.1f, 3.0f, w * 0.8f, height - 6.0f, w * 0.4f);
g.fillRoundedRectangle (3.0f, (height-3.0f) - (3.0f + i * h + h * 0.1f) , width - 6.0f, h * 0.8f, 0);
g.fillRoundedRectangle (3.0f, (height-4.0f) - (3.0f + i * h + h * 0.1f) , width - 6.0f, h * 0.8f, 0);
}
}

@ -50,8 +50,10 @@ public:
class VuMeter: public Component {
void paint(Graphics &g);
public :
public :
VuMeter();
float v;
int totalBlocks;
};
class LcdDisplay : public Component {

@ -165,6 +165,15 @@ GlobalEditor::GlobalEditor ()
addAndMakeVisible (lcdDisplay = new LcdDisplay());
lcdDisplay->setName ("lcdDisplay");
addAndMakeVisible (output = new Slider ("cutoff"));
output->setRange (0, 1, 0);
output->setSliderStyle (Slider::Rotary);
output->setTextBoxStyle (Slider::NoTextBox, false, 80, 20);
output->addListener (this);
addAndMakeVisible (vuOutput = new VuMeter());
vuOutput->setName ("vuOutput");
//[UserPreSize]
//[/UserPreSize]
@ -174,6 +183,7 @@ GlobalEditor::GlobalEditor ()
//[Constructor] You can add your own custom stuff here..
lcdDisplay->systemMsg << "*** DEXED FM synthesizer ***";
vuOutput->totalBlocks = 6;
//[/Constructor]
}
@ -207,6 +217,8 @@ GlobalEditor::~GlobalEditor()
feedback = nullptr;
algo = nullptr;
lcdDisplay = nullptr;
output = nullptr;
vuOutput = nullptr;
//[Destructor]. You can add your own custom destruction code here..
@ -219,6 +231,24 @@ void GlobalEditor::paint (Graphics& g)
//[UserPrePaint] Add your own custom painting code here..
//[/UserPrePaint]
g.setColour (Colours::black);
g.setFont (Font (10.00f, Font::plain));
g.drawText (TRANS("Volume"),
27, 73, 45, 15,
Justification::centred, true);
g.setColour (Colours::black);
g.setFont (Font (10.00f, Font::plain));
g.drawText (TRANS("Cutoff"),
75, 73, 45, 15,
Justification::centred, true);
g.setColour (Colours::black);
g.setFont (Font (10.00f, Font::plain));
g.drawText (TRANS("Resonance"),
123, 73, 45, 15,
Justification::centred, true);
//[UserPaint] Add your own custom painting code here..
//[/UserPaint]
@ -231,8 +261,8 @@ void GlobalEditor::resized()
lfoAmDepth->setBounds (672, 64, 24, 24);
lfoPitchDepth->setBounds (648, 64, 24, 24);
lfoDelay->setBounds (624, 64, 24, 24);
cutoff->setBounds (8, 40, 48, 48);
reso->setBounds (64, 40, 48, 48);
cutoff->setBounds (80, 40, 40, 40);
reso->setBounds (128, 40, 40, 40);
pitchRate2->setBounds (752, 64, 32, 24);
pitchRate3->setBounds (776, 64, 32, 24);
pitchRate4->setBounds (800, 64, 32, 24);
@ -249,7 +279,9 @@ void GlobalEditor::resized()
algoDisplay->setBounds (442, 8, 152, 74);
feedback->setBounds (568, 32, 24, 24);
algo->setBounds (568, 8, 24, 24);
lcdDisplay->setBounds (8, 0, 256, 32);
lcdDisplay->setBounds (8, 0, 232, 32);
output->setBounds (32, 40, 40, 40);
vuOutput->setBounds (8, 44, 16, 38);
//[UserResized] Add your own custom resize handling here..
//[/UserResized]
}
@ -372,6 +404,11 @@ void GlobalEditor::sliderValueChanged (Slider* sliderThatWasMoved)
//[UserSliderCode_algo] -- add your slider handling code here..
//[/UserSliderCode_algo]
}
else if (sliderThatWasMoved == output)
{
//[UserSliderCode_output] -- add your slider handling code here..
//[/UserSliderCode_output]
}
//[UsersliderValueChanged_Post]
//[/UsersliderValueChanged_Post]
@ -403,6 +440,7 @@ void GlobalEditor::bind(DexedAudioProcessor *parent) {
parent->pitchEgRate[3]->bind(pitchRate4);
parent->fxCutoff->bind(cutoff);
parent->fxReso->bind(reso);
parent->output->bind(output);
algoDisplay->algo = &(parent->data[134]);
pitchEnvDisplay->pvalues = &(parent->data[126]);
processor = parent;
@ -429,6 +467,11 @@ void GlobalEditor::updatePitchPos(int pos) {
pitchEnvDisplay->vPos = pos;
pitchEnvDisplay->repaint();
}
void GlobalEditor::updateVu(float f) {
vuOutput->v = f;
vuOutput->repaint();
}
//[/MiscUserCode]
@ -445,7 +488,14 @@ BEGIN_JUCER_METADATA
parentClasses="public Component" constructorParams="" variableInitialisers=""
snapPixels="8" snapActive="1" snapShown="1" overlayOpacity="0.330"
fixedSize="1" initialWidth="855" initialHeight="90">
<BACKGROUND backgroundColour="ffffff"/>
<BACKGROUND backgroundColour="ffffff">
<TEXT pos="27 73 45 15" fill="solid: ff000000" hasStroke="0" text="Volume"
fontname="Default font" fontsize="10" bold="0" italic="0" justification="36"/>
<TEXT pos="75 73 45 15" fill="solid: ff000000" hasStroke="0" text="Cutoff"
fontname="Default font" fontsize="10" bold="0" italic="0" justification="36"/>
<TEXT pos="123 73 45 15" fill="solid: ff000000" hasStroke="0" text="Resonance"
fontname="Default font" fontsize="10" bold="0" italic="0" justification="36"/>
</BACKGROUND>
<COMBOBOX name="lfoType" id="31018596af3b34e9" memberName="lfoType" virtualName=""
explicitFocusOrder="0" pos="624 40 96 16" editable="0" layout="33"
items="TRIANGLE&#10;SAW DOWN&#10;SAW UP&#10;SQUARE&#10;SINE&#10;S&amp;HOLD"
@ -467,11 +517,11 @@ BEGIN_JUCER_METADATA
style="Rotary" textBoxPos="NoTextBox" textBoxEditable="1" textBoxWidth="80"
textBoxHeight="20" skewFactor="1"/>
<SLIDER name="cutoff" id="40531f16bb0bd225" memberName="cutoff" virtualName=""
explicitFocusOrder="0" pos="8 40 48 48" min="0" max="1" int="0"
explicitFocusOrder="0" pos="80 40 40 40" min="0" max="1" int="0"
style="Rotary" textBoxPos="NoTextBox" textBoxEditable="1" textBoxWidth="80"
textBoxHeight="20" skewFactor="1"/>
<SLIDER name="reso" id="c8c13464e81a8d83" memberName="reso" virtualName=""
explicitFocusOrder="0" pos="64 40 48 48" min="0" max="1" int="0"
explicitFocusOrder="0" pos="128 40 40 40" min="0" max="1" int="0"
style="Rotary" textBoxPos="NoTextBox" textBoxEditable="1" textBoxWidth="80"
textBoxHeight="20" skewFactor="1"/>
<SLIDER name="pitchRate2" id="73f386b3c91d3de4" memberName="pitchRate2"
@ -535,8 +585,14 @@ BEGIN_JUCER_METADATA
style="Rotary" textBoxPos="NoTextBox" textBoxEditable="0" textBoxWidth="80"
textBoxHeight="20" skewFactor="1"/>
<GENERICCOMPONENT name="lcdDisplay" id="30c7bb8f114cbbe3" memberName="lcdDisplay"
virtualName="" explicitFocusOrder="0" pos="8 0 256 32" class="LcdDisplay"
virtualName="" explicitFocusOrder="0" pos="8 0 232 32" class="LcdDisplay"
params=""/>
<SLIDER name="cutoff" id="7697fdd54fd1593e" memberName="output" virtualName=""
explicitFocusOrder="0" pos="32 40 40 40" min="0" max="1" int="0"
style="Rotary" textBoxPos="NoTextBox" textBoxEditable="1" textBoxWidth="80"
textBoxHeight="20" skewFactor="1"/>
<GENERICCOMPONENT name="vuOutput" id="dac75af912267f51" memberName="vuOutput" virtualName=""
explicitFocusOrder="0" pos="8 44 16 38" class="VuMeter" params=""/>
</JUCER_COMPONENT>
END_JUCER_METADATA

@ -51,6 +51,7 @@ public:
void setSystemMessage(String msg);
void setParamMessage(String msg);
void updatePitchPos(int pos);
void updateVu(float v);
void updateDisplay();
//[/UserMethods]
@ -92,6 +93,8 @@ private:
ScopedPointer<Slider> feedback;
ScopedPointer<Slider> algo;
ScopedPointer<LcdDisplay> lcdDisplay;
ScopedPointer<Slider> output;
ScopedPointer<VuMeter> vuOutput;
//==============================================================================

@ -230,6 +230,7 @@ void DexedAudioProcessor::getStateInformation(MemoryBlock& destData) {
dexedState.setAttribute("cutoff", fx.uiCutoff);
dexedState.setAttribute("reso", fx.uiReso);
dexedState.setAttribute("gain", fx.uiGain);
dexedState.setAttribute("currentProgram", currentProgram);
char sysex_blob[4104];
@ -257,6 +258,7 @@ void DexedAudioProcessor::setStateInformation(const void* source, int sizeInByte
fx.uiCutoff = root->getDoubleAttribute("cutoff");
fx.uiReso = root->getDoubleAttribute("reso");
fx.uiGain = root->getDoubleAttribute("gain");
currentProgram = root->getIntAttribute("currentProgram");
XmlElement *dexedBlob = root->getChildByName("dexedBlob");

@ -278,6 +278,7 @@ void DexedAudioProcessorEditor::timerCallback() {
operators[i].updateEnvPos(processor->voiceStatus.ampStep[5 - i]);
}
global.updatePitchPos(processor->voiceStatus.pitchStep);
global.updateVu(processor->vuSignal);
}
void DexedAudioProcessorEditor::updateUI() {

@ -75,9 +75,11 @@ void PluginFx::init(int sr) {
uiCutoff = 1;
uiReso = 0;
uiGain = 0.8;
pCutoff = -1;
pReso = -1;
pGain = -1;
}
inline float PluginFx::NR24(float sample,float g,float lpc) {
@ -95,66 +97,73 @@ inline float PluginFx::NR(float sample, float g) {
void PluginFx::process(float *work, int sampleSize) {
// don't apply the LPF if the cutoff is to maximum
if ( uiCutoff == 1 )
return;
if ( uiCutoff != 1 ) {
if ( uiCutoff != pCutoff || uiReso != pReso ) {
rReso = (0.991-logsc(1-uiReso,0,0.991));
R24 = 3.5 * rReso;
if ( uiCutoff != pCutoff || uiReso != pReso ) {
rReso = (0.991-logsc(1-uiReso,0,0.991,40));
R24 = 3.5 * rReso;
float cutoffNorm = logsc(uiCutoff,60,19000);
rCutoff = (float)tan(cutoffNorm * sampleRateInv * juce::float_Pi);
float cutoffNorm = logsc(uiCutoff,60,19000,30);
rCutoff = (float)tan(cutoffNorm * sampleRateInv * juce::float_Pi);
pCutoff = uiCutoff;
pReso = uiReso;
pCutoff = uiCutoff;
pReso = uiReso;
R = 1 - rReso;
}
R = 1 - rReso;
}
// THIS IS MY FAVORITE 4POLE OBXd filter
// maybe smooth this value
float g = rCutoff;
float lpc = g / (1 + g);
for(int i=0; i < sampleSize; i++ ) {
float s = work[i];
s = s - 0.45*tptlpupw(c,s,15,sampleRateInv);
s = tptpc(d,s,bright);
float y0 = NR24(s,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;
// THIS IS MY FAVORITE 4POLE OBXd filter
// maybe smooth this value
float g = rCutoff;
float lpc = g / (1 + g);
for(int i=0; i < sampleSize; i++ ) {
float s = work[i];
s = s - 0.45*tptlpupw(c,s,15,sampleRateInv);
s = tptpc(d,s,bright);
float y0 = NR24(s,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;
}
//half volume comp
work[i] = mc * (1 + R24 * 0.45);
}
}
//half volume comp
work[i] = mc * (1 + R24 * 0.45);
if ( uiGain != pGain ) {
rGain = linsc(uiGain, 0, 1.25);
pGain = uiGain;
}
for(int i=0; i < sampleSize; i++ )
work[i] *= rGain;
}
/*

@ -39,11 +39,13 @@ class PluginFx {
// preprocess values taken the UI
float rCutoff;
float rReso;
float rGain;
// thread values; if these are different from the UI,
// it needs to be recalculated.
float pReso;
float pCutoff;
float pGain;
// I am still keeping the 2pole w/multimode filter
inline float NR(float sample, float g);
@ -56,6 +58,7 @@ public:
// this is set directly by the ui / parameter
float uiCutoff;
float uiReso;
float uiGain;
void init(int sampleRate);
void process(float *work, int sampleSize);

@ -215,6 +215,9 @@ void DexedAudioProcessor::initCtrl() {
fxReso = new CtrlFloat("Resonance", &fx.uiReso);
ctrl.add(fxReso);
output = new CtrlFloat("Output", &fx.uiGain);
ctrl.add(output);
algo = new CtrlDX("ALGORITHM", 32, 134, 1);
ctrl.add(algo);

@ -47,6 +47,7 @@ DexedAudioProcessor::DexedAudioProcessor() {
currentNote = -1;
workBlock = NULL;
vuSignal = 0;
initCtrl();
setCurrentProgram(0);
sendSysexChange = true;
@ -175,14 +176,24 @@ void DexedAudioProcessor::processBlock(AudioSampleBuffer& buffer, MidiBuffer& mi
*/
processSamples(block, workBlock);
for(int i = 0; i < block; i++ ) {
for(int i = 0; i < block; i++ )
channelData[i+samplePos] = workBlock[i];
}
samplePos += block;
}
fx.process(channelData, numSamples);
for(int i=0; i<numSamples; i++) {
float s = std::abs(channelData[i]);
const double decayFactor = 0.99992;
if (s > vuSignal)
vuSignal = s;
else if (vuSignal > 0.001f)
vuSignal *= decayFactor;
else
vuSignal = 0;
}
// DX7 is a mono synth
for (int channel = 1; channel < getNumInputChannels(); ++channel) {

@ -114,6 +114,8 @@ public :
bool forceRefreshUI;
float vuSignal;
Array<Ctrl*> ctrl;
OperatorCtrl opCtrl[6];
@ -133,6 +135,7 @@ public :
ScopedPointer<CtrlFloat> fxCutoff;
ScopedPointer<CtrlFloat> fxReso;
ScopedPointer<CtrlFloat> output;
int importSysex(const char *imported);
void setDxValue(int offset, int v);

Loading…
Cancel
Save