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. 19
      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 * Modulation wheel support
* Now using the [Obxd](https://obxd.wordpress.com) 4-pole lowpass filter implementation * Now using the [Obxd](https://obxd.wordpress.com) 4-pole lowpass filter implementation
* Pitchbend range / step * Pitchbend range / step
* Output VU status
Binary downloads Binary downloads
---------------- ----------------

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

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

@ -165,6 +165,15 @@ GlobalEditor::GlobalEditor ()
addAndMakeVisible (lcdDisplay = new LcdDisplay()); addAndMakeVisible (lcdDisplay = new LcdDisplay());
lcdDisplay->setName ("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]
//[/UserPreSize] //[/UserPreSize]
@ -174,6 +183,7 @@ GlobalEditor::GlobalEditor ()
//[Constructor] You can add your own custom stuff here.. //[Constructor] You can add your own custom stuff here..
lcdDisplay->systemMsg << "*** DEXED FM synthesizer ***"; lcdDisplay->systemMsg << "*** DEXED FM synthesizer ***";
vuOutput->totalBlocks = 6;
//[/Constructor] //[/Constructor]
} }
@ -207,6 +217,8 @@ GlobalEditor::~GlobalEditor()
feedback = nullptr; feedback = nullptr;
algo = nullptr; algo = nullptr;
lcdDisplay = nullptr; lcdDisplay = nullptr;
output = nullptr;
vuOutput = nullptr;
//[Destructor]. You can add your own custom destruction code here.. //[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] Add your own custom painting code here..
//[/UserPrePaint] //[/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] Add your own custom painting code here..
//[/UserPaint] //[/UserPaint]
@ -231,8 +261,8 @@ void GlobalEditor::resized()
lfoAmDepth->setBounds (672, 64, 24, 24); lfoAmDepth->setBounds (672, 64, 24, 24);
lfoPitchDepth->setBounds (648, 64, 24, 24); lfoPitchDepth->setBounds (648, 64, 24, 24);
lfoDelay->setBounds (624, 64, 24, 24); lfoDelay->setBounds (624, 64, 24, 24);
cutoff->setBounds (8, 40, 48, 48); cutoff->setBounds (80, 40, 40, 40);
reso->setBounds (64, 40, 48, 48); reso->setBounds (128, 40, 40, 40);
pitchRate2->setBounds (752, 64, 32, 24); pitchRate2->setBounds (752, 64, 32, 24);
pitchRate3->setBounds (776, 64, 32, 24); pitchRate3->setBounds (776, 64, 32, 24);
pitchRate4->setBounds (800, 64, 32, 24); pitchRate4->setBounds (800, 64, 32, 24);
@ -249,7 +279,9 @@ void GlobalEditor::resized()
algoDisplay->setBounds (442, 8, 152, 74); algoDisplay->setBounds (442, 8, 152, 74);
feedback->setBounds (568, 32, 24, 24); feedback->setBounds (568, 32, 24, 24);
algo->setBounds (568, 8, 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] Add your own custom resize handling here..
//[/UserResized] //[/UserResized]
} }
@ -372,6 +404,11 @@ void GlobalEditor::sliderValueChanged (Slider* sliderThatWasMoved)
//[UserSliderCode_algo] -- add your slider handling code here.. //[UserSliderCode_algo] -- add your slider handling code here..
//[/UserSliderCode_algo] //[/UserSliderCode_algo]
} }
else if (sliderThatWasMoved == output)
{
//[UserSliderCode_output] -- add your slider handling code here..
//[/UserSliderCode_output]
}
//[UsersliderValueChanged_Post] //[UsersliderValueChanged_Post]
//[/UsersliderValueChanged_Post] //[/UsersliderValueChanged_Post]
@ -403,6 +440,7 @@ void GlobalEditor::bind(DexedAudioProcessor *parent) {
parent->pitchEgRate[3]->bind(pitchRate4); parent->pitchEgRate[3]->bind(pitchRate4);
parent->fxCutoff->bind(cutoff); parent->fxCutoff->bind(cutoff);
parent->fxReso->bind(reso); parent->fxReso->bind(reso);
parent->output->bind(output);
algoDisplay->algo = &(parent->data[134]); algoDisplay->algo = &(parent->data[134]);
pitchEnvDisplay->pvalues = &(parent->data[126]); pitchEnvDisplay->pvalues = &(parent->data[126]);
processor = parent; processor = parent;
@ -429,6 +467,11 @@ void GlobalEditor::updatePitchPos(int pos) {
pitchEnvDisplay->vPos = pos; pitchEnvDisplay->vPos = pos;
pitchEnvDisplay->repaint(); pitchEnvDisplay->repaint();
} }
void GlobalEditor::updateVu(float f) {
vuOutput->v = f;
vuOutput->repaint();
}
//[/MiscUserCode] //[/MiscUserCode]
@ -445,7 +488,14 @@ BEGIN_JUCER_METADATA
parentClasses="public Component" constructorParams="" variableInitialisers="" parentClasses="public Component" constructorParams="" variableInitialisers=""
snapPixels="8" snapActive="1" snapShown="1" overlayOpacity="0.330" snapPixels="8" snapActive="1" snapShown="1" overlayOpacity="0.330"
fixedSize="1" initialWidth="855" initialHeight="90"> 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="" <COMBOBOX name="lfoType" id="31018596af3b34e9" memberName="lfoType" virtualName=""
explicitFocusOrder="0" pos="624 40 96 16" editable="0" layout="33" 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" 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" style="Rotary" textBoxPos="NoTextBox" textBoxEditable="1" textBoxWidth="80"
textBoxHeight="20" skewFactor="1"/> textBoxHeight="20" skewFactor="1"/>
<SLIDER name="cutoff" id="40531f16bb0bd225" memberName="cutoff" virtualName="" <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" style="Rotary" textBoxPos="NoTextBox" textBoxEditable="1" textBoxWidth="80"
textBoxHeight="20" skewFactor="1"/> textBoxHeight="20" skewFactor="1"/>
<SLIDER name="reso" id="c8c13464e81a8d83" memberName="reso" virtualName="" <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" style="Rotary" textBoxPos="NoTextBox" textBoxEditable="1" textBoxWidth="80"
textBoxHeight="20" skewFactor="1"/> textBoxHeight="20" skewFactor="1"/>
<SLIDER name="pitchRate2" id="73f386b3c91d3de4" memberName="pitchRate2" <SLIDER name="pitchRate2" id="73f386b3c91d3de4" memberName="pitchRate2"
@ -535,8 +585,14 @@ BEGIN_JUCER_METADATA
style="Rotary" textBoxPos="NoTextBox" textBoxEditable="0" textBoxWidth="80" style="Rotary" textBoxPos="NoTextBox" textBoxEditable="0" textBoxWidth="80"
textBoxHeight="20" skewFactor="1"/> textBoxHeight="20" skewFactor="1"/>
<GENERICCOMPONENT name="lcdDisplay" id="30c7bb8f114cbbe3" memberName="lcdDisplay" <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=""/> 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> </JUCER_COMPONENT>
END_JUCER_METADATA END_JUCER_METADATA

@ -51,6 +51,7 @@ public:
void setSystemMessage(String msg); void setSystemMessage(String msg);
void setParamMessage(String msg); void setParamMessage(String msg);
void updatePitchPos(int pos); void updatePitchPos(int pos);
void updateVu(float v);
void updateDisplay(); void updateDisplay();
//[/UserMethods] //[/UserMethods]
@ -92,6 +93,8 @@ private:
ScopedPointer<Slider> feedback; ScopedPointer<Slider> feedback;
ScopedPointer<Slider> algo; ScopedPointer<Slider> algo;
ScopedPointer<LcdDisplay> lcdDisplay; 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("cutoff", fx.uiCutoff);
dexedState.setAttribute("reso", fx.uiReso); dexedState.setAttribute("reso", fx.uiReso);
dexedState.setAttribute("gain", fx.uiGain);
dexedState.setAttribute("currentProgram", currentProgram); dexedState.setAttribute("currentProgram", currentProgram);
char sysex_blob[4104]; char sysex_blob[4104];
@ -257,6 +258,7 @@ void DexedAudioProcessor::setStateInformation(const void* source, int sizeInByte
fx.uiCutoff = root->getDoubleAttribute("cutoff"); fx.uiCutoff = root->getDoubleAttribute("cutoff");
fx.uiReso = root->getDoubleAttribute("reso"); fx.uiReso = root->getDoubleAttribute("reso");
fx.uiGain = root->getDoubleAttribute("gain");
currentProgram = root->getIntAttribute("currentProgram"); currentProgram = root->getIntAttribute("currentProgram");
XmlElement *dexedBlob = root->getChildByName("dexedBlob"); XmlElement *dexedBlob = root->getChildByName("dexedBlob");

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

@ -75,9 +75,11 @@ void PluginFx::init(int sr) {
uiCutoff = 1; uiCutoff = 1;
uiReso = 0; uiReso = 0;
uiGain = 0.8;
pCutoff = -1; pCutoff = -1;
pReso = -1; pReso = -1;
pGain = -1;
} }
inline float PluginFx::NR24(float sample,float g,float lpc) { inline float PluginFx::NR24(float sample,float g,float lpc) {
@ -95,14 +97,12 @@ inline float PluginFx::NR(float sample, float g) {
void PluginFx::process(float *work, int sampleSize) { void PluginFx::process(float *work, int sampleSize) {
// don't apply the LPF if the cutoff is to maximum // don't apply the LPF if the cutoff is to maximum
if ( uiCutoff == 1 ) if ( uiCutoff != 1 ) {
return;
if ( uiCutoff != pCutoff || uiReso != pReso ) { if ( uiCutoff != pCutoff || uiReso != pReso ) {
rReso = (0.991-logsc(1-uiReso,0,0.991,40)); rReso = (0.991-logsc(1-uiReso,0,0.991));
R24 = 3.5 * rReso; R24 = 3.5 * rReso;
float cutoffNorm = logsc(uiCutoff,60,19000,30); float cutoffNorm = logsc(uiCutoff,60,19000);
rCutoff = (float)tan(cutoffNorm * sampleRateInv * juce::float_Pi); rCutoff = (float)tan(cutoffNorm * sampleRateInv * juce::float_Pi);
pCutoff = uiCutoff; pCutoff = uiCutoff;
@ -155,6 +155,15 @@ void PluginFx::process(float *work, int sampleSize) {
//half volume comp //half volume comp
work[i] = mc * (1 + R24 * 0.45); 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 // preprocess values taken the UI
float rCutoff; float rCutoff;
float rReso; float rReso;
float rGain;
// thread values; if these are different from the UI, // thread values; if these are different from the UI,
// it needs to be recalculated. // it needs to be recalculated.
float pReso; float pReso;
float pCutoff; float pCutoff;
float pGain;
// I am still keeping the 2pole w/multimode filter // I am still keeping the 2pole w/multimode filter
inline float NR(float sample, float g); inline float NR(float sample, float g);
@ -56,6 +58,7 @@ public:
// this is set directly by the ui / parameter // this is set directly by the ui / parameter
float uiCutoff; float uiCutoff;
float uiReso; float uiReso;
float uiGain;
void init(int sampleRate); void init(int sampleRate);
void process(float *work, int sampleSize); void process(float *work, int sampleSize);

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

@ -47,6 +47,7 @@ DexedAudioProcessor::DexedAudioProcessor() {
currentNote = -1; currentNote = -1;
workBlock = NULL; workBlock = NULL;
vuSignal = 0;
initCtrl(); initCtrl();
setCurrentProgram(0); setCurrentProgram(0);
sendSysexChange = true; sendSysexChange = true;
@ -175,14 +176,24 @@ void DexedAudioProcessor::processBlock(AudioSampleBuffer& buffer, MidiBuffer& mi
*/ */
processSamples(block, workBlock); processSamples(block, workBlock);
for(int i = 0; i < block; i++ ) { for(int i = 0; i < block; i++ )
channelData[i+samplePos] = workBlock[i]; channelData[i+samplePos] = workBlock[i];
}
samplePos += block; samplePos += block;
} }
fx.process(channelData, numSamples); 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 // DX7 is a mono synth
for (int channel = 1; channel < getNumInputChannels(); ++channel) { for (int channel = 1; channel < getNumInputChannels(); ++channel) {

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

Loading…
Cancel
Save