diff --git a/NeuralAmpModeler/NeuralAmpModeler.cpp b/NeuralAmpModeler/NeuralAmpModeler.cpp index 738717dc..b2922ad9 100644 --- a/NeuralAmpModeler/NeuralAmpModeler.cpp +++ b/NeuralAmpModeler/NeuralAmpModeler.cpp @@ -81,6 +81,9 @@ NeuralAmpModeler::NeuralAmpModeler(const InstanceInfo& info) GetParam(kEQActive)->InitBool("ToneStack", true); GetParam(kOutNorm)->InitBool("OutNorm", true); GetParam(kIRToggle)->InitBool("IRToggle", true); + GetParam(kCalibrateInput)->InitBool("CalibrateInput", false); + // TODO Double, label "dBu" + GetParam(kInputCalibrationLevel)->InitDouble("InputCalibrationLevel", 12.5, -30.0, 30.0, 0.1, "dBu"); mNoiseGateTrigger.AddListener(&mNoiseGateGain); @@ -116,6 +119,7 @@ NeuralAmpModeler::NeuralAmpModeler(const InstanceInfo& info) const auto backgroundBitmap = pGraphics->LoadBitmap(BACKGROUND_FN); const auto fileBackgroundBitmap = pGraphics->LoadBitmap(FILEBACKGROUND_FN); + const auto inputLevelBackgroundBitmap = pGraphics->LoadBitmap(INPUTLEVELBACKGROUND_FN); const auto linesBitmap = pGraphics->LoadBitmap(LINES_FN); const auto knobBackgroundBitmap = pGraphics->LoadBitmap(KNOBBACKGROUND_FN); const auto switchHandleBitmap = pGraphics->LoadBitmap(SLIDESWITCHHANDLE_FN); @@ -130,9 +134,8 @@ NeuralAmpModeler::NeuralAmpModeler(const InstanceInfo& info) // Areas for knobs const auto knobsPad = 20.0f; const auto knobsExtraSpaceBelowTitle = 25.0f; - const auto knobHeight = 120.f; const auto singleKnobPad = -2.0f; - const auto knobsArea = contentArea.GetFromTop(knobHeight) + const auto knobsArea = contentArea.GetFromTop(NAM_KNOB_HEIGHT) .GetReducedFromLeft(knobsPad) .GetReducedFromRight(knobsPad) .GetVShifted(titleHeight + knobsExtraSpaceBelowTitle); @@ -250,7 +253,10 @@ NeuralAmpModeler::NeuralAmpModeler(const InstanceInfo& info) }, gearSVG)); - pGraphics->AttachControl(new NAMSettingsPageControl(b, backgroundBitmap, crossSVG, style), kCtrlTagSettingsBox) + pGraphics + ->AttachControl(new NAMSettingsPageControl( + b, backgroundBitmap, inputLevelBackgroundBitmap, switchHandleBitmap, crossSVG, style), + kCtrlTagSettingsBox) ->Hide(true); pGraphics->ForAllControlsFunc([](IControl* pControl) { @@ -258,7 +264,8 @@ NeuralAmpModeler::NeuralAmpModeler(const InstanceInfo& info) pControl->SetMouseOverWhenDisabled(true); }); - pGraphics->GetControlWithTag(kCtrlTagOutNorm)->SetMouseEventsWhenDisabled(false); + // pGraphics->GetControlWithTag(kCtrlTagOutNorm)->SetMouseEventsWhenDisabled(false); + // pGraphics->GetControlWithTag(kCtrlTagCalibrateInput)->SetMouseEventsWhenDisabled(false); }; } @@ -381,9 +388,19 @@ void NeuralAmpModeler::OnIdle() { pGraphics->GetControlWithTag(kCtrlTagOutNorm)->SetDisabled(!mModel->HasLoudness()); ModelInfo modelInfo; - modelInfo.sampleRate = mModel->GetEncapsulatedSampleRate(); - modelInfo.knownSampleRate = true; + modelInfo.sampleRate.known = true; + modelInfo.sampleRate.value = mModel->GetEncapsulatedSampleRate(); + modelInfo.inputCalibrationLevel.known = mModel->HasInputLevel(); + modelInfo.inputCalibrationLevel.value = mModel->HasInputLevel() ? mModel->GetInputLevel() : 0.0; + modelInfo.outputCalibrationLevel.known = mModel->HasOutputLevel(); + modelInfo.outputCalibrationLevel.value = mModel->HasOutputLevel() ? mModel->GetOutputLevel() : 0.0; + static_cast(pGraphics->GetControlWithTag(kCtrlTagSettingsBox))->SetModelInfo(modelInfo); + + const bool disableInputCalibrationControls = !mModel->HasInputLevel(); + pGraphics->GetControlWithTag(kCtrlTagCalibrateInput)->SetDisabled(disableInputCalibrationControls); + pGraphics->GetControlWithTag(kCtrlTagInputCalibrationLevel)->SetDisabled(disableInputCalibrationControls); + mNewModelLoadedInDSP = false; } } @@ -461,13 +478,25 @@ void NeuralAmpModeler::OnUIOpen() } if (mModel != nullptr) - GetUI()->GetControlWithTag(kCtrlTagOutNorm)->SetDisabled(!mModel->HasLoudness()); + { + auto* pGraphics = GetUI(); + assert(pGraphics != nullptr); + pGraphics->GetControlWithTag(kCtrlTagOutNorm)->SetDisabled(!mModel->HasLoudness()); + const bool disableInputCalibrationControls = !mModel->HasInputLevel(); + pGraphics->GetControlWithTag(kCtrlTagCalibrateInput)->SetDisabled(disableInputCalibrationControls); + pGraphics->GetControlWithTag(kCtrlTagInputCalibrationLevel)->SetDisabled(disableInputCalibrationControls); + } } void NeuralAmpModeler::OnParamChange(int paramIdx) { switch (paramIdx) { + // Changes to the input gain + case kCalibrateInput: + case kInputCalibrationLevel: + case kInputLevel: _SetInputGain(); break; + // Tone stack: case kToneBass: mToneStack->SetParam("bass", GetParam(paramIdx)->Value()); break; case kToneMid: mToneStack->SetParam("middle", GetParam(paramIdx)->Value()); break; case kToneTreble: mToneStack->SetParam("treble", GetParam(paramIdx)->Value()); break; @@ -487,7 +516,7 @@ void NeuralAmpModeler::OnParamChangeUI(int paramIdx, EParamSource source) case kEQActive: pGraphics->ForControlInGroup("EQ_KNOBS", [active](IControl* pControl) { pControl->SetDisabled(!active); }); break; - case kIRToggle: pGraphics->GetControlWithTag(kCtrlTagIRFileBrowser)->SetDisabled(!active); + case kIRToggle: pGraphics->GetControlWithTag(kCtrlTagIRFileBrowser)->SetDisabled(!active); break; default: break; } } @@ -551,6 +580,7 @@ void NeuralAmpModeler::_ApplyDSPStaging() mShouldRemoveModel = false; mModelCleared = true; _UpdateLatency(); + _SetInputGain(); } if (mShouldRemoveIR) { @@ -566,6 +596,7 @@ void NeuralAmpModeler::_ApplyDSPStaging() mStagedModel = nullptr; mNewModelLoadedInDSP = true; _UpdateLatency(); + _SetInputGain(); } if (mStagedIR != nullptr) { @@ -651,6 +682,17 @@ void NeuralAmpModeler::_ResetModelAndIR(const double sampleRate, const int maxBl } } +void NeuralAmpModeler::_SetInputGain() +{ + iplug::sample inputGainDB = GetParam(kInputLevel)->Value(); + // Input calibration + if ((mModel != nullptr) && (mModel->HasInputLevel()) && GetParam(kCalibrateInput)->Bool()) + { + inputGainDB += GetParam(kInputCalibrationLevel)->Value() - mModel->GetInputLevel(); + } + mInputGain = DBToAmp(inputGainDB); +} + std::string NeuralAmpModeler::_StageModel(const WDL_String& modelPath) { WDL_String previousNAMPath = mNAMPath; @@ -787,13 +829,12 @@ void NeuralAmpModeler::_ProcessInput(iplug::sample** inputs, const size_t nFrame } // On the standalone, we can probably assume that the user has plugged into only one input and they expect it to be - // carried straight through. Don't apply any division over nCahnsIn because we're just "catching anything out there." + // carried straight through. Don't apply any division over nChansIn because we're just "catching anything out there." // However, in a DAW, it's probably something providing stereo, and we want to take the average in order to avoid - // doubling the loudness. -#ifdef APP_API - const double gain = pow(10.0, GetParam(kInputLevel)->Value() / 20.0); -#else - const double gain = pow(10.0, GetParam(kInputLevel)->Value() / 20.0) / (float)nChansIn; + // doubling the loudness. (This would change w/ double mono processing) + double gain = mInputGain; +#ifndef APP_API + gain /= (float)nChansIn; #endif // Assume _PrepareBuffers() was already called for (size_t c = 0; c < nChansIn; c++) diff --git a/NeuralAmpModeler/NeuralAmpModeler.h b/NeuralAmpModeler/NeuralAmpModeler.h index a391e275..3179f026 100644 --- a/NeuralAmpModeler/NeuralAmpModeler.h +++ b/NeuralAmpModeler/NeuralAmpModeler.h @@ -41,6 +41,9 @@ enum EParams kEQActive, kOutNorm, kIRToggle, + // Input calibration + kCalibrateInput, + kInputCalibrationLevel, kNumParams }; @@ -54,6 +57,8 @@ enum ECtrlTags kCtrlTagOutputMeter, kCtrlTagSettingsBox, kCtrlTagOutNorm, + kCtrlTagCalibrateInput, + kCtrlTagInputCalibrationLevel, kNumCtrlTags }; @@ -102,7 +107,17 @@ class ResamplingNAM : public nam::DSP // Get the other information from the encapsulated NAM so that we can tell the outside world about what we're // holding. if (mEncapsulated->HasLoudness()) + { SetLoudness(mEncapsulated->GetLoudness()); + } + if (mEncapsulated->HasInputLevel()) + { + SetInputLevel(mEncapsulated->GetInputLevel()); + } + if (mEncapsulated->HasOutputLevel()) + { + SetOutputLevel(mEncapsulated->GetOutputLevel()); + } // NOTE: prewarm samples doesn't mean anything--we can prewarm the encapsulated model as it likes and be good to // go. @@ -228,6 +243,8 @@ class NeuralAmpModeler final : public iplug::Plugin // Resetting for models and IRs, called by OnReset void _ResetModelAndIR(const double sampleRate, const int maxBlockSize); + void _SetInputGain(); + // Unserialize current-version plug-in data: int _UnserializeStateCurrent(const iplug::IByteChunk& chunk, int startPos); // Unserialize v0.7.9 legacy data: @@ -253,6 +270,9 @@ class NeuralAmpModeler final : public iplug::Plugin iplug::sample** mInputPointers = nullptr; iplug::sample** mOutputPointers = nullptr; + // Input and (soon) output gain + iplug::sample mInputGain = 1.0; + // Noise gates dsp::noise_gate::Trigger mNoiseGateTrigger; dsp::noise_gate::Gain mNoiseGateGain; diff --git a/NeuralAmpModeler/NeuralAmpModelerControls.h b/NeuralAmpModeler/NeuralAmpModelerControls.h index 5449fce3..77724268 100644 --- a/NeuralAmpModeler/NeuralAmpModelerControls.h +++ b/NeuralAmpModeler/NeuralAmpModelerControls.h @@ -6,6 +6,8 @@ #include "IControls.h" #define PLUG() static_cast(GetDelegate()) +#define NAM_KNOB_HEIGHT 120.0f +#define NAM_SWTICH_HEIGHT 50.0f using namespace iplug; using namespace igraphics; @@ -453,12 +455,12 @@ class IContainerBaseWithNamedChildren : public IContainerBase ~IContainerBaseWithNamedChildren() = default; protected: - IControl* AddNamedChildControl(IControl* control, std::string name) + IControl* AddNamedChildControl(IControl* control, std::string name, int ctrlTag = kNoTag, const char* group = "") { // Make sure we haven't already used this name assert(mChildNameIndexMap.find(name) == mChildNameIndexMap.end()); mChildNameIndexMap[name] = NChildren(); - return AddChildControl(control); + return AddChildControl(control, ctrlTag, group); }; IControl* GetNamedChild(std::string name) @@ -472,10 +474,18 @@ class IContainerBaseWithNamedChildren : public IContainerBase std::unordered_map mChildNameIndexMap; }; // class IContainerBaseWithNamedChildren + +struct PossiblyKnownParameter +{ + bool known = false; + double value = 0.0; +}; + struct ModelInfo { - bool knownSampleRate = false; - double sampleRate = 0.0; + PossiblyKnownParameter sampleRate; + PossiblyKnownParameter inputCalibrationLevel; + PossiblyKnownParameter outputCalibrationLevel; }; class ModelInfoControl : public IContainerBaseWithNamedChildren @@ -499,26 +509,37 @@ class ModelInfoControl : public IContainerBaseWithNamedChildren void OnAttached() override { - AddChildControl(new IVLabelControl(GetRECT().GetGridCell(0, 0, 2, 1), "Model information:", mStyle)); - AddNamedChildControl(new IVLabelControl(GetRECT().GetGridCell(1, 0, 2, 1), "", mStyle), mControlNames.sampleRate); + AddChildControl(new IVLabelControl(GetRECT().SubRectVertical(4, 0), "Model information:", mStyle)); + AddNamedChildControl(new IVLabelControl(GetRECT().SubRectVertical(4, 1), "", mStyle), mControlNames.sampleRate); + // AddNamedChildControl( + // new IVLabelControl(GetRECT().SubRectVertical(4, 2), "", mStyle), mControlNames.inputCalibrationLevel); + // AddNamedChildControl( + // new IVLabelControl(GetRECT().SubRectVertical(4, 3), "", mStyle), mControlNames.outputCalibrationLevel); }; - // Click through me - void OnMouseDown(float x, float y, const IMouseMod& mod) override { GetParent()->OnMouseDown(x, y, mod); } - void SetModelInfo(const ModelInfo& modelInfo) { - std::stringstream ss; - ss << "Sample rate: "; - if (modelInfo.knownSampleRate) - { - ss << (int)modelInfo.sampleRate; - } - else - { - ss << "(Unknown)"; - } - static_cast(GetNamedChild(mControlNames.sampleRate))->SetStr(ss.str().c_str()); + auto SetControlStr = [&](const std::string& name, const PossiblyKnownParameter& p, const std::string& units, + const std::string& childName) { + std::stringstream ss; + ss << name << ": "; + if (p.known) + { + ss << p.value << " " << units; + } + else + { + ss << "(Unknown)"; + } + static_cast(GetNamedChild(childName))->SetStr(ss.str().c_str()); + }; + + SetControlStr("Sample rate", modelInfo.sampleRate, "Hz", mControlNames.sampleRate); + // SetControlStr( + // "Input calibration level", modelInfo.inputCalibrationLevel, "dBu", mControlNames.inputCalibrationLevel); + // SetControlStr( + // "Output calibration level", modelInfo.outputCalibrationLevel, "dBu", mControlNames.outputCalibrationLevel); + mHasInfo = true; }; @@ -527,6 +548,8 @@ class ModelInfoControl : public IContainerBaseWithNamedChildren struct { const std::string sampleRate = "sampleRate"; + // const std::string inputCalibrationLevel = "inputCalibrationLevel"; + // const std::string outputCalibrationLevel = "outputCalibrationLevel"; } mControlNames; // Do I have info? bool mHasInfo = false; @@ -535,10 +558,13 @@ class ModelInfoControl : public IContainerBaseWithNamedChildren class NAMSettingsPageControl : public IContainerBaseWithNamedChildren { public: - NAMSettingsPageControl(const IRECT& bounds, const IBitmap& bitmap, ISVG closeSVG, const IVStyle& style) + NAMSettingsPageControl(const IRECT& bounds, const IBitmap& bitmap, const IBitmap& inputLevelBackgroundBitmap, + const IBitmap& switchBitmap, ISVG closeSVG, const IVStyle& style) : IContainerBaseWithNamedChildren(bounds) , mAnimationTime(0) , mBitmap(bitmap) + , mInputLevelBackgroundBitmap(inputLevelBackgroundBitmap) + , mSwitchBitmap(switchBitmap) , mStyle(style) , mCloseSVG(closeSVG) { @@ -609,16 +635,41 @@ class NAMSettingsPageControl : public IContainerBaseWithNamedChildren const auto style = mStyle.WithDrawFrame(false).WithValueText(text); const IVStyle leftStyle = style.WithValueText(leftText); - // This'll get fixed on OnResize; FIXME - AddNamedChildControl(new IBitmapControl(IRECT(), mBitmap), mControlNames.bitmap)->SetIgnoreMouse(true); - AddNamedChildControl( - new IVLabelControl(GetRECT().GetPadded(-(pad + 10.0f)).GetFromTop(50.0f), "SETTINGS", titleStyle), - mControlNames.title); + AddNamedChildControl(new IBitmapControl(GetRECT(), mBitmap), mControlNames.bitmap)->SetIgnoreMouse(true); + const auto titleArea = GetRECT().GetPadded(-(pad + 10.0f)).GetFromTop(50.0f); + AddNamedChildControl(new IVLabelControl(titleArea, "SETTINGS", titleStyle), mControlNames.title); + + // Attach input/output calibration controls + { + const float height = NAM_KNOB_HEIGHT + NAM_SWTICH_HEIGHT + 10.0f; + const float width = titleArea.W(); + const auto inputOutputArea = titleArea.GetFromBottom(height).GetTranslated(0.0f, height); + const auto inputArea = inputOutputArea.GetFromLeft(0.5f * width); + // const auto outputArea = inputOutputArea.GetFromRight(0.5f * width); + + const float knobWidth = 87.0f; // HACK based on looking at the main page knobs. + const auto inputLevelArea = + inputArea.GetFromTop(NAM_KNOB_HEIGHT).GetFromBottom(25.0f).GetMidHPadded(0.5f * knobWidth); + const auto inputSwitchArea = inputArea.GetFromBottom(NAM_SWTICH_HEIGHT).GetMidHPadded(0.5f * knobWidth); + + auto* inputLevelControl = AddNamedChildControl( + new InputLevelControl(inputLevelArea, kInputCalibrationLevel, mInputLevelBackgroundBitmap, text), + mControlNames.inputCalibrationLevel, kCtrlTagInputCalibrationLevel); + inputLevelControl->SetTooltip( + "The analog level, in dBu RMS, that corresponds to digital level of 0 dBFS peak in the host as its signal " + "enters this plugin."); + AddNamedChildControl( + new NAMSwitchControl(inputSwitchArea, kCalibrateInput, "Calibrate Input", mStyle, mSwitchBitmap), + mControlNames.calibrateInput, kCtrlTagCalibrateInput); + + // TODO output--raw, normalized, calibrated + } const float halfWidth = PLUG_WIDTH / 2.0f - pad; const auto bottomArea = GetRECT().GetPadded(-pad).GetFromBottom(78.0f); - const auto modelInfoArea = bottomArea.GetFromLeft(halfWidth).GetFromTop(30.0f); - const auto aboutArea = bottomArea.GetFromRight(halfWidth); + const float lineHeight = 15.0f; + const auto modelInfoArea = bottomArea.GetFromLeft(halfWidth).GetFromTop(4 * lineHeight); + const auto aboutArea = bottomArea.GetFromRight(halfWidth).GetFromTop(5 * lineHeight); AddNamedChildControl(new ModelInfoControl(modelInfoArea, leftStyle), mControlNames.modelInfo); AddNamedChildControl(new AboutControl(aboutArea, leftStyle, leftText), mControlNames.about); @@ -631,15 +682,6 @@ class NAMSettingsPageControl : public IContainerBaseWithNamedChildren OnResize(); } - void OnResize() override - { - if (NChildren()) - { - GetNamedChild(mControlNames.bitmap)->SetTargetAndDrawRECTs(mRECT); - // Rework this later, but resizing on the main page needs to happen too. - } - } - void SetModelInfo(const ModelInfo& modelInfo) { auto* modelInfoControl = static_cast(GetNamedChild(mControlNames.modelInfo)); @@ -649,6 +691,8 @@ class NAMSettingsPageControl : public IContainerBaseWithNamedChildren private: IBitmap mBitmap; + IBitmap mInputLevelBackgroundBitmap; + IBitmap mSwitchBitmap; IVStyle mStyle; ISVG mCloseSVG; int mAnimationTime = 200; @@ -667,6 +711,51 @@ class NAMSettingsPageControl : public IContainerBaseWithNamedChildren const std::string title = "Title"; } mControlNames; + class InputLevelControl : public IEditableTextControl + { + public: + InputLevelControl(const IRECT& bounds, int paramIdx, const IBitmap& bitmap, const IText& text = DEFAULT_TEXT, + const IColor& BGColor = DEFAULT_BGCOLOR) + : IEditableTextControl(bounds, "", text, BGColor) + , mBitmap(bitmap) + { + SetParamIdx(paramIdx); + }; + + void Draw(IGraphics& g) override + { + g.DrawFittedBitmap(mBitmap, mRECT); + ITextControl::Draw(g); + }; + + void SetValueFromUserInput(double normalizedValue, int valIdx) override + { + IControl::SetValueFromUserInput(normalizedValue, valIdx); + const std::string s = ConvertToString(normalizedValue); + OnTextEntryCompletion(s.c_str(), valIdx); + }; + + void SetValueFromDelegate(double normalizedValue, int valIdx) override + { + IControl::SetValueFromDelegate(normalizedValue, valIdx); + const std::string s = ConvertToString(normalizedValue); + OnTextEntryCompletion(s.c_str(), valIdx); + }; + + private: + std::string ConvertToString(const double normalizedValue) + { + const double naturalValue = GetParam()->FromNormalized(normalizedValue); + // And make the value to display + std::stringstream ss; + ss << naturalValue << " dBu"; + std::string s = ss.str(); + return s; + }; + + IBitmap mBitmap; + }; + class AboutControl : public IContainerBase { public: @@ -682,14 +771,14 @@ class NAMSettingsPageControl : public IContainerBaseWithNamedChildren buildInfoStr.SetFormatted(100, "Version %s %s %s", verStr.Get(), PLUG()->GetArchStr(), PLUG()->GetAPIStr()); - AddChildControl(new IVLabelControl(GetRECT().GetGridCell(0, 0, 5, 1), "NEURAL AMP MODELER", mStyle)); - AddChildControl(new IVLabelControl(GetRECT().GetGridCell(1, 0, 5, 1), "By Steven Atkinson", mStyle)); - AddChildControl(new IVLabelControl(GetRECT().GetGridCell(2, 0, 5, 1), buildInfoStr.Get(), mStyle)); - AddChildControl(new IURLControl(GetRECT().GetGridCell(3, 0, 5, 1), + AddChildControl(new IVLabelControl(GetRECT().SubRectVertical(5, 0), "NEURAL AMP MODELER", mStyle)); + AddChildControl(new IVLabelControl(GetRECT().SubRectVertical(5, 1), "By Steven Atkinson", mStyle)); + AddChildControl(new IVLabelControl(GetRECT().SubRectVertical(5, 2), buildInfoStr.Get(), mStyle)); + AddChildControl(new IURLControl(GetRECT().SubRectVertical(5, 3), "Plug-in development: Steve Atkinson, Oli Larkin, ... ", "https://github.com/sdatkinson/NeuralAmpModelerPlugin/graphs/contributors", mText, COLOR_TRANSPARENT, PluginColors::HELP_TEXT_MO, PluginColors::HELP_TEXT_CLICKED)); - AddChildControl(new IURLControl(GetRECT().GetGridCell(4, 0, 5, 1), "www.neuralampmodeler.com", + AddChildControl(new IURLControl(GetRECT().SubRectVertical(5, 4), "www.neuralampmodeler.com", "https://www.neuralampmodeler.com", mText, COLOR_TRANSPARENT, PluginColors::HELP_TEXT_MO, PluginColors::HELP_TEXT_CLICKED)); }; diff --git a/NeuralAmpModeler/config.h b/NeuralAmpModeler/config.h index 790a142f..55ce7cc3 100644 --- a/NeuralAmpModeler/config.h +++ b/NeuralAmpModeler/config.h @@ -77,6 +77,9 @@ #define FILEBACKGROUND_FN "FileBackground.png" #define FILEBACKGROUND2X_FN "FileBackground@2x.png" #define FILEBACKGROUND3X_FN "FileBackground@3x.png" +#define INPUTLEVELBACKGROUND_FN "InputLevelBackground.png" +#define INPUTLEVELBACKGROUND2X_FN "InputLevelBackground@2x.png" +#define INPUTLEVELBACKGROUND3X_FN "InputLevelBackground@3x.png" #define LINES_FN "Lines.png" #define LINES2X_FN "Lines@2x.png" #define LINES3X_FN "Lines@3x.png" diff --git a/NeuralAmpModeler/resources/img/InputLevelBackground.png b/NeuralAmpModeler/resources/img/InputLevelBackground.png new file mode 100644 index 00000000..c4e10e37 Binary files /dev/null and b/NeuralAmpModeler/resources/img/InputLevelBackground.png differ diff --git a/NeuralAmpModeler/resources/img/InputLevelBackground@2x.png b/NeuralAmpModeler/resources/img/InputLevelBackground@2x.png new file mode 100644 index 00000000..1bad7770 Binary files /dev/null and b/NeuralAmpModeler/resources/img/InputLevelBackground@2x.png differ diff --git a/NeuralAmpModeler/resources/img/InputLevelBackground@3x.png b/NeuralAmpModeler/resources/img/InputLevelBackground@3x.png new file mode 100644 index 00000000..5eba9962 Binary files /dev/null and b/NeuralAmpModeler/resources/img/InputLevelBackground@3x.png differ diff --git a/NeuralAmpModeler/resources/main.rc b/NeuralAmpModeler/resources/main.rc index da444841..d11109ca 100644 --- a/NeuralAmpModeler/resources/main.rc +++ b/NeuralAmpModeler/resources/main.rc @@ -168,6 +168,9 @@ BEGIN "FILEBACKGROUND_FN PNG FILEBACKGROUND_FN\r\n" "FILEBACKGROUND2X_FN PNG FILEBACKGROUND2X_FN\r\n" "FILEBACKGROUND3X_FN PNG FILEBACKGROUND3X_FN\r\n" + "INPUTLEVELBACKGROUND_FN PNG INPUTLEVELBACKGROUND_FN\r\n" + "INPUTLEVELBACKGROUND2X_FN PNG INPUTLEVELBACKGROUND2X_FN\r\n" + "INPUTLEVELBACKGROUND3X_FN PNG INPUTLEVELBACKGROUND3X_FN\r\n" "LINES_FN PNG LINES_FN\r\n" "LINES2X_FN PNG LINES2X_FN\r\n" "LINES3X_FN PNG LINES3X_FN\r\n" @@ -275,6 +278,9 @@ KNOBBACKGROUND3X_FN PNG KNOBBACKGROUND3X_FN FILEBACKGROUND_FN PNG FILEBACKGROUND_FN FILEBACKGROUND2X_FN PNG FILEBACKGROUND2X_FN FILEBACKGROUND3X_FN PNG FILEBACKGROUND3X_FN +INPUTLEVELBACKGROUND_FN PNG INPUTLEVELBACKGROUND_FN +INPUTLEVELBACKGROUND2X_FN PNG INPUTLEVELBACKGROUND2X_FN +INPUTLEVELBACKGROUND3X_FN PNG INPUTLEVELBACKGROUND3X_FN LINES_FN PNG LINES_FN LINES2X_FN PNG LINES2X_FN LINES3X_FN PNG LINES3X_FN