Merge branch 'jameshball:main' into lua-voice-external-input

pull/285/head
DJLevel3 2025-06-21 18:22:25 -06:00 zatwierdzone przez GitHub
commit f40e19647b
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
35 zmienionych plików z 542 dodań i 170 usunięć

Wyświetl plik

@ -2,7 +2,6 @@ name: Build
on:
push:
branches:
- main
- develop
workflow_dispatch:
jobs:

Wyświetl plik

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M10.59,13.41C11,13.8 11,14.44 10.59,14.83C10.2,15.22 9.56,15.22 9.17,14.83C7.22,12.88 7.22,9.71 9.17,7.76V7.76L12.71,4.22C14.66,2.27 17.83,2.27 19.78,4.22C21.73,6.17 21.73,9.34 19.78,11.29L18.29,12.78C18.3,11.96 18.17,11.14 17.89,10.36L18.36,9.88C19.54,8.71 19.54,6.81 18.36,5.64C17.19,4.46 15.29,4.46 14.12,5.64L10.59,9.17C9.41,10.34 9.41,12.24 10.59,13.41M13.41,9.17C13.8,8.78 14.44,8.78 14.83,9.17C16.78,11.12 16.78,14.29 14.83,16.24V16.24L11.29,19.78C9.34,21.73 6.17,21.73 4.22,19.78C2.27,17.83 2.27,14.66 4.22,12.71L5.71,11.22C5.7,12.04 5.83,12.86 6.11,13.65L5.64,14.12C4.46,15.29 4.46,17.19 5.64,18.36C6.81,19.54 8.71,19.54 9.88,18.36L13.41,14.83C14.59,13.66 14.59,11.76 13.41,10.59C13,10.2 13,9.56 13.41,9.17Z" /></svg>

Po

Szerokość:  |  Wysokość:  |  Rozmiar: 795 B

Wyświetl plik

@ -45,7 +45,7 @@ CommonPluginEditor::CommonPluginEditor(CommonAudioProcessor& p, juce::String app
visualiserSettings.setColour(juce::ResizableWindow::backgroundColourId, Colours::dark);
recordingSettings.setLookAndFeel(&getLookAndFeel());
recordingSettings.setSize(300, 280);
recordingSettings.setSize(300, 330);
#if JUCE_WINDOWS
// if not standalone, use native title bar for compatibility with DAWs
recordingSettingsWindow.setUsingNativeTitleBar(processor.wrapperType == juce::AudioProcessor::WrapperType::wrapperType_Standalone);

Wyświetl plik

@ -44,14 +44,14 @@ public:
#endif
#if OSCI_PREMIUM
int VISUALISER_SETTINGS_HEIGHT = 1200;
int VISUALISER_SETTINGS_HEIGHT = 1230;
#else
int VISUALISER_SETTINGS_HEIGHT = 700;
#endif
VisualiserSettings visualiserSettings = VisualiserSettings(audioProcessor.visualiserParameters, 3);
RecordingSettings recordingSettings = RecordingSettings(audioProcessor.recordingParameters);
SettingsWindow recordingSettingsWindow = SettingsWindow("Recording Settings", recordingSettings, 330, 350, 330, 350);
SettingsWindow recordingSettingsWindow = SettingsWindow("Recording Settings", recordingSettings, 330, 360, 330, 360);
VisualiserComponent visualiser{
audioProcessor,
*this,

Wyświetl plik

@ -17,19 +17,30 @@ EffectPluginEditor::EffectPluginEditor(EffectAudioProcessor& p)
addAndMakeVisible(visualiser);
addAndMakeVisible(titleVisualiser);
addAndMakeVisible(bitCrush);
addAndMakeVisible(sliderVisualiser);
titleVisualiser.setCropRectangle(juce::Rectangle<float>(-0.1f, 0.35f, 1.2f, 0.3f));
// Configure the slider visualiser component
sliderVisualiser.onValueChange([this]() {
audioProcessor.bitCrush->parameters[0]->setUnnormalisedValueNotifyingHost(sliderVisualiser.getValue());
});
bitCrush.slider.onValueChange = [this] {
audioProcessor.bitCrush->parameters[0]->setUnnormalisedValueNotifyingHost(bitCrush.slider.getValue());
};
// Set the label for the slider
sliderVisualiser.setLabel("bit crush");
setSize(600, 200);
setResizable(false, false);
tooltipDropShadow.setOwner(&tooltipWindow.get());
tooltipWindow->setMillisecondsBeforeTipAppears(0);
audioProcessor.bitCrush->addListener(0, this);
}
EffectPluginEditor::~EffectPluginEditor() {
audioProcessor.bitCrush->removeListener(0, this);
setLookAndFeel(nullptr);
juce::Desktop::getInstance().setDefaultLookAndFeel(nullptr);
}
void EffectPluginEditor::resized() {
@ -40,10 +51,18 @@ void EffectPluginEditor::resized() {
auto titleBounds = bounds.removeFromTop(100);
titleVisualiser.setBounds(titleBounds);
bitCrush.setBounds(bounds);
// Set bounds for sliderVisualiser
sliderVisualiser.setBounds(bounds);
}
EffectPluginEditor::~EffectPluginEditor() {
setLookAndFeel(nullptr);
juce::Desktop::getInstance().setDefaultLookAndFeel(nullptr);
void EffectPluginEditor::parameterValueChanged(int parameterIndex, float newValue) {
if (parameterIndex == 0) {
juce::MessageManager::getInstance()->callAsync([this, newValue]() {
sliderVisualiser.setValue(newValue);
// Update visualizer directly as setValue doesn't always trigger onChange
sliderVisualiser.updateVisualiser();
});
}
}
void EffectPluginEditor::parameterGestureChanged(int parameterIndex, bool gestureIsStarting) {}

Wyświetl plik

@ -5,13 +5,16 @@
#include "visualiser/VisualiserRenderer.h"
#include "LookAndFeel.h"
#include "components/EffectComponent.h"
#include "components/SliderVisualiserComponent.h"
class EffectPluginEditor : public juce::AudioProcessorEditor {
class EffectPluginEditor : public juce::AudioProcessorEditor, public juce::AudioProcessorParameter::Listener {
public:
EffectPluginEditor(EffectAudioProcessor&);
~EffectPluginEditor() override;
void resized() override;
void parameterValueChanged(int parameterIndex, float newValue) override;
void parameterGestureChanged(int parameterIndex, bool gestureIsStarting) override;
private:
EffectAudioProcessor& audioProcessor;
@ -35,11 +38,13 @@ public:
"Title"
};
SliderVisualiserComponent sliderVisualiser{
audioProcessor
};
juce::SharedResourcePointer<juce::TooltipWindow> tooltipWindow;
juce::DropShadower tooltipDropShadow{juce::DropShadow(juce::Colours::black.withAlpha(0.5f), 6, {0,0})};
EffectComponent bitCrush{*audioProcessor.bitCrush};
#if JUCE_LINUX
juce::OpenGLContext openGlContext;
#endif

Wyświetl plik

@ -26,8 +26,11 @@ EffectAudioProcessor::EffectAudioProcessor()
}
}
titleShapes = titleParser.draw();
titleShapesLength = osci::Shape::totalLength(titleShapes);
// Initialize title shapes
juce::Font titleFont = juce::Font(1.0f, juce::Font::bold);
TextParser titleParser{"bit crush", titleFont};
auto titleShapes = titleParser.draw();
titleRenderer.setShapes(std::move(titleShapes));
}
const juce::String EffectAudioProcessor::getName() const {
@ -86,6 +89,7 @@ void EffectAudioProcessor::prepareToPlay(double sampleRate, int samplesPerBlock)
}
currentSampleRate = sampleRate;
titleRenderer.setSampleRate(sampleRate);
threadManager.prepare(sampleRate, samplesPerBlock);
}
@ -126,56 +130,25 @@ void EffectAudioProcessor::processBlock(juce::AudioBuffer<float>& buffer, juce::
if (output.getNumChannels() > 1) {
outputArray[1][sample] = point.y;
}
// handle the title drawing
osci::Point titlePoint = titleRenderer.nextVector();
// handle the title drawing
osci::Point titlePoint = { 0.0, 0.0, 1.0f };
if (currentTitleShape < titleShapes.size()) {
auto& shape = titleShapes[currentTitleShape];
double length = shape->length();
double drawingProgress = length == 0.0 ? 1 : titleShapeDrawn / length;
titlePoint = shape->nextVector(drawingProgress);
titlePoint.z = 1.0f;
// apply bit crush without animating values, as this has already been done
titlePoint = bitCrush->apply(sample, titlePoint, 0.0, false);
}
// apply bit crush without animating values, as this has already been done
titlePoint = bitCrush->apply(sample, titlePoint, 0.0, false);
threadManager.write(titlePoint, "VisualiserRendererTitle");
incrementTitleShapeDrawing();
if (titleFrameDrawn >= titleShapesLength) {
double currentShapeLength = 0;
if (currentTitleShape < titleShapes.size()) {
currentShapeLength = titleShapes[currentTitleShape]->len;
}
titleFrameDrawn -= titleShapesLength;
currentTitleShape = 0;
osci::Point sliderPoint;
{
juce::SpinLock::ScopedLockType lock(sliderLock);
sliderPoint = sliderRenderer.nextVector();
}
threadManager.write(sliderPoint, "VisualiserRendererSlider");
}
}
void EffectAudioProcessor::incrementTitleShapeDrawing() {
if (titleShapes.size() <= 0) return;
double length = currentTitleShape < titleShapes.size() ? titleShapes[currentTitleShape]->len : 0.0;
double FREQUENCY = 60.0;
double lengthIncrement = titleShapesLength / (currentSampleRate / FREQUENCY);
titleFrameDrawn += lengthIncrement;
titleShapeDrawn += lengthIncrement;
// Need to skip all shapes that the lengthIncrement draws over.
// This is especially an issue when there are lots of small lines being
// drawn.
while (titleShapeDrawn > length) {
titleShapeDrawn -= length;
currentTitleShape++;
if (currentTitleShape >= titleShapes.size()) {
currentTitleShape = 0;
}
length = titleShapes[currentTitleShape]->len;
}
}
void EffectAudioProcessor::getStateInformation(juce::MemoryBlock& destData) {
std::unique_ptr<juce::XmlElement> xml = std::make_unique<juce::XmlElement>("project");

Wyświetl plik

@ -6,6 +6,7 @@
#include "audio/BitCrushEffect.h"
#include "audio/AutoGainControlEffect.h"
#include "txt/TextParser.h"
#include "audio/ShapeVectorRenderer.h"
class EffectAudioProcessor : public juce::AudioProcessor
#if JucePlugin_Enable_ARA
@ -56,6 +57,9 @@ public:
VisualiserParameters visualiserParameters;
osci::AudioBackgroundThreadManager threadManager;
juce::SpinLock sliderLock;
ShapeVectorRenderer sliderRenderer;
protected:
@ -64,16 +68,7 @@ protected:
private:
double currentSampleRate = 44100.0;
// variables for the title
juce::Font titleFont = juce::Font(1.0f, juce::Font::bold);
TextParser titleParser{"bit crush", titleFont};
std::vector<std::unique_ptr<osci::Shape>> titleShapes;
double titleShapesLength = 0.0;
int currentTitleShape = 0;
double titleShapeDrawn = 0.0;
double titleFrameDrawn = 0.0;
void incrementTitleShapeDrawing();
ShapeVectorRenderer titleRenderer;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (EffectAudioProcessor)

Wyświetl plik

@ -11,10 +11,6 @@ EffectsComponent::EffectsComponent(OscirenderAudioProcessor& p, OscirenderAudioP
frequency.slider.setTextValueSuffix("Hz");
frequency.slider.setValue(audioProcessor.frequencyEffect->getValue(), juce::dontSendNotification);
frequency.slider.onValueChange = [this] {
audioProcessor.frequencyEffect->parameters[0]->setUnnormalisedValueNotifyingHost(frequency.slider.getValue());
};
/*addBtn.setButtonText("Add Item...");
addBtn.onClick = [this]()
{

Wyświetl plik

@ -36,15 +36,15 @@ FrameSettingsComponent::FrameSettingsComponent(OscirenderAudioProcessor& p, Osci
audioProcessor.animationOffset->setUnnormalisedValueNotifyingHost(offsetBox.getValue());
};
rateBox.onReturnKey = updateAnimation;
rateBox.onFocusLost = updateAnimation;
offsetBox.onFocusLost = updateAnimation;
offsetBox.onReturnKey = updateAnimation;
threshold.slider.onValueChange = [this]() {
audioProcessor.imageThreshold->setValue(threshold.slider.getValue());
};
stride.slider.onValueChange = [this]() {
audioProcessor.imageStride->setValue(stride.slider.getValue());
animate.setClickingTogglesState(true);
animate.onClick = [this]() {
audioProcessor.animateFrames->setValue(animate.getToggleState());
};
audioProcessor.animationRate->addListener(this);

Wyświetl plik

@ -7,9 +7,6 @@ PerspectiveComponent::PerspectiveComponent(OscirenderAudioProcessor& p, Oscirend
addAndMakeVisible(perspective);
addAndMakeVisible(focalLength);
perspective.setSliderOnValueChange();
focalLength.setSliderOnValueChange();
}
PerspectiveComponent::~PerspectiveComponent() {}

Wyświetl plik

@ -54,7 +54,7 @@ public:
juce::ComponentAnimator codeEditorAnimator;
LuaComponent lua{audioProcessor, *this};
SettingsWindow visualiserSettingsWindow = SettingsWindow("Visualiser Settings", visualiserSettings, 550, 500, 550, VISUALISER_SETTINGS_HEIGHT);
SettingsWindow visualiserSettingsWindow = SettingsWindow("Visualiser Settings", visualiserSettings, 550, 500, 1500, VISUALISER_SETTINGS_HEIGHT);
LuaConsole console;

Wyświetl plik

@ -34,16 +34,19 @@ OscirenderAudioProcessor::OscirenderAudioProcessor() : CommonAudioProcessor(Buse
toggleableEffects.push_back(std::make_shared<osci::Effect>(
std::make_shared<VectorCancellingEffect>(),
new osci::EffectParameter("Vector Cancelling", "Inverts the audio and image every few samples to 'cancel out' the audio, making the audio quiet, and distorting the image.", "vectorCancelling", VERSION_HINT, 0.1111111, 0.0, 1.0)));
toggleableEffects.push_back(std::make_shared<osci::Effect>(
auto scaleEffect = std::make_shared<osci::Effect>(
[this](int index, osci::Point input, const std::vector<std::atomic<double>>& values, double sampleRate) {
return input * osci::Point(values[0], values[1], values[2]);
},
std::vector<osci::EffectParameter*>{
new osci::EffectParameter("Scale X", "Scales the object in the horizontal direction.", "scaleX", VERSION_HINT, 1.0, -5.0, 5.0),
new osci::EffectParameter("Scale Y", "Scales the object in the vertical direction.", "scaleY", VERSION_HINT, 1.0, -5.0, 5.0),
new osci::EffectParameter("Scale Z", "Scales the depth of the object.", "scaleZ", VERSION_HINT, 1.0, -5.0, 5.0),
}));
toggleableEffects.push_back(std::make_shared<osci::Effect>(
new osci::EffectParameter("Scale X", "Scales the object in the horizontal direction.", "scaleX", VERSION_HINT, 1.0, -3.0, 3.0),
new osci::EffectParameter("Scale Y", "Scales the object in the vertical direction.", "scaleY", VERSION_HINT, 1.0, -3.0, 3.0),
new osci::EffectParameter("Scale Z", "Scales the depth of the object.", "scaleZ", VERSION_HINT, 1.0, -3.0, 3.0),
});
scaleEffect->markLockable(true);
booleanParameters.push_back(scaleEffect->linked);
toggleableEffects.push_back(scaleEffect);
auto distortEffect = std::make_shared<osci::Effect>(
[this](int index, osci::Point input, const std::vector<std::atomic<double>>& values, double sampleRate) {
int flip = index % 2 == 0 ? 1 : -1;
osci::Point jitter = osci::Point(flip * values[0], flip * values[1], flip * values[2]);
@ -53,7 +56,10 @@ OscirenderAudioProcessor::OscirenderAudioProcessor() : CommonAudioProcessor(Buse
new osci::EffectParameter("Distort X", "Distorts the image in the horizontal direction by jittering the audio sample being drawn.", "distortX", VERSION_HINT, 0.0, 0.0, 1.0),
new osci::EffectParameter("Distort Y", "Distorts the image in the vertical direction by jittering the audio sample being drawn.", "distortY", VERSION_HINT, 0.0, 0.0, 1.0),
new osci::EffectParameter("Distort Z", "Distorts the depth of the image by jittering the audio sample being drawn.", "distortZ", VERSION_HINT, 0.1, 0.0, 1.0),
}));
});
distortEffect->markLockable(false);
booleanParameters.push_back(distortEffect->linked);
toggleableEffects.push_back(distortEffect);
auto rippleEffect = std::make_shared<osci::Effect>(
[this](int index, osci::Point input, const std::vector<std::atomic<double>>& values, double sampleRate) {
double phase = values[1] * std::numbers::pi;

Wyświetl plik

@ -43,6 +43,17 @@ public:
activeWriter = threadedWriter.get();
}
}
} else {
// Error: Invalid sample rate
juce::AlertWindow::showMessageBoxAsync(
juce::AlertWindow::WarningIcon,
"Recording Error",
"Cannot start recording: Invalid sample rate (" + juce::String(sampleRate) + "). Sample rate must be greater than 0.",
"OK"
);
stop();
stopCallback();
return;
}
}
@ -91,7 +102,7 @@ private:
juce::int64 nextSampleNum = 0;
double recordingLength = 99999999999.0;
double sampleRate = 192000;
double sampleRate = -1;
juce::CriticalSection writerLock;
std::atomic<juce::AudioFormatWriter::ThreadedWriter*> activeWriter { nullptr };

Wyświetl plik

@ -0,0 +1,77 @@
#include "ShapeVectorRenderer.h"
ShapeVectorRenderer::ShapeVectorRenderer(double sampleRate, double frequency)
: currentSampleRate(sampleRate), frequency(frequency) {
}
void ShapeVectorRenderer::setShapes(std::vector<std::unique_ptr<osci::Shape>> newShapes) {
shapes.clear();
// Move the shapes from the input vector to our internal vector
for (auto& shape : newShapes) {
shapes.push_back(std::move(shape));
}
// Calculate the total length of all shapes
shapesLength = osci::Shape::totalLength(shapes);
// Reset the drawing state
currentShape = 0;
shapeDrawn = 0.0;
frameDrawn = 0.0;
}
osci::Point ShapeVectorRenderer::nextVector() {
osci::Point point = { 0.0, 0.0, 1.0f };
if (shapes.size() <= 0) {
return point;
}
if (currentShape < shapes.size()) {
auto& shape = shapes[currentShape];
double length = shape->length();
double drawingProgress = length == 0.0 ? 1.0 : shapeDrawn / length;
point = shape->nextVector(drawingProgress);
point.z = 1.0f;
}
incrementShapeDrawing();
if (frameDrawn >= shapesLength) {
frameDrawn -= shapesLength;
currentShape = 0;
}
return point;
}
void ShapeVectorRenderer::setSampleRate(double newSampleRate) {
currentSampleRate = newSampleRate;
}
void ShapeVectorRenderer::setFrequency(double newFrequency) {
frequency = newFrequency;
}
void ShapeVectorRenderer::incrementShapeDrawing() {
if (shapes.size() <= 0) return;
double length = currentShape < shapes.size() ? shapes[currentShape]->len : 0.0;
double lengthIncrement = shapesLength / (currentSampleRate / frequency);
frameDrawn += lengthIncrement;
shapeDrawn += lengthIncrement;
// Need to skip all shapes that the lengthIncrement draws over.
// This is especially an issue when there are lots of small lines being
// drawn.
while (shapeDrawn > length) {
shapeDrawn -= length;
currentShape++;
if (currentShape >= shapes.size()) {
currentShape = 0;
}
length = shapes[currentShape]->len;
}
}

Wyświetl plik

@ -0,0 +1,35 @@
#pragma once
#include <JuceHeader.h>
#include <vector>
#include <memory>
#include "../visualiser/VisualiserParameters.h"
class ShapeVectorRenderer {
public:
ShapeVectorRenderer(double sampleRate = 44100.0, double frequency = 60.0);
// Set new shapes to render
void setShapes(std::vector<std::unique_ptr<osci::Shape>> newShapes);
// Get the next point in the shape vector sequence
osci::Point nextVector();
// Update sample rate if it changes
void setSampleRate(double newSampleRate);
// Set the frequency at which shapes should be drawn
void setFrequency(double newFrequency);
private:
double currentSampleRate = 44100.0;
double frequency = 60.0;
std::vector<std::unique_ptr<osci::Shape>> shapes;
double shapesLength = 0.0;
int currentShape = 0;
double shapeDrawn = 0.0;
double frameDrawn = 0.0;
void incrementShapeDrawing();
};

Wyświetl plik

@ -8,6 +8,7 @@ public:
setMultiLine(false);
setJustification(juce::Justification::centred);
setFont(juce::Font(15.0f, juce::Font::plain));
setSelectAllWhenFocused(true);
onTextChange = [this]() {
setText(getText(), false);
};

Wyświetl plik

@ -1,4 +1,5 @@
#include "EffectComponent.h"
#include "../LookAndFeel.h"
EffectComponent::EffectComponent(osci::Effect& effect, int index) : effect(effect), index(index) {
@ -15,6 +16,16 @@ EffectComponent::EffectComponent(osci::Effect& effect, int index) : effect(effec
addAndMakeVisible(*sidechainButton);
}
if (effect.linked != nullptr && index == 0) {
linkButton.setTooltip("When enabled, parameters are linked and changes to one parameter will affect all parameters.");
linkButton.onClick = [this]() {
if (this->effect.linked != nullptr) {
this->effect.linked->setBoolValueNotifyingHost(!this->effect.linked->getBoolValue());
}
};
addAndMakeVisible(linkButton);
}
slider.setSliderStyle(juce::Slider::LinearHorizontal);
slider.setTextBoxStyle(juce::Slider::TextBoxRight, false, TEXT_BOX_WIDTH, slider.getTextBoxHeight());
if (effect.parameters[index]->step == 1.0) {
@ -57,8 +68,8 @@ EffectComponent::EffectComponent(osci::Effect& effect) : EffectComponent(effect,
void EffectComponent::setSliderValueIfChanged(osci::FloatParameter* parameter, juce::Slider& slider) {
juce::String newSliderValue = juce::String(parameter->getValueUnnormalised(), 3);
juce::String oldSliderValue = juce::String((float) slider.getValue(), 3);
juce::String oldSliderValue = juce::String((float)slider.getValue(), 3);
// only set the slider value if the parameter value is different so that we prefer the more
// precise slider value.
if (newSliderValue != oldSliderValue) {
@ -70,7 +81,17 @@ void EffectComponent::setupComponent() {
osci::EffectParameter* parameter = effect.parameters[index];
setEnabled(effect.enabled == nullptr || effect.enabled->getBoolValue());
if (effect.linked != nullptr && index == 0) {
linkButton.setToggleState(effect.linked->getBoolValue(), juce::dontSendNotification);
if (effect.linked->getBoolValue()) {
for (int i = 1; i < effect.parameters.size(); i++) {
effect.setValue(i, effect.parameters[0]->getValueUnnormalised());
}
}
}
if (updateToggleState != nullptr) {
updateToggleState();
}
@ -83,6 +104,20 @@ void EffectComponent::setupComponent() {
setSliderValueIfChanged(parameter, slider);
slider.setDoubleClickReturnValue(true, parameter->defaultValue);
// Set the new slider value change handler
slider.onValueChange = [this] {
// Update the effect parameter with this slider's value
effect.setValue(index, slider.getValue());
if (effect.linked != nullptr && effect.linked->getBoolValue()) {
for (int i = 0; i < effect.parameters.size(); i++) {
if (i != index) {
effect.setValue(i, slider.getValue());
}
}
}
};
lfoEnabled = parameter->lfo != nullptr && parameter->lfoRate != nullptr;
if (lfoEnabled) {
lfo.setSelectedId(parameter->lfo->getValueUnnormalised(), juce::dontSendNotification);
@ -125,7 +160,6 @@ void EffectComponent::setupComponent() {
effect.parameters[index]->sidechain->setBoolValueNotifyingHost(!effect.parameters[index]->sidechain->getBoolValue());
};
}
if (sidechainEnabled && effect.parameters[index]->sidechain->getBoolValue()) {
slider.setEnabled(false);
@ -138,7 +172,6 @@ void EffectComponent::setupComponent() {
}
}
EffectComponent::~EffectComponent() {
effect.removeListener(index, this);
}
@ -146,14 +179,17 @@ EffectComponent::~EffectComponent() {
void EffectComponent::resized() {
auto bounds = getLocalBounds();
auto componentBounds = bounds.removeFromRight(25);
if (component != nullptr) {
if (effect.linked != nullptr) {
linkButton.setBounds(componentBounds);
} else if (component != nullptr) {
component->setBounds(componentBounds);
}
if (sidechainEnabled) {
sidechainButton->setBounds(bounds.removeFromRight(20));
}
if (settingsButton.isVisible()) {
settingsButton.setBounds(bounds.removeFromRight(20));
}
@ -165,7 +201,7 @@ void EffectComponent::resized() {
}
bounds.removeFromRight(2);
bounds.removeFromLeft(5);
label.setBounds(bounds.removeFromLeft(drawingSmall ? SMALL_TEXT_WIDTH : TEXT_WIDTH));
@ -205,12 +241,6 @@ void EffectComponent::setRangeEnabled(bool enabled) {
}
void EffectComponent::setComponent(std::shared_ptr<juce::Component> component) {
this->component = component;
this->component = component;
addAndMakeVisible(component.get());
}
void EffectComponent::setSliderOnValueChange() {
slider.onValueChange = [this] {
effect.setValue(index, slider.getValue());
};
}

Wyświetl plik

@ -1,5 +1,6 @@
#pragma once
#include <JuceHeader.h>
#include "LabelledTextBox.h"
#include "SvgButton.h"
@ -18,14 +19,13 @@ public:
void setRangeEnabled(bool enabled);
void setComponent(std::shared_ptr<juce::Component> component);
void setSliderOnValueChange();
juce::Slider slider;
juce::Slider lfoSlider;
osci::Effect& effect;
int index = 0;
juce::ComboBox lfo;
class EffectSettingsComponent : public juce::Component {
public:
EffectSettingsComponent(EffectComponent* parent) {
@ -38,9 +38,9 @@ public:
addAndMakeVisible(lfoEndSlider);
addAndMakeVisible(smoothValueChangeLabel);
addAndMakeVisible(smoothValueChangeSlider);
osci::EffectParameter* parameter = parent->effect.parameters[parent->index];
min.textBox.setValue(parameter->min, juce::dontSendNotification);
max.textBox.setValue(parameter->max, juce::dontSendNotification);
@ -87,7 +87,7 @@ public:
lfoEndSlider.onValueChange = [this, parameter]() {
parameter->lfoEndPercent->setUnnormalisedValueNotifyingHost(lfoEndSlider.getValue());
};
smoothValueChangeLabel.setText("Smooth Value Change Speed", juce::dontSendNotification);
smoothValueChangeLabel.setJustificationType(juce::Justification::centred);
smoothValueChangeLabel.setFont(juce::Font(14.0f, juce::Font::bold));
@ -102,7 +102,7 @@ public:
popupLabel.setJustificationType(juce::Justification::centred);
popupLabel.setFont(juce::Font(14.0f, juce::Font::bold));
}
void resized() override {
auto bounds = getLocalBounds();
popupLabel.setBounds(bounds.removeFromTop(30));
@ -115,7 +115,7 @@ public:
smoothValueChangeLabel.setBounds(bounds.removeFromTop(20));
smoothValueChangeSlider.setBounds(bounds.removeFromTop(40));
}
private:
juce::Label popupLabel;
LabelledTextBox min{"Min"};
@ -127,7 +127,7 @@ public:
juce::Label smoothValueChangeLabel;
juce::Slider smoothValueChangeSlider;
};
std::function<void()> updateToggleState;
private:
@ -145,9 +145,17 @@ private:
std::unique_ptr<SvgButton> sidechainButton;
SvgButton linkButton = SvgButton(effect.parameters[index]->name + " Link",
BinaryData::link_svg,
juce::Colours::white,
juce::Colours::red,
nullptr,
BinaryData::link_svg
);
juce::Label label;
SvgButton settingsButton = { "settingsButton", BinaryData::cog_svg, juce::Colours::white };
SvgButton settingsButton = {"settingsButton", BinaryData::cog_svg, juce::Colours::white};
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(EffectComponent)
};

Wyświetl plik

@ -12,11 +12,6 @@ effect(effect), audioProcessor(data.audioProcessor), editor(data.editor) {
// using weak_ptr to avoid circular reference and memory leak
std::weak_ptr<EffectComponent> weakEffectComponent = effectComponent;
effectComponent->slider.setValue(parameters[i]->getValueUnnormalised(), juce::dontSendNotification);
effectComponent->slider.onValueChange = [this, i, weakEffectComponent] {
if (auto effectComponent = weakEffectComponent.lock()) {
this->effect.setValue(i, effectComponent->slider.getValue());
}
};
list.setEnabled(selected.getToggleState());
selected.onClick = [this, weakEffectComponent] {

Wyświetl plik

@ -3,10 +3,6 @@
LuaListComponent::LuaListComponent(OscirenderAudioProcessor& p, osci::Effect& effect) {
effectComponent = std::make_shared<EffectComponent>(effect);
effectComponent->slider.onValueChange = [this, &effect, &p] {
effect.setValue(effectComponent->slider.getValue());
};
addAndMakeVisible(*effectComponent);
}

Wyświetl plik

@ -0,0 +1,149 @@
#include "SliderVisualiserComponent.h"
SliderVisualiserComponent::SliderVisualiserComponent(EffectAudioProcessor& processor)
: audioProcessor(processor)
{
sliderVisualiser.setCropRectangle(juce::Rectangle<float>(0.0f, 0.35f, 1.0f, 0.25f));
sliderVisualiser.setInterceptsMouseClicks(false, false);
// Configure slider to be invisible but functional
slider.setLookAndFeel(nullptr); // Remove any look and feel
slider.setColour(juce::Slider::trackColourId, juce::Colours::transparentBlack);
slider.setColour(juce::Slider::backgroundColourId, juce::Colours::transparentBlack);
slider.setColour(juce::Slider::thumbColourId, juce::Colours::transparentBlack);
slider.setColour(juce::Slider::textBoxOutlineColourId, juce::Colours::transparentBlack);
slider.setColour(juce::Slider::textBoxTextColourId, juce::Colours::transparentBlack);
slider.setColour(juce::Slider::textBoxBackgroundColourId, juce::Colours::transparentBlack);
slider.setTextBoxStyle(juce::Slider::NoTextBox, true, 0, 0);
slider.setRange(0.0, 1.0, 0.001);
// Setup default callback
slider.onValueChange = [this] { updateVisualiser(); };
// Set default label
setLabel("Param");
addAndMakeVisible(sliderVisualiser);
addAndMakeVisible(slider);
}
SliderVisualiserComponent::~SliderVisualiserComponent()
{
}
void SliderVisualiserComponent::resized()
{
auto bounds = getLocalBounds();
sliderVisualiser.setBounds(bounds);
// Scale down the slider to match the visual representation
// It should only occupy the portion where the slider visuals appear (not the label area)
int labelWidth = bounds.getWidth() * labelWidthProportion;
auto sliderBounds = bounds.withTrimmedLeft(labelWidth - 5);
slider.setBounds(sliderBounds.withTrimmedRight(10)); // Add some padding on the right
}
void SliderVisualiserComponent::setValue(double newValue)
{
slider.setValue(newValue);
}
double SliderVisualiserComponent::getValue() const
{
return slider.getValue();
}
void SliderVisualiserComponent::setRange(double newMinimum, double newMaximum, double newInterval)
{
slider.setRange(newMinimum, newMaximum, newInterval);
}
void SliderVisualiserComponent::addListener(juce::Slider::Listener* listener)
{
slider.addListener(listener);
}
void SliderVisualiserComponent::removeListener(juce::Slider::Listener* listener)
{
slider.removeListener(listener);
}
void SliderVisualiserComponent::onValueChange(std::function<void()> callback)
{
slider.onValueChange = [this, callback]() {
updateVisualiser();
callback();
};
}
void SliderVisualiserComponent::setLabel(const juce::String& labelText)
{
// Only update if the label has changed
if (label != labelText) {
label = labelText;
updateLabelShapes();
updateVisualiser();
}
}
void SliderVisualiserComponent::updateLabelShapes()
{
// Create text shapes using TextParser
if (label.isNotEmpty()) {
TextParser labelParser{label, labelFont};
labelShapes = labelParser.draw();
// Calculate the center of the label area
double labelCenter = -1.0 + (labelWidthProportion * 1.0); // Center of the label area in oscilloscope space
// Scale and position the label shapes to appear on the left side
for (auto& shape : labelShapes) {
// Scale down the text to fit nicely
shape->scale(0.3, 0.3, 1.0);
// Position centered in the label area
shape->translate(labelCenter, 0.0, 0.0);
}
} else {
labelShapes.clear();
}
}
void SliderVisualiserComponent::updateVisualiser()
{
// Create shapes for the slider indicator
std::vector<std::unique_ptr<osci::Shape>> combinedShapes;
// First add the label shapes
for (auto& shape : labelShapes) {
combinedShapes.push_back(shape->clone());
}
// Calculate the visualizer coordinates that exactly match our component layout
// Convert component coordinates to oscilloscope coordinates (-1.0 to 1.0)
double sliderStart = -1.0 + (labelWidthProportion * 2.0); // Scaled from component space to oscilloscope space
double sliderEnd = 1.0;
double sliderRange = sliderEnd - sliderStart;
double value = slider.getValue();
double circleRadius = 0.07;
// Map the normalized slider value (0-1) to our visual slider range
double xPos = sliderStart + (value * sliderRange);
// Add the left line only if there's space for it (circle not at left edge)
if (xPos - circleRadius > sliderStart) {
combinedShapes.push_back(std::make_unique<osci::Line>(sliderStart, 0.0, xPos - circleRadius, 0.0)); // Left line
}
// Add the right line only if there's space for it (circle not at right edge)
if (xPos + circleRadius < sliderEnd) {
combinedShapes.push_back(std::make_unique<osci::Line>(xPos + circleRadius, 0.0, sliderEnd, 0.0)); // Right line
}
// Add circle
combinedShapes.push_back(std::make_unique<osci::CircleArc>(xPos, 0.0, circleRadius, circleRadius, 0.0, 2.0 * M_PI));
juce::SpinLock::ScopedLockType lock(audioProcessor.sliderLock);
// Set the shapes in the renderer
audioProcessor.sliderRenderer.setShapes(std::move(combinedShapes));
}

Wyświetl plik

@ -0,0 +1,52 @@
#pragma once
#include <JuceHeader.h>
#include "../visualiser/VisualiserRenderer.h"
#include "../EffectPluginProcessor.h"
#include "../txt/TextParser.h"
class SliderVisualiserComponent : public juce::Component
{
public:
SliderVisualiserComponent(EffectAudioProcessor& processor);
~SliderVisualiserComponent() override;
void resized() override;
void setValue(double newValue);
double getValue() const;
// Forwards to underlying slider
void setRange(double newMinimum, double newMaximum, double newInterval = 0.0);
void addListener(juce::Slider::Listener* listener);
void removeListener(juce::Slider::Listener* listener);
void onValueChange(std::function<void()> callback);
// Set the label text to be displayed next to the slider
void setLabel(const juce::String& labelText);
// Update the visualiser display
void updateVisualiser();
private:
EffectAudioProcessor& audioProcessor;
VisualiserRenderer sliderVisualiser{
audioProcessor.visualiserParameters,
audioProcessor.threadManager,
512,
60.0,
"Slider"
};
juce::Slider slider;
juce::String label;
std::vector<std::unique_ptr<osci::Shape>> labelShapes;
juce::Font labelFont{0.7f};
// Proportion of the width allocated for the label
const double labelWidthProportion = 0.35;
void updateLabelShapes();
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SliderVisualiserComponent)
};

Wyświetl plik

@ -338,7 +338,12 @@ float ImageParser::getPixelValue(int x, int y, bool invert) {
if (usingLiveImage) {
if (liveImage.isValid()) {
if (x < 0 || x >= width || y < 0 || y >= height) return 0;
#if JUCE_MAC
juce::Colour pixel = liveImage.getPixelAt(x, y);
#else
juce::Colour pixel = liveImage.getPixelAt(x, height - y - 1);
#endif
float value = pixel.getBrightness();
if (invert && value > 0) value = 1.0f - value;
return value;

Wyświetl plik

@ -15,9 +15,7 @@ void FileParser::showFileSizeWarning(juce::String fileName, int64_t totalBytes,
}
const double fileSizeMB = totalBytes / (1024.0 * 1024.0);
juce::String message = juce::String::formatted(
"The %s file '%s' you're trying to open is %.2f MB in size, and may time a long time to open. "
"Would you like to continue loading it?", fileType.toRawUTF8(), fileName.toRawUTF8(), fileSizeMB);
juce::String message = "The " + fileType + " file '" + fileName + "' you're trying to open is " + juce::String(fileSizeMB, 2) + " MB in size, and may time a long time to open.\n\nWould you like to continue loading it?";
juce::MessageManager::callAsync([this, message, callback]() {
juce::AlertWindow::showOkCancelBox(

Wyświetl plik

@ -18,11 +18,8 @@ RecordingSettings::RecordingSettings(RecordingParameters& ps) : parameters(ps) {
addAndMakeVisible(customSharedTextureOutputLabel);
addAndMakeVisible(customSharedTextureOutputEditor);
quality.setSliderOnValueChange();
quality.setRangeEnabled(false);
resolution.setSliderOnValueChange();
resolution.setRangeEnabled(false);
frameRate.setSliderOnValueChange();
frameRate.setRangeEnabled(false);
recordAudio.onClick = [this] {

Wyświetl plik

@ -26,6 +26,8 @@ VisualiserComponent::VisualiserComponent(
visualiserOnly(visualiserOnly),
parent(parent),
editor(pluginEditor) {
setShouldBeRunning(true);
#if OSCI_PREMIUM
addAndMakeVisible(editor.ffmpegDownloader);
#endif

Wyświetl plik

@ -86,6 +86,12 @@ public:
class VisualiserParameters {
public:
VisualiserParameters() {
#if OSCI_PREMIUM
scaleEffect->markLockable(true);
booleans.push_back(scaleEffect->linked);
#endif
}
double getIntensity() {
return intensityEffect->getActualValue() / 100;

Wyświetl plik

@ -30,7 +30,6 @@ VisualiserRenderer::VisualiserRenderer(
{
openGLContext.setRenderer(this);
openGLContext.attachTo(*this);
setShouldBeRunning(true);
}
VisualiserRenderer::~VisualiserRenderer() {
@ -203,6 +202,10 @@ void VisualiserRenderer::newOpenGLContextCreated() {
juce::CriticalSection::ScopedLockType lock(samplesLock);
#if JUCE_WINDOWS && JUCE_DEBUG
glDisable(GL_DEBUG_OUTPUT);
#endif
glColorMask(true, true, true, true);
viewportChanged(viewportArea);

Wyświetl plik

@ -15,7 +15,8 @@ VisualiserSettings::VisualiserSettings(VisualiserParameters& p, int numChannels)
addAndMakeVisible(screenOverlayLabel);
addAndMakeVisible(screenOverlay);
#if OSCI_PREMIUM
addAndMakeVisible(positionSize);
addAndMakeVisible(scale);
addAndMakeVisible(position);
addAndMakeVisible(screenColour);
addAndMakeVisible(flipVerticalToggle);
addAndMakeVisible(flipHorizontalToggle);
@ -31,9 +32,6 @@ VisualiserSettings::VisualiserSettings(VisualiserParameters& p, int numChannels)
parameters.screenOverlay->setUnnormalisedValueNotifyingHost(screenOverlay.getSelectedId());
};
sweepMs.setSliderOnValueChange();
triggerValue.setSliderOnValueChange();
sweepMs.setEnabled(sweepToggle.getToggleState());
triggerValue.setEnabled(sweepToggle.getToggleState());
@ -79,7 +77,9 @@ void VisualiserSettings::resized() {
#if OSCI_PREMIUM
area.removeFromTop(10);
positionSize.setBounds(area.removeFromTop(positionSize.getHeight()));
scale.setBounds(area.removeFromTop(scale.getHeight()));
area.removeFromTop(10);
position.setBounds(area.removeFromTop(position.getHeight()));
area.removeFromTop(10);
flipVerticalToggle.setBounds(area.removeFromTop(rowHeight));
flipHorizontalToggle.setBounds(area.removeFromTop(rowHeight));

Wyświetl plik

@ -3,12 +3,13 @@
#define VERSION_HINT 2
#include <JuceHeader.h>
#include "../components/EffectComponent.h"
#include "../components/SvgButton.h"
#include "../LookAndFeel.h"
#include "../components/SwitchButton.h"
#include "../audio/SmoothEffect.h"
#include "../audio/StereoEffect.h"
#include "../components/EffectComponent.h"
#include "../components/SvgButton.h"
#include "../components/SwitchButton.h"
#include "VisualiserParameters.h"
class GroupedSettings : public juce::GroupComponent {
@ -16,29 +17,28 @@ public:
GroupedSettings(std::vector<std::shared_ptr<EffectComponent>> effects, juce::String label) : effects(effects), juce::GroupComponent(label, label) {
for (auto effect : effects) {
addAndMakeVisible(effect.get());
effect->setSliderOnValueChange();
}
setColour(groupComponentBackgroundColourId, Colours::veryDark.withMultipliedBrightness(3.0));
}
void resized() override {
auto area = getLocalBounds();
area.removeFromTop(35);
double rowHeight = 30;
for (auto effect : effects) {
effect->setBounds(area.removeFromTop(rowHeight));
}
}
int getHeight() {
return 40 + effects.size() * 30;
}
private:
std::vector<std::shared_ptr<EffectComponent>> effects;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(GroupedSettings)
};
@ -62,9 +62,8 @@ private:
std::make_shared<EffectComponent>(*parameters.lineSaturationEffect),
std::make_shared<EffectComponent>(*parameters.intensityEffect),
},
"Line Colour"
};
"Line Colour"};
#if OSCI_PREMIUM
GroupedSettings screenColour{
std::vector<std::shared_ptr<EffectComponent>>{
@ -72,10 +71,9 @@ private:
std::make_shared<EffectComponent>(*parameters.screenSaturationEffect),
std::make_shared<EffectComponent>(*parameters.ambientEffect),
},
"Screen Colour"
};
"Screen Colour"};
#endif
GroupedSettings lightEffects{
std::vector<std::shared_ptr<EffectComponent>>{
std::make_shared<EffectComponent>(*parameters.persistenceEffect),
@ -88,16 +86,14 @@ private:
std::make_shared<EffectComponent>(*parameters.ambientEffect),
#endif
},
"Light Effects"
};
"Light Effects"};
GroupedSettings videoEffects{
std::vector<std::shared_ptr<EffectComponent>>{
std::make_shared<EffectComponent>(*parameters.noiseEffect),
},
"Video Effects"
};
"Video Effects"};
GroupedSettings lineEffects{
std::vector<std::shared_ptr<EffectComponent>>{
std::make_shared<EffectComponent>(*parameters.smoothEffect),
@ -105,28 +101,31 @@ private:
std::make_shared<EffectComponent>(*parameters.stereoEffect),
#endif
},
"Line Effects"
};
"Line Effects"};
EffectComponent sweepMs{*parameters.sweepMsEffect};
EffectComponent triggerValue{*parameters.triggerValueEffect};
juce::Label screenOverlayLabel{"Screen Overlay", "Screen Overlay"};
juce::ComboBox screenOverlay;
jux::SwitchButton upsamplingToggle{parameters.upsamplingEnabled};
jux::SwitchButton sweepToggle{parameters.sweepEnabled};
#if OSCI_PREMIUM
GroupedSettings positionSize{
GroupedSettings scale{
std::vector<std::shared_ptr<EffectComponent>>{
std::make_shared<EffectComponent>(*parameters.scaleEffect, 0),
std::make_shared<EffectComponent>(*parameters.scaleEffect, 1),
},
"Image Scale"};
GroupedSettings position{
std::vector<std::shared_ptr<EffectComponent>>{
std::make_shared<EffectComponent>(*parameters.offsetEffect, 0),
std::make_shared<EffectComponent>(*parameters.offsetEffect, 1),
},
"Line Position & Scale"
};
"Image Position"};
jux::SwitchButton flipVerticalToggle{parameters.flipVertical};
jux::SwitchButton flipHorizontalToggle{parameters.flipHorizontal};
@ -160,7 +159,7 @@ private:
class SettingsWindow : public juce::DialogWindow {
public:
SettingsWindow(juce::String name, juce::Component& component, int windowWidth, int windowHeight, int componentWidth, int componentHeight) : juce::DialogWindow(name, Colours::darker, true, true), component(component) {
SettingsWindow(juce::String name, juce::Component& component, int windowWidth, int windowHeight, int componentWidth, int componentHeight) : juce::DialogWindow(name, Colours::darker, true, true), component(component), componentHeight(componentHeight) {
setContentComponent(&viewport);
centreWithSize(windowWidth, windowHeight);
setResizeLimits(windowWidth, windowHeight, componentWidth, componentHeight);
@ -175,7 +174,14 @@ public:
setVisible(false);
}
void resized() override {
DialogWindow::resized();
// Update the component width to match the viewport width while maintaining its height
component.setSize(viewport.getWidth(), componentHeight);
}
private:
juce::Viewport viewport;
juce::Component& component;
int componentHeight;
};

@ -1 +1 @@
Subproject commit 3e2d2daa7e07e4317bdd096bcdb3dbb721241efa
Subproject commit 4ddac1f6ff0853c989bf3ab619e0f1e0264f5a45

Wyświetl plik

@ -81,6 +81,10 @@
<GROUP id="{85A33213-D880-BD92-70D8-1901DA6D23F0}" name="audio">
<FILE id="fwEcan" name="AutoGainControlEffect.h" compile="0" resource="0"
file="Source/audio/AutoGainControlEffect.h"/>
<FILE id="m3ONmD" name="ShapeVectorRenderer.cpp" compile="1" resource="0"
file="Source/audio/ShapeVectorRenderer.cpp"/>
<FILE id="EEZHBS" name="ShapeVectorRenderer.h" compile="0" resource="0"
file="Source/audio/ShapeVectorRenderer.h"/>
<FILE id="GSnwBW" name="SmoothEffect.h" compile="0" resource="0" file="Source/audio/SmoothEffect.h"/>
<FILE id="jq3EXV" name="StereoEffect.h" compile="0" resource="0" file="Source/audio/StereoEffect.h"/>
</GROUP>
@ -93,6 +97,10 @@
file="Source/components/MainMenuBarModel.cpp"/>
<FILE id="t6oUhv" name="MainMenuBarModel.h" compile="0" resource="0"
file="Source/components/MainMenuBarModel.h"/>
<FILE id="i4SGze" name="SliderVisualiserComponent.cpp" compile="1"
resource="0" file="Source/components/SliderVisualiserComponent.cpp"/>
<FILE id="vRJQLf" name="SliderVisualiserComponent.h" compile="0" resource="0"
file="Source/components/SliderVisualiserComponent.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"/>
</GROUP>

Wyświetl plik

@ -4,7 +4,7 @@
addUsingNamespaceToJuceHeader="0" jucerFormatVersion="1" pluginCharacteristicsValue="pluginWantsMidiIn"
pluginManufacturer="jameshball" aaxIdentifier="sh.ball.oscirender"
cppLanguageStandard="20" projectLineFeed="&#10;" headerPath="./include"
version="2.5.0.7" companyName="James H Ball" companyWebsite="https://osci-render.com"
version="2.5.1.1" companyName="James H Ball" companyWebsite="https://osci-render.com"
companyEmail="james@ball.sh" defines="NOMINMAX=1&#10;INTERNET_FLAG_NO_AUTO_REDIRECT=0&#10;OSCI_PREMIUM=1&#10;JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP=1&#10;JUCE_MODAL_LOOPS_PERMITTED=1"
pluginAUMainType="'aumf'">
<MAINGROUP id="j5Ge2T" name="osci-render">
@ -53,6 +53,7 @@
file="Resources/svg/fixed_rotate.svg"/>
<FILE id="WIkl6l" name="fullscreen.svg" compile="0" resource="1" file="Resources/svg/fullscreen.svg"/>
<FILE id="n1esUp" name="left_arrow.svg" compile="0" resource="1" file="Resources/svg/left_arrow.svg"/>
<FILE id="WdfE7J" name="link.svg" compile="0" resource="1" file="Resources/svg/link.svg"/>
<FILE id="PxYKbt" name="microphone.svg" compile="0" resource="1" file="Resources/svg/microphone.svg"/>
<FILE id="eGMxwy" name="mute.svg" compile="0" resource="1" file="Resources/svg/mute.svg"/>
<FILE id="hJHxFY" name="open_in_new.svg" compile="0" resource="1" file="Resources/svg/open_in_new.svg"/>

Wyświetl plik

@ -3,7 +3,7 @@
<JUCERPROJECT id="HH2E72" name="sosci" projectType="audioplug" useAppConfig="0"
addUsingNamespaceToJuceHeader="0" jucerFormatVersion="1" pluginManufacturer="jameshball"
aaxIdentifier="sh.ball.sosci" cppLanguageStandard="20" projectLineFeed="&#10;"
headerPath="./include" version="1.1.6.2" companyName="James H Ball"
headerPath="./include" version="1.1.7.1" companyName="James H Ball"
companyWebsite="https://osci-render.com" companyEmail="james@ball.sh"
defines="NOMINMAX=1&#10;INTERNET_FLAG_NO_AUTO_REDIRECT=0&#10;OSCI_PREMIUM=1&#10;JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP=1&#10;JUCE_MODAL_LOOPS_PERMITTED=1"
pluginManufacturerCode="Jhba" pluginCode="Sosc" pluginAUMainType="'aufx'">
@ -57,6 +57,7 @@
file="Resources/svg/fixed_rotate.svg"/>
<FILE id="WIkl6l" name="fullscreen.svg" compile="0" resource="1" file="Resources/svg/fullscreen.svg"/>
<FILE id="n1esUp" name="left_arrow.svg" compile="0" resource="1" file="Resources/svg/left_arrow.svg"/>
<FILE id="Q2mSgZ" name="link.svg" compile="0" resource="1" file="Resources/svg/link.svg"/>
<FILE id="PxYKbt" name="microphone.svg" compile="0" resource="1" file="Resources/svg/microphone.svg"/>
<FILE id="WoY9r2" name="mute.svg" compile="0" resource="1" file="Resources/svg/mute.svg"/>
<FILE id="hJHxFY" name="open_in_new.svg" compile="0" resource="1" file="Resources/svg/open_in_new.svg"/>