Add output volume control to sosci

pre-release-3
James H Ball 2025-01-06 09:14:34 +00:00
rodzic 14bfcce37f
commit 3340d9dd45
12 zmienionych plików z 63 dodań i 40 usunięć

Wyświetl plik

@ -7,6 +7,7 @@
#include "visualiser/VisualiserSettings.h"
#include "components/SosciMainMenuBarModel.h"
#include "components/SvgButton.h"
#include "components/VolumeComponent.h"
class CommonPluginEditor : public juce::AudioProcessorEditor {
public:
@ -66,6 +67,8 @@ public:
appName == "sosci"
};
VolumeComponent volume{audioProcessor};
std::unique_ptr<juce::FileChooser> chooser;
juce::MenuBarComponent menuBar;

Wyświetl plik

@ -33,6 +33,11 @@ CommonAudioProcessor::CommonAudioProcessor()
for (auto parameter : visualiserParameters.integers) {
intParameters.push_back(parameter);
}
permanentEffects.push_back(volumeEffect);
permanentEffects.push_back(thresholdEffect);
effects.push_back(volumeEffect);
effects.push_back(thresholdEffect);
}
void CommonAudioProcessor::addAllParameters() {

Wyświetl plik

@ -55,6 +55,33 @@ public:
void changeProgramName(int index, const juce::String& newName) override;
double getSampleRate() override;
std::atomic<double> volume = 1.0;
std::atomic<double> threshold = 1.0;
std::shared_ptr<Effect> volumeEffect = std::make_shared<Effect>(
[this](int index, OsciPoint input, const std::vector<std::atomic<double>>& values, double sampleRate) {
volume = values[0].load();
return input;
}, new EffectParameter(
"Volume",
"Controls the volume of the output audio.",
"volume",
VERSION_HINT, 1.0, 0.0, 3.0
)
);
std::shared_ptr<Effect> thresholdEffect = std::make_shared<Effect>(
[this](int index, OsciPoint input, const std::vector<std::atomic<double>>& values, double sampleRate) {
threshold = values[0].load();
return input;
}, new EffectParameter(
"Threshold",
"Clips the audio to a maximum value. Applying a harsher threshold results in a more distorted sound.",
"threshold",
VERSION_HINT, 1.0, 0.0, 1.0
)
);
std::atomic<double> currentSampleRate = 0.0;
juce::SpinLock effectsLock;
VisualiserParameters visualiserParameters;

Wyświetl plik

@ -4,7 +4,6 @@
#include "PluginProcessor.h"
#include "SettingsComponent.h"
#include "MidiComponent.h"
#include "components/VolumeComponent.h"
#include "components/OsciMainMenuBarModel.h"
#include "LookAndFeel.h"
#include "components/ErrorCodeEditorComponent.h"
@ -48,7 +47,6 @@ public:
juce::ComponentAnimator codeEditorAnimator;
LuaComponent lua{audioProcessor, *this};
VolumeComponent volume{audioProcessor};
LuaConsole console;

Wyświetl plik

@ -135,8 +135,6 @@ OscirenderAudioProcessor::OscirenderAudioProcessor() {
std::vector<std::shared_ptr<Effect>> osciPermanentEffects;
osciPermanentEffects.push_back(perspective);
osciPermanentEffects.push_back(frequencyEffect);
osciPermanentEffects.push_back(volumeEffect);
osciPermanentEffects.push_back(thresholdEffect);
osciPermanentEffects.push_back(imageThreshold);
osciPermanentEffects.push_back(imageStride);

Wyświetl plik

@ -72,30 +72,6 @@ public:
)
);
std::shared_ptr<Effect> volumeEffect = std::make_shared<Effect>(
[this](int index, OsciPoint input, const std::vector<std::atomic<double>>& values, double sampleRate) {
volume = values[0].load();
return input;
}, new EffectParameter(
"Volume",
"Controls the volume of the sound. Works by scaling the image and sound by a factor.",
"volume",
VERSION_HINT, 1.0, 0.0, 3.0
)
);
std::shared_ptr<Effect> thresholdEffect = std::make_shared<Effect>(
[this](int index, OsciPoint input, const std::vector<std::atomic<double>>& values, double sampleRate) {
threshold = values[0].load();
return input;
}, new EffectParameter(
"Threshold",
"Clips the sound and image to a maximum value. Applying a harsher threshold results in a more distorted sound.",
"threshold",
VERSION_HINT, 1.0, 0.0, 1.0
)
);
std::shared_ptr<Effect> traceMax = std::make_shared<Effect>(
new EffectParameter(
"Trace max",
@ -232,8 +208,6 @@ public:
void removeErrorListener(ErrorListener* listener);
void notifyErrorListeners(int lineNumber, juce::String id, juce::String error);
private:
std::atomic<double> volume = 1.0;
std::atomic<double> threshold = 1.0;
bool prevMidiEnabled = !midiEnabled->getBoolValue();

Wyświetl plik

@ -4,6 +4,7 @@
SosciPluginEditor::SosciPluginEditor(SosciAudioProcessor& p) : CommonPluginEditor(p, "sosci", "sosci", 700, 750), audioProcessor(p) {
initialiseMenuBar(model);
addAndMakeVisible(volume);
resized();
}
@ -16,9 +17,12 @@ void SosciPluginEditor::paint(juce::Graphics& g) {
}
void SosciPluginEditor::resized() {
auto topBar = getLocalBounds().removeFromTop(25);
menuBar.setBounds(topBar);
auto visualiserArea = getLocalBounds();
visualiserArea.removeFromTop(25);
visualiser.setBounds(visualiserArea);
auto area = getLocalBounds();
menuBar.setBounds(area.removeFromTop(25));
auto volumeArea = area.removeFromLeft(30);
volume.setBounds(volumeArea.withSizeKeepingCentre(volumeArea.getWidth(), juce::jmin(volumeArea.getHeight(), 300)));
visualiser.setBounds(area);
}

Wyświetl plik

@ -51,8 +51,18 @@ void SosciAudioProcessor::processBlock(juce::AudioBuffer<float>& buffer, juce::M
point = effect->apply(sample, point);
}
// no negative brightness
point.z = juce::jmax(0.0, juce::jmin(1.0, point.z));
// this is the point that the visualiser will draw
threadManager.write(point);
point.scale(volume, volume, volume);
// clip
point.x = juce::jmax(-threshold, juce::jmin(threshold.load(), point.x));
point.y = juce::jmax(-threshold, juce::jmin(threshold.load(), point.y));
if (output.getNumChannels() > 0) {
outputArray[0][sample] = point.x;
}

Wyświetl plik

@ -1,6 +1,6 @@
#include "VolumeComponent.h"
VolumeComponent::VolumeComponent(OscirenderAudioProcessor& p) : AudioBackgroundThread("VolumeComponent", p.threadManager), audioProcessor(p) {
VolumeComponent::VolumeComponent(CommonAudioProcessor& p) : AudioBackgroundThread("VolumeComponent", p.threadManager), audioProcessor(p) {
setOpaque(false);
setShouldBeRunning(true);

Wyświetl plik

@ -1,7 +1,7 @@
#pragma once
#include <JuceHeader.h>
#include "../PluginProcessor.h"
#include "../CommonPluginProcessor.h"
#include "../LookAndFeel.h"
#include "../concurrency/AudioBackgroundThread.h"
@ -61,7 +61,7 @@ public:
class VolumeComponent : public juce::Component, public juce::AsyncUpdater, public AudioBackgroundThread {
public:
VolumeComponent(OscirenderAudioProcessor& p);
VolumeComponent(CommonAudioProcessor& p);
void paint(juce::Graphics&) override;
void handleAsyncUpdate() override;
@ -71,7 +71,7 @@ public:
void resized() override;
private:
OscirenderAudioProcessor& audioProcessor;
CommonAudioProcessor& audioProcessor;
const int DEFAULT_SAMPLE_RATE = 192000;
const double BUFFER_DURATION_SECS = 0.02;

Wyświetl plik

@ -603,7 +603,7 @@ void VisualiserComponent::renderOpenGL() {
using namespace juce::gl;
if (openGLContext.isActive()) {
juce::OpenGLHelpers::clear(Colours::veryDark);
juce::OpenGLHelpers::clear(juce::Colours::black);
// we have a new buffer to render
if (sampleBufferCount != prevSampleBufferCount) {

Wyświetl plik

@ -122,6 +122,10 @@
file="Source/components/StopwatchComponent.h"/>
<FILE id="f2kkHV" name="SvgButton.h" compile="0" resource="0" file="Source/components/SvgButton.h"/>
<FILE id="qzfstC" name="SwitchButton.h" compile="0" resource="0" file="Source/components/SwitchButton.h"/>
<FILE id="HC8nNY" name="VolumeComponent.cpp" compile="1" resource="0"
file="Source/components/VolumeComponent.cpp"/>
<FILE id="qwpGcH" name="VolumeComponent.h" compile="0" resource="0"
file="Source/components/VolumeComponent.h"/>
</GROUP>
<GROUP id="{9F5970A9-8094-E7F3-7AC1-812AE5589B9F}" name="concurrency">
<FILE id="wAUzPb" name="AudioBackgroundThread.cpp" compile="1" resource="0"