mirror of
https://codeberg.org/armin/terion.git
synced 2026-10-11 16:41:53 +02:00
many UI fixes and new screenshot
This commit is contained in:
parent
5904430490
commit
88ed77a0c6
8 changed files with 43 additions and 29 deletions
|
|
@ -36,14 +36,16 @@ if(NOT GIT_HASH)
|
|||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND git rev-list --count HEAD
|
||||
COMMAND git status --porcelain
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
OUTPUT_VARIABLE GIT_LOCAL_COMMITS
|
||||
OUTPUT_VARIABLE GIT_STATUS
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET
|
||||
)
|
||||
if(NOT GIT_LOCAL_COMMITS)
|
||||
set(GIT_LOCAL_COMMITS "0")
|
||||
if(GIT_STATUS STREQUAL "")
|
||||
set(GIT_DIRTY "clean")
|
||||
else()
|
||||
set(GIT_DIRTY "dirty")
|
||||
endif()
|
||||
|
||||
string(TIMESTAMP BUILD_TIME "%Y-%m-%d %H:%M:%S")
|
||||
|
|
|
|||
|
|
@ -60,10 +60,10 @@ make install # build, codesign, un-quarantine, install to ~/Library/Audio/Plu
|
|||
| Parameter | Range | Description |
|
||||
|---|---|---|
|
||||
| Fade | 0.1 – 10 s | Trail persistence time |
|
||||
| Sensitivity | -12 – +24 dB | Input gain for M/S decode |
|
||||
| Dot size | 0.5 – 8.0 px | Size of each plotted point |
|
||||
| Smoothing | 0 – 0.99 | One-pole smoothing on M/S signals |
|
||||
| Afterglow | 0 – 5 s | Extra lingers of the trail after the fade time |
|
||||
| Response | -12 – +24 dB | Input gain for M/S decode |
|
||||
| Size | 0.5 – 8.0 px | Size of each plotted point |
|
||||
| Smooth | 0 – 0.99 | One-pole smoothing on M/S signals |
|
||||
| Glow | 0 – 5 s | Extra lingers of the trail after the fade time |
|
||||
| Freeze | on/off | Stop capturing new points |
|
||||
|
||||
## Project structure
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ TerionProcessorEditor::TerionProcessorEditor(TerionProcessor& p)
|
|||
|
||||
// Freeze button
|
||||
addAndMakeVisible(freezeButton);
|
||||
freezeButton.setButtonText("FRZ");
|
||||
freezeButton.setButtonText("Freeze");
|
||||
freezeButton.setColour(juce::ToggleButton::textColourId, juce::Colour(0xff888899));
|
||||
freezeButton.setColour(juce::ToggleButton::tickColourId, juce::Colour(0xff7ecfcf));
|
||||
freezeAttachment = std::make_unique<juce::AudioProcessorValueTreeState::ButtonAttachment>(
|
||||
|
|
@ -55,7 +55,7 @@ TerionProcessorEditor::TerionProcessorEditor(TerionProcessor& p)
|
|||
|
||||
// Mono button
|
||||
addAndMakeVisible(monoButton);
|
||||
monoButton.setButtonText("MONO");
|
||||
monoButton.setButtonText("Mono");
|
||||
monoButton.setColour(juce::ToggleButton::textColourId, juce::Colour(0xff888899));
|
||||
monoButton.setColour(juce::ToggleButton::tickColourId, juce::Colour(0xff7ecfcf));
|
||||
monoAttachment = std::make_unique<juce::AudioProcessorValueTreeState::ButtonAttachment>(
|
||||
|
|
@ -133,10 +133,10 @@ void TerionProcessorEditor::paint(juce::Graphics& g)
|
|||
g.setColour(juce::Colour(0xff555566));
|
||||
g.setFont(juce::Font(juce::FontOptions(9.0f * s)));
|
||||
|
||||
juce::String footerText = "Terion "
|
||||
juce::String footerText = "Terion (Git: "
|
||||
+ juce::String(TERION_GIT_HASH)
|
||||
+ " | " + juce::String(TERION_BUILD_TIME)
|
||||
+ " | " + juce::String(TERION_GIT_LOCAL_COMMITS) + " local";
|
||||
+ ", " + juce::String(TERION_GIT_DIRTY)
|
||||
+ ") | built: " + juce::String(TERION_BUILD_TIME);
|
||||
|
||||
g.drawFittedText(footerText, footer.reduced(static_cast<int>(10.0f * s), 0),
|
||||
juce::Justification::centredLeft, 1);
|
||||
|
|
@ -149,20 +149,18 @@ void TerionProcessorEditor::resized()
|
|||
const int knobs = static_cast<int>(kKnobSize * s);
|
||||
const int margin = static_cast<int>(kKnobMargin * s);
|
||||
const int scaleW = static_cast<int>(76.0f * s);
|
||||
const int monoW = static_cast<int>(72.0f * s);
|
||||
const int gap = static_cast<int>(8.0f * s);
|
||||
|
||||
auto bounds = getLocalBounds();
|
||||
auto footer = bounds.removeFromBottom(footerH);
|
||||
|
||||
// Footer: scale dropdown + mono toggle on the right
|
||||
scaleBox.setBounds(footer.getWidth() - scaleW, 1, scaleW, footerH - 2);
|
||||
monoButton.setBounds(footer.getWidth() - scaleW - monoW, 1, monoW, footerH - 2);
|
||||
// Footer: scale dropdown with an 8px gap on the top and right
|
||||
scaleBox.setBounds(footer.getWidth() - scaleW - gap, gap, scaleW, footerH - 2 - gap);
|
||||
|
||||
// Scope fills the remaining area
|
||||
scope.setBounds(bounds);
|
||||
|
||||
// Controls layout: knob row sits 8px above the footer, FRZ stays top-right
|
||||
const int gap = static_cast<int>(8.0f * s);
|
||||
// Controls layout: knob row sits 8px above the footer, Freeze/Mono stay top-right
|
||||
const int numKnobs = 5;
|
||||
const int rowH = knobs + static_cast<int>(12.0f * s) - static_cast<int>(6.0f * s);
|
||||
const int startX = bounds.getWidth() - (numKnobs * (knobs + margin) + knobs + margin);
|
||||
|
|
@ -173,8 +171,11 @@ void TerionProcessorEditor::resized()
|
|||
dotSizeKnob.setBounds(startX + 2 * (knobs + margin), startY, knobs, knobs);
|
||||
smoothingKnob.setBounds(startX + 3 * (knobs + margin), startY, knobs, knobs);
|
||||
afterglowKnob.setBounds(startX + 4 * (knobs + margin), startY, knobs, knobs);
|
||||
freezeButton.setBounds(bounds.getWidth() - knobs - margin, static_cast<int>(20.0f * s),
|
||||
knobs, knobs - static_cast<int>(20.0f * s));
|
||||
const int freezeY = static_cast<int>(20.0f * s);
|
||||
const int freezeH = knobs - static_cast<int>(20.0f * s);
|
||||
freezeButton.setBounds(bounds.getWidth() - knobs - margin, freezeY, knobs, freezeH);
|
||||
monoButton.setBounds(bounds.getWidth() - knobs - margin, freezeY + freezeH + gap,
|
||||
knobs, freezeH);
|
||||
|
||||
const int labelY = startY + knobs - static_cast<int>(6.0f * s);
|
||||
const int labelH = static_cast<int>(12.0f * s);
|
||||
|
|
|
|||
|
|
@ -8,22 +8,22 @@ TerionProcessor::TerionProcessor()
|
|||
apvts(*this, nullptr, "Parameters", {
|
||||
std::make_unique<juce::AudioParameterFloat>(
|
||||
juce::ParameterID{"fadeTime", 1},
|
||||
"Fade Time",
|
||||
"Fade",
|
||||
juce::NormalisableRange<float>(0.1f, 10.0f, 0.01f, 0.4f),
|
||||
2.0f),
|
||||
std::make_unique<juce::AudioParameterFloat>(
|
||||
juce::ParameterID{"sensitivity", 2},
|
||||
"Sensitivity",
|
||||
"Response",
|
||||
juce::NormalisableRange<float>(-12.0f, 24.0f, 0.1f, 0.5f),
|
||||
0.0f),
|
||||
std::make_unique<juce::AudioParameterFloat>(
|
||||
juce::ParameterID{"dotSize", 3},
|
||||
"Dot Size",
|
||||
"Size",
|
||||
juce::NormalisableRange<float>(0.5f, 8.0f, 0.1f, 0.5f),
|
||||
1.0f),
|
||||
std::make_unique<juce::AudioParameterFloat>(
|
||||
juce::ParameterID{"smoothing", 4},
|
||||
"Smoothing",
|
||||
"Smooth",
|
||||
juce::NormalisableRange<float>(0.0f, 0.99f, 0.01f, 0.5f),
|
||||
0.0f),
|
||||
std::make_unique<juce::AudioParameterBool>(
|
||||
|
|
@ -36,7 +36,7 @@ TerionProcessor::TerionProcessor()
|
|||
false),
|
||||
std::make_unique<juce::AudioParameterFloat>(
|
||||
juce::ParameterID{"afterglow", 7},
|
||||
"Afterglow",
|
||||
"Glow",
|
||||
juce::NormalisableRange<float>(0.0f, 5.0f, 0.01f, 0.5f),
|
||||
0.5f)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -13,6 +13,14 @@ VectorScope::~VectorScope()
|
|||
|
||||
void VectorScope::timerCallback()
|
||||
{
|
||||
// Refresh the numeric readouts at kMetricsRateHz while keeping the trail
|
||||
// animation running at the full 30 Hz.
|
||||
const float frozen = processor.apvts.getRawParameterValue("freeze")->load();
|
||||
if (frozen < 0.5f && ++metricFrame >= 30 / kMetricsRateHz)
|
||||
{
|
||||
metricFrame = 0;
|
||||
cachedMetrics = processor.getMetrics();
|
||||
}
|
||||
repaint();
|
||||
}
|
||||
|
||||
|
|
@ -183,7 +191,7 @@ void VectorScope::drawLegends(juce::Graphics& g, float cx, float cy, float radiu
|
|||
|
||||
void VectorScope::drawMetricsOverlay(juce::Graphics& g, const juce::Rectangle<int>& bounds)
|
||||
{
|
||||
const auto& metrics = processor.getMetrics();
|
||||
const auto& metrics = cachedMetrics;
|
||||
const float s = currentScale;
|
||||
const int margin = static_cast<int>(10.0f * s);
|
||||
const int lineHeight = static_cast<int>(14.0f * s);
|
||||
|
|
@ -217,6 +225,6 @@ void VectorScope::drawMetricsOverlay(juce::Graphics& g, const juce::Rectangle<in
|
|||
drawMetric("Mid", metrics.midLevel, "dB", y); y += lineHeight;
|
||||
drawMetric("Side", metrics.sideLevel, "dB", y); y += lineHeight;
|
||||
drawMetric("Balance", metrics.balance, "dB", y); y += lineHeight;
|
||||
drawMetric("Phase", metrics.phaseAngle, "\u00B0", y); y += lineHeight;
|
||||
drawMetric("Phase", metrics.phaseAngle, "deg", y); y += lineHeight;
|
||||
drawMetric("Crest", metrics.crestFactor, "dB", y); y += lineHeight;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@ private:
|
|||
TerionProcessor& processor;
|
||||
float currentScale = 1.0f;
|
||||
juce::Image trail;
|
||||
StereoMetrics cachedMetrics;
|
||||
int metricFrame = 0;
|
||||
static constexpr int kMetricsRateHz = 2;
|
||||
|
||||
void drawLegends(juce::Graphics& g, float cx, float cy, float radius);
|
||||
void drawHairCross(juce::Graphics& g, float cx, float cy);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#define TERION_GIT_HASH "@GIT_HASH@"
|
||||
#define TERION_GIT_DIRTY "@GIT_DIRTY@"
|
||||
#define TERION_BUILD_TIME "@BUILD_TIME@"
|
||||
#define TERION_GIT_LOCAL_COMMITS "@GIT_LOCAL_COMMITS@"
|
||||
|
|
|
|||
BIN
shot.png
BIN
shot.png
Binary file not shown.
|
Before Width: | Height: | Size: 224 KiB After Width: | Height: | Size: 170 KiB |
Loading…
Add table
Add a link
Reference in a new issue