mirror of
https://codeberg.org/armin/mindball.git
synced 2026-09-01 03:40:49 +02:00
fixes
This commit is contained in:
parent
4706489173
commit
831d53380b
4 changed files with 48 additions and 27 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
cmake_minimum_required(VERSION 3.22)
|
cmake_minimum_required(VERSION 3.22)
|
||||||
project(Mindball VERSION 1.0.0 LANGUAGES C CXX)
|
project(Mindball VERSION 0.0.5 LANGUAGES C CXX)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
@ -54,8 +54,8 @@ endif()
|
||||||
juce_add_plugin(Mindball
|
juce_add_plugin(Mindball
|
||||||
PRODUCT_NAME "Mindball"
|
PRODUCT_NAME "Mindball"
|
||||||
VENDOR_NAME "Mindball"
|
VENDOR_NAME "Mindball"
|
||||||
VERSION "1.0.0"
|
VERSION "0.0.5"
|
||||||
DESCRIPTION "Mindball - a tiny, minimal delay plugin"
|
DESCRIPTION "Mindball - a minimalist delay plugin"
|
||||||
FORMATS ${_formats}
|
FORMATS ${_formats}
|
||||||
PLUGIN_MANUFACTURER_CODE Mind
|
PLUGIN_MANUFACTURER_CODE Mind
|
||||||
PLUGIN_CODE Mbll
|
PLUGIN_CODE Mbll
|
||||||
|
|
@ -116,7 +116,7 @@ if(Git_FOUND)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
string(TIMESTAMP MINDBALL_BUILD_TIME "%Y-%m-%d %H:%M:%S UTC")
|
string(TIMESTAMP MINDBALL_BUILD_TIME "%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Source/BuildInfo.h.in
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Source/BuildInfo.h.in
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/buildinfo/BuildInfo.h @ONLY)
|
${CMAKE_CURRENT_BINARY_DIR}/buildinfo/BuildInfo.h @ONLY)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# Mindball
|
# Mindball
|
||||||
|
|
||||||
A tiny, minimal stereo delay plugin with a no-frills UI. Feedback echoes, ping-pong
|
A minimalist stereo delay plugin with a no-frills UI. Feedback echoes, ping-pong
|
||||||
and inverting modes, tempo-synced delay time, and an auto-panner - all wrapped in a
|
and inverting modes, tempo-synced delay time, and an auto-panner - all wrapped in a
|
||||||
clean, resizable interface with 20 factory presets.
|
clean, resizable interface with 20 factory presets.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ public:
|
||||||
if (branch.isEmpty() || branch == "n/a")
|
if (branch.isEmpty() || branch == "n/a")
|
||||||
branch = "-";
|
branch = "-";
|
||||||
|
|
||||||
buildInfo.setText ("Mindball v1.0.0\n"
|
buildInfo.setText ("Mindball v0.0.5\n"
|
||||||
+ hash + " " + branch + dirty + "\n"
|
+ hash + " " + branch + dirty + "\n"
|
||||||
+ juce::String (mindball::BuildInfo::buildTime),
|
+ juce::String (mindball::BuildInfo::buildTime),
|
||||||
juce::dontSendNotification);
|
juce::dontSendNotification);
|
||||||
|
|
@ -88,9 +88,8 @@ public:
|
||||||
|
|
||||||
void timerCallback() override
|
void timerCallback() override
|
||||||
{
|
{
|
||||||
const float decay = std::exp (-1.0f / (0.9f * 30.0f));
|
dryMeter.update (proc.getDryMeterL(), proc.getDryMeterR(), meterDecay);
|
||||||
dryMeter.update (proc.getDryMeterL(), proc.getDryMeterR(), decay);
|
wetMeter.update (proc.getWetMeterL(), proc.getWetMeterR(), meterDecay);
|
||||||
wetMeter.update (proc.getWetMeterL(), proc.getWetMeterR(), decay);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void parameterChanged (const juce::String& paramID, float) override
|
void parameterChanged (const juce::String& paramID, float) override
|
||||||
|
|
@ -176,6 +175,8 @@ private:
|
||||||
using SliderAttachment = juce::AudioProcessorValueTreeState::SliderAttachment;
|
using SliderAttachment = juce::AudioProcessorValueTreeState::SliderAttachment;
|
||||||
using ButtonAttachment = juce::AudioProcessorValueTreeState::ButtonAttachment;
|
using ButtonAttachment = juce::AudioProcessorValueTreeState::ButtonAttachment;
|
||||||
|
|
||||||
|
static constexpr float meterDecay = 0.9636077f; // exp (-1.0f / (0.9f * 30.0f))
|
||||||
|
|
||||||
MindballAudioProcessor& proc;
|
MindballAudioProcessor& proc;
|
||||||
|
|
||||||
static const juce::StringArray syncDivisionNames;
|
static const juce::StringArray syncDivisionNames;
|
||||||
|
|
|
||||||
|
|
@ -155,18 +155,16 @@ public:
|
||||||
|
|
||||||
void update (float linL, float linR, float decay)
|
void update (float linL, float linR, float decay)
|
||||||
{
|
{
|
||||||
levels[0] = linL;
|
const bool changedL = updateChannel (0, linL, decay);
|
||||||
levels[1] = linR;
|
const bool changedR = updateChannel (1, linR, decay);
|
||||||
peaks[0] = std::max (peaks[0] * decay, linL);
|
|
||||||
peaks[1] = std::max (peaks[1] * decay, linR);
|
if (changedL || changedR)
|
||||||
repaint();
|
repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
void paint (juce::Graphics& g) override
|
void paint (juce::Graphics& g) override
|
||||||
{
|
{
|
||||||
constexpr int steps = 15;
|
constexpr int steps = 15;
|
||||||
constexpr float dbMin = -30.0f;
|
|
||||||
constexpr float dbPerStep = 2.0f;
|
|
||||||
|
|
||||||
auto b = getLocalBounds().toFloat();
|
auto b = getLocalBounds().toFloat();
|
||||||
g.setColour (MindballColors::textDim);
|
g.setColour (MindballColors::textDim);
|
||||||
|
|
@ -180,32 +178,54 @@ public:
|
||||||
for (int ch = 0; ch < 2; ++ch)
|
for (int ch = 0; ch < 2; ++ch)
|
||||||
{
|
{
|
||||||
auto row = b.removeFromTop (rowH);
|
auto row = b.removeFromTop (rowH);
|
||||||
const float lin = std::max (0.0f, levels[ch]);
|
|
||||||
const float db = 20.0f * std::log10 (lin > 0.0f ? lin : 1e-9f);
|
|
||||||
const int lit = juce::jlimit (0, steps, juce::roundToInt ((db - dbMin) / dbPerStep));
|
|
||||||
const int pk = juce::jlimit (0, steps, juce::roundToInt ((20.0f * std::log10 (std::max (1e-9f, peaks[ch])) - dbMin) / dbPerStep));
|
|
||||||
|
|
||||||
for (int s = 0; s < steps; ++s)
|
for (int s = 0; s < steps; ++s)
|
||||||
{
|
{
|
||||||
const auto seg = juce::Rectangle<float> (row.getX() + s * (segW + segGap),
|
const auto seg = juce::Rectangle<float> (row.getX() + s * (segW + segGap),
|
||||||
row.getY() + 2.0f, segW, rowH - 4.0f);
|
row.getY() + 2.0f, segW, rowH - 4.0f);
|
||||||
g.setColour (s < lit ? MindballColors::meterGreen : MindballColors::arcBg);
|
g.setColour (s < lit[ch] ? MindballColors::meterGreen : MindballColors::arcBg);
|
||||||
g.fillRoundedRectangle (seg, 1.0f);
|
g.fillRect (seg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pk > lit)
|
if (pk[ch] > 0)
|
||||||
{
|
{
|
||||||
const auto seg = juce::Rectangle<float> (row.getX() + pk * (segW + segGap),
|
const int peakSeg = juce::jmin (pk[ch], steps - 1);
|
||||||
|
const auto seg = juce::Rectangle<float> (row.getX() + peakSeg * (segW + segGap),
|
||||||
row.getY() + 2.0f, segW, rowH - 4.0f);
|
row.getY() + 2.0f, segW, rowH - 4.0f);
|
||||||
g.setColour (MindballColors::meterRed);
|
g.setColour (MindballColors::meterRed);
|
||||||
g.fillRoundedRectangle (seg, 1.0f);
|
g.fillRect (seg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool updateChannel (int ch, float lin, float decay)
|
||||||
|
{
|
||||||
|
peaks[ch] = std::max (peaks[ch] * decay, lin);
|
||||||
|
|
||||||
|
const int newLit = levelToSteps (lin);
|
||||||
|
const int newPk = levelToSteps (peaks[ch]);
|
||||||
|
|
||||||
|
if (newLit == lit[ch] && newPk == pk[ch])
|
||||||
|
return false;
|
||||||
|
|
||||||
|
lit[ch] = newLit;
|
||||||
|
pk[ch] = newPk;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int levelToSteps (float lin)
|
||||||
|
{
|
||||||
|
constexpr int steps = 15;
|
||||||
|
constexpr float dbMin = -30.0f;
|
||||||
|
constexpr float dbPerStep = 2.0f;
|
||||||
|
const float db = 20.0f * std::log10 (lin > 0.0f ? lin : 1e-9f);
|
||||||
|
return juce::jlimit (0, steps, juce::roundToInt ((db - dbMin) / dbPerStep));
|
||||||
|
}
|
||||||
|
|
||||||
juce::String name;
|
juce::String name;
|
||||||
float levels[2] = { 0.0f, 0.0f };
|
int lit[2] = { 0, 0 };
|
||||||
|
int pk[2] = { 0, 0 };
|
||||||
float peaks[2] = { 0.0f, 0.0f };
|
float peaks[2] = { 0.0f, 0.0f };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue